xref: /freebsd-src/lib/msun/ld80/e_powl.c (revision 0c00dbfeb0c814c3a87a4d490db3692c1f9441e9)
16813d08fSMatt Macy /*-
26813d08fSMatt Macy  * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
36813d08fSMatt Macy  *
46813d08fSMatt Macy  * Permission to use, copy, modify, and distribute this software for any
56813d08fSMatt Macy  * purpose with or without fee is hereby granted, provided that the above
66813d08fSMatt Macy  * copyright notice and this permission notice appear in all copies.
76813d08fSMatt Macy  *
86813d08fSMatt Macy  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
96813d08fSMatt Macy  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
106813d08fSMatt Macy  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
116813d08fSMatt Macy  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
126813d08fSMatt Macy  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
136813d08fSMatt Macy  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
146813d08fSMatt Macy  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
156813d08fSMatt Macy  */
166813d08fSMatt Macy 
175a4c3b83SDimitry Andric #include <math.h>
185a4c3b83SDimitry Andric 
195a4c3b83SDimitry Andric #include "math_private.h"
205a4c3b83SDimitry Andric 
215a4c3b83SDimitry Andric /*
225a4c3b83SDimitry Andric  * Polynomial evaluator:
235a4c3b83SDimitry Andric  *  P[0] x^n  +  P[1] x^(n-1)  +  ...  +  P[n]
245a4c3b83SDimitry Andric  */
255a4c3b83SDimitry Andric static inline long double
2610ac6c48SKonstantin Belousov __polevll(long double x, const long double *PP, int n)
275a4c3b83SDimitry Andric {
285a4c3b83SDimitry Andric 	long double y;
2910ac6c48SKonstantin Belousov 	const long double *P;
305a4c3b83SDimitry Andric 
315a4c3b83SDimitry Andric 	P = PP;
325a4c3b83SDimitry Andric 	y = *P++;
335a4c3b83SDimitry Andric 	do {
345a4c3b83SDimitry Andric 		y = y * x + *P++;
355a4c3b83SDimitry Andric 	} while (--n);
365a4c3b83SDimitry Andric 
375a4c3b83SDimitry Andric 	return (y);
385a4c3b83SDimitry Andric }
395a4c3b83SDimitry Andric 
405a4c3b83SDimitry Andric /*
415a4c3b83SDimitry Andric  * Polynomial evaluator:
425a4c3b83SDimitry Andric  *  x^n  +  P[0] x^(n-1)  +  P[1] x^(n-2)  +  ...  +  P[n]
435a4c3b83SDimitry Andric  */
445a4c3b83SDimitry Andric static inline long double
4510ac6c48SKonstantin Belousov __p1evll(long double x, const long double *PP, int n)
465a4c3b83SDimitry Andric {
475a4c3b83SDimitry Andric 	long double y;
4810ac6c48SKonstantin Belousov 	const long double *P;
495a4c3b83SDimitry Andric 
505a4c3b83SDimitry Andric 	P = PP;
515a4c3b83SDimitry Andric 	n -= 1;
525a4c3b83SDimitry Andric 	y = x + *P++;
535a4c3b83SDimitry Andric 	do {
545a4c3b83SDimitry Andric 		y = y * x + *P++;
555a4c3b83SDimitry Andric 	} while (--n);
565a4c3b83SDimitry Andric 
575a4c3b83SDimitry Andric 	return (y);
585a4c3b83SDimitry Andric }
595a4c3b83SDimitry Andric 
606813d08fSMatt Macy /*							powl.c
616813d08fSMatt Macy  *
626813d08fSMatt Macy  *	Power function, long double precision
636813d08fSMatt Macy  *
646813d08fSMatt Macy  *
656813d08fSMatt Macy  *
666813d08fSMatt Macy  * SYNOPSIS:
676813d08fSMatt Macy  *
686813d08fSMatt Macy  * long double x, y, z, powl();
696813d08fSMatt Macy  *
706813d08fSMatt Macy  * z = powl( x, y );
716813d08fSMatt Macy  *
726813d08fSMatt Macy  *
736813d08fSMatt Macy  *
746813d08fSMatt Macy  * DESCRIPTION:
756813d08fSMatt Macy  *
766813d08fSMatt Macy  * Computes x raised to the yth power.  Analytically,
776813d08fSMatt Macy  *
786813d08fSMatt Macy  *      x**y  =  exp( y log(x) ).
796813d08fSMatt Macy  *
806813d08fSMatt Macy  * Following Cody and Waite, this program uses a lookup table
816813d08fSMatt Macy  * of 2**-i/32 and pseudo extended precision arithmetic to
826813d08fSMatt Macy  * obtain several extra bits of accuracy in both the logarithm
836813d08fSMatt Macy  * and the exponential.
846813d08fSMatt Macy  *
856813d08fSMatt Macy  *
866813d08fSMatt Macy  *
876813d08fSMatt Macy  * ACCURACY:
886813d08fSMatt Macy  *
896813d08fSMatt Macy  * The relative error of pow(x,y) can be estimated
906813d08fSMatt Macy  * by   y dl ln(2),   where dl is the absolute error of
916813d08fSMatt Macy  * the internally computed base 2 logarithm.  At the ends
926813d08fSMatt Macy  * of the approximation interval the logarithm equal 1/32
936813d08fSMatt Macy  * and its relative error is about 1 lsb = 1.1e-19.  Hence
946813d08fSMatt Macy  * the predicted relative error in the result is 2.3e-21 y .
956813d08fSMatt Macy  *
966813d08fSMatt Macy  *                      Relative error:
976813d08fSMatt Macy  * arithmetic   domain     # trials      peak         rms
986813d08fSMatt Macy  *
996813d08fSMatt Macy  *    IEEE     +-1000       40000      2.8e-18      3.7e-19
1006813d08fSMatt Macy  * .001 < x < 1000, with log(x) uniformly distributed.
1016813d08fSMatt Macy  * -1000 < y < 1000, y uniformly distributed.
1026813d08fSMatt Macy  *
1036813d08fSMatt Macy  *    IEEE     0,8700       60000      6.5e-18      1.0e-18
1046813d08fSMatt Macy  * 0.99 < x < 1.01, 0 < y < 8700, uniformly distributed.
1056813d08fSMatt Macy  *
1066813d08fSMatt Macy  *
1076813d08fSMatt Macy  * ERROR MESSAGES:
1086813d08fSMatt Macy  *
1096813d08fSMatt Macy  *   message         condition      value returned
1106813d08fSMatt Macy  * pow overflow     x**y > MAXNUM      INFINITY
1116813d08fSMatt Macy  * pow underflow   x**y < 1/MAXNUM       0.0
1126813d08fSMatt Macy  * pow domain      x<0 and y noninteger  0.0
1136813d08fSMatt Macy  *
1146813d08fSMatt Macy  */
1156813d08fSMatt Macy 
1166813d08fSMatt Macy #include <float.h>
1176813d08fSMatt Macy #include <math.h>
1186813d08fSMatt Macy 
1196813d08fSMatt Macy #include "math_private.h"
1206813d08fSMatt Macy 
1216813d08fSMatt Macy /* Table size */
1226813d08fSMatt Macy #define NXT 32
1236813d08fSMatt Macy /* log2(Table size) */
1246813d08fSMatt Macy #define LNXT 5
1256813d08fSMatt Macy 
1266813d08fSMatt Macy /* log(1+x) =  x - .5x^2 + x^3 *  P(z)/Q(z)
1276813d08fSMatt Macy  * on the domain  2^(-1/32) - 1  <=  x  <=  2^(1/32) - 1
1286813d08fSMatt Macy  */
12910ac6c48SKonstantin Belousov static const long double P[] = {
1306813d08fSMatt Macy  8.3319510773868690346226E-4L,
1316813d08fSMatt Macy  4.9000050881978028599627E-1L,
1326813d08fSMatt Macy  1.7500123722550302671919E0L,
1336813d08fSMatt Macy  1.4000100839971580279335E0L,
1346813d08fSMatt Macy };
13510ac6c48SKonstantin Belousov static const long double Q[] = {
1366813d08fSMatt Macy /* 1.0000000000000000000000E0L,*/
1376813d08fSMatt Macy  5.2500282295834889175431E0L,
1386813d08fSMatt Macy  8.4000598057587009834666E0L,
1396813d08fSMatt Macy  4.2000302519914740834728E0L,
1406813d08fSMatt Macy };
1416813d08fSMatt Macy /* A[i] = 2^(-i/32), rounded to IEEE long double precision.
1426813d08fSMatt Macy  * If i is even, A[i] + B[i/2] gives additional accuracy.
1436813d08fSMatt Macy  */
14410ac6c48SKonstantin Belousov static const long double A[33] = {
1456813d08fSMatt Macy  1.0000000000000000000000E0L,
1466813d08fSMatt Macy  9.7857206208770013448287E-1L,
1476813d08fSMatt Macy  9.5760328069857364691013E-1L,
1486813d08fSMatt Macy  9.3708381705514995065011E-1L,
1496813d08fSMatt Macy  9.1700404320467123175367E-1L,
1506813d08fSMatt Macy  8.9735453750155359320742E-1L,
1516813d08fSMatt Macy  8.7812608018664974155474E-1L,
1526813d08fSMatt Macy  8.5930964906123895780165E-1L,
1536813d08fSMatt Macy  8.4089641525371454301892E-1L,
1546813d08fSMatt Macy  8.2287773907698242225554E-1L,
1556813d08fSMatt Macy  8.0524516597462715409607E-1L,
1566813d08fSMatt Macy  7.8799042255394324325455E-1L,
1576813d08fSMatt Macy  7.7110541270397041179298E-1L,
1586813d08fSMatt Macy  7.5458221379671136985669E-1L,
1596813d08fSMatt Macy  7.3841307296974965571198E-1L,
1606813d08fSMatt Macy  7.2259040348852331001267E-1L,
1616813d08fSMatt Macy  7.0710678118654752438189E-1L,
1626813d08fSMatt Macy  6.9195494098191597746178E-1L,
1636813d08fSMatt Macy  6.7712777346844636413344E-1L,
1646813d08fSMatt Macy  6.6261832157987064729696E-1L,
1656813d08fSMatt Macy  6.4841977732550483296079E-1L,
1666813d08fSMatt Macy  6.3452547859586661129850E-1L,
1676813d08fSMatt Macy  6.2092890603674202431705E-1L,
1686813d08fSMatt Macy  6.0762367999023443907803E-1L,
1696813d08fSMatt Macy  5.9460355750136053334378E-1L,
1706813d08fSMatt Macy  5.8186242938878875689693E-1L,
1716813d08fSMatt Macy  5.6939431737834582684856E-1L,
1726813d08fSMatt Macy  5.5719337129794626814472E-1L,
1736813d08fSMatt Macy  5.4525386633262882960438E-1L,
1746813d08fSMatt Macy  5.3357020033841180906486E-1L,
1756813d08fSMatt Macy  5.2213689121370692017331E-1L,
1766813d08fSMatt Macy  5.1094857432705833910408E-1L,
1776813d08fSMatt Macy  5.0000000000000000000000E-1L,
1786813d08fSMatt Macy };
17910ac6c48SKonstantin Belousov static const long double B[17] = {
1806813d08fSMatt Macy  0.0000000000000000000000E0L,
1816813d08fSMatt Macy  2.6176170809902549338711E-20L,
1826813d08fSMatt Macy -1.0126791927256478897086E-20L,
1836813d08fSMatt Macy  1.3438228172316276937655E-21L,
1846813d08fSMatt Macy  1.2207982955417546912101E-20L,
1856813d08fSMatt Macy -6.3084814358060867200133E-21L,
1866813d08fSMatt Macy  1.3164426894366316434230E-20L,
1876813d08fSMatt Macy -1.8527916071632873716786E-20L,
1886813d08fSMatt Macy  1.8950325588932570796551E-20L,
1896813d08fSMatt Macy  1.5564775779538780478155E-20L,
1906813d08fSMatt Macy  6.0859793637556860974380E-21L,
1916813d08fSMatt Macy -2.0208749253662532228949E-20L,
1926813d08fSMatt Macy  1.4966292219224761844552E-20L,
1936813d08fSMatt Macy  3.3540909728056476875639E-21L,
1946813d08fSMatt Macy -8.6987564101742849540743E-22L,
1956813d08fSMatt Macy -1.2327176863327626135542E-20L,
1966813d08fSMatt Macy  0.0000000000000000000000E0L,
1976813d08fSMatt Macy };
1986813d08fSMatt Macy 
1996813d08fSMatt Macy /* 2^x = 1 + x P(x),
2006813d08fSMatt Macy  * on the interval -1/32 <= x <= 0
2016813d08fSMatt Macy  */
20210ac6c48SKonstantin Belousov static const long double R[] = {
2036813d08fSMatt Macy  1.5089970579127659901157E-5L,
2046813d08fSMatt Macy  1.5402715328927013076125E-4L,
2056813d08fSMatt Macy  1.3333556028915671091390E-3L,
2066813d08fSMatt Macy  9.6181291046036762031786E-3L,
2076813d08fSMatt Macy  5.5504108664798463044015E-2L,
2086813d08fSMatt Macy  2.4022650695910062854352E-1L,
2096813d08fSMatt Macy  6.9314718055994530931447E-1L,
2106813d08fSMatt Macy };
2116813d08fSMatt Macy 
2126813d08fSMatt Macy #define douba(k) A[k]
2136813d08fSMatt Macy #define doubb(k) B[k]
2146813d08fSMatt Macy #define MEXP (NXT*16384.0L)
2156813d08fSMatt Macy /* The following if denormal numbers are supported, else -MEXP: */
2166813d08fSMatt Macy #define MNEXP (-NXT*(16384.0L+64.0L))
2176813d08fSMatt Macy /* log2(e) - 1 */
2186813d08fSMatt Macy #define LOG2EA 0.44269504088896340735992L
2196813d08fSMatt Macy 
2206813d08fSMatt Macy #define F W
2216813d08fSMatt Macy #define Fa Wa
2226813d08fSMatt Macy #define Fb Wb
2236813d08fSMatt Macy #define G W
2246813d08fSMatt Macy #define Ga Wa
2256813d08fSMatt Macy #define Gb u
2266813d08fSMatt Macy #define H W
2276813d08fSMatt Macy #define Ha Wb
2286813d08fSMatt Macy #define Hb Wb
2296813d08fSMatt Macy 
2306813d08fSMatt Macy static const long double MAXLOGL = 1.1356523406294143949492E4L;
2316813d08fSMatt Macy static const long double MINLOGL = -1.13994985314888605586758E4L;
2326813d08fSMatt Macy static const long double LOGE2L = 6.9314718055994530941723E-1L;
233*0c00dbfeSKonstantin Belousov static _Thread_local volatile long double z;
234*0c00dbfeSKonstantin Belousov static _Thread_local long double w, W, Wa, Wb, ya, yb, u;
2356813d08fSMatt Macy static const long double huge = 0x1p10000L;
2366813d08fSMatt Macy #if 0 /* XXX Prevent gcc from erroneously constant folding this. */
2376813d08fSMatt Macy static const long double twom10000 = 0x1p-10000L;
2386813d08fSMatt Macy #else
239*0c00dbfeSKonstantin Belousov static _Thread_local volatile long double twom10000 = 0x1p-10000L;
2406813d08fSMatt Macy #endif
2416813d08fSMatt Macy 
2426813d08fSMatt Macy static long double reducl( long double );
2436813d08fSMatt Macy static long double powil ( long double, int );
2446813d08fSMatt Macy 
2456813d08fSMatt Macy long double
2466813d08fSMatt Macy powl(long double x, long double y)
2476813d08fSMatt Macy {
2486813d08fSMatt Macy /* double F, Fa, Fb, G, Ga, Gb, H, Ha, Hb */
2496813d08fSMatt Macy int i, nflg, iyflg, yoddint;
2506813d08fSMatt Macy long e;
2516813d08fSMatt Macy 
2526813d08fSMatt Macy if( y == 0.0L )
2536813d08fSMatt Macy 	return( 1.0L );
2546813d08fSMatt Macy 
2556813d08fSMatt Macy if( x == 1.0L )
2566813d08fSMatt Macy 	return( 1.0L );
2576813d08fSMatt Macy 
2586813d08fSMatt Macy if( isnan(x) )
2596f1b8a07SBruce Evans 	return ( nan_mix(x, y) );
2606813d08fSMatt Macy if( isnan(y) )
2616f1b8a07SBruce Evans 	return ( nan_mix(x, y) );
2626813d08fSMatt Macy 
2636813d08fSMatt Macy if( y == 1.0L )
2646813d08fSMatt Macy 	return( x );
2656813d08fSMatt Macy 
2666813d08fSMatt Macy if( !isfinite(y) && x == -1.0L )
2676813d08fSMatt Macy 	return( 1.0L );
2686813d08fSMatt Macy 
2696813d08fSMatt Macy if( y >= LDBL_MAX )
2706813d08fSMatt Macy 	{
2716813d08fSMatt Macy 	if( x > 1.0L )
2726813d08fSMatt Macy 		return( INFINITY );
2736813d08fSMatt Macy 	if( x > 0.0L && x < 1.0L )
2746813d08fSMatt Macy 		return( 0.0L );
2756813d08fSMatt Macy 	if( x < -1.0L )
2766813d08fSMatt Macy 		return( INFINITY );
2776813d08fSMatt Macy 	if( x > -1.0L && x < 0.0L )
2786813d08fSMatt Macy 		return( 0.0L );
2796813d08fSMatt Macy 	}
2806813d08fSMatt Macy if( y <= -LDBL_MAX )
2816813d08fSMatt Macy 	{
2826813d08fSMatt Macy 	if( x > 1.0L )
2836813d08fSMatt Macy 		return( 0.0L );
2846813d08fSMatt Macy 	if( x > 0.0L && x < 1.0L )
2856813d08fSMatt Macy 		return( INFINITY );
2866813d08fSMatt Macy 	if( x < -1.0L )
2876813d08fSMatt Macy 		return( 0.0L );
2886813d08fSMatt Macy 	if( x > -1.0L && x < 0.0L )
2896813d08fSMatt Macy 		return( INFINITY );
2906813d08fSMatt Macy 	}
2916813d08fSMatt Macy if( x >= LDBL_MAX )
2926813d08fSMatt Macy 	{
2936813d08fSMatt Macy 	if( y > 0.0L )
2946813d08fSMatt Macy 		return( INFINITY );
2956813d08fSMatt Macy 	return( 0.0L );
2966813d08fSMatt Macy 	}
2976813d08fSMatt Macy 
2986813d08fSMatt Macy w = floorl(y);
2996813d08fSMatt Macy /* Set iyflg to 1 if y is an integer.  */
3006813d08fSMatt Macy iyflg = 0;
3016813d08fSMatt Macy if( w == y )
3026813d08fSMatt Macy 	iyflg = 1;
3036813d08fSMatt Macy 
3046813d08fSMatt Macy /* Test for odd integer y.  */
3056813d08fSMatt Macy yoddint = 0;
3066813d08fSMatt Macy if( iyflg )
3076813d08fSMatt Macy 	{
3086813d08fSMatt Macy 	ya = fabsl(y);
3096813d08fSMatt Macy 	ya = floorl(0.5L * ya);
3106813d08fSMatt Macy 	yb = 0.5L * fabsl(w);
3116813d08fSMatt Macy 	if( ya != yb )
3126813d08fSMatt Macy 		yoddint = 1;
3136813d08fSMatt Macy 	}
3146813d08fSMatt Macy 
3156813d08fSMatt Macy if( x <= -LDBL_MAX )
3166813d08fSMatt Macy 	{
3176813d08fSMatt Macy 	if( y > 0.0L )
3186813d08fSMatt Macy 		{
3196813d08fSMatt Macy 		if( yoddint )
3206813d08fSMatt Macy 			return( -INFINITY );
3216813d08fSMatt Macy 		return( INFINITY );
3226813d08fSMatt Macy 		}
3236813d08fSMatt Macy 	if( y < 0.0L )
3246813d08fSMatt Macy 		{
3256813d08fSMatt Macy 		if( yoddint )
3266813d08fSMatt Macy 			return( -0.0L );
3276813d08fSMatt Macy 		return( 0.0 );
3286813d08fSMatt Macy 		}
3296813d08fSMatt Macy 	}
3306813d08fSMatt Macy 
3316813d08fSMatt Macy 
3326813d08fSMatt Macy nflg = 0;	/* flag = 1 if x<0 raised to integer power */
3336813d08fSMatt Macy if( x <= 0.0L )
3346813d08fSMatt Macy 	{
3356813d08fSMatt Macy 	if( x == 0.0L )
3366813d08fSMatt Macy 		{
3376813d08fSMatt Macy 		if( y < 0.0 )
3386813d08fSMatt Macy 			{
3396813d08fSMatt Macy 			if( signbit(x) && yoddint )
3406813d08fSMatt Macy 				return( -INFINITY );
3416813d08fSMatt Macy 			return( INFINITY );
3426813d08fSMatt Macy 			}
3436813d08fSMatt Macy 		if( y > 0.0 )
3446813d08fSMatt Macy 			{
3456813d08fSMatt Macy 			if( signbit(x) && yoddint )
3466813d08fSMatt Macy 				return( -0.0L );
3476813d08fSMatt Macy 			return( 0.0 );
3486813d08fSMatt Macy 			}
3496813d08fSMatt Macy 		if( y == 0.0L )
3506813d08fSMatt Macy 			return( 1.0L );  /*   0**0   */
3516813d08fSMatt Macy 		else
3526813d08fSMatt Macy 			return( 0.0L );  /*   0**y   */
3536813d08fSMatt Macy 		}
3546813d08fSMatt Macy 	else
3556813d08fSMatt Macy 		{
3566813d08fSMatt Macy 		if( iyflg == 0 )
3576813d08fSMatt Macy 			return (x - x) / (x - x); /* (x<0)**(non-int) is NaN */
3586813d08fSMatt Macy 		nflg = 1;
3596813d08fSMatt Macy 		}
3606813d08fSMatt Macy 	}
3616813d08fSMatt Macy 
3626813d08fSMatt Macy /* Integer power of an integer.  */
3636813d08fSMatt Macy 
3646813d08fSMatt Macy if( iyflg )
3656813d08fSMatt Macy 	{
3666813d08fSMatt Macy 	i = w;
3676813d08fSMatt Macy 	w = floorl(x);
3686813d08fSMatt Macy 	if( (w == x) && (fabsl(y) < 32768.0) )
3696813d08fSMatt Macy 		{
3706813d08fSMatt Macy 		w = powil( x, (int) y );
3716813d08fSMatt Macy 		return( w );
3726813d08fSMatt Macy 		}
3736813d08fSMatt Macy 	}
3746813d08fSMatt Macy 
3756813d08fSMatt Macy 
3766813d08fSMatt Macy if( nflg )
3776813d08fSMatt Macy 	x = fabsl(x);
3786813d08fSMatt Macy 
3796813d08fSMatt Macy /* separate significand from exponent */
3806813d08fSMatt Macy x = frexpl( x, &i );
3816813d08fSMatt Macy e = i;
3826813d08fSMatt Macy 
3836813d08fSMatt Macy /* find significand in antilog table A[] */
3846813d08fSMatt Macy i = 1;
3856813d08fSMatt Macy if( x <= douba(17) )
3866813d08fSMatt Macy 	i = 17;
3876813d08fSMatt Macy if( x <= douba(i+8) )
3886813d08fSMatt Macy 	i += 8;
3896813d08fSMatt Macy if( x <= douba(i+4) )
3906813d08fSMatt Macy 	i += 4;
3916813d08fSMatt Macy if( x <= douba(i+2) )
3926813d08fSMatt Macy 	i += 2;
3936813d08fSMatt Macy if( x >= douba(1) )
3946813d08fSMatt Macy 	i = -1;
3956813d08fSMatt Macy i += 1;
3966813d08fSMatt Macy 
3976813d08fSMatt Macy 
3986813d08fSMatt Macy /* Find (x - A[i])/A[i]
3996813d08fSMatt Macy  * in order to compute log(x/A[i]):
4006813d08fSMatt Macy  *
4016813d08fSMatt Macy  * log(x) = log( a x/a ) = log(a) + log(x/a)
4026813d08fSMatt Macy  *
4036813d08fSMatt Macy  * log(x/a) = log(1+v),  v = x/a - 1 = (x-a)/a
4046813d08fSMatt Macy  */
4056813d08fSMatt Macy x -= douba(i);
4066813d08fSMatt Macy x -= doubb(i/2);
4076813d08fSMatt Macy x /= douba(i);
4086813d08fSMatt Macy 
4096813d08fSMatt Macy 
4106813d08fSMatt Macy /* rational approximation for log(1+v):
4116813d08fSMatt Macy  *
4126813d08fSMatt Macy  * log(1+v)  =  v  -  v**2/2  +  v**3 P(v) / Q(v)
4136813d08fSMatt Macy  */
4146813d08fSMatt Macy z = x*x;
4156813d08fSMatt Macy w = x * ( z * __polevll( x, P, 3 ) / __p1evll( x, Q, 3 ) );
4166813d08fSMatt Macy w = w - ldexpl( z, -1 );   /*  w - 0.5 * z  */
4176813d08fSMatt Macy 
4186813d08fSMatt Macy /* Convert to base 2 logarithm:
4196813d08fSMatt Macy  * multiply by log2(e) = 1 + LOG2EA
4206813d08fSMatt Macy  */
4216813d08fSMatt Macy z = LOG2EA * w;
4226813d08fSMatt Macy z += w;
4236813d08fSMatt Macy z += LOG2EA * x;
4246813d08fSMatt Macy z += x;
4256813d08fSMatt Macy 
4266813d08fSMatt Macy /* Compute exponent term of the base 2 logarithm. */
4276813d08fSMatt Macy w = -i;
4286813d08fSMatt Macy w = ldexpl( w, -LNXT );	/* divide by NXT */
4296813d08fSMatt Macy w += e;
4306813d08fSMatt Macy /* Now base 2 log of x is w + z. */
4316813d08fSMatt Macy 
4326813d08fSMatt Macy /* Multiply base 2 log by y, in extended precision. */
4336813d08fSMatt Macy 
4346813d08fSMatt Macy /* separate y into large part ya
4356813d08fSMatt Macy  * and small part yb less than 1/NXT
4366813d08fSMatt Macy  */
4376813d08fSMatt Macy ya = reducl(y);
4386813d08fSMatt Macy yb = y - ya;
4396813d08fSMatt Macy 
4406813d08fSMatt Macy /* (w+z)(ya+yb)
4416813d08fSMatt Macy  * = w*ya + w*yb + z*y
4426813d08fSMatt Macy  */
4436813d08fSMatt Macy F = z * y  +  w * yb;
4446813d08fSMatt Macy Fa = reducl(F);
4456813d08fSMatt Macy Fb = F - Fa;
4466813d08fSMatt Macy 
4476813d08fSMatt Macy G = Fa + w * ya;
4486813d08fSMatt Macy Ga = reducl(G);
4496813d08fSMatt Macy Gb = G - Ga;
4506813d08fSMatt Macy 
4516813d08fSMatt Macy H = Fb + Gb;
4526813d08fSMatt Macy Ha = reducl(H);
4536813d08fSMatt Macy w = ldexpl( Ga+Ha, LNXT );
4546813d08fSMatt Macy 
4556813d08fSMatt Macy /* Test the power of 2 for overflow */
4566813d08fSMatt Macy if( w > MEXP )
4576813d08fSMatt Macy 	return (huge * huge);		/* overflow */
4586813d08fSMatt Macy 
4596813d08fSMatt Macy if( w < MNEXP )
4606813d08fSMatt Macy 	return (twom10000 * twom10000);	/* underflow */
4616813d08fSMatt Macy 
4626813d08fSMatt Macy e = w;
4636813d08fSMatt Macy Hb = H - Ha;
4646813d08fSMatt Macy 
4656813d08fSMatt Macy if( Hb > 0.0L )
4666813d08fSMatt Macy 	{
4676813d08fSMatt Macy 	e += 1;
4686813d08fSMatt Macy 	Hb -= (1.0L/NXT);  /*0.0625L;*/
4696813d08fSMatt Macy 	}
4706813d08fSMatt Macy 
4716813d08fSMatt Macy /* Now the product y * log2(x)  =  Hb + e/NXT.
4726813d08fSMatt Macy  *
4736813d08fSMatt Macy  * Compute base 2 exponential of Hb,
4746813d08fSMatt Macy  * where -0.0625 <= Hb <= 0.
4756813d08fSMatt Macy  */
4766813d08fSMatt Macy z = Hb * __polevll( Hb, R, 6 );  /*    z  =  2**Hb - 1    */
4776813d08fSMatt Macy 
4786813d08fSMatt Macy /* Express e/NXT as an integer plus a negative number of (1/NXT)ths.
4796813d08fSMatt Macy  * Find lookup table entry for the fractional power of 2.
4806813d08fSMatt Macy  */
4816813d08fSMatt Macy if( e < 0 )
4826813d08fSMatt Macy 	i = 0;
4836813d08fSMatt Macy else
4846813d08fSMatt Macy 	i = 1;
4856813d08fSMatt Macy i = e/NXT + i;
4866813d08fSMatt Macy e = NXT*i - e;
4876813d08fSMatt Macy w = douba( e );
4886813d08fSMatt Macy z = w * z;      /*    2**-e * ( 1 + (2**Hb-1) )    */
4896813d08fSMatt Macy z = z + w;
4906813d08fSMatt Macy z = ldexpl( z, i );  /* multiply by integer power of 2 */
4916813d08fSMatt Macy 
4926813d08fSMatt Macy if( nflg )
4936813d08fSMatt Macy 	{
4946813d08fSMatt Macy /* For negative x,
4956813d08fSMatt Macy  * find out if the integer exponent
4966813d08fSMatt Macy  * is odd or even.
4976813d08fSMatt Macy  */
4986813d08fSMatt Macy 	w = ldexpl( y, -1 );
4996813d08fSMatt Macy 	w = floorl(w);
5006813d08fSMatt Macy 	w = ldexpl( w, 1 );
5016813d08fSMatt Macy 	if( w != y )
5026813d08fSMatt Macy 		z = -z; /* odd exponent */
5036813d08fSMatt Macy 	}
5046813d08fSMatt Macy 
5056813d08fSMatt Macy return( z );
5066813d08fSMatt Macy }
5076813d08fSMatt Macy 
5086813d08fSMatt Macy 
5096813d08fSMatt Macy /* Find a multiple of 1/NXT that is within 1/NXT of x. */
5105a4c3b83SDimitry Andric static inline long double
5116813d08fSMatt Macy reducl(long double x)
5126813d08fSMatt Macy {
5136813d08fSMatt Macy long double t;
5146813d08fSMatt Macy 
5156813d08fSMatt Macy t = ldexpl( x, LNXT );
5166813d08fSMatt Macy t = floorl( t );
5176813d08fSMatt Macy t = ldexpl( t, -LNXT );
5186813d08fSMatt Macy return(t);
5196813d08fSMatt Macy }
5206813d08fSMatt Macy 
5216813d08fSMatt Macy /*							powil.c
5226813d08fSMatt Macy  *
5236813d08fSMatt Macy  *	Real raised to integer power, long double precision
5246813d08fSMatt Macy  *
5256813d08fSMatt Macy  *
5266813d08fSMatt Macy  *
5276813d08fSMatt Macy  * SYNOPSIS:
5286813d08fSMatt Macy  *
5296813d08fSMatt Macy  * long double x, y, powil();
5306813d08fSMatt Macy  * int n;
5316813d08fSMatt Macy  *
5326813d08fSMatt Macy  * y = powil( x, n );
5336813d08fSMatt Macy  *
5346813d08fSMatt Macy  *
5356813d08fSMatt Macy  *
5366813d08fSMatt Macy  * DESCRIPTION:
5376813d08fSMatt Macy  *
5386813d08fSMatt Macy  * Returns argument x raised to the nth power.
5396813d08fSMatt Macy  * The routine efficiently decomposes n as a sum of powers of
5406813d08fSMatt Macy  * two. The desired power is a product of two-to-the-kth
5416813d08fSMatt Macy  * powers of x.  Thus to compute the 32767 power of x requires
5426813d08fSMatt Macy  * 28 multiplications instead of 32767 multiplications.
5436813d08fSMatt Macy  *
5446813d08fSMatt Macy  *
5456813d08fSMatt Macy  *
5466813d08fSMatt Macy  * ACCURACY:
5476813d08fSMatt Macy  *
5486813d08fSMatt Macy  *
5496813d08fSMatt Macy  *                      Relative error:
5506813d08fSMatt Macy  * arithmetic   x domain   n domain  # trials      peak         rms
5516813d08fSMatt Macy  *    IEEE     .001,1000  -1022,1023  50000       4.3e-17     7.8e-18
5526813d08fSMatt Macy  *    IEEE        1,2     -1022,1023  20000       3.9e-17     7.6e-18
5536813d08fSMatt Macy  *    IEEE     .99,1.01     0,8700    10000       3.6e-16     7.2e-17
5546813d08fSMatt Macy  *
5556813d08fSMatt Macy  * Returns MAXNUM on overflow, zero on underflow.
5566813d08fSMatt Macy  *
5576813d08fSMatt Macy  */
5586813d08fSMatt Macy 
5596813d08fSMatt Macy static long double
5606813d08fSMatt Macy powil(long double x, int nn)
5616813d08fSMatt Macy {
5626813d08fSMatt Macy long double ww, y;
5636813d08fSMatt Macy long double s;
5646813d08fSMatt Macy int n, e, sign, asign, lx;
5656813d08fSMatt Macy 
5666813d08fSMatt Macy if( x == 0.0L )
5676813d08fSMatt Macy 	{
5686813d08fSMatt Macy 	if( nn == 0 )
5696813d08fSMatt Macy 		return( 1.0L );
5706813d08fSMatt Macy 	else if( nn < 0 )
5716813d08fSMatt Macy 		return( LDBL_MAX );
5726813d08fSMatt Macy 	else
5736813d08fSMatt Macy 		return( 0.0L );
5746813d08fSMatt Macy 	}
5756813d08fSMatt Macy 
5766813d08fSMatt Macy if( nn == 0 )
5776813d08fSMatt Macy 	return( 1.0L );
5786813d08fSMatt Macy 
5796813d08fSMatt Macy 
5806813d08fSMatt Macy if( x < 0.0L )
5816813d08fSMatt Macy 	{
5826813d08fSMatt Macy 	asign = -1;
5836813d08fSMatt Macy 	x = -x;
5846813d08fSMatt Macy 	}
5856813d08fSMatt Macy else
5866813d08fSMatt Macy 	asign = 0;
5876813d08fSMatt Macy 
5886813d08fSMatt Macy 
5896813d08fSMatt Macy if( nn < 0 )
5906813d08fSMatt Macy 	{
5916813d08fSMatt Macy 	sign = -1;
5926813d08fSMatt Macy 	n = -nn;
5936813d08fSMatt Macy 	}
5946813d08fSMatt Macy else
5956813d08fSMatt Macy 	{
5966813d08fSMatt Macy 	sign = 1;
5976813d08fSMatt Macy 	n = nn;
5986813d08fSMatt Macy 	}
5996813d08fSMatt Macy 
6006813d08fSMatt Macy /* Overflow detection */
6016813d08fSMatt Macy 
6026813d08fSMatt Macy /* Calculate approximate logarithm of answer */
6036813d08fSMatt Macy s = x;
6046813d08fSMatt Macy s = frexpl( s, &lx );
6056813d08fSMatt Macy e = (lx - 1)*n;
6066813d08fSMatt Macy if( (e == 0) || (e > 64) || (e < -64) )
6076813d08fSMatt Macy 	{
6086813d08fSMatt Macy 	s = (s - 7.0710678118654752e-1L) / (s +  7.0710678118654752e-1L);
6096813d08fSMatt Macy 	s = (2.9142135623730950L * s - 0.5L + lx) * nn * LOGE2L;
6106813d08fSMatt Macy 	}
6116813d08fSMatt Macy else
6126813d08fSMatt Macy 	{
6136813d08fSMatt Macy 	s = LOGE2L * e;
6146813d08fSMatt Macy 	}
6156813d08fSMatt Macy 
6166813d08fSMatt Macy if( s > MAXLOGL )
6176813d08fSMatt Macy 	return (huge * huge);		/* overflow */
6186813d08fSMatt Macy 
6196813d08fSMatt Macy if( s < MINLOGL )
6206813d08fSMatt Macy 	return (twom10000 * twom10000);	/* underflow */
6216813d08fSMatt Macy /* Handle tiny denormal answer, but with less accuracy
6226813d08fSMatt Macy  * since roundoff error in 1.0/x will be amplified.
6236813d08fSMatt Macy  * The precise demarcation should be the gradual underflow threshold.
6246813d08fSMatt Macy  */
6256813d08fSMatt Macy if( s < (-MAXLOGL+2.0L) )
6266813d08fSMatt Macy 	{
6276813d08fSMatt Macy 	x = 1.0L/x;
6286813d08fSMatt Macy 	sign = -sign;
6296813d08fSMatt Macy 	}
6306813d08fSMatt Macy 
6316813d08fSMatt Macy /* First bit of the power */
6326813d08fSMatt Macy if( n & 1 )
6336813d08fSMatt Macy 	y = x;
6346813d08fSMatt Macy 
6356813d08fSMatt Macy else
6366813d08fSMatt Macy 	{
6376813d08fSMatt Macy 	y = 1.0L;
6386813d08fSMatt Macy 	asign = 0;
6396813d08fSMatt Macy 	}
6406813d08fSMatt Macy 
6416813d08fSMatt Macy ww = x;
6426813d08fSMatt Macy n >>= 1;
6436813d08fSMatt Macy while( n )
6446813d08fSMatt Macy 	{
6456813d08fSMatt Macy 	ww = ww * ww;	/* arg to the 2-to-the-kth power */
6466813d08fSMatt Macy 	if( n & 1 )	/* if that bit is set, then include in product */
6476813d08fSMatt Macy 		y *= ww;
6486813d08fSMatt Macy 	n >>= 1;
6496813d08fSMatt Macy 	}
6506813d08fSMatt Macy 
6516813d08fSMatt Macy if( asign )
6526813d08fSMatt Macy 	y = -y; /* odd power of negative number */
6536813d08fSMatt Macy if( sign < 0 )
6546813d08fSMatt Macy 	y = 1.0L/y;
6556813d08fSMatt Macy return(y);
6566813d08fSMatt Macy }
657