Home | History | Annotate | Line # | Download | only in math
powq.c revision 1.1
      1 /*
      2  * ====================================================
      3  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
      4  *
      5  * Developed at SunPro, a Sun Microsystems, Inc. business.
      6  * Permission to use, copy, modify, and distribute this
      7  * software is freely granted, provided that this notice
      8  * is preserved.
      9  * ====================================================
     10  */
     11 
     12 /* Expansions and modifications for 128-bit long double are
     13    Copyright (C) 2001 Stephen L. Moshier <moshier (at) na-net.ornl.gov>
     14    and are incorporated herein by permission of the author.  The author
     15    reserves the right to distribute this material elsewhere under different
     16    copying permissions.  These modifications are distributed here under
     17    the following terms:
     18 
     19     This library is free software; you can redistribute it and/or
     20     modify it under the terms of the GNU Lesser General Public
     21     License as published by the Free Software Foundation; either
     22     version 2.1 of the License, or (at your option) any later version.
     23 
     24     This library is distributed in the hope that it will be useful,
     25     but WITHOUT ANY WARRANTY; without even the implied warranty of
     26     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     27     Lesser General Public License for more details.
     28 
     29     You should have received a copy of the GNU Lesser General Public
     30     License along with this library; if not, see
     31     <http://www.gnu.org/licenses/>.  */
     32 
     33 /* powq(x,y) return x**y
     34  *
     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 113-53 = 60 bit trailing zeros.
     40  *	2. Perform y*log2(x) = n+y' by simulating muti-precision
     41  *	   arithmetic, where |y'|<=0.5.
     42  *	3. Return x**y = 2**n*exp(y'*log2)
     43  *
     44  * Special cases:
     45  *	1.  (anything) ** 0  is 1
     46  *	2.  (anything) ** 1  is itself
     47  *	3.  (anything) ** NAN is NAN
     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 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  */
     66 
     67 #include "quadmath-imp.h"
     68 
     69 static const __float128 bp[] = {
     70   1,
     71   1.5Q,
     72 };
     73 
     74 /* log_2(1.5) */
     75 static const __float128 dp_h[] = {
     76   0.0,
     77   5.8496250072115607565592654282227158546448E-1Q
     78 };
     79 
     80 /* Low part of log_2(1.5) */
     81 static const __float128 dp_l[] = {
     82   0.0,
     83   1.0579781240112554492329533686862998106046E-16Q
     84 };
     85 
     86 static const __float128 zero = 0,
     87   one = 1,
     88   two = 2,
     89   two113 = 1.0384593717069655257060992658440192E34Q,
     90   huge = 1.0e3000Q,
     91   tiny = 1.0e-3000Q;
     92 
     93 /* 3/2 log x = 3 z + z^3 + z^3 (z^2 R(z^2))
     94    z = (x-1)/(x+1)
     95    1 <= x <= 1.25
     96    Peak relative error 2.3e-37 */
     97 static const __float128 LN[] =
     98 {
     99  -3.0779177200290054398792536829702930623200E1Q,
    100   6.5135778082209159921251824580292116201640E1Q,
    101  -4.6312921812152436921591152809994014413540E1Q,
    102   1.2510208195629420304615674658258363295208E1Q,
    103  -9.9266909031921425609179910128531667336670E-1Q
    104 };
    105 static const __float128 LD[] =
    106 {
    107  -5.129862866715009066465422805058933131960E1Q,
    108   1.452015077564081884387441590064272782044E2Q,
    109  -1.524043275549860505277434040464085593165E2Q,
    110   7.236063513651544224319663428634139768808E1Q,
    111  -1.494198912340228235853027849917095580053E1Q
    112   /* 1.0E0 */
    113 };
    114 
    115 /* exp(x) = 1 + x - x / (1 - 2 / (x - x^2 R(x^2)))
    116    0 <= x <= 0.5
    117    Peak relative error 5.7e-38  */
    118 static const __float128 PN[] =
    119 {
    120   5.081801691915377692446852383385968225675E8Q,
    121   9.360895299872484512023336636427675327355E6Q,
    122   4.213701282274196030811629773097579432957E4Q,
    123   5.201006511142748908655720086041570288182E1Q,
    124   9.088368420359444263703202925095675982530E-3Q,
    125 };
    126 static const __float128 PD[] =
    127 {
    128   3.049081015149226615468111430031590411682E9Q,
    129   1.069833887183886839966085436512368982758E8Q,
    130   8.259257717868875207333991924545445705394E5Q,
    131   1.872583833284143212651746812884298360922E3Q,
    132   /* 1.0E0 */
    133 };
    134 
    135 static const __float128
    136   /* ln 2 */
    137   lg2 = 6.9314718055994530941723212145817656807550E-1Q,
    138   lg2_h = 6.9314718055994528622676398299518041312695E-1Q,
    139   lg2_l = 2.3190468138462996154948554638754786504121E-17Q,
    140   ovt = 8.0085662595372944372e-0017Q,
    141   /* 2/(3*log(2)) */
    142   cp = 9.6179669392597560490661645400126142495110E-1Q,
    143   cp_h = 9.6179669392597555432899980587535537779331E-1Q,
    144   cp_l = 5.0577616648125906047157785230014751039424E-17Q;
    145 
    146 __float128
    147 powq (__float128 x, __float128 y)
    148 {
    149   __float128 z, ax, z_h, z_l, p_h, p_l;
    150   __float128 y1, t1, t2, r, s, sgn, t, u, v, w;
    151   __float128 s2, s_h, s_l, t_h, t_l, ay;
    152   int32_t i, j, k, yisint, n;
    153   uint32_t ix, iy;
    154   int32_t hx, hy;
    155   ieee854_float128 o, p, q;
    156 
    157   p.value = x;
    158   hx = p.words32.w0;
    159   ix = hx & 0x7fffffff;
    160 
    161   q.value = y;
    162   hy = q.words32.w0;
    163   iy = hy & 0x7fffffff;
    164 
    165 
    166   /* y==zero: x**0 = 1 */
    167   if ((iy | q.words32.w1 | q.words32.w2 | q.words32.w3) == 0
    168       && !issignalingq (x))
    169     return one;
    170 
    171   /* 1.0**y = 1; -1.0**+-Inf = 1 */
    172   if (x == one && !issignalingq (y))
    173     return one;
    174   if (x == -1 && iy == 0x7fff0000
    175       && (q.words32.w1 | q.words32.w2 | q.words32.w3) == 0)
    176     return one;
    177 
    178   /* +-NaN return x+y */
    179   if ((ix > 0x7fff0000)
    180       || ((ix == 0x7fff0000)
    181 	  && ((p.words32.w1 | p.words32.w2 | p.words32.w3) != 0))
    182       || (iy > 0x7fff0000)
    183       || ((iy == 0x7fff0000)
    184 	  && ((q.words32.w1 | q.words32.w2 | q.words32.w3) != 0)))
    185     return x + y;
    186 
    187   /* determine if y is an odd int when x < 0
    188    * yisint = 0       ... y is not an integer
    189    * yisint = 1       ... y is an odd int
    190    * yisint = 2       ... y is an even int
    191    */
    192   yisint = 0;
    193   if (hx < 0)
    194     {
    195       if (iy >= 0x40700000)	/* 2^113 */
    196 	yisint = 2;		/* even integer y */
    197       else if (iy >= 0x3fff0000)	/* 1.0 */
    198 	{
    199 	  if (floorq (y) == y)
    200 	    {
    201 	      z = 0.5 * y;
    202 	      if (floorq (z) == z)
    203 		yisint = 2;
    204 	      else
    205 		yisint = 1;
    206 	    }
    207 	}
    208     }
    209 
    210   /* special value of y */
    211   if ((q.words32.w1 | q.words32.w2 | q.words32.w3) == 0)
    212     {
    213       if (iy == 0x7fff0000)	/* y is +-inf */
    214 	{
    215 	  if (((ix - 0x3fff0000) | p.words32.w1 | p.words32.w2 | p.words32.w3)
    216 	      == 0)
    217 	    return y - y;	/* +-1**inf is NaN */
    218 	  else if (ix >= 0x3fff0000)	/* (|x|>1)**+-inf = inf,0 */
    219 	    return (hy >= 0) ? y : zero;
    220 	  else			/* (|x|<1)**-,+inf = inf,0 */
    221 	    return (hy < 0) ? -y : zero;
    222 	}
    223       if (iy == 0x3fff0000)
    224 	{			/* y is  +-1 */
    225 	  if (hy < 0)
    226 	    return one / x;
    227 	  else
    228 	    return x;
    229 	}
    230       if (hy == 0x40000000)
    231 	return x * x;		/* y is  2 */
    232       if (hy == 0x3ffe0000)
    233 	{			/* y is  0.5 */
    234 	  if (hx >= 0)		/* x >= +0 */
    235 	    return sqrtq (x);
    236 	}
    237     }
    238 
    239   ax = fabsq (x);
    240   /* special value of x */
    241   if ((p.words32.w1 | p.words32.w2 | p.words32.w3) == 0)
    242     {
    243       if (ix == 0x7fff0000 || ix == 0 || ix == 0x3fff0000)
    244 	{
    245 	  z = ax;		/*x is +-0,+-inf,+-1 */
    246 	  if (hy < 0)
    247 	    z = one / z;	/* z = (1/|x|) */
    248 	  if (hx < 0)
    249 	    {
    250 	      if (((ix - 0x3fff0000) | yisint) == 0)
    251 		{
    252 		  z = (z - z) / (z - z);	/* (-1)**non-int is NaN */
    253 		}
    254 	      else if (yisint == 1)
    255 		z = -z;		/* (x<0)**odd = -(|x|**odd) */
    256 	    }
    257 	  return z;
    258 	}
    259     }
    260 
    261   /* (x<0)**(non-int) is NaN */
    262   if (((((uint32_t) hx >> 31) - 1) | yisint) == 0)
    263     return (x - x) / (x - x);
    264 
    265   /* sgn (sign of result -ve**odd) = -1 else = 1 */
    266   sgn = one;
    267   if (((((uint32_t) hx >> 31) - 1) | (yisint - 1)) == 0)
    268     sgn = -one;			/* (-ve)**(odd int) */
    269 
    270   /* |y| is huge.
    271      2^-16495 = 1/2 of smallest representable value.
    272      If (1 - 1/131072)^y underflows, y > 1.4986e9 */
    273   if (iy > 0x401d654b)
    274     {
    275       /* if (1 - 2^-113)^y underflows, y > 1.1873e38 */
    276       if (iy > 0x407d654b)
    277 	{
    278 	  if (ix <= 0x3ffeffff)
    279 	    return (hy < 0) ? huge * huge : tiny * tiny;
    280 	  if (ix >= 0x3fff0000)
    281 	    return (hy > 0) ? huge * huge : tiny * tiny;
    282 	}
    283       /* over/underflow if x is not close to one */
    284       if (ix < 0x3ffeffff)
    285 	return (hy < 0) ? sgn * huge * huge : sgn * tiny * tiny;
    286       if (ix > 0x3fff0000)
    287 	return (hy > 0) ? sgn * huge * huge : sgn * tiny * tiny;
    288     }
    289 
    290   ay = y > 0 ? y : -y;
    291   if (ay < 0x1p-128)
    292     y = y < 0 ? -0x1p-128 : 0x1p-128;
    293 
    294   n = 0;
    295   /* take care subnormal number */
    296   if (ix < 0x00010000)
    297     {
    298       ax *= two113;
    299       n -= 113;
    300       o.value = ax;
    301       ix = o.words32.w0;
    302     }
    303   n += ((ix) >> 16) - 0x3fff;
    304   j = ix & 0x0000ffff;
    305   /* determine interval */
    306   ix = j | 0x3fff0000;		/* normalize ix */
    307   if (j <= 0x3988)
    308     k = 0;			/* |x|<sqrt(3/2) */
    309   else if (j < 0xbb67)
    310     k = 1;			/* |x|<sqrt(3)   */
    311   else
    312     {
    313       k = 0;
    314       n += 1;
    315       ix -= 0x00010000;
    316     }
    317 
    318   o.value = ax;
    319   o.words32.w0 = ix;
    320   ax = o.value;
    321 
    322   /* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
    323   u = ax - bp[k];		/* bp[0]=1.0, bp[1]=1.5 */
    324   v = one / (ax + bp[k]);
    325   s = u * v;
    326   s_h = s;
    327 
    328   o.value = s_h;
    329   o.words32.w3 = 0;
    330   o.words32.w2 &= 0xf8000000;
    331   s_h = o.value;
    332   /* t_h=ax+bp[k] High */
    333   t_h = ax + bp[k];
    334   o.value = t_h;
    335   o.words32.w3 = 0;
    336   o.words32.w2 &= 0xf8000000;
    337   t_h = o.value;
    338   t_l = ax - (t_h - bp[k]);
    339   s_l = v * ((u - s_h * t_h) - s_h * t_l);
    340   /* compute log(ax) */
    341   s2 = s * s;
    342   u = LN[0] + s2 * (LN[1] + s2 * (LN[2] + s2 * (LN[3] + s2 * LN[4])));
    343   v = LD[0] + s2 * (LD[1] + s2 * (LD[2] + s2 * (LD[3] + s2 * (LD[4] + s2))));
    344   r = s2 * s2 * u / v;
    345   r += s_l * (s_h + s);
    346   s2 = s_h * s_h;
    347   t_h = 3.0 + s2 + r;
    348   o.value = t_h;
    349   o.words32.w3 = 0;
    350   o.words32.w2 &= 0xf8000000;
    351   t_h = o.value;
    352   t_l = r - ((t_h - 3.0) - s2);
    353   /* u+v = s*(1+...) */
    354   u = s_h * t_h;
    355   v = s_l * t_h + t_l * s;
    356   /* 2/(3log2)*(s+...) */
    357   p_h = u + v;
    358   o.value = p_h;
    359   o.words32.w3 = 0;
    360   o.words32.w2 &= 0xf8000000;
    361   p_h = o.value;
    362   p_l = v - (p_h - u);
    363   z_h = cp_h * p_h;		/* cp_h+cp_l = 2/(3*log2) */
    364   z_l = cp_l * p_h + p_l * cp + dp_l[k];
    365   /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */
    366   t = (__float128) n;
    367   t1 = (((z_h + z_l) + dp_h[k]) + t);
    368   o.value = t1;
    369   o.words32.w3 = 0;
    370   o.words32.w2 &= 0xf8000000;
    371   t1 = o.value;
    372   t2 = z_l - (((t1 - t) - dp_h[k]) - z_h);
    373 
    374   /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
    375   y1 = y;
    376   o.value = y1;
    377   o.words32.w3 = 0;
    378   o.words32.w2 &= 0xf8000000;
    379   y1 = o.value;
    380   p_l = (y - y1) * t1 + y * t2;
    381   p_h = y1 * t1;
    382   z = p_l + p_h;
    383   o.value = z;
    384   j = o.words32.w0;
    385   if (j >= 0x400d0000) /* z >= 16384 */
    386     {
    387       /* if z > 16384 */
    388       if (((j - 0x400d0000) | o.words32.w1 | o.words32.w2 | o.words32.w3) != 0)
    389 	return sgn * huge * huge;	/* overflow */
    390       else
    391 	{
    392 	  if (p_l + ovt > z - p_h)
    393 	    return sgn * huge * huge;	/* overflow */
    394 	}
    395     }
    396   else if ((j & 0x7fffffff) >= 0x400d01b9)	/* z <= -16495 */
    397     {
    398       /* z < -16495 */
    399       if (((j - 0xc00d01bc) | o.words32.w1 | o.words32.w2 | o.words32.w3)
    400 	  != 0)
    401 	return sgn * tiny * tiny;	/* underflow */
    402       else
    403 	{
    404 	  if (p_l <= z - p_h)
    405 	    return sgn * tiny * tiny;	/* underflow */
    406 	}
    407     }
    408   /* compute 2**(p_h+p_l) */
    409   i = j & 0x7fffffff;
    410   k = (i >> 16) - 0x3fff;
    411   n = 0;
    412   if (i > 0x3ffe0000)
    413     {				/* if |z| > 0.5, set n = [z+0.5] */
    414       n = floorq (z + 0.5Q);
    415       t = n;
    416       p_h -= t;
    417     }
    418   t = p_l + p_h;
    419   o.value = t;
    420   o.words32.w3 = 0;
    421   o.words32.w2 &= 0xf8000000;
    422   t = o.value;
    423   u = t * lg2_h;
    424   v = (p_l - (t - p_h)) * lg2 + t * lg2_l;
    425   z = u + v;
    426   w = v - (z - u);
    427   /*  exp(z) */
    428   t = z * z;
    429   u = PN[0] + t * (PN[1] + t * (PN[2] + t * (PN[3] + t * PN[4])));
    430   v = PD[0] + t * (PD[1] + t * (PD[2] + t * (PD[3] + t)));
    431   t1 = z - t * u / v;
    432   r = (z * t1) / (t1 - two) - (w + z * w);
    433   z = one - (r - z);
    434   o.value = z;
    435   j = o.words32.w0;
    436   j += (n << 16);
    437   if ((j >> 16) <= 0)
    438     {
    439       z = scalbnq (z, n);	/* subnormal output */
    440       __float128 force_underflow = z * z;
    441       math_force_eval (force_underflow);
    442     }
    443   else
    444     {
    445       o.words32.w0 = j;
    446       z = o.value;
    447     }
    448   return sgn * z;
    449 }
    450