EMMA Coverage Report (generated Fri Jul 01 07:36:49 EDT 2005)
[all classes][rossi.dfp]

COVERAGE SUMMARY FOR SOURCE FILE [dfpmath.java]

nameclass, %method, %block, %line, %
dfpmath.java100% (1/1)77%  (17/22)86%  (1575/1834)83%  (312.9/376)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class dfpmath100% (1/1)77%  (17/22)86%  (1575/1834)83%  (312.9/376)
acos (dfp): dfp 0%   (0/1)0%   (0/32)0%   (0/8)
asin (dfp): dfp 0%   (0/1)0%   (0/10)0%   (0/1)
cos (dfp): dfp 0%   (0/1)0%   (0/81)0%   (0/19)
dfpmath (): void 0%   (0/1)0%   (0/3)0%   (0/1)
tan (dfp): dfp 0%   (0/1)0%   (0/6)0%   (0/1)
pow (dfp, int): dfp 100% (1/1)12%  (8/65)18%  (4/22)
exp (dfp): dfp 100% (1/1)76%  (31/41)82%  (9/11)
atan (dfp): dfp 100% (1/1)82%  (132/160)82%  (27/33)
ln (dfp): dfp 100% (1/1)92%  (217/237)86%  (32/37)
lnInternal (dfp []): dfp [] 100% (1/1)93%  (81/87)93%  (15.9/17)
pow (dfp, dfp): dfp 100% (1/1)98%  (359/365)99%  (69/70)
<static initializer> 100% (1/1)100% (61/61)100% (14/14)
atanInternal (dfp): dfp 100% (1/1)100% (51/51)100% (12/12)
cosInternal (dfp []): dfp 100% (1/1)100% (63/63)100% (15/15)
expInternal (dfp): dfp 100% (1/1)100% (44/44)100% (12/12)
sin (dfp): dfp 100% (1/1)100% (82/82)100% (19/19)
sinInternal (dfp []): dfp 100% (1/1)100% (63/63)100% (15/15)
split (String): dfp [] 100% (1/1)100% (128/128)100% (24/24)
split (dfp): dfp [] 100% (1/1)100% (33/33)100% (6/6)
splitDiv (dfp [], dfp []): dfp [] 100% (1/1)100% (55/55)100% (5/5)
splitMult (dfp [], dfp []): dfp [] 100% (1/1)100% (61/61)100% (7/7)
splitPow (dfp [], int): dfp 100% (1/1)100% (106/106)100% (27/27)

