1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 /*
  27  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  28  * Use is subject to license terms.
  29  */
  30 
  31 #pragma weak __pow = pow
  32 
  33 /*
  34  * pow(x,y) return x**y
  35  *                    n
  36  * Method:  Let x =  2   * (1+f)
  37  *      1. Compute and return log2(x) in two pieces:
  38  *              log2(x) = w1 + w2,
  39  *         where w1 has 24 bits trailing zero.
  40  *      2. Perform y*log2(x) by simulating muti-precision arithmetic
  41  *      3. Return x**y = exp2(y*log(x))
  42  *
  43  * Special cases:
  44  *      1.  (anything) ** +-0 is 1
  45  *      1'. 1 ** (anything)   is 1      (C99; 1 ** +-INF/NAN used to be NAN)
  46  *      2.  (anything) ** 1   is itself
  47  *      3.  (anything except 1) ** NAN is NAN ("except 1" is C99)
  48  *      4.  NAN ** (anything except 0) is NAN
  49  *      5.  +-(|x| > 1) **  +INF is +INF
  50  *      6.  +-(|x| > 1) **  -INF is +0
  51  *      7.  +-(|x| < 1) **  +INF is +0
  52  *      8.  +-(|x| < 1) **  -INF is +INF
  53  *      9.  -1          ** +-INF is 1   (C99; -1 ** +-INF used to be NAN)
  54  *      10. +0 ** (+anything except 0, NAN)               is +0
  55  *      11. -0 ** (+anything except 0, NAN, odd integer)  is +0
  56  *      12. +0 ** (-anything except 0, NAN)               is +INF
  57  *      13. -0 ** (-anything except 0, NAN, odd integer)  is +INF
  58  *      14. -0 ** (odd integer) = -( +0 ** (odd integer) )
  59  *      15. +INF ** (+anything except 0,NAN) is +INF
  60  *      16. +INF ** (-anything except 0,NAN) is +0
  61  *      17. -INF ** (anything)  = -0 ** (-anything)
  62  *      18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer)
  63  *      19. (-anything except 0 and inf) ** (non-integer) is NAN
  64  *
  65  * Accuracy:
  66  *      pow(x,y) returns x**y nearly rounded. In particular
  67  *                      pow(integer,integer)
  68  *      always returns the correct integer provided it is representable.
  69  */
  70 
  71 #include "libm.h"
  72 #include "xpg6.h"                       /* __xpg6 */
  73 #define _C99SUSv3_pow   _C99SUSv3_pow_treats_Inf_as_an_even_int
  74 
  75 static const double zero = 0.0,
  76         one = 1.0,
  77         two = 2.0;
  78 
  79 extern const double _TBL_log2_hi[], _TBL_log2_lo[];
  80 
  81 static const double two53 = 9007199254740992.0,
  82         A1_hi = 2.8853900432586669921875,
  83         A1_lo = 3.8519259825035041963606002e-8,
  84         A1 = 2.885390081777926817222541963606002026086e+0000,
  85         A2 = 9.617966939207270828380543979852286255862e-0001,
  86         A3 = 5.770807680887875964868853124873696201995e-0001,
  87         B0_hi = 2.8853900432586669921875,
  88         B0_lo = 3.8519259822532793056374320585e-8,
  89         B0 = 2.885390081777926814720293056374320585689e+0000,
  90         B1 = 9.617966939259755138949202350396200257632e-0001,
  91         B2 = 5.770780163585687000782112776448797953382e-0001,
  92         B3 = 4.121985488948771523290174512461778354953e-0001,
  93         B4 = 3.207590534812432970433641789022666850193e-0001;
  94 
  95 static double
  96 log2_x(double x, double *w)
  97 {
  98         double f, s, z, qn, h, t;
  99         int *px = (int *)&x;
 100         int *pz = (int *)&z;
 101         int i, j, ix, n;
 102 
 103         n = 0;
 104         ix = px[HIWORD];
 105 
 106         if (ix >= 0x3fef03f1 && ix < 0x3ff08208) {        /* 65/63 > x > 63/65 */
 107                 double f1, v;
 108 
 109                 f = x - one;
 110 
 111                 if (((ix - 0x3ff00000) | px[LOWORD]) == 0) {
 112                         *w = zero;
 113                         return (zero);  /* log2(1)= +0 */
 114                 }
 115 
 116                 qn = one / (two + f);
 117                 s = f * qn;             /* |s|<2**-6 */
 118                 v = s * s;
 119                 h = (double)((float)s);
 120                 f1 = (double)((float)f);
 121                 t = qn * (((f - two * h) - h * f1) - h * (f - f1));
 122                 /* s = h+t */
 123                 f1 = h * B0_lo + s * (v * (B1 + v * (B2 + v * (B3 + v * B4))));
 124                 t = f1 + t * B0;
 125                 h *= B0_hi;
 126                 s = (double)((float)(h + t));
 127                 *w = t - (s - h);
 128                 return (s);
 129         }
 130 
 131         if (ix < 0x00100000) {               /* subnormal x */
 132                 x *= two53;
 133                 n = -53;
 134                 ix = px[HIWORD];
 135         }
 136 
 137         /* LARGE N */
 138         n += ((ix + 0x1000) >> 20) - 0x3ff;
 139         ix = (ix & 0x000fffff) | 0x3ff00000;        /* scale x to [1,2] */
 140         px[HIWORD] = ix;
 141         i = ix + 0x1000;
 142         pz[HIWORD] = i & 0xffffe000;
 143         pz[LOWORD] = 0;
 144         qn = one / (x + z);
 145         f = x - z;
 146         s = f * qn;
 147         h = (double)((float)s);
 148         t = qn * ((f - (h + h) * z) - h * f);
 149         j = (i >> 13) & 0x7f;
 150         f = s * s;
 151         t = t * A1 + h * A1_lo;
 152         t += (s * f) * (A2 + f * A3);
 153         qn = h * A1_hi;
 154         s = n + _TBL_log2_hi[j];
 155         h = qn + s;
 156         t += _TBL_log2_lo[j] - ((h - s) - qn);
 157         f = (double)((float)(h + t));
 158         *w = t - (f - h);
 159         return (f);
 160 }
 161 
 162 extern const double _TBL_exp2_hi[], _TBL_exp2_lo[];
 163 static const double             /* poly app of 2^x-1 on [-1e-10,2^-7+1e-10] */
 164         E1 = 6.931471805599453100674958533810346197328e-0001,
 165         E2 = 2.402265069587779347846769151717493815979e-0001,
 166         E3 = 5.550410866475410512631124892773937864699e-0002,
 167         E4 = 9.618143209991026824853712740162451423355e-0003,
 168         E5 = 1.333357676549940345096774122231849082991e-0003;
 169 
 170 double
 171 pow(double x, double y)
 172 {
 173         double z, ax;
 174         double y1, y2, w1, w2;
 175         int sbx, sby, j, k, yisint;
 176         int hx, hy, ahx, ahy;
 177         unsigned lx, ly;
 178         int *pz = (int *)&z;
 179 
 180         hx = ((int *)&x)[HIWORD];
 181         lx = ((unsigned *)&x)[LOWORD];
 182         hy = ((int *)&y)[HIWORD];
 183         ly = ((unsigned *)&y)[LOWORD];
 184         ahx = hx & ~0x80000000;
 185         ahy = hy & ~0x80000000;
 186 
 187         if ((ahy | ly) == 0) {                          /* y==zero  */
 188                 if ((ahx | lx) == 0)
 189                         z = _SVID_libm_err(x, y, 20);   /* +-0**+-0 */
 190                 else if ((ahx | (((lx | -lx) >> 31) & 1)) > 0x7ff00000)
 191                         z = _SVID_libm_err(x, y, 42);   /* NaN**+-0 */
 192                 else
 193                         z = one;                        /* x**+-0 = 1 */
 194 
 195                 return (z);
 196         } else if (hx == 0x3ff00000 && lx == 0 && (__xpg6 & _C99SUSv3_pow) !=
 197             0) {
 198                 return (one);           /* C99: 1**anything = 1 */
 199         } else if (ahx > 0x7ff00000 || (ahx == 0x7ff00000 && lx != 0) || ahy >
 200             0x7ff00000 || (ahy == 0x7ff00000 && ly != 0)) {
 201                 return (x * y); /* +-NaN return x*y; + -> * for Cheetah */
 202         }
 203 
 204         /* includes Sun: 1**NaN = NaN */
 205         sbx = (unsigned)hx >> 31;
 206         sby = (unsigned)hy >> 31;
 207         ax = fabs(x);
 208 
 209         /*
 210          * determine if y is an odd int when x < 0
 211          * yisint = 0 ... y is not an integer
 212          * yisint = 1 ... y is an odd int
 213          * yisint = 2 ... y is an even int
 214          */
 215         yisint = 0;
 216 
 217         if (sbx) {
 218                 if (ahy >= 0x43400000) {
 219                         yisint = 2;                     /* even integer y */
 220                 } else if (ahy >= 0x3ff00000) {
 221                         k = (ahy >> 20) - 0x3ff;  /* exponent */
 222 
 223                         if (k > 20) {
 224                                 j = ly >> (52 - k);
 225 
 226                                 if ((j << (52 - k)) == ly)
 227                                         yisint = 2 - (j & 1);
 228                         } else if (ly == 0) {
 229                                 j = ahy >> (20 - k);
 230 
 231                                 if ((j << (20 - k)) == ahy)
 232                                         yisint = 2 - (j & 1);
 233                         }
 234                 }
 235         }
 236 
 237         /* special value of y */
 238         if (ly == 0) {
 239                 if (ahy == 0x7ff00000) {        /* y is +-inf */
 240                         if (((ahx - 0x3ff00000) | lx) == 0) {
 241                                 if ((__xpg6 & _C99SUSv3_pow) != 0)
 242                                         return (one);
 243                                 /* C99: (-1)**+-inf = 1 */
 244                                 else
 245                                         return (y - y);
 246 
 247                                 /* Sun: (+-1)**+-inf = NaN */
 248                         } else if (ahx >= 0x3ff00000) {
 249                                 /* (|x|>1)**+,-inf = inf,0 */
 250                                 return (sby == 0 ? y : zero);
 251                         } else {        /* (|x|<1)**-,+inf = inf,0 */
 252                                 return (sby != 0 ? -y : zero);
 253                         }
 254                 }
 255 
 256                 if (ahy == 0x3ff00000) {        /* y is  +-1 */
 257                         if (sby != 0) {         /* y is -1 */
 258                                 if (x == zero)  /* divided by zero */
 259                                         return (_SVID_libm_err(x, y, 23));
 260                                 else if (ahx < 0x40000 || ((ahx - 0x40000) |
 261                                     lx) == 0)   /* overflow */
 262                                         return (_SVID_libm_err(x, y, 21));
 263                                 else
 264                                         return (one / x);
 265                         } else {
 266                                 return (x);
 267                         }
 268                 }
 269 
 270                 if (hy == 0x40000000) { /* y is  2 */
 271                         if (ahx >= 0x5ff00000 && ahx < 0x7ff00000)
 272                                 return (_SVID_libm_err(x, y, 21));
 273                         /* x*x overflow */
 274                         else if ((ahx < 0x1e56a09e && (ahx | lx) != 0) ||
 275                             (ahx == 0x1e56a09e && lx < 0x667f3bcd))
 276                                 return (_SVID_libm_err(x, y, 22));
 277                         /* x*x underflow */
 278                         else
 279                                 return (x * x);
 280                 }
 281 
 282                 if (hy == 0x3fe00000) {
 283                         if (!((ahx | lx) == 0 || ((ahx - 0x7ff00000) | lx) ==
 284                             0 || sbx == 1))
 285                                 return (sqrt(x));       /* y is 0.5 and x > 0 */
 286                 }
 287         }
 288 
 289         /* special value of x */
 290         if (lx == 0) {
 291                 if (ahx == 0x7ff00000 || ahx == 0 || ahx == 0x3ff00000) {
 292                         /* x is +-0,+-inf,-1 */
 293                         z = ax;
 294 
 295                         if (sby == 1) {
 296                                 z = one / z;    /* z = |x|**y */
 297 
 298                                 if (ahx == 0)
 299                                         return (_SVID_libm_err(x, y, 23));
 300                         }
 301 
 302                         if (sbx == 1) {
 303                                 if (ahx == 0x3ff00000 && yisint == 0)
 304                                         z = _SVID_libm_err(x, y, 24);
 305                                 /* neg**non-integral is NaN + invalid */
 306                                 else if (yisint == 1)
 307                                         z = -z; /* (x<0)**odd = -(|x|**odd) */
 308                         }
 309 
 310                         return (z);
 311                 }
 312         }
 313 
 314         /* (x<0)**(non-int) is NaN */
 315         if (sbx == 1 && yisint == 0)
 316                 return (_SVID_libm_err(x, y, 24));
 317 
 318         /*
 319          * Now ax is finite, y is finite
 320          * first compute log2(ax) = w1+w2, with 24 bits w1
 321          */
 322         w1 = log2_x(ax, &w2);
 323 
 324         /* split up y into y1+y2 and compute (y1+y2)*(w1+w2) */
 325         if (((ly & 0x07ffffff) == 0) || ahy >= 0x47e00000 || ahy <=
 326             0x38100000) {
 327                 /* no need to split if y is short or too large or too small */
 328                 y1 = y * w1;
 329                 y2 = y * w2;
 330         } else {
 331                 y1 = (double)((float)y);
 332                 y2 = (y - y1) * w1 + y * w2;
 333                 y1 *= w1;
 334         }
 335 
 336         z = y1 + y2;
 337         j = pz[HIWORD];
 338 
 339         if (j >= 0x40900000) {                                       /* z >= 1024 */
 340                 if (!(j == 0x40900000 && pz[LOWORD] == 0)) {    /* z > 1024 */
 341                         return (_SVID_libm_err(x, y, 21));      /* overflow */
 342                 } else {
 343                         w2 = y1 - z;
 344                         w2 += y2;
 345 
 346                         /* rounded to inf */
 347                         if (w2 >= -8.008566259537296567160e-17)
 348                                 return (_SVID_libm_err(x, y, 21));
 349 
 350                         /* overflow */
 351                 }
 352         } else if ((j & ~0x80000000) >= 0x4090cc00) {            /* z <= -1075 */
 353                 if (!(j == 0xc090cc00 && pz[LOWORD] == 0)) {    /* z < -1075 */
 354                         return (_SVID_libm_err(x, y, 22));      /* underflow */
 355                 } else {
 356                         w2 = y1 - z;
 357                         w2 += y2;
 358 
 359                         if (w2 <= zero)      /* underflow */
 360                                 return (_SVID_libm_err(x, y, 22));
 361                 }
 362         }
 363 
 364         /*
 365          * compute 2**(k+f[j]+g)
 366          */
 367         k = (int)(z * 64.0 + (((hy ^ (ahx - 0x3ff00000)) > 0) ? 0.5 : -0.5));
 368         j = k & 63;
 369         w1 = y2 - ((double)k * 0.015625 - y1);
 370         w2 = _TBL_exp2_hi[j];
 371         z = _TBL_exp2_lo[j] + (w2 * w1) * (E1 + w1 * (E2 + w1 * (E3 + w1 * (E4 +
 372             w1 * E5))));
 373         z += w2;
 374         k >>= 6;
 375 
 376         if (k < -1021)
 377                 z = scalbn(z, k);
 378         else                            /* subnormal output */
 379                 pz[HIWORD] += k << 20;
 380 
 381         if (sbx == 1 && yisint == 1)
 382                 z = -z;                 /* (-ve)**(odd int) */
 383 
 384         return (z);
 385 }