Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
git-mirror
/
glibc
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Pull requests
0
Actions
Projects
0
Security
Insights
Additional navigation options
Code
Pull requests
Actions
Projects
Security
Insights
Files
eb92c48
abilist
argp
assert
bits
catgets
conf
conform
crypt
csu
ctype
debug
dirent
dlfcn
elf
gmon
gnulib
grp
gshadow
hesiod
hurd
iconv
iconvdata
include
inet
intl
io
libidn
libio
locale
localedata
login
mach
malloc
manual
math
misc
nis
nptl
nptl_db
nscd
nss
po
posix
pwd
resolv
resource
rt
scripts
setjmp
shadow
signal
socket
soft-fp
stdio-common
stdlib
streams
string
sunrpc
sysdeps
generic
gnu
i386
ieee754
bits
dbl-64
wordsize-64
MathLib.h
asincos.tbl
atnat.h
atnat2.h
branred.c
branred.h
dbl2mpn.c
dla.h
doasin.c
doasin.h
dosincos.c
dosincos.h
e_acos.c
e_acosh.c
e_asin.c
e_atan2.c
e_atanh.c
e_cosh.c
e_exp.c
e_exp2.c
e_fmod.c
e_gamma_r.c
e_hypot.c
e_j0.c
e_j1.c
e_jn.c
e_lgamma_r.c
e_log.c
e_log10.c
e_log2.c
e_pow.c
e_rem_pio2.c
e_remainder.c
e_sinh.c
e_sqrt.c
halfulp.c
k_cos.c
k_rem_pio2.c
k_sin.c
k_tan.c
mpa.c
mpa.h
mpa2.h
mpatan.c
mpatan.h
mpatan2.c
mpexp.c
mpexp.h
mplog.c
mplog.h
mpn2dbl.c
mpsqrt.c
mpsqrt.h
mptan.c
mydefs.h
powtwo.tbl
root.tbl
s_asinh.c
s_atan.c
s_cbrt.c
s_ceil.c
s_copysign.c
s_cos.c
s_erf.c
s_expm1.c
s_fabs.c
s_finite.c
s_floor.c
s_fma.c
s_fmaf.c
s_fpclassify.c
s_frexp.c
s_ilogb.c
s_isinf.c
s_isinf_ns.c
s_isnan.c
s_llrint.c
s_llround.c
s_log1p.c
s_logb.c
s_lrint.c
s_lround.c
s_modf.c
s_nearbyint.c
s_nexttoward.c
s_remquo.c
s_rint.c
s_round.c
s_scalbln.c
s_scalbn.c
s_signbit.c
s_sin.c
s_sincos.c
s_tan.c
s_tanh.c
s_trunc.c
sincos32.c
sincos32.h
sincostab.c
slowexp.c
slowpow.c
t_exp.c
t_exp2.h
uasncs.h
uatan.tbl
uexp.h
uexp.tbl
ulog.h
ulog.tbl
upow.h
upow.tbl
urem.h
uroot.h
usncs.h
utan.h
utan.tbl
w_exp.c
flt-32
ldbl-128
ldbl-128ibm
ldbl-64-128
ldbl-96
ldbl-opt
Makefile
ieee754.h
k_standard.c
s_lib_version.c
s_matherr.c
s_signgam.c
support.c
mach
posix
powerpc
pthread
s390
sh
sparc
unix
wordsize-32
wordsize-64
x86_64
sysvipc
termios
time
timezone
wcsmbs
wctype
.gitattributes
.gitignore
BUGS
CANCEL-FCT-WAIVE
CANCEL-FILE-WAIVE
CONFORMANCE
COPYING
COPYING.LIB
ChangeLog
ChangeLog.1
ChangeLog.10
ChangeLog.11
ChangeLog.12
ChangeLog.13
ChangeLog.14
ChangeLog.15
ChangeLog.16
ChangeLog.17
ChangeLog.2
ChangeLog.3
ChangeLog.4
ChangeLog.5
ChangeLog.6
ChangeLog.7
ChangeLog.8
ChangeLog.9
FAQ
FAQ.in
INSTALL
LICENSES
Makeconfig
Makefile
Makefile.in
Makerules
NAMESPACE
NEWS
NOTES
PROJECTS
README
README.libm
Rules
Versions.def
WUR-REPORT
abi-tags
aclocal.m4
config.h.in
config.make.in
configure
configure.in
cppflags-iterator.mk
extra-lib.mk
extra-modules.mk
libc-abis
o-iterator.mk
shlib-versions
test-skeleton.c
version.h
Breadcrumbs
glibc
/
sysdeps
/
ieee754
/
dbl-64
/
e_pow.c
Blame
Blame
Latest commit
History
History
414 lines (389 loc) · 12.9 KB
Breadcrumbs
glibc
/
sysdeps
/
ieee754
/
dbl-64
/
e_pow.c
Top
File metadata and controls
Code
Blame
414 lines (389 loc) · 12.9 KB
Raw
/* * IBM Accurate Mathematical Library * written by International Business Machines Corp. * Copyright (C) 2001-2012 Free Software Foundation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, see <http://www.gnu.org/licenses/>. */ /***************************************************************************/ /* MODULE_NAME: upow.c */ /* */ /* FUNCTIONS: upow */ /* power1 */ /* my_log2 */ /* log1 */ /* checkint */ /* FILES NEEDED: dla.h endian.h mpa.h mydefs.h */ /* halfulp.c mpexp.c mplog.c slowexp.c slowpow.c mpa.c */ /* uexp.c upow.c */ /* root.tbl uexp.tbl upow.tbl */ /* An ultimate power routine. Given two IEEE double machine numbers y,x */ /* it computes the correctly rounded (to nearest) value of x^y. */ /* Assumption: Machine arithmetic operations are performed in */ /* round to nearest mode of IEEE 754 standard. */ /* */ /***************************************************************************/ #include "endian.h" #include "upow.h" #include <dla.h> #include "mydefs.h" #include "MathLib.h" #include "upow.tbl" #include <math_private.h> #include <fenv.h> #ifndef SECTION # define SECTION #endif double __exp1(double x, double xx, double error); static double log1(double x, double *delta, double *error); static double my_log2(double x, double *delta, double *error); double __slowpow(double x, double y,double z); static double power1(double x, double y); static int checkint(double x); /***************************************************************************/ /* An ultimate power routine. Given two IEEE double machine numbers y,x */ /* it computes the correctly rounded (to nearest) value of X^y. */ /***************************************************************************/ double SECTION __ieee754_pow(double x, double y) { double z,a,aa,error, t,a1,a2,y1,y2; #if 0 double gor=1.0; #endif mynumber u,v; int k; int4 qx,qy; v.x=y; u.x=x; if (v.i[LOW_HALF] == 0) { /* of y */ qx = u.i[HIGH_HALF]&0x7fffffff; /* Checking if x is not too small to compute */ if (((qx==0x7ff00000)&&(u.i[LOW_HALF]!=0))||(qx>0x7ff00000)) return NaNQ.x; if (y == 1.0) return x; if (y == 2.0) return x*x; if (y == -1.0) return 1.0/x; if (y == 0) return 1.0; } /* else */ if(((u.i[HIGH_HALF]>0 && u.i[HIGH_HALF]<0x7ff00000)|| /* x>0 and not x->0 */ (u.i[HIGH_HALF]==0 && u.i[LOW_HALF]!=0)) && /* 2^-1023< x<= 2^-1023 * 0x1.0000ffffffff */ (v.i[HIGH_HALF]&0x7fffffff) < 0x4ff00000) { /* if y<-1 or y>1 */ double retval; SET_RESTORE_ROUND (FE_TONEAREST); z = log1(x,&aa,&error); /* x^y =e^(y log (X)) */ t = y*134217729.0; y1 = t - (t-y); y2 = y - y1; t = z*134217729.0; a1 = t - (t-z); a2 = (z - a1)+aa; a = y1*a1; aa = y2*a1 + y*a2; a1 = a+aa; a2 = (a-a1)+aa; error = error*ABS(y); t = __exp1(a1,a2,1.9e16*error); /* return -10 or 0 if wasn't computed exactly */ retval = (t>0)?t:power1(x,y); return retval; } if (x == 0) { if (((v.i[HIGH_HALF] & 0x7fffffff) == 0x7ff00000 && v.i[LOW_HALF] != 0) || (v.i[HIGH_HALF] & 0x7fffffff) > 0x7ff00000) return y; if (ABS(y) > 1.0e20) return (y>0)?0:INF.x; k = checkint(y); if (k == -1) return y < 0 ? 1.0/x : x; else return y < 0 ? 1.0/ABS(x) : 0.0; /* return 0 */ } qx = u.i[HIGH_HALF]&0x7fffffff; /* no sign */ qy = v.i[HIGH_HALF]&0x7fffffff; /* no sign */ if (qx >= 0x7ff00000 && (qx > 0x7ff00000 || u.i[LOW_HALF] != 0)) return NaNQ.x; if (qy >= 0x7ff00000 && (qy > 0x7ff00000 || v.i[LOW_HALF] != 0)) return x == 1.0 ? 1.0 : NaNQ.x; /* if x<0 */ if (u.i[HIGH_HALF] < 0) { k = checkint(y); if (k==0) { if (qy == 0x7ff00000) { if (x == -1.0) return 1.0; else if (x > -1.0) return v.i[HIGH_HALF] < 0 ? INF.x : 0.0; else return v.i[HIGH_HALF] < 0 ? 0.0 : INF.x; } else if (qx == 0x7ff00000) return y < 0 ? 0.0 : INF.x; return NaNQ.x; /* y not integer and x<0 */ } else if (qx == 0x7ff00000) { if (k < 0) return y < 0 ? nZERO.x : nINF.x; else return y < 0 ? 0.0 : INF.x; } return (k==1)?__ieee754_pow(-x,y):-__ieee754_pow(-x,y); /* if y even or odd */ } /* x>0 */ if (qx == 0x7ff00000) /* x= 2^-0x3ff */ {if (y == 0) return NaNQ.x; return (y>0)?x:0; } if (qy > 0x45f00000 && qy < 0x7ff00000) { if (x == 1.0) return 1.0; if (y>0) return (x>1.0)?INF.x:0; if (y<0) return (x<1.0)?INF.x:0; } if (x == 1.0) return 1.0; if (y>0) return (x>1.0)?INF.x:0; if (y<0) return (x<1.0)?INF.x:0; return 0; /* unreachable, to make the compiler happy */ } #ifndef __ieee754_pow strong_alias (__ieee754_pow, __pow_finite) #endif /**************************************************************************/ /* Computing x^y using more accurate but more slow log routine */ /**************************************************************************/ static double SECTION power1(double x, double y) { double z,a,aa,error, t,a1,a2,y1,y2; z = my_log2(x,&aa,&error); t = y*134217729.0; y1 = t - (t-y); y2 = y - y1; t = z*134217729.0; a1 = t - (t-z); a2 = z - a1; a = y*z; aa = ((y1*a1-a)+y1*a2+y2*a1)+y2*a2+aa*y; a1 = a+aa; a2 = (a-a1)+aa; error = error*ABS(y); t = __exp1(a1,a2,1.9e16*error); return (t >= 0)?t:__slowpow(x,y,z); } /****************************************************************************/ /* Computing log(x) (x is left argument). The result is the returned double */ /* + the parameter delta. */ /* The result is bounded by error (rightmost argument) */ /****************************************************************************/ static double SECTION log1(double x, double *delta, double *error) { int i,j,m; #if 0 int n; #endif double uu,vv,eps,nx,e,e1,e2,t,t1,t2,res,add=0; #if 0 double cor; #endif mynumber u,v; #ifdef BIG_ENDI mynumber /**/ two52 = {{0x43300000, 0x00000000}}; /* 2**52 */ #else #ifdef LITTLE_ENDI mynumber /**/ two52 = {{0x00000000, 0x43300000}}; /* 2**52 */ #endif #endif u.x = x; m = u.i[HIGH_HALF]; *error = 0; *delta = 0; if (m < 0x00100000) /* 1<x<2^-1007 */ { x = x*t52.x; add = -52.0; u.x = x; m = u.i[HIGH_HALF];} if ((m&0x000fffff) < 0x0006a09e) {u.i[HIGH_HALF] = (m&0x000fffff)|0x3ff00000; two52.i[LOW_HALF]=(m>>20); } else {u.i[HIGH_HALF] = (m&0x000fffff)|0x3fe00000; two52.i[LOW_HALF]=(m>>20)+1; } v.x = u.x + bigu.x; uu = v.x - bigu.x; i = (v.i[LOW_HALF]&0x000003ff)<<2; if (two52.i[LOW_HALF] == 1023) /* nx = 0 */ { if (i > 1192 && i < 1208) /* |x-1| < 1.5*2**-10 */ { t = x - 1.0; t1 = (t+5.0e6)-5.0e6; t2 = t-t1; e1 = t - 0.5*t1*t1; e2 = t*t*t*(r3+t*(r4+t*(r5+t*(r6+t*(r7+t*r8)))))-0.5*t2*(t+t1); res = e1+e2; *error = 1.0e-21*ABS(t); *delta = (e1-res)+e2; return res; } /* |x-1| < 1.5*2**-10 */ else { v.x = u.x*(ui.x[i]+ui.x[i+1])+bigv.x; vv = v.x-bigv.x; j = v.i[LOW_HALF]&0x0007ffff; j = j+j+j; eps = u.x - uu*vv; e1 = eps*ui.x[i]; e2 = eps*(ui.x[i+1]+vj.x[j]*(ui.x[i]+ui.x[i+1])); e = e1+e2; e2 = ((e1-e)+e2); t=ui.x[i+2]+vj.x[j+1]; t1 = t+e; t2 = (((t-t1)+e)+(ui.x[i+3]+vj.x[j+2]))+e2+e*e*(p2+e*(p3+e*p4)); res=t1+t2; *error = 1.0e-24; *delta = (t1-res)+t2; return res; } } /* nx = 0 */ else /* nx != 0 */ { eps = u.x - uu; nx = (two52.x - two52e.x)+add; e1 = eps*ui.x[i]; e2 = eps*ui.x[i+1]; e=e1+e2; e2 = (e1-e)+e2; t=nx*ln2a.x+ui.x[i+2]; t1=t+e; t2=(((t-t1)+e)+nx*ln2b.x+ui.x[i+3]+e2)+e*e*(q2+e*(q3+e*(q4+e*(q5+e*q6)))); res = t1+t2; *error = 1.0e-21; *delta = (t1-res)+t2; return res; } /* nx != 0 */ } /****************************************************************************/ /* More slow but more accurate routine of log */ /* Computing log(x)(x is left argument).The result is return double + delta.*/ /* The result is bounded by error (right argument) */ /****************************************************************************/ static double SECTION my_log2(double x, double *delta, double *error) { int i,j,m; #if 0 int n; #endif double uu,vv,eps,nx,e,e1,e2,t,t1,t2,res,add=0; #if 0 double cor; #endif double ou1,ou2,lu1,lu2,ov,lv1,lv2,a,a1,a2; double y,yy,z,zz,j1,j2,j7,j8; #ifndef DLA_FMS double j3,j4,j5,j6; #endif mynumber u,v; #ifdef BIG_ENDI mynumber /**/ two52 = {{0x43300000, 0x00000000}}; /* 2**52 */ #else #ifdef LITTLE_ENDI mynumber /**/ two52 = {{0x00000000, 0x43300000}}; /* 2**52 */ #endif #endif u.x = x; m = u.i[HIGH_HALF]; *error = 0; *delta = 0; add=0; if (m<0x00100000) { /* x < 2^-1022 */ x = x*t52.x; add = -52.0; u.x = x; m = u.i[HIGH_HALF]; } if ((m&0x000fffff) < 0x0006a09e) {u.i[HIGH_HALF] = (m&0x000fffff)|0x3ff00000; two52.i[LOW_HALF]=(m>>20); } else {u.i[HIGH_HALF] = (m&0x000fffff)|0x3fe00000; two52.i[LOW_HALF]=(m>>20)+1; } v.x = u.x + bigu.x; uu = v.x - bigu.x; i = (v.i[LOW_HALF]&0x000003ff)<<2; /*------------------------------------- |x-1| < 2**-11------------------------------- */ if ((two52.i[LOW_HALF] == 1023) && (i == 1200)) { t = x - 1.0; EMULV(t,s3,y,yy,j1,j2,j3,j4,j5); ADD2(-0.5,0,y,yy,z,zz,j1,j2); MUL2(t,0,z,zz,y,yy,j1,j2,j3,j4,j5,j6,j7,j8); MUL2(t,0,y,yy,z,zz,j1,j2,j3,j4,j5,j6,j7,j8); e1 = t+z; e2 = (((t-e1)+z)+zz)+t*t*t*(ss3+t*(s4+t*(s5+t*(s6+t*(s7+t*s8))))); res = e1+e2; *error = 1.0e-25*ABS(t); *delta = (e1-res)+e2; return res; } /*----------------------------- |x-1| > 2**-11 -------------------------- */ else { /*Computing log(x) according to log table */ nx = (two52.x - two52e.x)+add; ou1 = ui.x[i]; ou2 = ui.x[i+1]; lu1 = ui.x[i+2]; lu2 = ui.x[i+3]; v.x = u.x*(ou1+ou2)+bigv.x; vv = v.x-bigv.x; j = v.i[LOW_HALF]&0x0007ffff; j = j+j+j; eps = u.x - uu*vv; ov = vj.x[j]; lv1 = vj.x[j+1]; lv2 = vj.x[j+2]; a = (ou1+ou2)*(1.0+ov); a1 = (a+1.0e10)-1.0e10; a2 = a*(1.0-a1*uu*vv); e1 = eps*a1; e2 = eps*a2; e = e1+e2; e2 = (e1-e)+e2; t=nx*ln2a.x+lu1+lv1; t1 = t+e; t2 = (((t-t1)+e)+(lu2+lv2+nx*ln2b.x+e2))+e*e*(p2+e*(p3+e*p4)); res=t1+t2; *error = 1.0e-27; *delta = (t1-res)+t2; return res; } } /**********************************************************************/ /* Routine receives a double x and checks if it is an integer. If not */ /* it returns 0, else it returns 1 if even or -1 if odd. */ /**********************************************************************/ static int SECTION checkint(double x) { union {int4 i[2]; double x;} u; int k,m,n; #if 0 int l; #endif u.x = x; m = u.i[HIGH_HALF]&0x7fffffff; /* no sign */ if (m >= 0x7ff00000) return 0; /* x is +/-inf or NaN */ if (m >= 0x43400000) return 1; /* |x| >= 2**53 */ if (m < 0x40000000) return 0; /* |x| < 2, can not be 0 or 1 */ n = u.i[LOW_HALF]; k = (m>>20)-1023; /* 1 <= k <= 52 */ if (k == 52) return (n&1)? -1:1; /* odd or even*/ if (k>20) { if (n<<(k-20)) return 0; /* if not integer */ return (n<<(k-21))?-1:1; } if (n) return 0; /*if not integer*/ if (k == 20) return (m&1)? -1:1; if (m<<(k+12)) return 0; return (m<<(k+11))?-1:1; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
You can’t perform that action at this time.