Blame sysdeps/ieee754/ldbl-128/e_powl.c

Packit 6c4009
/*
Packit 6c4009
 * ====================================================
Packit 6c4009
 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
Packit 6c4009
 *
Packit 6c4009
 * Developed at SunPro, a Sun Microsystems, Inc. business.
Packit 6c4009
 * Permission to use, copy, modify, and distribute this
Packit 6c4009
 * software is freely granted, provided that this notice
Packit 6c4009
 * is preserved.
Packit 6c4009
 * ====================================================
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
/* Expansions and modifications for 128-bit long double are
Packit 6c4009
   Copyright (C) 2001 Stephen L. Moshier <moshier@na-net.ornl.gov>
Packit 6c4009
   and are incorporated herein by permission of the author.  The author
Packit 6c4009
   reserves the right to distribute this material elsewhere under different
Packit 6c4009
   copying permissions.  These modifications are distributed here under
Packit 6c4009
   the following terms:
Packit 6c4009
Packit 6c4009
    This library is free software; you can redistribute it and/or
Packit 6c4009
    modify it under the terms of the GNU Lesser General Public
Packit 6c4009
    License as published by the Free Software Foundation; either
Packit 6c4009
    version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
    This library is distributed in the hope that it will be useful,
Packit 6c4009
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
    Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
    You should have received a copy of the GNU Lesser General Public
Packit 6c4009
    License along with this library; if not, see
Packit 6c4009
    <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
/* __ieee754_powl(x,y) return x**y
Packit 6c4009
 *
Packit 6c4009
 *		      n
Packit 6c4009
 * Method:  Let x =  2   * (1+f)
Packit 6c4009
 *	1. Compute and return log2(x) in two pieces:
Packit 6c4009
 *		log2(x) = w1 + w2,
Packit 6c4009
 *	   where w1 has 113-53 = 60 bit trailing zeros.
Packit 6c4009
 *	2. Perform y*log2(x) = n+y' by simulating muti-precision
Packit 6c4009
 *	   arithmetic, where |y'|<=0.5.
Packit 6c4009
 *	3. Return x**y = 2**n*exp(y'*log2)
Packit 6c4009
 *
Packit 6c4009
 * Special cases:
Packit 6c4009
 *	1.  (anything) ** 0  is 1
Packit 6c4009
 *	2.  (anything) ** 1  is itself
Packit 6c4009
 *	3.  (anything) ** NAN is NAN
Packit 6c4009
 *	4.  NAN ** (anything except 0) is NAN
Packit 6c4009
 *	5.  +-(|x| > 1) **  +INF is +INF
Packit 6c4009
 *	6.  +-(|x| > 1) **  -INF is +0
Packit 6c4009
 *	7.  +-(|x| < 1) **  +INF is +0
Packit 6c4009
 *	8.  +-(|x| < 1) **  -INF is +INF
Packit 6c4009
 *	9.  +-1         ** +-INF is NAN
Packit 6c4009
 *	10. +0 ** (+anything except 0, NAN)               is +0
Packit 6c4009
 *	11. -0 ** (+anything except 0, NAN, odd integer)  is +0
Packit 6c4009
 *	12. +0 ** (-anything except 0, NAN)               is +INF
Packit 6c4009
 *	13. -0 ** (-anything except 0, NAN, odd integer)  is +INF
Packit 6c4009
 *	14. -0 ** (odd integer) = -( +0 ** (odd integer) )
Packit 6c4009
 *	15. +INF ** (+anything except 0,NAN) is +INF
Packit 6c4009
 *	16. +INF ** (-anything except 0,NAN) is +0
Packit 6c4009
 *	17. -INF ** (anything)  = -0 ** (-anything)
Packit 6c4009
 *	18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer)
Packit 6c4009
 *	19. (-anything except 0 and inf) ** (non-integer) is NAN
Packit 6c4009
 *
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
#include <math.h>
Packit 6c4009
#include <math-barriers.h>
Packit 6c4009
#include <math_private.h>
Packit 6c4009
Packit 6c4009
static const _Float128 bp[] = {
Packit 6c4009
  1,
Packit 6c4009
  L(1.5),
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
/* log_2(1.5) */
Packit 6c4009
static const _Float128 dp_h[] = {
Packit 6c4009
  0.0,
Packit 6c4009
  L(5.8496250072115607565592654282227158546448E-1)
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
/* Low part of log_2(1.5) */
Packit 6c4009
static const _Float128 dp_l[] = {
Packit 6c4009
  0.0,
Packit 6c4009
  L(1.0579781240112554492329533686862998106046E-16)
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
static const _Float128 zero = 0,
Packit 6c4009
  one = 1,
Packit 6c4009
  two = 2,
Packit 6c4009
  two113 = L(1.0384593717069655257060992658440192E34),
Packit 6c4009
  huge = L(1.0e3000),
Packit 6c4009
  tiny = L(1.0e-3000);
Packit 6c4009
Packit 6c4009
/* 3/2 log x = 3 z + z^3 + z^3 (z^2 R(z^2))
Packit 6c4009
   z = (x-1)/(x+1)
Packit 6c4009
   1 <= x <= 1.25
Packit 6c4009
   Peak relative error 2.3e-37 */
Packit 6c4009
static const _Float128 LN[] =
Packit 6c4009
{
Packit 6c4009
 L(-3.0779177200290054398792536829702930623200E1),
Packit 6c4009
  L(6.5135778082209159921251824580292116201640E1),
Packit 6c4009
 L(-4.6312921812152436921591152809994014413540E1),
Packit 6c4009
  L(1.2510208195629420304615674658258363295208E1),
Packit 6c4009
 L(-9.9266909031921425609179910128531667336670E-1)
Packit 6c4009
};
Packit 6c4009
static const _Float128 LD[] =
Packit 6c4009
{
Packit 6c4009
 L(-5.129862866715009066465422805058933131960E1),
Packit 6c4009
  L(1.452015077564081884387441590064272782044E2),
Packit 6c4009
 L(-1.524043275549860505277434040464085593165E2),
Packit 6c4009
  L(7.236063513651544224319663428634139768808E1),
Packit 6c4009
 L(-1.494198912340228235853027849917095580053E1)
Packit 6c4009
  /* 1.0E0 */
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
/* exp(x) = 1 + x - x / (1 - 2 / (x - x^2 R(x^2)))
Packit 6c4009
   0 <= x <= 0.5
Packit 6c4009
   Peak relative error 5.7e-38  */
Packit 6c4009
static const _Float128 PN[] =
Packit 6c4009
{
Packit 6c4009
  L(5.081801691915377692446852383385968225675E8),
Packit 6c4009
  L(9.360895299872484512023336636427675327355E6),
Packit 6c4009
  L(4.213701282274196030811629773097579432957E4),
Packit 6c4009
  L(5.201006511142748908655720086041570288182E1),
Packit 6c4009
  L(9.088368420359444263703202925095675982530E-3),
Packit 6c4009
};
Packit 6c4009
static const _Float128 PD[] =
Packit 6c4009
{
Packit 6c4009
  L(3.049081015149226615468111430031590411682E9),
Packit 6c4009
  L(1.069833887183886839966085436512368982758E8),
Packit 6c4009
  L(8.259257717868875207333991924545445705394E5),
Packit 6c4009
  L(1.872583833284143212651746812884298360922E3),
Packit 6c4009
  /* 1.0E0 */
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
static const _Float128
Packit 6c4009
  /* ln 2 */
Packit 6c4009
  lg2 = L(6.9314718055994530941723212145817656807550E-1),
Packit 6c4009
  lg2_h = L(6.9314718055994528622676398299518041312695E-1),
Packit 6c4009
  lg2_l = L(2.3190468138462996154948554638754786504121E-17),
Packit 6c4009
  ovt = L(8.0085662595372944372e-0017),
Packit 6c4009
  /* 2/(3*log(2)) */
Packit 6c4009
  cp = L(9.6179669392597560490661645400126142495110E-1),
Packit 6c4009
  cp_h = L(9.6179669392597555432899980587535537779331E-1),
Packit 6c4009
  cp_l = L(5.0577616648125906047157785230014751039424E-17);
Packit 6c4009
Packit 6c4009
_Float128
Packit 6c4009
__ieee754_powl (_Float128 x, _Float128 y)
Packit 6c4009
{
Packit 6c4009
  _Float128 z, ax, z_h, z_l, p_h, p_l;
Packit 6c4009
  _Float128 y1, t1, t2, r, s, sgn, t, u, v, w;
Packit 6c4009
  _Float128 s2, s_h, s_l, t_h, t_l, ay;
Packit 6c4009
  int32_t i, j, k, yisint, n;
Packit 6c4009
  uint32_t ix, iy;
Packit 6c4009
  int32_t hx, hy;
Packit 6c4009
  ieee854_long_double_shape_type o, p, q;
Packit 6c4009
Packit 6c4009
  p.value = x;
Packit 6c4009
  hx = p.parts32.w0;
Packit 6c4009
  ix = hx & 0x7fffffff;
Packit 6c4009
Packit 6c4009
  q.value = y;
Packit 6c4009
  hy = q.parts32.w0;
Packit 6c4009
  iy = hy & 0x7fffffff;
Packit 6c4009
Packit 6c4009
Packit 6c4009
  /* y==zero: x**0 = 1 */
Packit 6c4009
  if ((iy | q.parts32.w1 | q.parts32.w2 | q.parts32.w3) == 0
Packit 6c4009
      && !issignaling (x))
Packit 6c4009
    return one;
Packit 6c4009
Packit 6c4009
  /* 1.0**y = 1; -1.0**+-Inf = 1 */
Packit 6c4009
  if (x == one && !issignaling (y))
Packit 6c4009
    return one;
Packit 6c4009
  if (x == -1 && iy == 0x7fff0000
Packit 6c4009
      && (q.parts32.w1 | q.parts32.w2 | q.parts32.w3) == 0)
Packit 6c4009
    return one;
Packit 6c4009
Packit 6c4009
  /* +-NaN return x+y */
Packit 6c4009
  if ((ix > 0x7fff0000)
Packit 6c4009
      || ((ix == 0x7fff0000)
Packit 6c4009
	  && ((p.parts32.w1 | p.parts32.w2 | p.parts32.w3) != 0))
Packit 6c4009
      || (iy > 0x7fff0000)
Packit 6c4009
      || ((iy == 0x7fff0000)
Packit 6c4009
	  && ((q.parts32.w1 | q.parts32.w2 | q.parts32.w3) != 0)))
Packit 6c4009
    return x + y;
Packit 6c4009
Packit 6c4009
  /* determine if y is an odd int when x < 0
Packit 6c4009
   * yisint = 0       ... y is not an integer
Packit 6c4009
   * yisint = 1       ... y is an odd int
Packit 6c4009
   * yisint = 2       ... y is an even int
Packit 6c4009
   */
Packit 6c4009
  yisint = 0;
Packit 6c4009
  if (hx < 0)
Packit 6c4009
    {
Packit 6c4009
      if (iy >= 0x40700000)	/* 2^113 */
Packit 6c4009
	yisint = 2;		/* even integer y */
Packit 6c4009
      else if (iy >= 0x3fff0000)	/* 1.0 */
Packit 6c4009
	{
Packit 6c4009
	  if (__floorl (y) == y)
Packit 6c4009
	    {
Packit 6c4009
	      z = 0.5 * y;
Packit 6c4009
	      if (__floorl (z) == z)
Packit 6c4009
		yisint = 2;
Packit 6c4009
	      else
Packit 6c4009
		yisint = 1;
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* special value of y */
Packit 6c4009
  if ((q.parts32.w1 | q.parts32.w2 | q.parts32.w3) == 0)
Packit 6c4009
    {
Packit 6c4009
      if (iy == 0x7fff0000)	/* y is +-inf */
Packit 6c4009
	{
Packit 6c4009
	  if (((ix - 0x3fff0000) | p.parts32.w1 | p.parts32.w2 | p.parts32.w3)
Packit 6c4009
	      == 0)
Packit 6c4009
	    return y - y;	/* +-1**inf is NaN */
Packit 6c4009
	  else if (ix >= 0x3fff0000)	/* (|x|>1)**+-inf = inf,0 */
Packit 6c4009
	    return (hy >= 0) ? y : zero;
Packit 6c4009
	  else			/* (|x|<1)**-,+inf = inf,0 */
Packit 6c4009
	    return (hy < 0) ? -y : zero;
Packit 6c4009
	}
Packit 6c4009
      if (iy == 0x3fff0000)
Packit 6c4009
	{			/* y is  +-1 */
Packit 6c4009
	  if (hy < 0)
Packit 6c4009
	    return one / x;
Packit 6c4009
	  else
Packit 6c4009
	    return x;
Packit 6c4009
	}
Packit 6c4009
      if (hy == 0x40000000)
Packit 6c4009
	return x * x;		/* y is  2 */
Packit 6c4009
      if (hy == 0x3ffe0000)
Packit 6c4009
	{			/* y is  0.5 */
Packit 6c4009
	  if (hx >= 0)		/* x >= +0 */
Packit 6c4009
	    return sqrtl (x);
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  ax = fabsl (x);
Packit 6c4009
  /* special value of x */
Packit 6c4009
  if ((p.parts32.w1 | p.parts32.w2 | p.parts32.w3) == 0)
Packit 6c4009
    {
Packit 6c4009
      if (ix == 0x7fff0000 || ix == 0 || ix == 0x3fff0000)
Packit 6c4009
	{
Packit 6c4009
	  z = ax;		/*x is +-0,+-inf,+-1 */
Packit 6c4009
	  if (hy < 0)
Packit 6c4009
	    z = one / z;	/* z = (1/|x|) */
Packit 6c4009
	  if (hx < 0)
Packit 6c4009
	    {
Packit 6c4009
	      if (((ix - 0x3fff0000) | yisint) == 0)
Packit 6c4009
		{
Packit 6c4009
		  z = (z - z) / (z - z);	/* (-1)**non-int is NaN */
Packit 6c4009
		}
Packit 6c4009
	      else if (yisint == 1)
Packit 6c4009
		z = -z;		/* (x<0)**odd = -(|x|**odd) */
Packit 6c4009
	    }
Packit 6c4009
	  return z;
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* (x<0)**(non-int) is NaN */
Packit 6c4009
  if (((((uint32_t) hx >> 31) - 1) | yisint) == 0)
Packit 6c4009
    return (x - x) / (x - x);
Packit 6c4009
Packit 6c4009
  /* sgn (sign of result -ve**odd) = -1 else = 1 */
Packit 6c4009
  sgn = one;
Packit 6c4009
  if (((((uint32_t) hx >> 31) - 1) | (yisint - 1)) == 0)
Packit 6c4009
    sgn = -one;			/* (-ve)**(odd int) */
Packit 6c4009
Packit 6c4009
  /* |y| is huge.
Packit 6c4009
     2^-16495 = 1/2 of smallest representable value.
Packit 6c4009
     If (1 - 1/131072)^y underflows, y > 1.4986e9 */
Packit 6c4009
  if (iy > 0x401d654b)
Packit 6c4009
    {
Packit 6c4009
      /* if (1 - 2^-113)^y underflows, y > 1.1873e38 */
Packit 6c4009
      if (iy > 0x407d654b)
Packit 6c4009
	{
Packit 6c4009
	  if (ix <= 0x3ffeffff)
Packit 6c4009
	    return (hy < 0) ? huge * huge : tiny * tiny;
Packit 6c4009
	  if (ix >= 0x3fff0000)
Packit 6c4009
	    return (hy > 0) ? huge * huge : tiny * tiny;
Packit 6c4009
	}
Packit 6c4009
      /* over/underflow if x is not close to one */
Packit 6c4009
      if (ix < 0x3ffeffff)
Packit 6c4009
	return (hy < 0) ? sgn * huge * huge : sgn * tiny * tiny;
Packit 6c4009
      if (ix > 0x3fff0000)
Packit 6c4009
	return (hy > 0) ? sgn * huge * huge : sgn * tiny * tiny;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  ay = y > 0 ? y : -y;
Packit 6c4009
  if (ay < 0x1p-128)
Packit 6c4009
    y = y < 0 ? -0x1p-128 : 0x1p-128;
Packit 6c4009
Packit 6c4009
  n = 0;
Packit 6c4009
  /* take care subnormal number */
Packit 6c4009
  if (ix < 0x00010000)
Packit 6c4009
    {
Packit 6c4009
      ax *= two113;
Packit 6c4009
      n -= 113;
Packit 6c4009
      o.value = ax;
Packit 6c4009
      ix = o.parts32.w0;
Packit 6c4009
    }
Packit 6c4009
  n += ((ix) >> 16) - 0x3fff;
Packit 6c4009
  j = ix & 0x0000ffff;
Packit 6c4009
  /* determine interval */
Packit 6c4009
  ix = j | 0x3fff0000;		/* normalize ix */
Packit 6c4009
  if (j <= 0x3988)
Packit 6c4009
    k = 0;			/* |x|
Packit 6c4009
  else if (j < 0xbb67)
Packit 6c4009
    k = 1;			/* |x|
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      k = 0;
Packit 6c4009
      n += 1;
Packit 6c4009
      ix -= 0x00010000;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  o.value = ax;
Packit 6c4009
  o.parts32.w0 = ix;
Packit 6c4009
  ax = o.value;
Packit 6c4009
Packit 6c4009
  /* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
Packit 6c4009
  u = ax - bp[k];		/* bp[0]=1.0, bp[1]=1.5 */
Packit 6c4009
  v = one / (ax + bp[k]);
Packit 6c4009
  s = u * v;
Packit 6c4009
  s_h = s;
Packit 6c4009
Packit 6c4009
  o.value = s_h;
Packit 6c4009
  o.parts32.w3 = 0;
Packit 6c4009
  o.parts32.w2 &= 0xf8000000;
Packit 6c4009
  s_h = o.value;
Packit 6c4009
  /* t_h=ax+bp[k] High */
Packit 6c4009
  t_h = ax + bp[k];
Packit 6c4009
  o.value = t_h;
Packit 6c4009
  o.parts32.w3 = 0;
Packit 6c4009
  o.parts32.w2 &= 0xf8000000;
Packit 6c4009
  t_h = o.value;
Packit 6c4009
  t_l = ax - (t_h - bp[k]);
Packit 6c4009
  s_l = v * ((u - s_h * t_h) - s_h * t_l);
Packit 6c4009
  /* compute log(ax) */
Packit 6c4009
  s2 = s * s;
Packit 6c4009
  u = LN[0] + s2 * (LN[1] + s2 * (LN[2] + s2 * (LN[3] + s2 * LN[4])));
Packit 6c4009
  v = LD[0] + s2 * (LD[1] + s2 * (LD[2] + s2 * (LD[3] + s2 * (LD[4] + s2))));
Packit 6c4009
  r = s2 * s2 * u / v;
Packit 6c4009
  r += s_l * (s_h + s);
Packit 6c4009
  s2 = s_h * s_h;
Packit 6c4009
  t_h = 3.0 + s2 + r;
Packit 6c4009
  o.value = t_h;
Packit 6c4009
  o.parts32.w3 = 0;
Packit 6c4009
  o.parts32.w2 &= 0xf8000000;
Packit 6c4009
  t_h = o.value;
Packit 6c4009
  t_l = r - ((t_h - 3.0) - s2);
Packit 6c4009
  /* u+v = s*(1+...) */
Packit 6c4009
  u = s_h * t_h;
Packit 6c4009
  v = s_l * t_h + t_l * s;
Packit 6c4009
  /* 2/(3log2)*(s+...) */
Packit 6c4009
  p_h = u + v;
Packit 6c4009
  o.value = p_h;
Packit 6c4009
  o.parts32.w3 = 0;
Packit 6c4009
  o.parts32.w2 &= 0xf8000000;
Packit 6c4009
  p_h = o.value;
Packit 6c4009
  p_l = v - (p_h - u);
Packit 6c4009
  z_h = cp_h * p_h;		/* cp_h+cp_l = 2/(3*log2) */
Packit 6c4009
  z_l = cp_l * p_h + p_l * cp + dp_l[k];
Packit 6c4009
  /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */
Packit 6c4009
  t = (_Float128) n;
Packit 6c4009
  t1 = (((z_h + z_l) + dp_h[k]) + t);
Packit 6c4009
  o.value = t1;
Packit 6c4009
  o.parts32.w3 = 0;
Packit 6c4009
  o.parts32.w2 &= 0xf8000000;
Packit 6c4009
  t1 = o.value;
Packit 6c4009
  t2 = z_l - (((t1 - t) - dp_h[k]) - z_h);
Packit 6c4009
Packit 6c4009
  /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
Packit 6c4009
  y1 = y;
Packit 6c4009
  o.value = y1;
Packit 6c4009
  o.parts32.w3 = 0;
Packit 6c4009
  o.parts32.w2 &= 0xf8000000;
Packit 6c4009
  y1 = o.value;
Packit 6c4009
  p_l = (y - y1) * t1 + y * t2;
Packit 6c4009
  p_h = y1 * t1;
Packit 6c4009
  z = p_l + p_h;
Packit 6c4009
  o.value = z;
Packit 6c4009
  j = o.parts32.w0;
Packit 6c4009
  if (j >= 0x400d0000) /* z >= 16384 */
Packit 6c4009
    {
Packit 6c4009
      /* if z > 16384 */
Packit 6c4009
      if (((j - 0x400d0000) | o.parts32.w1 | o.parts32.w2 | o.parts32.w3) != 0)
Packit 6c4009
	return sgn * huge * huge;	/* overflow */
Packit 6c4009
      else
Packit 6c4009
	{
Packit 6c4009
	  if (p_l + ovt > z - p_h)
Packit 6c4009
	    return sgn * huge * huge;	/* overflow */
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
  else if ((j & 0x7fffffff) >= 0x400d01b9)	/* z <= -16495 */
Packit 6c4009
    {
Packit 6c4009
      /* z < -16495 */
Packit 6c4009
      if (((j - 0xc00d01bc) | o.parts32.w1 | o.parts32.w2 | o.parts32.w3)
Packit 6c4009
	  != 0)
Packit 6c4009
	return sgn * tiny * tiny;	/* underflow */
Packit 6c4009
      else
Packit 6c4009
	{
Packit 6c4009
	  if (p_l <= z - p_h)
Packit 6c4009
	    return sgn * tiny * tiny;	/* underflow */
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
  /* compute 2**(p_h+p_l) */
Packit 6c4009
  i = j & 0x7fffffff;
Packit 6c4009
  k = (i >> 16) - 0x3fff;
Packit 6c4009
  n = 0;
Packit 6c4009
  if (i > 0x3ffe0000)
Packit 6c4009
    {				/* if |z| > 0.5, set n = [z+0.5] */
Packit 6c4009
      n = __floorl (z + L(0.5));
Packit 6c4009
      t = n;
Packit 6c4009
      p_h -= t;
Packit 6c4009
    }
Packit 6c4009
  t = p_l + p_h;
Packit 6c4009
  o.value = t;
Packit 6c4009
  o.parts32.w3 = 0;
Packit 6c4009
  o.parts32.w2 &= 0xf8000000;
Packit 6c4009
  t = o.value;
Packit 6c4009
  u = t * lg2_h;
Packit 6c4009
  v = (p_l - (t - p_h)) * lg2 + t * lg2_l;
Packit 6c4009
  z = u + v;
Packit 6c4009
  w = v - (z - u);
Packit 6c4009
  /*  exp(z) */
Packit 6c4009
  t = z * z;
Packit 6c4009
  u = PN[0] + t * (PN[1] + t * (PN[2] + t * (PN[3] + t * PN[4])));
Packit 6c4009
  v = PD[0] + t * (PD[1] + t * (PD[2] + t * (PD[3] + t)));
Packit 6c4009
  t1 = z - t * u / v;
Packit 6c4009
  r = (z * t1) / (t1 - two) - (w + z * w);
Packit 6c4009
  z = one - (r - z);
Packit 6c4009
  o.value = z;
Packit 6c4009
  j = o.parts32.w0;
Packit 6c4009
  j += (n << 16);
Packit 6c4009
  if ((j >> 16) <= 0)
Packit 6c4009
    {
Packit 6c4009
      z = __scalbnl (z, n);	/* subnormal output */
Packit 6c4009
      _Float128 force_underflow = z * z;
Packit 6c4009
      math_force_eval (force_underflow);
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      o.parts32.w0 = j;
Packit 6c4009
      z = o.value;
Packit 6c4009
    }
Packit 6c4009
  return sgn * z;
Packit 6c4009
}
Packit 6c4009
strong_alias (__ieee754_powl, __powl_finite)