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
__polevll(long double x,const long double * PP,int n)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
__p1evll(long double x,const long double * PP,int n)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
powl(long double x,long double y)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
reducl(long double x)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
powil(long double x,int nn)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