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