Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /* @(#)e_pow.c 5.1 93/09/24 */
  2. /*
  3.  * ====================================================
  4.  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  5.  *
  6.  * Developed at SunPro, a Sun Microsystems, Inc. business.
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software is freely granted, provided that this notice
  9.  * is preserved.
  10.  * ====================================================
  11.  */
  12. /* Modified by Naohiko Shimizu/Tokai University, Japan 1997/08/25,
  13.    for performance improvement on pipelined processors.
  14. */
  15.  
  16. #if defined(LIBM_SCCS) && !defined(lint)
  17. static char rcsid[] = "$NetBSD: e_pow.c,v 1.9 1995/05/12 04:57:32 jtc Exp $";
  18. #endif
  19.  
  20. /* __ieee754_pow(x,y) return x**y
  21.  *
  22.  *                    n
  23.  * Method:  Let x =  2   * (1+f)
  24.  *      1. Compute and return log2(x) in two pieces:
  25.  *              log2(x) = w1 + w2,
  26.  *         where w1 has 53-24 = 29 bit trailing zeros.
  27.  *      2. Perform y*log2(x) = n+y' by simulating muti-precision
  28.  *         arithmetic, where |y'|<=0.5.
  29.  *      3. Return x**y = 2**n*exp(y'*log2)
  30.  *
  31.  * Special cases:
  32.  *      1.  (anything) ** 0  is 1
  33.  *      2.  (anything) ** 1  is itself
  34.  *      3.  (anything) ** NAN is NAN
  35.  *      4.  NAN ** (anything except 0) is NAN
  36.  *      5.  +-(|x| > 1) **  +INF is +INF
  37.  *      6.  +-(|x| > 1) **  -INF is +0
  38.  *      7.  +-(|x| < 1) **  +INF is +0
  39.  *      8.  +-(|x| < 1) **  -INF is +INF
  40.  *      9.  +-1         ** +-INF is NAN
  41.  *      10. +0 ** (+anything except 0, NAN)               is +0
  42.  *      11. -0 ** (+anything except 0, NAN, odd integer)  is +0
  43.  *      12. +0 ** (-anything except 0, NAN)               is +INF
  44.  *      13. -0 ** (-anything except 0, NAN, odd integer)  is +INF
  45.  *      14. -0 ** (odd integer) = -( +0 ** (odd integer) )
  46.  *      15. +INF ** (+anything except 0,NAN) is +INF
  47.  *      16. +INF ** (-anything except 0,NAN) is +0
  48.  *      17. -INF ** (anything)  = -0 ** (-anything)
  49.  *      18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer)
  50.  *      19. (-anything except 0 and inf) ** (non-integer) is NAN
  51.  *
  52.  * Accuracy:
  53.  *      pow(x,y) returns x**y nearly rounded. In particular
  54.  *                      pow(integer,integer)
  55.  *      always returns the correct integer provided it is
  56.  *      representable.
  57.  *
  58.  * Constants :
  59.  * The hexadecimal values are the intended ones for the following
  60.  * constants. The decimal values may be used, provided that the
  61.  * compiler will convert from decimal to binary accurately enough
  62.  * to produce the hexadecimal values shown.
  63.  */
  64.  
  65. #include "math.h"
  66. #include "math_private.h"
  67. #define zero      C[0]
  68. #define one       C[1]
  69. #define two       C[2]
  70. #define two53     C[3]
  71. #define huge      C[4]
  72. #define tiny      C[5]
  73. #define L1        C[6]
  74. #define L2        C[7]
  75. #define L3        C[8]
  76. #define L4        C[9]
  77. #define L5        C[10]
  78. #define L6        C[11]
  79. #define P1        C[12]
  80. #define P2        C[13]
  81. #define P3        C[14]
  82. #define P4        C[15]
  83. #define P5        C[16]
  84. #define lg2       C[17]
  85. #define lg2_h     C[18]
  86. #define lg2_l     C[19]
  87. #define ovt       C[20]
  88. #define cp        C[21]
  89. #define cp_h      C[22]
  90. #define cp_l      C[23]
  91. #define ivln2     C[24]
  92. #define ivln2_h   C[25]
  93. #define ivln2_l   C[26]
  94.  
  95. double scalbn(double,int);
  96.  
  97. #define EXTRACT_WORDS(ix0,ix1,d)                                \
  98. do {                                                            \
  99.   ieee_double_shape_type ew_u;                                  \
  100.   ew_u.value = (d);                                             \
  101.   (ix0) = ew_u.parts.msw;                                       \
  102.   (ix1) = ew_u.parts.lsw;                                       \
  103. } while (0)
  104.  
  105. #ifdef __STDC__
  106. static const double
  107. #else
  108. static double
  109. #endif
  110. bp[] = {1.0, 1.5,},
  111. dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */
  112. dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */
  113. C[] = {
  114. 0.0,
  115. 1.0,
  116. 2.0,
  117. 9007199254740992.0      ,
  118. 1.0e300,
  119. 1.0e-300,
  120. 5.99999999999994648725e-01 ,
  121. 4.28571428578550184252e-01 ,
  122. 3.33333329818377432918e-01 ,
  123. 2.72728123808534006489e-01 ,
  124. 2.30660745775561754067e-01 ,
  125. 2.06975017800338417784e-01 ,
  126. 1.66666666666666019037e-01 ,
  127. -2.77777777770155933842e-03 ,
  128. 6.61375632143793436117e-05 ,
  129. -1.65339022054652515390e-06 ,
  130. 4.13813679705723846039e-08 ,
  131. 6.93147180559945286227e-01 ,
  132. 6.93147182464599609375e-01 ,
  133. -1.90465429995776804525e-09 ,
  134. 8.0085662595372944372e-0017 ,
  135. 9.61796693925975554329e-01 ,
  136. 9.61796700954437255859e-01 ,
  137. -7.02846165095275826516e-09 ,
  138. 1.44269504088896338700e+00 ,
  139. 1.44269502162933349609e+00 ,
  140. 1.92596299112661746887e-08 };
  141.  
  142.         double pow_test(x,y)
  143.         double x, y;
  144. {
  145.         double z,ax,z_h,z_l,p_h,p_l;
  146.         double y1,t1,t2,r,s,t,u,v,w, t12,t14,r_1,r_2,r_3;
  147.         int32_t i,j,k,yisint,n;
  148.         int32_t hx,hy,ix,iy;
  149.         u_int32_t lx,ly;
  150.  
  151.         EXTRACT_WORDS(hx,lx,x);
  152.         EXTRACT_WORDS(hy,ly,y);
  153.         ix = hx&0x7fffffff;  iy = hy&0x7fffffff;
  154.  
  155.     /* y==zero: x**0 = 1 */
  156.         if((iy|ly)==0) return C[1];
  157.  
  158.     /* +-NaN return x+y */
  159.         if(ix > 0x7ff00000 || ((ix==0x7ff00000)&&(lx!=0)) ||
  160.            iy > 0x7ff00000 || ((iy==0x7ff00000)&&(ly!=0)))
  161.                 return x+y;
  162.  
  163.     /* determine if y is an odd int when x < 0
  164.      * yisint = 0       ... y is not an integer
  165.      * yisint = 1       ... y is an odd int
  166.      * yisint = 2       ... y is an even int
  167.      */
  168.         yisint  = 0;
  169.         if(hx<0) {
  170.             if(iy>=0x43400000) yisint = 2; /* even integer y */
  171.             else if(iy>=0x3ff00000) {
  172.                 k = (iy>>20)-0x3ff;        /* exponent */
  173.                 if(k>20) {
  174.                     j = ly>>(52-k);
  175.                     if((u_int32_t)(j<<(52-k))==ly) yisint = 2-(j&1);
  176.                 } else if(ly==0) {
  177.                     j = iy>>(20-k);
  178.                     if((int32_t)(j<<(20-k))==iy) yisint = 2-(j&1);
  179.                 }
  180.             }
  181.         }
  182.  
  183.     /* special value of y */
  184.         if(ly==0) {
  185.             if (iy==0x7ff00000) {       /* y is +-inf */
  186.                 if(((ix-0x3ff00000)|lx)==0)
  187.                     return  y - y;      /* inf**+-1 is NaN */
  188.                 else if (ix >= 0x3ff00000)/* (|x|>1)**+-inf = inf,0 */
  189.                     return (hy>=0)? y: C[0];
  190.                 else                    /* (|x|<1)**-,+inf = inf,0 */
  191.                     return (hy<0)?-y: C[0];
  192.             }
  193.             if(iy==0x3ff00000) {        /* y is  +-1 */
  194.                 if(hy<0) return C[1]/x; else return x;
  195.             }
  196.             if(hy==0x40000000) return x*x; /* y is  2 */
  197.             if(hy==0x3fe00000) {        /* y is  0.5 */
  198.                 if(hx>=0)       /* x >= +0 */
  199.                 return sqrt(x);
  200.             }
  201.         }
  202.  
  203.         ax   = fabs(x);
  204.     /* special value of x */
  205.         if(lx==0) {
  206.             if(ix==0x7ff00000||ix==0||ix==0x3ff00000){
  207.                 z = ax;                 /*x is +-0,+-inf,+-1*/
  208.                 if(hy<0) z = C[1]/z;    /* z = (1/|x|) */
  209.                 if(hx<0) {
  210.                     if(((ix-0x3ff00000)|yisint)==0) {
  211.                         z = (z-z)/(z-z); /* (-1)**non-int is NaN */
  212.                     } else if(yisint==1)
  213.                         z = -z;         /* (x<0)**odd = -(|x|**odd) */
  214.                 }
  215.                 return z;
  216.             }
  217.         }
  218.  
  219.     /* (x<0)**(non-int) is NaN */
  220.         if(((((u_int32_t)hx>>31)-1)|yisint)==0) return (x-x)/(x-x);
  221.  
  222.     /* |y| is huge */
  223.         if(iy>0x41e00000) { /* if |y| > 2**31 */
  224.             if(iy>0x43f00000){  /* if |y| > 2**64, must o/uflow */
  225.                 if(ix<=0x3fefffff) return (hy<0)? C[4]*C[4]:C[5]*C[5];
  226.                 if(ix>=0x3ff00000) return (hy>0)? C[4]*C[4]:C[5]*C[5];
  227.             }
  228.         /* over/underflow if x is not close to one */
  229.             if(ix<0x3fefffff) return (hy<0)? C[4]*C[4]:C[5]*C[5];
  230.             if(ix>0x3ff00000) return (hy>0)? C[4]*C[4]:C[5]*C[5];
  231.         /* now |1-x| is tiny <= 2**-20, suffice to compute
  232.            log(x) by x-x^2/2+x^3/3-x^4/4 */
  233.             t = x-1;            /* t has 20 trailing zeros */
  234.             w = (t*t)*(0.5-t*(0.3333333333333333333333-t*0.25));
  235.             u = C[25]*t;        /* ivln2_h has 21 sig. bits */
  236.             v = t*C[26]-w*C[24];
  237.             t1 = u+v;
  238.             SET_LOW_WORD(t1,0);
  239.             t2 = v-(t1-u);
  240.         } else {
  241.             double s2,s_h,s_l,t_h,t_l,s22,s24,s26,r1,r2,r3;
  242.             n = 0;
  243.         /* take care subnormal number */
  244.             if(ix<0x00100000)
  245.                 {ax *= C[3]; n -= 53; GET_HIGH_WORD(ix,ax); }
  246.             n  += ((ix)>>20)-0x3ff;
  247.             j  = ix&0x000fffff;
  248.         /* determine interval */
  249.             ix = j|0x3ff00000;          /* normalize ix */
  250.             if(j<=0x3988E) k=0;         /* |x|<sqrt(3/2) */
  251.             else if(j<0xBB67A) k=1;     /* |x|<sqrt(3)   */
  252.             else {k=0;n+=1;ix -= 0x00100000;}
  253.             SET_HIGH_WORD(ax,ix);
  254.  
  255.         /* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
  256.             u = ax-bp[k];               /* bp[0]=1.0, bp[1]=1.5 */
  257.             v = C[1]/(ax+bp[k]);
  258.             s = u*v;
  259.             s_h = s;
  260.             SET_LOW_WORD(s_h,0);
  261.         /* t_h=ax+bp[k] High */
  262.             t_h = C[0];
  263.             SET_HIGH_WORD(t_h,((ix>>1)|0x20000000)+0x00080000+(k<<18));
  264.             t_l = ax - (t_h-bp[k]);
  265.             s_l = v*((u-s_h*t_h)-s_h*t_l);
  266.         /* compute log(ax) */
  267.             s2 = s*s;
  268. #ifdef DO_NOT_USE_THIS
  269.             r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6)))));
  270. #else
  271.             r1 = C[10]+s2*C[11]; s22=s2*s2;
  272.             r2 = C[8]+s2*C[9]; s24=s22*s22;
  273.             r3 = C[6]+s2*C[7]; s26=s24*s22;
  274.             r = r3*s22 + r2*s24 + r1*s26;
  275. #endif
  276.             r += s_l*(s_h+s);
  277.             s2  = s_h*s_h;
  278.             t_h = 3.0+s2+r;
  279.             SET_LOW_WORD(t_h,0);
  280.             t_l = r-((t_h-3.0)-s2);
  281.         /* u+v = s*(1+...) */
  282.             u = s_h*t_h;
  283.             v = s_l*t_h+t_l*s;
  284.         /* 2/(3log2)*(s+...) */
  285.             p_h = u+v;
  286.             SET_LOW_WORD(p_h,0);
  287.             p_l = v-(p_h-u);
  288.             z_h = C[22]*p_h;            /* cp_h+cp_l = 2/(3*log2) */
  289.             z_l = C[23]*p_h+p_l*C[21]+dp_l[k];
  290.         /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */
  291.             t = (double)n;
  292.             t1 = (((z_h+z_l)+dp_h[k])+t);
  293.             SET_LOW_WORD(t1,0);
  294.             t2 = z_l-(((t1-t)-dp_h[k])-z_h);
  295.         }
  296.  
  297.         s = C[1]; /* s (sign of result -ve**odd) = -1 else = 1 */
  298.         if(((((u_int32_t)hx>>31)-1)|(yisint-1))==0)
  299.             s = -C[1];/* (-ve)**(odd int) */
  300.  
  301.     /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
  302.         y1  = y;
  303.         SET_LOW_WORD(y1,0);
  304.         p_l = (y-y1)*t1+y*t2;
  305.         p_h = y1*t1;
  306.         z = p_l+p_h;
  307.         EXTRACT_WORDS(j,i,z);
  308.         if (j>=0x40900000) {                            /* z >= 1024 */
  309.             if(((j-0x40900000)|i)!=0)                   /* if z > 1024 */
  310.                 return s*C[4]*C[4];                     /* overflow */
  311.             else {
  312.                 if(p_l+C[20]>z-p_h) return s*C[4]*C[4]; /* overflow */
  313.             }
  314.         } else if((j&0x7fffffff)>=0x4090cc00 ) {        /* z <= -1075 */
  315.             if(((j-0xc090cc00)|i)!=0)           /* z < -1075 */
  316.                 return s*C[5]*C[5];             /* underflow */
  317.             else {
  318.                 if(p_l<=z-p_h) return s*C[5]*C[5];      /* underflow */
  319.             }
  320.         }
  321.     /*
  322.      * compute 2**(p_h+p_l)
  323.      */
  324.         i = j&0x7fffffff;
  325.         k = (i>>20)-0x3ff;
  326.         n = 0;
  327.         if(i>0x3fe00000) {              /* if |z| > 0.5, set n = [z+0.5] */
  328.             n = j+(0x00100000>>(k+1));
  329.             k = ((n&0x7fffffff)>>20)-0x3ff;     /* new k for n */
  330.             t = C[0];
  331.             SET_HIGH_WORD(t,n&~(0x000fffff>>k));
  332.             n = ((n&0x000fffff)|0x00100000)>>(20-k);
  333.             if(j<0) n = -n;
  334.             p_h -= t;
  335.         }
  336.         t = p_l+p_h;
  337.         SET_LOW_WORD(t,0);
  338.         u = t*C[18];
  339.         v = (p_l-(t-p_h))*C[17]+t*C[19];
  340.         z = u+v;
  341.         w = v-(z-u);
  342.         t  = z*z;
  343. #ifdef DO_NOT_USE_THIS
  344.         t1  = z - t*(C[12]+t*(C[13]+t*(C[14]+t*(C[15]+t*C[16]))));
  345. #else
  346.         r_1 = C[15]+t*C[16]; t12 = t*t;
  347.         r_2 = C[13]+t*C[14]; t14 = t12*t12;
  348.         r_3 = t*C[12];
  349.         t1 = z - r_3 - t12*r_2 - t14*r_1;
  350. #endif
  351.         r  = (z*t1)/(t1-C[2])-(w+z*w);
  352.         z  = C[1]-(r-z);
  353.         GET_HIGH_WORD(j,z);
  354.         j += (n<<20);
  355.         if((j>>20)<=0) z = scalbn(z,n); /* subnormal output */
  356.         else SET_HIGH_WORD(z,j);
  357.         return s*z;
  358. }
  359.