/*Converting from double precision to Multi-precision and calculating e^x */ double __slowexp(double x) { #ifdef NO_LONG_DOUBLE double w,z,res,eps=3.0e-26; int p; mp_no mpx, mpy, mpz,mpw,mpeps,mpcor; p=6; __dbl_mp(x,&mpx,p); /* Convert a double precision number x */ /* into a multiple precision number mpx with prec. p. */ __mpexp(&mpx, &mpy, p); /* Multi-Precision exponential function */ __dbl_mp(eps,&mpeps,p); __mul(&mpeps,&mpy,&mpcor,p); __add(&mpy,&mpcor,&mpw,p); __sub(&mpy,&mpcor,&mpz,p); __mp_dbl(&mpw, &w, p); __mp_dbl(&mpz, &z, p); if (w == z) return w; else { /* if calculating is not exactly */ p = 32; __dbl_mp(x,&mpx,p); __mpexp(&mpx, &mpy, p); __mp_dbl(&mpy, &res, p); return res; } #else return (double) __ieee754_expl((long double)x); #endif }
/*Converting from double precision to Multi-precision and calculating e^x */ double SECTION __slowexp(double x) { double w,z,res,eps=3.0e-26; #if 0 double y; #endif int p; #if 0 int orig,i; #endif mp_no mpx, mpy, mpz,mpw,mpeps,mpcor; p=6; __dbl_mp(x,&mpx,p); /* Convert a double precision number x */ /* into a multiple precision number mpx with prec. p. */ __mpexp(&mpx, &mpy, p); /* Multi-Precision exponential function */ __dbl_mp(eps,&mpeps,p); __mul(&mpeps,&mpy,&mpcor,p); __add(&mpy,&mpcor,&mpw,p); __sub(&mpy,&mpcor,&mpz,p); __mp_dbl(&mpw, &w, p); __mp_dbl(&mpz, &z, p); if (w == z) return w; else { /* if calculating is not exactly */ p = 32; __dbl_mp(x,&mpx,p); __mpexp(&mpx, &mpy, p); __mp_dbl(&mpy, &res, p); return res; } }
double __slowpow(double x, double y, double z) { double res,res1; mp_no mpx, mpy, mpz,mpw,mpp,mpr,mpr1; static const mp_no eps = {-3,{1.0,4.0}}; int p; res = __halfulp(x,y); /* halfulp() returns -10 or x^y */ if (res >= 0) return res; /* if result was really computed by halfulp */ /* else, if result was not really computed by halfulp */ p = 10; /* p=precision */ __dbl_mp(x,&mpx,p); __dbl_mp(y,&mpy,p); __dbl_mp(z,&mpz,p); __mplog(&mpx, &mpz, p); /* log(x) = z */ __mul(&mpy,&mpz,&mpw,p); /* y * z =w */ __mpexp(&mpw, &mpp, p); /* e^w =pp */ __add(&mpp,&eps,&mpr,p); /* pp+eps =r */ __mp_dbl(&mpr, &res, p); __sub(&mpp,&eps,&mpr1,p); /* pp -eps =r1 */ __mp_dbl(&mpr1, &res1, p); /* converting into double precision */ if (res == res1) return res; p = 32; /* if we get here result wasn't calculated exactly, continue */ __dbl_mp(x,&mpx,p); /* for more exact calculation */ __dbl_mp(y,&mpy,p); __dbl_mp(z,&mpz,p); __mplog(&mpx, &mpz, p); /* log(c)=z */ __mul(&mpy,&mpz,&mpw,p); /* y*z =w */ __mpexp(&mpw, &mpp, p); /* e^w=pp */ __mp_dbl(&mpp, &res, p); /* converting into double precision */ return res; }
/*Converting from double precision to Multi-precision and calculating e^x */ double SECTION __slowexp (double x) { #ifndef USE_LONG_DOUBLE_FOR_MP double w, z, res, eps = 3.0e-26; int p; mp_no mpx, mpy, mpz, mpw, mpeps, mpcor; /* Use the multiple precision __MPEXP function to compute the exponential First at 144 bits and if it is not accurate enough, at 768 bits. */ p = 6; __dbl_mp (x, &mpx, p); __mpexp (&mpx, &mpy, p); __dbl_mp (eps, &mpeps, p); __mul (&mpeps, &mpy, &mpcor, p); __add (&mpy, &mpcor, &mpw, p); __sub (&mpy, &mpcor, &mpz, p); __mp_dbl (&mpw, &w, p); __mp_dbl (&mpz, &z, p); if (w == z) return w; else { p = 32; __dbl_mp (x, &mpx, p); __mpexp (&mpx, &mpy, p); __mp_dbl (&mpy, &res, p); return res; } #else return (double) __ieee754_expl((long double)x); #endif }
void __mplog(mp_no *x, mp_no *y, int p) { #include "mplog.h" int i,m; #if 0 int j,k,m1,m2,n; double a,b; #endif static const int mp[33] = {0,0,0,0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3, 4,4,4,4,4,4,4,4,4,4,4,4,4,4}; mp_no mpone = {0,{0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0}}; mp_no mpt1,mpt2; /* Choose m and initiate mpone */ m = mp[p]; mpone.e = 1; mpone.d[0]=mpone.d[1]=ONE; /* Perform m newton iterations to solve for y: exp(y)-x=0. */ /* The iterations formula is: y(n+1)=y(n)+(x*exp(-y(n))-1). */ __cpy(y,&mpt1,p); for (i=0; i<m; i++) { mpt1.d[0]=-mpt1.d[0]; __mpexp(&mpt1,&mpt2,p); __mul(x,&mpt2,&mpt1,p); __sub(&mpt1,&mpone,&mpt2,p); __add(y,&mpt2,&mpt1,p); __cpy(&mpt1,y,p); } return; }
/*Converting from double precision to Multi-precision and calculating e^x */ double SECTION __slowexp (double x) { #ifndef USE_LONG_DOUBLE_FOR_MP double w, z, res, eps = 3.0e-26; int p; mp_no mpx, mpy, mpz, mpw, mpeps, mpcor; /* Use the multiple precision __MPEXP function to compute the exponential First at 144 bits and if it is not accurate enough, at 768 bits. */ p = 6; __dbl_mp (x, &mpx, p); __mpexp (&mpx, &mpy, p); __dbl_mp (eps, &mpeps, p); __mul (&mpeps, &mpy, &mpcor, p); __add (&mpy, &mpcor, &mpw, p); __sub (&mpy, &mpcor, &mpz, p); __mp_dbl (&mpw, &w, p); __mp_dbl (&mpz, &z, p); if (w == z) { /* Track how often we get to the slow exp code plus its input/output values. */ LIBC_PROBE (slowexp_p6, 2, &x, &w); return w; } else { p = 32; __dbl_mp (x, &mpx, p); __mpexp (&mpx, &mpy, p); __mp_dbl (&mpy, &res, p); /* Track how often we get to the uber-slow exp code plus its input/output values. */ LIBC_PROBE (slowexp_p32, 2, &x, &res); return res; } #else return (double) __ieee754_expl((long double)x); #endif }
/*Converting from double precision to Multi-precision and calculating e^x */ double __slowexp(double x) { double w,z,res,eps=3.0e-26; #if 0 double y; #endif int p; #if 0 int orig,i; #endif mp_no mpx, mpy, mpz,mpw,mpeps,mpcor; p=6; __dbl_mp(x,&mpx,p); /* Convert a double precision number x */ /* into a multiple precision number mpx with prec. p. */ __mpexp(&mpx, &mpy, p); /* Multi-Precision exponential function */ __dbl_mp(eps,&mpeps,p); __mul(&mpeps,&mpy,&mpcor,p); __add(&mpy,&mpcor,&mpw,p); __sub(&mpy,&mpcor,&mpz,p); __mp_dbl(&mpw, &w, p); __mp_dbl(&mpz, &z, p); if (w == z) { /* Track how often we get to the slow exp code plus its input/output values. */ LIBC_PROBE (slowexp_p6, 2, &x, &w); return w; } else { /* if calculating is not exactly */ p = 32; __dbl_mp(x,&mpx,p); __mpexp(&mpx, &mpy, p); __mp_dbl(&mpy, &res, p); /* Track how often we get to the uber-slow exp code plus its input/output values. */ LIBC_PROBE (slowexp_p32, 2, &x, &res); return res; } }