View Javadoc
1   package org.djutils.float128;
2   
3   /**
4    * PerformanceTests.java. <br>
5    * <br>
6    * Copyright (c) 2020-2020 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
7    * for project information <a href="https://djutils.org" target="_blank"> https://djutils.org</a>. The DJUTILS project is
8    * distributed under a three-clause BSD-style license, which can be found at
9    * <a href="https://djutils.org/docs/license.html" target="_blank"> https://djutils.org/docs/license.html</a>. <br>
10   * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
11   * @author <a href="https://www.tudelft.nl/pknoppers">Peter Knoppers</a>
12   */
13  public final class TestHypotAtan
14  {
15      /**
16       * Do not instantiate.
17       */
18      private TestHypotAtan()
19      {
20          // Do not instantiate
21      }
22  
23      /**
24       * Measure performance of atan2, hypot, sine and cosine.
25       * @param args String[]; the command line arguments (not used)
26       */
27      public static void main(final String[] args)
28      {
29          // Ensure that all classes are loaded before measuring things
30          Math.atan2(0.5, 1.5);
31          Math.hypot(1.2, 3.4);
32          Math.sin(0.8);
33          Math.cos(0.6);
34          Math.sqrt(2.3);
35  
36          int iterations = 100000000;
37  
38          long startNanos = System.nanoTime();
39          for (int i = 0; i < iterations; i++)
40          {
41              @SuppressWarnings("unused")
42              double x = 0.1 + i / 1000.0;
43              @SuppressWarnings("unused")
44              double y = -0.5 + i / 2000.0;
45          }
46          long nowNanos = System.nanoTime();
47          long baseNanos = nowNanos - startNanos;
48          System.out.println(String.format("base loop: %d invocations in %.6f s (%.1f ns/invocation)", iterations,
49                  baseNanos / 1000000000.0, 1.0 * baseNanos / iterations));
50  
51          startNanos = System.nanoTime();
52          for (int i = 0; i < iterations; i++)
53          {
54              double x = 0.1 + i / 1000.0;
55              double y = -0.5 + i / 2000.0;
56              Math.atan2(y, x);
57          }
58          nowNanos = System.nanoTime();
59          long durationNanos = nowNanos - startNanos - baseNanos;
60          System.out.println(String.format("atan2: %d invocations in %.6f s (%.1f ns/invocation)", iterations,
61                  durationNanos / 1000000000.0, 1.0 * durationNanos / iterations));
62  
63          startNanos = System.nanoTime();
64          for (int i = 0; i < iterations; i++)
65          {
66              double x = 0.1 + i / 1000.0;
67              double y = -0.5 + i / 2000.0;
68              TestHypotAtan.atan2(y, x);
69          }
70          nowNanos = System.nanoTime();
71          durationNanos = nowNanos - startNanos - baseNanos;
72          System.out.println(String.format("PerformanceTests.atan2: %d invocations in %.6f s (%.1f ns/invocation)", iterations,
73                  durationNanos / 1000000000.0, 1.0 * durationNanos / iterations));
74  
75          startNanos = System.nanoTime();
76          for (int i = 0; i < iterations; i++)
77          {
78              double x = 0.1 + i / 1000.0;
79              TestHypotAtan.fastAtan(x);
80          }
81          nowNanos = System.nanoTime();
82          durationNanos = nowNanos - startNanos - baseNanos;
83          System.out.println(String.format("PerformanceTests.fastAtan: %d invocations in %.6f s (%.1f ns/invocation)", iterations,
84                  durationNanos / 1000000000.0, 1.0 * durationNanos / iterations));
85  
86          startNanos = System.nanoTime();
87          for (int i = 0; i < iterations; i++)
88          {
89              double x = 0.1 + i / 1000.0;
90              double y = -0.5 + i / 2000.0;
91              Math.hypot(y, x);
92          }
93          nowNanos = System.nanoTime();
94          durationNanos = nowNanos - startNanos - baseNanos;
95          System.out.println(String.format("hypot: %d invocations in %.6f s (%.1f ns/invocation)", iterations,
96                  durationNanos / 1000000000.0, 1.0 * durationNanos / iterations));
97  
98          startNanos = System.nanoTime();
99          for (int i = 0; i < iterations; i++)
100         {
101             double x = 0.1 + i / 1000.0;
102             double y = -0.5 + i / 2000.0;
103             TestHypotAtan.hypotA(y, x);
104         }
105         nowNanos = System.nanoTime();
106         durationNanos = nowNanos - startNanos - baseNanos;
107         System.out.println(String.format("PerformanceTests.hypotA: %d invocations in %.6f s (%.1f ns/invocation)", iterations,
108                 durationNanos / 1000000000.0, 1.0 * durationNanos / iterations));
109 
110         startNanos = System.nanoTime();
111         for (int i = 0; i < iterations; i++)
112         {
113             double x = 0.1 + i / 1000.0;
114             double y = -0.5 + i / 2000.0;
115             TestHypotAtan.hypotB(y, x);
116         }
117         nowNanos = System.nanoTime();
118         durationNanos = nowNanos - startNanos - baseNanos;
119         System.out.println(String.format("PerformanceTests.hypotB: %d invocations in %.6f s (%.1f ns/invocation)", iterations,
120                 durationNanos / 1000000000.0, 1.0 * durationNanos / iterations));
121 
122         startNanos = System.nanoTime();
123         for (int i = 0; i < iterations; i++)
124         {
125             double x = 0.1 + i / 1000.0;
126             double y = -0.5 + i / 2000.0;
127             TestHypotAtan.hypotC(y, x);
128         }
129         nowNanos = System.nanoTime();
130         durationNanos = nowNanos - startNanos - baseNanos;
131         System.out.println(String.format("PerformanceTests.hypotC: %d invocations in %.6f s (%.1f ns/invocation)", iterations,
132                 durationNanos / 1000000000.0, 1.0 * durationNanos / iterations));
133 
134         startNanos = System.nanoTime();
135         for (int i = 0; i < iterations; i++)
136         {
137             double x = 0.1 + i / 1000000.0;
138             Math.sin(x);
139         }
140         nowNanos = System.nanoTime();
141         durationNanos = nowNanos - startNanos - baseNanos;
142         System.out.println(String.format("  sin: %d invocations in %.6f s (%.1f ns/invocation)", iterations,
143                 durationNanos / 1000000000.0, 1.0 * durationNanos / iterations));
144 
145         startNanos = System.nanoTime();
146         for (int i = 0; i < iterations; i++)
147         {
148             double x = 0.1 + i / 1000000.0;
149             Math.cos(x);
150         }
151         nowNanos = System.nanoTime();
152         durationNanos = nowNanos - startNanos - baseNanos;
153         System.out.println(String.format("  cos: %d invocations in %.6f s (%.1f ns/invocation)", iterations,
154                 durationNanos / 1000000000.0, 1.0 * durationNanos / iterations));
155 
156         startNanos = System.nanoTime();
157         for (int i = 0; i < iterations; i++)
158         {
159             double x = 0.1 + i / 1000.0;
160             double y = -0.5 + i / 2000.0;
161             Math.atan2(y, x);
162         }
163         nowNanos = System.nanoTime();
164         durationNanos = nowNanos - startNanos - baseNanos;
165         System.out.println(String.format("atan2: %d invocations in %.6f s (%.1f ns/invocation)", iterations,
166                 durationNanos / 1000000000.0, 1.0 * durationNanos / iterations));
167 
168         startNanos = System.nanoTime();
169         for (int i = 0; i < iterations; i++)
170         {
171             double x = 0.1 + i / 1000.0;
172             double y = -0.5 + i / 2000.0;
173             Math.sqrt(x * x + y * y);
174         }
175         nowNanos = System.nanoTime();
176         durationNanos = nowNanos - startNanos - baseNanos;
177         System.out.println(String.format("sqrt(x*x+y*y): %d invocations in %.6f s (%.1f ns/invocation)", iterations,
178                 durationNanos / 1000000000.0, 1.0 * durationNanos / iterations));
179     }
180 
181     /** 2^450. */
182     private static final double TWO_POW_450 = Double.longBitsToDouble(0x5C10000000000000L);
183 
184     /** 2^-450. */
185     private static final double TWO_POW_N450 = Double.longBitsToDouble(0x23D0000000000000L);
186 
187     /** 2^750? */
188     private static final double TWO_POW_750 = Double.longBitsToDouble(0x6ED0000000000000L);
189 
190     /** 2^-750? */
191     private static final double TWO_POW_N750 = Double.longBitsToDouble(0x1110000000000000L);
192 
193     /**
194      * Implementation of hypot taken from https://stackoverflow.com/questions/3764978/why-hypot-function-is-so-slow.
195      * @param x double; x
196      * @param y double; y
197      * @return double; the hypot of x, and y
198      */
199     public static double hypotA(double x, double y)
200     {
201         x = Math.abs(x);
202         y = Math.abs(y);
203         if (y < x)
204         {
205             double a = x;
206             x = y;
207             y = a;
208         }
209         else if (!(y >= x))
210         { // Testing if we have some NaN.
211             if ((x == Double.POSITIVE_INFINITY) || (y == Double.POSITIVE_INFINITY))
212             {
213                 return Double.POSITIVE_INFINITY;
214             }
215             else
216             {
217                 return Double.NaN;
218             }
219         }
220         if (y - x == y)
221         { // x too small to substract from y
222             return y;
223         }
224         else
225         {
226             double factor;
227             if (x > TWO_POW_450)
228             { // 2^450 < x < y
229                 x *= TWO_POW_N750;
230                 y *= TWO_POW_N750;
231                 factor = TWO_POW_750;
232             }
233             else if (y < TWO_POW_N450)
234             { // x < y < 2^-450
235                 x *= TWO_POW_750;
236                 y *= TWO_POW_750;
237                 factor = TWO_POW_N750;
238             }
239             else
240             {
241                 factor = 1.0;
242             }
243             return factor * Math.sqrt(x * x + y * y);
244         }
245     }
246 
247     /**
248      * <b>hypot</b>.
249      * @param x double; x
250      * @param y double; y
251      * @return sqrt(x*x +y*y) without intermediate overflow or underflow.
252      * Note {@link Math#hypot} is unnecessarily slow. This returns the identical result to Math.hypot with reasonable run times
253      *       (~40 nsec vs. 800 nsec).
254      *       The logic for computing z is copied from "Freely Distributable Math Library" fdlibm's e_hypot.c. This minimizes
255      *       rounding error to provide 1 ulb accuracy.
256      */
257     public static double hypotB(double x, double y)
258     {
259         if (Double.isInfinite(x) || Double.isInfinite(y))
260         {
261             return Double.POSITIVE_INFINITY;
262         }
263         if (Double.isNaN(x) || Double.isNaN(y))
264         {
265             return Double.NaN;
266         }
267 
268         x = Math.abs(x);
269         y = Math.abs(y);
270 
271         if (x < y)
272         {
273             double d = x;
274             x = y;
275             y = d;
276         }
277 
278         int xi = Math.getExponent(x);
279         int yi = Math.getExponent(y);
280 
281         if (xi > yi + 27)
282         {
283             return x;
284         }
285 
286         int bias = 0;
287         if (xi > 510 || xi < -511)
288         {
289             bias = xi;
290             x = Math.scalb(x, -bias);
291             y = Math.scalb(y, -bias);
292         }
293 
294         // translated from "Freely Distributable Math Library" e_hypot.c to minimize rounding errors
295         double z = 0;
296         if (x > 2 * y)
297         {
298             double x1 = Double.longBitsToDouble(Double.doubleToLongBits(x) & 0xffffffff00000000L);
299             double x2 = x - x1;
300             z = Math.sqrt(x1 * x1 + (y * y + x2 * (x + x1)));
301         }
302         else
303         {
304             double t = 2 * x;
305             double t1 = Double.longBitsToDouble(Double.doubleToLongBits(t) & 0xffffffff00000000L);
306             double t2 = t - t1;
307             double y1 = Double.longBitsToDouble(Double.doubleToLongBits(y) & 0xffffffff00000000L);
308             double y2 = y - y1;
309             double xMinusY = x - y;
310             z = Math.sqrt(t1 * y1 + (xMinusY * xMinusY + (t1 * y2 + t2 * y))); // Note: 2*x*y <= x*x + y*y
311         }
312 
313         if (bias == 0)
314         {
315             return z;
316         }
317         else
318         {
319             return Math.scalb(z, bias);
320         }
321     }
322 
323     /**
324      * <b>hypot</b>. C.F. Borges, An Improved Algorithm for hypot(a, b). arXiv:1904.09481v6 [math.NA] 14 Jun 2019.
325      * @param x double; x
326      * @param y double; y
327      * @return sqrt(x*x +y*y) without intermediate overflow or underflow.
328      */
329     public static double hypotC(final double x, final double y)
330     {
331         if (Double.isInfinite(x) || Double.isInfinite(y))
332         {
333             return Double.POSITIVE_INFINITY;
334         }
335         if (Double.isNaN(x) || Double.isNaN(y))
336         {
337             return Double.NaN;
338         }
339 
340         // scaling if necessary to avoid overflow of x*x or y*y
341 
342         double h = Math.sqrt(Math.fma(x, x, y * y));
343         double hsq = h * h;
344         double xsq = x * x;
345         double a = Math.fma(-y, y, hsq - xsq) + Math.fma(h, h, -hsq) - Math.fma(x, x, -xsq);
346         return h - a / (2.0 * h);
347     }
348 
349     /* @(#)e_atan2.c 1.3 95/01/18 */
350     /*-
351      * ====================================================
352      * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
353      *
354      * Developed at SunSoft, a Sun Microsystems, Inc. business.
355      * Permission to use, copy, modify, and distribute this
356      * software is freely granted, provided that this notice 
357      * is preserved.
358      * ====================================================
359      *
360      */
361 
362     /*- __ieee754_atan2(y,x)
363      * Method :
364      *  1. Reduce y to positive by atan2(y,x)=-atan2(-y,x).
365      *  2. Reduce x to positive by (if x and y are unexceptional): 
366      *      ARG (x+iy) = arctan(y/x)       ... if x > 0,
367      *      ARG (x+iy) = pi - arctan[y/(-x)]   ... if x < 0,
368      *
369      * Special cases:
370      *
371      *  ATAN2((anything), NaN ) is NaN;
372      *  ATAN2(NAN , (anything) ) is NaN;
373      *  ATAN2(+-0, +(anything but NaN)) is +-0  ;
374      *  ATAN2(+-0, -(anything but NaN)) is +-pi ;
375      *  ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2;
376      *  ATAN2(+-(anything but INF and NaN), +INF) is +-0 ;
377      *  ATAN2(+-(anything but INF and NaN), -INF) is +-pi;
378      *  ATAN2(+-INF,+INF ) is +-pi/4 ;
379      *  ATAN2(+-INF,-INF ) is +-3pi/4;
380      *  ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2;
381      *
382      * Constants:
383      * The hexadecimal values are the intended ones for the following 
384      * constants. The decimal values may be used, provided that the 
385      * compiler will convert from decimal to binary accurately enough 
386      * to produce the hexadecimal values shown.
387      */
388 
389     /** */
390     private static double tiny = 1.0e-300;
391 
392     /** */
393     private static double zero = 0.0;
394 
395     /** */
396     private static double pi_o_4 = 7.8539816339744827900E-01; /* 0x3FE921FB, 0x54442D18 */
397 
398     /** */
399     private static double pi_o_2 = 1.5707963267948965580E+00; /* 0x3FF921FB, 0x54442D18 */
400 
401     /** */
402     private static double pi = 3.1415926535897931160E+00; /* 0x400921FB, 0x54442D18 */
403 
404     /** */
405     private static double pi_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */
406 
407     /**
408      * atan.c implementation of Sun in fdlibm: http://www.netlib.org/fdlibm/.
409      * @param y double
410      * @param x double
411      * @return atan2(y, x)
412      */
413     @SuppressWarnings("checkstyle:needbraces")
414     private static double atan2(double y, double x)
415     {
416         double z;
417         int k, m, hx, hy, ix, iy;
418         long lx, ly;
419 
420         hx = __HI(x);
421         ix = hx & 0x7fffffff;
422         lx = __LO(x);
423         hy = __HI(y);
424         iy = hy & 0x7fffffff;
425         ly = __LO(y);
426         if (((ix | ((lx | -lx) >> 31)) > 0x7ff00000) || ((iy | ((ly | -ly) >> 31)) > 0x7ff00000)) /* x or y is NaN */
427             return x + y;
428         if ((hx - 0x3ff00000 | lx) == 0)
429             return atan(y); /* x=1.0 */
430         m = ((hy >> 31) & 1) | ((hx >> 30) & 2); /* 2*sign(x)+sign(y) */
431 
432         /* when y = 0 */
433         if ((iy | ly) == 0)
434         {
435             switch (m)
436             {
437                 case 0:
438                 case 1:
439                     return y; /* atan(+-0,+anything)=+-0 */
440                 case 2:
441                     return pi + tiny; /* atan(+0,-anything) = pi */
442                 case 3:
443                     return -pi - tiny; /* atan(-0,-anything) =-pi */
444             }
445         }
446         /* when x = 0 */
447         if ((ix | lx) == 0)
448             return (hy < 0) ? -pi_o_2 - tiny : pi_o_2 + tiny;
449 
450         /* when x is INF */
451         if (ix == 0x7ff00000)
452         {
453             if (iy == 0x7ff00000)
454             {
455                 switch (m)
456                 {
457                     case 0:
458                         return pi_o_4 + tiny; /* atan(+INF,+INF) */
459                     case 1:
460                         return -pi_o_4 - tiny; /* atan(-INF,+INF) */
461                     case 2:
462                         return 3.0 * pi_o_4 + tiny; /* atan(+INF,-INF) */
463                     case 3:
464                         return -3.0 * pi_o_4 - tiny; /* atan(-INF,-INF) */
465                 }
466             }
467             else
468             {
469                 switch (m)
470                 {
471                     case 0:
472                         return zero; /* atan(+...,+INF) */
473                     case 1:
474                         return -zero; /* atan(-...,+INF) */
475                     case 2:
476                         return pi + tiny; /* atan(+...,-INF) */
477                     case 3:
478                         return -pi - tiny; /* atan(-...,-INF) */
479                 }
480             }
481         }
482         /* when y is INF */
483         if (iy == 0x7ff00000)
484             return (hy < 0) ? -pi_o_2 - tiny : pi_o_2 + tiny;
485 
486         /* compute y/x */
487         k = (iy - ix) >> 20;
488         if (k > 60)
489             z = pi_o_2 + 0.5 * pi_lo; /* |y/x| > 2**60 */
490         else if (hx < 0 && k < -60)
491             z = 0.0; /* |y|/x < -2**60 */
492         else
493             z = atan(Math.abs(y / x)); /* safe to do y/x */
494         switch (m)
495         {
496             case 0:
497                 return z; /* atan(+,+) */
498             case 1:
499                 // __HI(z) ^= 0x80000000;
500                 z = __HI(z, __HI(z) ^ 0x80000000);
501                 return z; /* atan(-,+) */
502             case 2:
503                 return pi - (z - pi_lo); /* atan(+,-) */
504             default: /* case 3 */
505                 return (z - pi_lo) - pi; /* atan(-,-) */
506         }
507     }
508 
509     /*- @(#)s_atan.c 1.3 95/01/18 */
510     /*
511      * ==================================================== Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
512      * Developed at SunSoft, a Sun Microsystems, Inc. business. Permission to use, copy, modify, and distribute this software is
513      * freely granted, provided that this notice is preserved. ====================================================
514      */
515 
516     /*- atan(x)
517      * Method
518      *   1. Reduce x to positive by atan(x) = -atan(-x).
519      *   2. According to the integer k=4t+0.25 chopped, t=x, the argument
520      *      is further reduced to one of the following intervals and the
521      *      arctangent of t is evaluated by the corresponding formula:
522      *
523      *      [0,7/16]      atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...)
524      *      [7/16,11/16]  atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) )
525      *      [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) )
526      *      [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) )
527      *      [39/16,INF]   atan(x) = atan(INF) + atan( -1/t )
528      *
529      * Constants:
530      * The hexadecimal values are the intended ones for the following 
531      * constants. The decimal values may be used, provided that the 
532      * compiler will convert from decimal to binary accurately enough 
533      * to produce the hexadecimal values shown.
534      */
535 
536     /** */
537     private static double[] atanhi = {4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */
538             7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */
539             9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */
540             1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */
541     };
542 
543     /** */
544     private static double[] atanlo = {2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */
545             3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */
546             1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */
547             6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */
548     };
549 
550     /** */
551     private static double[] aT = {3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */
552             -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */
553             1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */
554             -1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */
555             9.09088713343650656196e-02, /* 0x3FB745CD, 0xC54C206E */
556             -7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */
557             6.66107313738753120669e-02, /* 0x3FB10D66, 0xA0D03D51 */
558             -5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */
559             4.97687799461593236017e-02, /* 0x3FA97B4B, 0x24760DEB */
560             -3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */
561             1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */
562     };
563 
564     /** */
565     private static double one = 1.0;
566 
567     /** */
568     private static double huge = 1.0e300;
569 
570     /**
571      * atan from http://www.netlib.org/fdlibm/.
572      * @param x double
573      * @return atan(x)
574      */
575     @SuppressWarnings("checkstyle:needbraces")
576     static double atan(double x)
577     {
578         double w, s1, s2, z;
579         int ix, hx, id;
580 
581         hx = __HI(x);
582         ix = hx & 0x7fffffff;
583         if (ix >= 0x44100000)
584         { /* if |x| >= 2^66 */
585             if (ix > 0x7ff00000 || (ix == 0x7ff00000 && (__LO(x) != 0)))
586                 return x + x; /* NaN */
587             if (hx > 0)
588                 return atanhi[3] + atanlo[3];
589             else
590                 return -atanhi[3] - atanlo[3];
591         }
592         if (ix < 0x3fdc0000)
593         { /* |x| < 0.4375 */
594             if (ix < 0x3e200000)
595             { /* |x| < 2^-29 */
596                 if (huge + x > one)
597                     return x; /* raise inexact */
598             }
599             id = -1;
600         }
601         else
602         {
603             x = Math.abs(x);
604             if (ix < 0x3ff30000)
605             { /* |x| < 1.1875 */
606                 if (ix < 0x3fe60000)
607                 { /* 7/16 <=|x|<11/16 */
608                     id = 0;
609                     x = (2.0 * x - one) / (2.0 + x);
610                 }
611                 else
612                 { /* 11/16<=|x|< 19/16 */
613                     id = 1;
614                     x = (x - one) / (x + one);
615                 }
616             }
617             else
618             {
619                 if (ix < 0x40038000)
620                 { /* |x| < 2.4375 */
621                     id = 2;
622                     x = (x - 1.5) / (one + 1.5 * x);
623                 }
624                 else
625                 { /* 2.4375 <= |x| < 2^66 */
626                     id = 3;
627                     x = -1.0 / x;
628                 }
629             }
630         }
631         /* end of argument reduction */
632         z = x * x;
633         w = z * z;
634         /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
635         s1 = z * (aT[0] + w * (aT[2] + w * (aT[4] + w * (aT[6] + w * (aT[8] + w * aT[10])))));
636         s2 = w * (aT[1] + w * (aT[3] + w * (aT[5] + w * (aT[7] + w * aT[9]))));
637         if (id < 0)
638             return x - x * (s1 + s2);
639         else
640         {
641             z = atanhi[id] - ((x * (s1 + s2) - atanlo[id]) - x);
642             return (hx < 0) ? -z : z;
643         }
644     }
645 
646     /**
647      * Return the low-order 32 bits of the double argument as an int.
648      * @param x x
649      * @return __LO
650      */
651     private static int __LO(double x)
652     {
653         long transducer = Double.doubleToRawLongBits(x);
654         return (int) transducer;
655     }
656 
657     /**
658      * Return a double with its low-order bits of the second argument and the high-order bits of the first argument..
659      * @param x x
660      * @param low lo
661      * @return __LO
662      */
663     private static double __LO(double x, int low)
664     {
665         long transX = Double.doubleToRawLongBits(x);
666         return Double.longBitsToDouble((transX & 0xFFFF_FFFF_0000_0000L) | (low & 0x0000_0000_FFFF_FFFFL));
667     }
668 
669     /**
670      * Return the high-order 32 bits of the double argument as an int.
671      * @param x x
672      * @return __HI
673      */
674     private static int __HI(double x)
675     {
676         long transducer = Double.doubleToRawLongBits(x);
677         return (int) (transducer >> 32);
678     }
679 
680     /**
681      * Return a double with its high-order bits of the second argument and the low-order bits of the first argument..
682      * @param x x
683      * @param high hi
684      * @return __HI
685      */
686     private static double __HI(double x, int high)
687     {
688         long transX = Double.doubleToRawLongBits(x);
689         return Double.longBitsToDouble((transX & 0x0000_0000_FFFF_FFFFL) | (((long) high)) << 32);
690     }
691 
692     /**
693      * @param x param
694      * @return atan(x)
695      */
696     static double fastAtan(double x)
697     {
698         double u = 1.3654703620217001424e-2;
699         u = u * x + -1.0046251337641932974e-1;
700         u = u * x + 2.7313356251360220792e-1;
701         u = u * x + -3.2614626783181052668e-1;
702         u = u * x + 7.5150001258356942267e-2;
703         u = u * x + 1.8054329923285069577e-1;
704         u = u * x + 3.1227633392937778104e-3;
705         u = u * x + -3.3362526818403318876e-1;
706         u = u * x + 1.3994641595913163446e-5;
707         u = u * x + 9.9999973830765721236e-1;
708         return u * x + 8.0891638103222688273e-10;
709     }
710 
711 }