1 
2package rossi.dfp;
3 
4/** Mathematical routines and constants for use with dfp.  Constants are 
5 *  defined with in dfpconstants.java
6 */
7 
8public class dfpmath implements dfpconstants
9{
10  /** sqrt(2) */
11  public final static dfp SQR2 = new dfp(STR_SQR2);
12  /** sqrt(2) in 2 pieces */
13  public final static dfp[] SQR2_SPLIT = split(STR_SQR2);
14  /** sqrt(2)/2 */
15  public final static dfp SQR2_2 = new dfp(STR_SQR2_2);
16  /** sqrt(3) */
17  public final static dfp SQR3 = new dfp(STR_SQR3);
18  /** sqrt(3)/3 */
19  public final static dfp SQR3_3 = new dfp(STR_SQR3_3);
20  /** PI */
21  public final static dfp PI = new dfp(STR_PI);
22  /** PI_SPLIT in 2 pieces */
23  public final static dfp[] PI_SPLIT = split(STR_PI);
24  /** E */
25  public final static dfp E = new dfp(STR_E);
26  /** E_SPLIT  The number e split in two pieces */
27  public final static dfp[] E_SPLIT = split(STR_E);
28  /** ln(2) */
29  public final static dfp LN2 = new dfp(STR_LN2);
30  /** LN2_SPLIT  The number e split in two pieces */
31  public final static dfp[] LN2_SPLIT = split(STR_LN2);
32  /** ln(5) */
33  public final static dfp LN5 = new dfp(STR_LN5);
34  /** LN5_SPLIT  The number e split in two pieces */
35  public final static dfp[] LN5_SPLIT = split(STR_LN5);
36  /** ln(10) */
37  public final static dfp LN10 = new dfp(STR_LN10);
38 
39  /** Breaks a string representation up into two dfp's such 
40   * that the sum of them is equivilent to the input string, but
41   * has higher precision than using a single dfp.  Useful for
42   * improving accuracy of exponentination and critical multplies */
43  protected static dfp[] split(String a)
44  {
45    dfp result[] = new dfp[2];
46    char[] buf;
47    boolean leading = true;
48    int sp = 0;
49    int sig = 0;
50 
51    buf = new char[a.length()];
52 
53    for (int i=0; i<buf.length; i++)
54    {
55      buf[i] = a.charAt(i);
56 
57      if (buf[i] >= '1' && buf[i] <= '9')
58        leading = false;
59 
60      if (buf[i] == '.')
61      {
62        sig += ((400-sig) % 4);
63        leading = false;
64      }
65 
66      if (sig == (dfp.DIGITS/2) * 4)
67      {
68        sp = i;
69        break;
70      }
71 
72      if (buf[i] >= '0' && buf[i] <= '9' && !leading)
73        sig ++;
74    }
75 
76    result[0] = new dfp(new String(buf, 0, sp));
77 
78    for (int i=0; i<buf.length; i++)
79    {
80      buf[i] = a.charAt(i);
81      if (buf[i] >= '0' && buf[i] <= '9' && i < sp)
82        buf[i] = '0';
83    }
84 
85    result[1] = new dfp(new String(buf));
86 
87    return result;
88  }
89 
90  /** Splits a dfp into 2 dfp's such that their sum is equal to the
91   *  input dfp */
92  protected static dfp[] split(dfp a)
93  {
94    dfp[] result;
95    dfp shift;
96    int ex;
97 
98    result = new dfp[2];
99 
100    ex = a.log10K();
101    shift = a.power10K(dfp.DIGITS/2-ex-1);
102    result[0] = a.multiply(shift).rint().divide(shift);
103    result[1] = a.subtract(result[0]);
104 
105    return result;
106  }
107 
108  /** Multiply two numbers that are split in to two pices that are
109   *  meant to be added together.  Use binomail multiplication so
110   *  ab = a0 b0 + a0 b1 + a1 b0 + a1 b1
111   *  Store the first term in result0, the rest in result1
112   */
113  protected static dfp[] splitMult(dfp[] a, dfp[] b)
114  {
115    dfp[] result = new dfp[2];
116 
117    result[1] = dfp.zero;
118    result[0] = a[0].multiply(b[0]);
119 
120    /* If result[0] is infinite or zero, don't compute result[1].  
121     * Attempting to do so may produce NaNs.
122     */
123 
124    if (result[0].classify() == dfp.INFINITE || result[0].equal(result[1]))
125      return result;
126 
127    result[1] = a[0].multiply(b[1]).add(a[1].multiply(b[0])).add(a[1].multiply(b[1]));
128 
129    return result;
130  }
131 
132  /** Divide two numbers that are split in to two pices that are
133   *  meant to be added together.  Inverse of split mult above:
134   *  
135   *  (a+b) / (c+d) = (a/c) + ( (bc-ad)/(c**2+cd) )
136   */
137  protected static dfp[] splitDiv(dfp[] a, dfp[] b)
138  {
139    dfp[] result;
140 
141    result = new dfp[2];
142  
143    result[0] = a[0].divide(b[0]);
144    result[1] = a[1].multiply(b[0]).subtract(a[0].multiply(b[1]));
145    result[1] = result[1].divide(b[0].multiply(b[0]).add(b[0].multiply(b[1])));
146   
147    return result;
148  }
149 
150  /** Raise a split base to the a power.  return a combined result */
151  protected static dfp splitPow(dfp[] base, int a)
152  {
153    int trial, prevtrial;
154    dfp[] result, r;
155    boolean invert = false;
156 
157    r = new dfp[2];
158 
159    result = new dfp[2];
160    result[0] = dfp.one;
161    result[1] = dfp.zero;
162 
163    if (a == 0)       /* Special case a = 0 */
164      return result[0].add(result[1]);
165 
166    if (a < 0)   /* If a is less than zero */
167    {
168      invert = true;
169      a = -a;
170    }
171 
172    /* Exponentiate by successive squaring */
173    do
174    {
175      r[0] = new dfp(base[0]);
176      r[1] = new dfp(base[1]);
177      trial = 1;
178      
179      while(true)
180      {
181        prevtrial = trial;
182        trial = trial * 2;
183        if (trial > a)
184          break;
185        r = splitMult(r, r);
186      }
187 
188      trial = prevtrial;
189 
190      a = a - trial;
191      result = splitMult(result, r);
192 
193    } while (a >= 1);
194 
195    result[0] = result[0].add(result[1]);
196 
197    if (invert)
198      result[0] = dfp.one.divide(result[0]);
199 
200    return result[0];
201  }
202 
203  /** Raises base to the power a by successive squaring */
204  public static dfp pow(dfp base, int a)
205  {
206    int trial, prevtrial;
207    dfp result, r, prevr;
208    boolean invert = false;
209 
210    result = dfp.one;
211 
212    if (a == 0)       /* Special case */
213      return result;
214 
215    if (a < 0)
216    {
217      invert = true;
218      a = -a;
219    }
220 
221    /* Exponentiate by successive squaring */
222    do
223    {
224      r = new dfp(base);
225      trial = 1;
226      
227      do
228      {
229        prevr = new dfp(r);
230        prevtrial = trial;
231        r = r.multiply(r);
232        trial = trial * 2;
233      } while (a>trial);
234 
235      r = prevr;
236      trial = prevtrial;
237 
238      a = a - trial;
239      result = result.multiply(r);
240 
241    } while (a >= 1);
242 
243    if (invert)
244      result = dfp.one.divide(result);
245 
246    return base.newInstance(result);
247  }
248 
249  /** Computes e to the given power.  a is broken into two parts, 
250   *  such that a = n+m  where n is an integer. 
251   *
252   *  We use pow() to compute e**n and a taylor series to compute
253   *  e**m.  We return (e**n)(e**m)
254   */
255  public static dfp exp(dfp a)
256  {
257    dfp inta, fraca, einta, efraca;
258    int ia;
259    dfp result;
260 
261    inta = a.rint();
262    fraca = a.subtract(inta);
263 
264    ia = inta.intValue();
265    if (ia > 2147483646)  // return +Infinity
266      return a.newInstance(dfp.create((byte)1, (byte) dfp.INFINITE));
267 
268    if (ia < -2147483646)  // return 0;
269      return a.newInstance(dfp.zero);
270 
271    einta = splitPow(E_SPLIT, ia);
272    efraca = expInternal(fraca);
273 
274    result = einta.multiply(efraca);
275    return a.newInstance(result);
276  }
277 
278  /** Computes e to the given power.  Where -1 < a < 1.  Use the
279   *  classic Taylor series.  1 + x**2/2! + x**3/3! + x**4/4!  ...
280   */
281  protected static dfp expInternal(dfp a)
282  {
283    int i;
284    dfp y, py, x, fact;
285 
286    y = dfp.one;
287    x = dfp.one;
288    fact = dfp.one;
289    py = new dfp(y);
290 
291    for (i=1; i<90; i++)
292    {
293      x = x.multiply(a);
294      fact = fact.multiply(i);
295      y = y.add(x.divide(fact));
296      if (y.equal(py))
297        break;
298      py = new dfp(y);
299    }
300 
301    return y;
302  }
303 
304  /** Returns the natural logarithm of a.  a is first split into three
305   *  parts such that  a = (10000^h)(2^j)k.  ln(a) is computed by
306   *  ln(a) = ln(5)*h + ln(2)*(h+j) + ln(k)
307   *  k is in the range 2/3 < k <4/3 and is passed on to a series 
308   *  expansion.
309   */
310  public static dfp ln(dfp a)
311  {
312    int lr;
313    dfp x;
314    int ix;
315    int p2 = 0;
316    dfp spx[], spy[], spz[];
317 
318    /* Check the arguments somewhat here */
319    if (a.equal(dfp.zero) || a.lessThan(dfp.zero) ||  // negative or zero
320       (a.equal(a) == false))                         // or NaN
321    {
322      dfp.setIEEEFlags(dfp.getIEEEFlags() | dfp.FLAG_INVALID);
323      return a.dotrap(dfp.FLAG_INVALID, "ln", a, dfp.create((byte)1, (byte) dfp.QNAN));
324    }
325 
326    if (a.classify() == dfp.INFINITE)
327    {
328      return a;
329    }
330 
331    spx = new dfp[2];
332    spy = new dfp[2];
333    spz = new dfp[2];
334    
335    x = new dfp(a);
336    lr = x.log10K();
337 
338    x = x.divide(pow(new dfp("10000"), lr));  /* This puts x in the range 0-10000 */
339    ix = x.floor().intValue();
340 
341    while (ix > 2)
342    {
343      ix >>= 1;     
344      p2++;
345    }
346 
347 
348    spx = split(x);
349    spy[0] = pow(dfp.two, p2);          // use spy[0] temporarily as a divisor
350    spx[0] = spx[0].divide(spy[0]);
351    spx[1] = spx[1].divide(spy[0]);
352 
353    spy[0] = new dfp("1.33333");    // Use spy[0] for comparison 
354    while (spx[0].add(spx[1]).greaterThan(spy[0]))
355    {
356      spx[0] = spx[0].divide(2);
357      spx[1] = spx[1].divide(2);
358      p2++;
359    }
360 
361    /** X is now in the range of 2/3 < x < 4/3 */
362 
363    spz = lnInternal(spx);
364 
365    spx[0] = new dfp(new StringBuffer().append(p2+4*lr).toString());
366    spx[1] = dfp.zero;
367    spy = splitMult(LN2_SPLIT, spx);
368 
369    spz[0] = spz[0].add(spy[0]);
370    spz[1] = spz[1].add(spy[1]);
371 
372    spx[0] = new dfp(new StringBuffer().append(4*lr).toString());
373    spx[1] = dfp.zero;
374    spy = splitMult(LN5_SPLIT, spx);
375 
376    spz[0] = spz[0].add(spy[0]);
377    spz[1] = spz[1].add(spy[1]);
378 
379    return a.newInstance(spz[0].add(spz[1]));
380  }
381 
382  /** Computes the natural log of a number between 0 and 2 */
383  /*
384   *  Much better ln(x) algorithm....
385   *
386   *  Let f(x) = ln(x),
387   *
388   *  We know that f'(x) = 1/x, thus from Taylor's theorum we have: 
389   *
390   *           -----          n+1         n
391   *  f(x) =   \           (-1)    (x - 1)
392   *           /          ----------------    for 1 <= n <= infinity
393   *           -----             n
394   *
395   *  or
396   *                       2        3       4
397   *                   (x-1)   (x-1)    (x-1)
398   *  ln(x) =  (x-1) - ----- + ------ - ------ + ...
399   *                     2       3        4
400   *
401   *  alternatively,
402   *
403   *                  2    3   4
404   *                 x    x   x
405   *  ln(x+1) =  x - -  + - - - + ...
406   *                 2    3   4
407   *
408   *  This series can be used to compute ln(x), but it converges too slowly.
409   *
410   *  If we substitute -x for x above, we get
411   *
412   *                   2    3    4
413   *                  x    x    x
414   *  ln(1-x) =  -x - -  - -  - - + ...
415   *                  2    3    4
416   *
417   *  Note that all terms are now negative.  Because the even powered ones 
418   *  absorbed the sign.  Now, subtract the series above from the previous
419   *  one to get ln(x+1) - ln(1-x).  Note the even terms cancel out leaving 
420   *  only the odd ones
421   *
422   *                             3     5      7
423   *                           2x    2x     2x
424   *  ln(x+1) - ln(x-1) = 2x + --- + --- + ---- + ...
425   *                            3     5      7
426   *
427   *  By the property of logarithms that ln(a) - ln(b) = ln (a/b) we have:
428   *
429   *                                3        5        7
430   *      x+1           /          x        x        x          \
431   *  ln ----- =   2 *  |  x  +   ----  +  ----  +  ---- + ...  |
432   *      x-1           \          3        5        7          /
433   *
434   *  But now we want to find ln(a), so we need to find the value of x 
435   *  such that a = (x+1)/(x-1).   This is easily solved to find that
436   *  x = (a-1)/(a+1).
437   */
438  protected static dfp[] lnInternal(dfp a[])
439  {
440    dfp x, y, py, num, t;
441    int den;
442 
443    den = 1;
444 
445    /* Now we want to compute x = (a-1)/(a+1) but this is prone to 
446     * loss of precision.  So instead, compute x = (a/4 - 1/4) / (a/4 + 1/4)
447     */
448    t = a[0].divide(4).add(a[1].divide(4));
449    x = t.add(new dfp("-0.25")).divide(t.add(new dfp("0.25")));
450 
451    y = new dfp(x);
452    num = new dfp(x);
453    py = new dfp(y);
454    for (int i=0; i<10000; i++)
455    {
456      num = num.multiply(x);
457      num = num.multiply(x);
458      den = den + 2;
459      t = num.divide(den);
460      y = y.add(t);
461      if (y.equal(py))
462        break;
463      py = new dfp(y);
464    }
465 
466    y = y.multiply(dfp.two);
467 
468    return split(y);
469  }
470 
471  /** Computes x to the y power.<p>
472   *
473   *  Uses the following method:<p>
474   * 
475   *  <ol>
476   *  <li> Set u = rint(y), v = y-u 
477   *  <li> Compute a = v * ln(x)
478   *  <li> Compute b = rint( a/ln(2) )
479   *  <li> Compute c = a - b*ln(2)
480   *  <li> x<sup>y</sup> = x<sup>u</sup>  *   2<sup>b</sup> * e<sup>c</sup>
481   *  </ol>
482   *  if |y| > 1e8, then we compute by exp(y*ln(x))   <p>
483   *
484   *  <b>Special Cases</b><p>
485   *  <ul>
486   *  <li>  if y is 0.0 or -0.0 then result is 1.0
487   *  <li>  if y is 1.0 then result is x
488   *  <li>  if y is NaN then result is NaN
489   *  <li>  if x is NaN and y is not zero then result is NaN
490   *  <li>  if |x| > 1.0 and y is +Infinity then result is +Infinity
491   *  <li>  if |x| < 1.0 and y is -Infinity then result is +Infinity
492   *  <li>  if |x| > 1.0 and y is -Infinity then result is +0
493   *  <li>  if |x| < 1.0 and y is +Infinity then result is +0
494   *  <li>  if |x| = 1.0 and y is +/-Infinity then result is NaN
495   *  <li>  if x = +0 and y > 0 then result is +0
496   *  <li>  if x = +Inf and y < 0 then result is +0
497   *  <li>  if x = +0 and y < 0 then result is +Inf
498   *  <li>  if x = +Inf and y > 0 then result is +Inf
499   *  <li>  if x = -0 and y > 0, finite, not odd integer then result is +0
500   *  <li>  if x = -0 and y < 0, finite, and odd integer then result is -Inf
501   *  <li>  if x = -Inf and y > 0, finite, and odd integer then result is -Inf
502   *  <li>  if x = -0 and y < 0, not finite odd integer then result is +Inf
503   *  <li>  if x = -Inf and y > 0, not finite odd integer then result is +Inf
504   *  <li>  if x < 0 and y > 0, finite, and odd integer then result is -(|x|<sup>y</sup>)
505   *  <li>  if x < 0 and y > 0, finite, and not integer then result is NaN
506   *  </ul>
507   */
508 
509  public static dfp pow(dfp x, dfp y)
510  {
511    dfp a, b, c, u, v, r;
512    boolean invert = false;
513    int ui, bi;
514 
515    /* Check for special cases */
516    if (y.equal(dfp.zero))
517      return x.newInstance(dfp.one);
518 
519    if (y.equal(dfp.one))
520    {
521      if (!x.equal(x))  // Test for NaNs
522      {
523        dfp.setIEEEFlags(dfp.getIEEEFlags() | dfp.FLAG_INVALID);
524        return x.dotrap(dfp.FLAG_INVALID, "pow", x, x);
525      }
526      return x;
527    }
528 
529    if (!x.equal(x) || !y.equal(y)) // Test for NaNs
530    {
531      dfp.setIEEEFlags(dfp.getIEEEFlags() | dfp.FLAG_INVALID);
532      return x.dotrap(dfp.FLAG_INVALID, "pow", x, dfp.create((byte)1, (byte) dfp.QNAN));
533    }
534 
535    // X == 0
536    if (x.equal(dfp.zero))
537    {
538      if (dfp.copysign(dfp.one, x).greaterThan(dfp.zero))  // X == +0
539      {
540        if (y.greaterThan(dfp.zero))
541          return x.newInstance(dfp.zero);
542        else
543          return x.newInstance(dfp.create((byte)1, (byte)dfp.INFINITE));
544      }
545      else  // X == -0
546      {
547        /* If y is odd integer */
548        if (y.classify() == dfp.FINITE && y.rint().equal(y) && !y.remainder(dfp.two).equal(dfp.zero))
549        {
550          if (y.greaterThan(dfp.zero))
551            return x.newInstance(dfp.zero.negate());
552          else
553            return x.newInstance(dfp.create((byte)-1, (byte)dfp.INFINITE));
554        }
555        else  // Y is not odd integer
556        {
557          if (y.greaterThan(dfp.zero))
558            return x.newInstance(dfp.zero);
559          else
560            return x.newInstance(dfp.create((byte)1, (byte)dfp.INFINITE));
561        }
562      }
563    }
564 
565    if (x.lessThan(dfp.zero))  /* Make x positive, but keep track of it */
566    {
567      x = x.negate();
568      invert = true;
569    }
570 
571    if (x.greaterThan(dfp.one) && y.classify() == dfp.INFINITE)
572    {
573      if (y.greaterThan(dfp.zero))
574        return y;
575      else
576        return x.newInstance(dfp.zero);
577    }
578 
579    if (x.lessThan(dfp.one) && y.classify() == dfp.INFINITE)
580    {
581      if (y.greaterThan(dfp.zero))
582        return x.newInstance(dfp.zero);
583      else
584        return x.newInstance(dfp.copysign(y, dfp.one));
585    }
586 
587    if (x.equal(dfp.one) && y.classify() == dfp.INFINITE)
588    {
589      dfp.setIEEEFlags(dfp.getIEEEFlags() | dfp.FLAG_INVALID);
590      return x.dotrap(dfp.FLAG_INVALID, "pow", x, dfp.create((byte)1, (byte) dfp.QNAN));
591    }
592 
593    if (x.classify() == dfp.INFINITE)  // x = +/- inf
594    {
595      if (invert)  // negative infinity
596      {
597        /* If y is odd integer */
598        if (y.classify() == dfp.FINITE && y.rint().equal(y) && !y.remainder(dfp.two).equal(dfp.zero))
599        {
600          if (y.greaterThan(dfp.zero))
601            return x.newInstance(dfp.create((byte)-1, (byte)dfp.INFINITE));
602          else
603            return x.newInstance(dfp.zero.negate());
604        }
605        else  // Y is not odd integer
606        {
607          if (y.greaterThan(dfp.zero))
608            return x.newInstance(dfp.create((byte)1, (byte)dfp.INFINITE));
609          else
610            return x.newInstance(dfp.zero);
611        }
612      }
613      else         // positive infinity
614      {
615        if (y.greaterThan(dfp.zero))
616          return x;
617        else
618          return x.newInstance(dfp.zero);
619      }
620    }
621 
622    if (invert && !y.rint().equal(y))
623    {
624      dfp.setIEEEFlags(dfp.getIEEEFlags() | dfp.FLAG_INVALID);
625      return x.dotrap(dfp.FLAG_INVALID, "pow", x, dfp.create((byte)1, (byte) dfp.QNAN));
626    }
627 
628    /* End special cases */
629 
630    if (y.lessThan(new dfp("1e8")) && y.greaterThan(new dfp("-1e8")))
631    {
632      u = y.rint();
633      ui = u.intValue();
634 
635      v = y.subtract(u);
636 
637      if (v.unequal(dfp.zero))
638      {
639        a = v.multiply(ln(x));
640        b = a.divide(LN2).rint();
641        bi = b.intValue();
642 
643        c = a.subtract(b.multiply(LN2));
644        r = splitPow(split(x), ui);
645        r = r.multiply(pow(dfp.two, b.intValue()));
646        r = r.multiply(exp(c));
647      }
648      else   
649      {
650        r = splitPow(split(x), ui);
651      }
652    }
653    else   // very large exponent.  |y| > 1e8
654    {
655      r = exp(ln(x).multiply(y));
656    }
657 
658    if (invert)
659    {
660      // if y is odd integer
661      if (y.rint().equal(y) && !y.remainder(dfp.two).equal(dfp.zero))
662        r = r.negate();
663    }
664 
665    return x.newInstance(r);
666  }
667 
668  /** Computes sin(a)  Used when 0 < a < pi/4.  Uses the
669   *  classic Taylor series.  x - x**3/3! + x**5/5!  ...
670   */
671  protected static dfp sinInternal(dfp a[])
672  {
673    int i;
674    dfp c, y, py, x, fact;
675 
676    c = a[0].add(a[1]);
677    y = c;
678    c = c.multiply(c);
679    x = y;
680    fact = dfp.one;
681    py = new dfp(y);
682 
683    for (i=3; i<90; i+=2)
684    {
685      x = x.multiply(c);
686      x = x.negate();
687 
688      fact = fact.divide((i-1)*i);  // 1 over fact
689      y = y.add(x.multiply(fact));
690      if (y.equal(py))
691        break;
692      py = new dfp(y);
693    }
694 
695    return y;
696  }
697 
698  /** Computes cos(a)  Used when 0 < a < pi/4.  Uses the
699   *  classic Taylor series for cosine.  1 - x**2/2! + x**4/4!  ...
700   */
701  protected static dfp cosInternal(dfp a[])
702  {
703    int i;
704    dfp y, py, x, c, fact;
705 
706 
707    x = dfp.one;
708    y = dfp.one;
709    c = a[0].add(a[1]);
710    c = c.multiply(c);
711 
712    fact = dfp.one;
713    py = new dfp(y);
714 
715    for (i=2; i<90; i+=2)
716    {
717      x = x.multiply(c);
718      x = x.negate();
719 
720      fact = fact.divide((i-1)*i);  // 1 over fact
721 
722      y = y.add(x.multiply(fact));
723      if (y.equal(py))
724        break;
725      py = new dfp(y);
726    }
727 
728    return y;
729  }
730 
731  /** computes the sine of the argument */
732  public static dfp sin(dfp a)
733  {
734    dfp x, y;
735    boolean neg = false;
736 
737    /* First reduce the argument to the range of +/- PI */
738    x = a.remainder(PI.multiply(2));
739 
740    /* if x < 0 then apply identity sin(-x) = -sin(x) */
741    /* This puts x in the range 0 < x < PI            */
742    if (x.lessThan(dfp.zero))
743    {
744      x = x.negate();
745      neg = true;
746    }
747 
748    /* Since sine(x) = sine(pi - x) we can reduce the range to
749     * 0 < x < pi/2
750     */
751 
752    if (x.greaterThan(PI.divide(2)))
753      x = PI.subtract(x);
754 
755    if (x.lessThan(PI.divide(4)))
756    {
757      dfp c[] = new dfp[2];
758      c[0] = x;
759      c[1] = dfp.zero;
760 
761      //y = sinInternal(c);
762      y = sinInternal(split(x));
763    }
764    else
765    {
766      dfp c[] = new dfp[2];
767 
768      c[0] = PI_SPLIT[0].divide(2).subtract(x);
769      c[1] = PI_SPLIT[1].divide(2);
770      y = cosInternal(c);
771    }
772 
773    if (neg)
774      y = y.negate();
775 
776    return a.newInstance(y);
777  }
778 
779  /** computes the cosine of the argument */
780  public static dfp cos(dfp a)
781  {
782    dfp x, y;
783    boolean neg = false;
784 
785    /* First reduce the argument to the range of +/- PI */
786    x = a.remainder(PI.multiply(2));
787 
788    /* if x < 0 then apply identity cos(-x) = cos(x) */
789    /* This puts x in the range 0 < x < PI           */
790    if (x.lessThan(dfp.zero))
791      x = x.negate();
792 
793    /* Since cos(x) = -cos(pi - x) we can reduce the range to
794     * 0 < x < pi/2
795     */
796 
797    if (x.greaterThan(PI.divide(2)))
798    {
799      x = PI.subtract(x);
800      neg = true;
801    }
802 
803    if (x.lessThan(PI.divide(4)))
804    {
805      dfp c[] = new dfp[2];
806      c[0] = x;
807      c[1] = dfp.zero;
808 
809      y = cosInternal(c);
810    }
811    else
812    {
813      dfp c[] = new dfp[2];
814 
815      c[0] = PI_SPLIT[0].divide(2).subtract(x);
816      c[1] = PI_SPLIT[1].divide(2);
817      y = sinInternal(c);
818    }
819 
820    if (neg)
821      y = y.negate();
822 
823    return a.newInstance(y);
824  }
825 
826  /** computes the tangent of the argument */
827  public static dfp tan(dfp a)
828  {
829    return sin(a).divide(cos(a));
830  }
831 
832  protected static dfp atanInternal(dfp a)
833  {
834    int i;
835    dfp y, py, x;
836 
837    y = new dfp(a);
838    x = new dfp(y);
839    py = new dfp(y);
840 
841    for (i=3; i<90; i+=2)
842    {
843      x = x.multiply(a);
844      x = x.multiply(a);
845      x = x.negate();
846      y = y.add(x.divide(i));
847      if (y.equal(py))
848        break;
849      py = new dfp(y);
850    }
851 
852    return y;
853  }
854 
855  /** computes the arc tangent of the argument 
856   *  
857   *  Uses the typical taylor series
858   *
859   *  but may reduce arguments using the following identity
860   * tan(x+y) = (tan(x) + tan(y)) / (1 - tan(x)*tan(y))
861   *
862   * since tan(PI/8) = sqrt(2)-1,
863   *
864   * atan(x) = atan( (x - sqrt(2) + 1) / (1+x*sqrt(2) - x) + PI/8.0
865   */
866  public static dfp atan(dfp a)
867  {
868    dfp x, y, ty;
869    boolean recp = false;
870    boolean neg = false;
871    boolean sub = false;
872 
873    ty = SQR2_SPLIT[0].subtract(dfp.one).add(SQR2_SPLIT[1]);
874 
875    x = new dfp(a);
876    if (x.lessThan(dfp.zero))
877    {
878      neg = true;
879      x = x.negate();
880    }
881 
882    if (x.greaterThan(dfp.one))
883    {
884      recp = true; 
885      x = dfp.one.divide(a);
886    }
887 
888    if (x.greaterThan(ty))
889    {
890      dfp sty[] = new dfp[2];
891      dfp xs[] = new dfp[2];
892      dfp ds[] = new dfp[2];
893      sub = true;
894 
895      sty[0] = SQR2_SPLIT[0].subtract(dfp.one);
896      sty[1] = SQR2_SPLIT[1];
897 
898      xs = split(x);
899 
900      ds = splitMult(xs, sty);
901      ds[0] = ds[0].add(dfp.one);
902 
903      xs[0] = xs[0].subtract(sty[0]);
904      xs[1] = xs[1].subtract(sty[1]);
905 
906      xs = splitDiv(xs, ds);
907      x = xs[0].add(xs[1]);
908 
909      //x = x.subtract(ty).divide(dfp.one.add(x.multiply(ty)));
910    }
911 
912    y = atanInternal(x);
913 
914    if (sub)
915      y = y.add(PI_SPLIT[0].divide(8)).add(PI_SPLIT[1].divide(8));
916 
917    if (recp)
918      y = PI_SPLIT[0].divide(2).subtract(y).add(PI_SPLIT[1].divide(2));
919 
920    if (neg)
921      y = y.negate(); 
922 
923    return a.newInstance(y);
924  }
925 
926  public static dfp asin(dfp a)
927  {
928    return atan(a.divide(dfp.one.subtract(a.multiply(a)).sqrt()));
929  }
930 
931  public static dfp acos(dfp a)
932  {
933    dfp result;
934    boolean negative = false;
935  
936    if (a.lessThan(dfp.zero))
937      negative = true;
938 
939    a = dfp.copysign(a, dfp.one);  // absolute value
940 
941    result = atan(dfp.one.subtract(a.multiply(a)).sqrt().divide(a));
942 
943    if (negative)
944      result = PI.subtract(result);
945 
946    return a.newInstance(result);
947  }
948}

[all classes][rossi.dfp]
EMMA 2.0.5312 (C) Vladimir Roubtsov