예제 #1
0
파일: e_atan2.c 프로젝트: riscv/riscv-glibc
/* Stage 3: Perform a multi-Precision computation */
static double
SECTION
atan2Mp (double x, double y, const int pr[])
{
  double z1, z2;
  int i, p;
  mp_no mpx, mpy, mpz, mpz1, mpz2, mperr, mpt1;
  for (i = 0; i < MM; i++)
    {
      p = pr[i];
      __dbl_mp (x, &mpx, p);
      __dbl_mp (y, &mpy, p);
      __mpatan2 (&mpy, &mpx, &mpz, p);
      __dbl_mp (ud[i].d, &mpt1, p);
      __mul (&mpz, &mpt1, &mperr, p);
      __add (&mpz, &mperr, &mpz1, p);
      __sub (&mpz, &mperr, &mpz2, p);
      __mp_dbl (&mpz1, &z1, p);
      __mp_dbl (&mpz2, &z2, p);
      if (z1 == z2)
	{
	  LIBC_PROBE (slowatan2, 4, &p, &x, &y, &z1);
	  return z1;
	}
    }
  LIBC_PROBE (slowatan2_inexact, 4, &p, &x, &y, &z1);
  return z1;			/*if impossible to do exact computing */
}
예제 #2
0
파일: slowexp.c 프로젝트: gf-chen/glibc
/*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
}
예제 #3
0
/*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;
  }
}
예제 #4
0
파일: s_atan.c 프로젝트: siddhesh/glibc
 /* Final stages. Compute atan(x) by multiple precision arithmetic */
static double
atanMp (double x, const int pr[])
{
  mp_no mpx, mpy, mpy2, mperr, mpt1, mpy1;
  double y1, y2;
  int i, p;

  for (i = 0; i < M; i++)
    {
      p = pr[i];
      __dbl_mp (x, &mpx, p);
      __mpatan (&mpx, &mpy, p);
      __dbl_mp (u9[i].d, &mpt1, p);
      __mul (&mpy, &mpt1, &mperr, p);
      __add (&mpy, &mperr, &mpy1, p);
      __sub (&mpy, &mperr, &mpy2, p);
      __mp_dbl (&mpy1, &y1, p);
      __mp_dbl (&mpy2, &y2, p);
      if (y1 == y2)
	{
	  LIBC_PROBE (slowatan, 3, &p, &x, &y1);
	  return y1;
	}
    }
  LIBC_PROBE (slowatan_inexact, 3, &p, &x, &y1);
  return y1;			/*if impossible to do exact computing */
}
예제 #5
0
/*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
}
예제 #6
0
파일: sincos32.c 프로젝트: gf-chen/glibc
double
SECTION
__mpsin1(double x)
{
  int p;
  int n;
  mp_no u,s,c;
  double y;
  p=32;
  n=__mpranred(x,&u,p);               /* n is 0, 1, 2 or 3 */
  __c32(&u,&c,&s,p);
  switch (n) {                      /* in which quarter of unit circle y is*/
  case 0:
    __mp_dbl(&s,&y,p);
    return y;
    break;

  case 2:
    __mp_dbl(&s,&y,p);
    return -y;
    break;

  case 1:
    __mp_dbl(&c,&y,p);
    return y;
    break;

  case 3:
    __mp_dbl(&c,&y,p);
    return -y;
    break;

  }
  return 0;                     /* unreachable, to make the compiler happy */
}
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;
}
예제 #8
0
파일: sincos32.c 프로젝트: AubrCool/glibc
/* Compute cos() of double-length number (X + DX) as Multi Precision number and
   return result as double.  If REDUCE_RANGE is true, X is assumed to be the
   original input and DX is ignored.  */
double
SECTION
__mpcos (double x, double dx, bool reduce_range)
{
  double y;
  mp_no a, b, c, s;
  int n;
  int p = 32;

  if (reduce_range)
    {
      n = __mpranred (x, &a, p);	/* n is 0, 1, 2 or 3.  */
      __c32 (&a, &c, &s, p);
    }
  else
    {
      n = -1;
      __dbl_mp (x, &b, p);
      __dbl_mp (dx, &c, p);
      __add (&b, &c, &a, p);
      if (x > 0.8)
        {
          __sub (&hp, &a, &b, p);
          __c32 (&b, &s, &c, p);
        }
      else
        __c32 (&a, &c, &s, p);	/* a = cos(x+dx)     */
    }

  /* Convert result based on which quarter of unit circle y is in.  */
  switch (n)
    {
    case 1:
      __mp_dbl (&s, &y, p);
      y = -y;
      break;

    case 3:
      __mp_dbl (&s, &y, p);
      break;

    case 2:
      __mp_dbl (&c, &y, p);
      y = -y;
      break;

    /* Quadrant not set, so the result must be cos (X + DX), which is also
       stored in C.  */
    case 0:
    default:
      __mp_dbl (&c, &y, p);
    }
  LIBC_PROBE (slowcos, 3, &x, &dx, &y);
  return y;
}
void __inv(const mp_no *x, mp_no *y, int p) {
  int i;
#if 0
  int l;
#endif
  double t;
  mp_no z,w;
  static const int np1[] = {0,0,0,0,1,2,2,2,2,3,3,3,3,3,3,3,3,3,
                            4,4,4,4,4,4,4,4,4,4,4,4,4,4,4};
  const mp_no mptwo = {1,{1.0,2.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}};

  __cpy(x,&z,p);  z.e=0;  __mp_dbl(&z,&t,p);
  t=ONE/t;   __dbl_mp(t,y,p);    EY -= EX;

  for (i=0; i<np1[p]; i++) {
    __cpy(y,&w,p);
    __mul(x,&w,y,p);
    __sub(&mptwo,y,&z,p);
    __mul(&w,&z,y,p);
  }
  return;
}
예제 #10
0
파일: mpsqrt.c 프로젝트: riscv/riscv-glibc
void
SECTION
__mpsqrt (mp_no *x, mp_no *y, int p)
{
  int i, m, ey;
  double dx, dy;
  static const mp_no mphalf = {0, {1.0, HALFRAD}};
  static const mp_no mp3halfs = {1, {1.0, 1.0, HALFRAD}};
  mp_no mpxn, mpz, mpu, mpt1, mpt2;

  ey = EX / 2;
  __cpy (x, &mpxn, p);
  mpxn.e -= (ey + ey);
  __mp_dbl (&mpxn, &dx, p);
  dy = fastiroot (dx);
  __dbl_mp (dy, &mpu, p);
  __mul (&mpxn, &mphalf, &mpz, p);

  m = __mpsqrt_mp[p];
  for (i = 0; i < m; i++)
    {
      __sqr (&mpu, &mpt1, p);
      __mul (&mpt1, &mpz, &mpt2, p);
      __sub (&mp3halfs, &mpt2, &mpt1, p);
      __mul (&mpu, &mpt1, &mpt2, p);
      __cpy (&mpt2, &mpu, p);
    }
  __mul (&mpxn, &mpu, y, p);
  EY += ey;
}
예제 #11
0
/* Invert *X and store in *Y.  Relative error bound:
   - For P = 2: 1.001 * R ^ (1 - P)
   - For P = 3: 1.063 * R ^ (1 - P)
   - For P > 3: 2.001 * R ^ (1 - P)

   *X = 0 is not permissible.  */
static void
SECTION
__inv (const mp_no *x, mp_no *y, int p)
{
  long i;
  double t;
  mp_no z, w;
  static const int np1[] =
    { 0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
  };

  __cpy (x, &z, p);
  z.e = 0;
  __mp_dbl (&z, &t, p);
  t = 1 / t;
  __dbl_mp (t, y, p);
  EY -= EX;

  for (i = 0; i < np1[p]; i++)
    {
      __cpy (y, &w, p);
      __mul (x, &w, y, p);
      __sub (&__mptwo, y, &z, p);
      __mul (&w, &z, y, p);
    }
}
예제 #12
0
파일: slowexp.c 프로젝트: riscv/riscv-glibc
/*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
}
예제 #13
0
/*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;
  }
}
예제 #14
0
double __mpsin(double x, double dx) {
  int p;
  double y;
  mp_no a,b,c;
  p=32;
  __dbl_mp(x,&a,p);
  __dbl_mp(dx,&b,p);
  __add(&a,&b,&c,p);
  if (x>0.8) { __sub(&hp,&c,&a,p); __c32(&a,&b,&c,p); }
  else __c32(&c,&a,&b,p);     /* b = sin(x+dx)     */
  __mp_dbl(&b,&y,p);
  return y;
}
예제 #15
0
파일: e_atan2.c 프로젝트: gf-chen/glibc
/* Treat the Denormalized case */
static double
SECTION
normalized (double ax, double ay, double y, double z)
{
  int p;
  mp_no mpx, mpy, mpz, mperr, mpz2, mpt1;
  p = 6;
  __dbl_mp (ax, &mpx, p);
  __dbl_mp (ay, &mpy, p);
  __dvd (&mpy, &mpx, &mpz, p);
  __dbl_mp (ue.d, &mpt1, p);
  __mul (&mpz, &mpt1, &mperr, p);
  __sub (&mpz, &mperr, &mpz2, p);
  __mp_dbl (&mpz2, &z, p);
  return signArctan2 (y, z);
}
예제 #16
0
파일: mpatan.c 프로젝트: dreal/tai
void
SECTION
__mpatan(mp_no *x, mp_no *y, int p) {

  int i,m,n;
  double dx;
  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}},
    mptwo    = {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}},
    mptwoim1 = {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 mps,mpsm,mpt,mpt1,mpt2,mpt3;

		      /* Choose m and initiate mpone, mptwo & mptwoim1 */
    if      (EX>0) m=7;
    else if (EX<0) m=0;
    else {
      __mp_dbl(x,&dx,p);  dx=ABS(dx);
      for (m=6; m>0; m--)
	{if (dx>__atan_xm[m].d) break;}
    }
    mpone.e    = mptwo.e    = mptwoim1.e = 1;
    mpone.d[0] = mpone.d[1] = mptwo.d[0] = mptwoim1.d[0] = ONE;
    mptwo.d[1] = TWO;

				 /* Reduce x m times */
    __mul(x,x,&mpsm,p);
    if (m==0) __cpy(x,&mps,p);
    else {
      for (i=0; i<m; i++) {
	__add(&mpone,&mpsm,&mpt1,p);
	__mpsqrt(&mpt1,&mpt2,p);
	__add(&mpt2,&mpt2,&mpt1,p);
	__add(&mptwo,&mpsm,&mpt2,p);
	__add(&mpt1,&mpt2,&mpt3,p);
	__dvd(&mpsm,&mpt3,&mpt1,p);
	__cpy(&mpt1,&mpsm,p);
      }
      __mpsqrt(&mpsm,&mps,p);    mps.d[0] = X[0];
    }

		    /* Evaluate a truncated power series for Atan(s) */
    n=__atan_np[p];    mptwoim1.d[1] = __atan_twonm1[p].d;
    __dvd(&mpsm,&mptwoim1,&mpt,p);
    for (i=n-1; i>1; i--) {
      mptwoim1.d[1] -= TWO;
      __dvd(&mpsm,&mptwoim1,&mpt1,p);
      __mul(&mpsm,&mpt,&mpt2,p);
      __sub(&mpt1,&mpt2,&mpt,p);
    }
    __mul(&mps,&mpt,&mpt1,p);
    __sub(&mps,&mpt1,&mpt,p);

			  /* Compute Atan(x) */
    mptwoim1.d[1] = __atan_twom[m].d;
    __mul(&mptwoim1,&mpt,y,p);

  return;
}
예제 #17
0
double
SECTION
__ieee754_log(double x) {
#define M 4
  static const int pr[M]={8,10,18,32};
  int i,j,n,ux,dx,p;
#if 0
  int k;
#endif
  double dbl_n,u,p0,q,r0,w,nln2a,luai,lubi,lvaj,lvbj,
	 sij,ssij,ttij,A,B,B0,y,y1,y2,polI,polII,sa,sb,
	 t1,t2,t7,t8,t,ra,rb,ww,
	 a0,aa0,s1,s2,ss2,s3,ss3,a1,aa1,a,aa,b,bb,c;
#ifndef DLA_FMS
  double t3,t4,t5,t6;
#endif
  number num;
  mp_no mpx,mpy,mpy1,mpy2,mperr;

#include "ulog.tbl"
#include "ulog.h"

  /* Treating special values of x ( x<=0, x=INF, x=NaN etc.). */

  num.d = x;  ux = num.i[HIGH_HALF];  dx = num.i[LOW_HALF];
  n=0;
  if (__builtin_expect(ux < 0x00100000, 0)) {
    if (__builtin_expect(((ux & 0x7fffffff) | dx) == 0, 0))
      return MHALF/ZERO; /* return -INF */
    if (__builtin_expect(ux < 0, 0))
      return (x-x)/ZERO;                         /* return NaN  */
    n -= 54;    x *= two54.d;                              /* scale x     */
    num.d = x;
  }
  if (__builtin_expect(ux >= 0x7ff00000, 0))
    return x+x;                        /* INF or NaN  */

  /* Regular values of x */

  w = x-ONE;
  if (__builtin_expect(ABS(w) > U03, 1)) { goto case_03; }


  /*--- Stage I, the case abs(x-1) < 0.03 */

  t8 = MHALF*w;
  EMULV(t8,w,a,aa,t1,t2,t3,t4,t5)
  EADD(w,a,b,bb)

  /* Evaluate polynomial II */
  polII = (b0.d+w*(b1.d+w*(b2.d+w*(b3.d+w*(b4.d+
	  w*(b5.d+w*(b6.d+w*(b7.d+w*b8.d))))))))*w*w*w;
  c = (aa+bb)+polII;

  /* End stage I, case abs(x-1) < 0.03 */
  if ((y=b+(c+b*E2)) == b+(c-b*E2))  return y;

  /*--- Stage II, the case abs(x-1) < 0.03 */

  a = d11.d+w*(d12.d+w*(d13.d+w*(d14.d+w*(d15.d+w*(d16.d+
	    w*(d17.d+w*(d18.d+w*(d19.d+w*d20.d))))))));
  EMULV(w,a,s2,ss2,t1,t2,t3,t4,t5)
  ADD2(d10.d,dd10.d,s2,ss2,s3,ss3,t1,t2)
  MUL2(w,ZERO,s3,ss3,s2,ss2,t1,t2,t3,t4,t5,t6,t7,t8)
  ADD2(d9.d,dd9.d,s2,ss2,s3,ss3,t1,t2)
  MUL2(w,ZERO,s3,ss3,s2,ss2,t1,t2,t3,t4,t5,t6,t7,t8)
  ADD2(d8.d,dd8.d,s2,ss2,s3,ss3,t1,t2)
  MUL2(w,ZERO,s3,ss3,s2,ss2,t1,t2,t3,t4,t5,t6,t7,t8)
  ADD2(d7.d,dd7.d,s2,ss2,s3,ss3,t1,t2)
  MUL2(w,ZERO,s3,ss3,s2,ss2,t1,t2,t3,t4,t5,t6,t7,t8)
  ADD2(d6.d,dd6.d,s2,ss2,s3,ss3,t1,t2)
  MUL2(w,ZERO,s3,ss3,s2,ss2,t1,t2,t3,t4,t5,t6,t7,t8)
  ADD2(d5.d,dd5.d,s2,ss2,s3,ss3,t1,t2)
  MUL2(w,ZERO,s3,ss3,s2,ss2,t1,t2,t3,t4,t5,t6,t7,t8)
  ADD2(d4.d,dd4.d,s2,ss2,s3,ss3,t1,t2)
  MUL2(w,ZERO,s3,ss3,s2,ss2,t1,t2,t3,t4,t5,t6,t7,t8)
  ADD2(d3.d,dd3.d,s2,ss2,s3,ss3,t1,t2)
  MUL2(w,ZERO,s3,ss3,s2,ss2,t1,t2,t3,t4,t5,t6,t7,t8)
  ADD2(d2.d,dd2.d,s2,ss2,s3,ss3,t1,t2)
  MUL2(w,ZERO,s3,ss3,s2,ss2,t1,t2,t3,t4,t5,t6,t7,t8)
  MUL2(w,ZERO,s2,ss2,s3,ss3,t1,t2,t3,t4,t5,t6,t7,t8)
  ADD2(w,ZERO,    s3,ss3, b, bb,t1,t2)

  /* End stage II, case abs(x-1) < 0.03 */
  if ((y=b+(bb+b*E4)) == b+(bb-b*E4))  return y;
  goto stage_n;

  /*--- Stage I, the case abs(x-1) > 0.03 */
  case_03:

  /* Find n,u such that x = u*2**n,   1/sqrt(2) < u < sqrt(2)  */
  n += (num.i[HIGH_HALF] >> 20) - 1023;
  num.i[HIGH_HALF] = (num.i[HIGH_HALF] & 0x000fffff) | 0x3ff00000;
  if (num.d > SQRT_2) { num.d *= HALF;  n++; }
  u = num.d;  dbl_n = (double) n;

  /* Find i such that ui=1+(i-75)/2**8 is closest to u (i= 0,1,2,...,181) */
  num.d += h1.d;
  i = (num.i[HIGH_HALF] & 0x000fffff) >> 12;

  /* Find j such that vj=1+(j-180)/2**16 is closest to v=u/ui (j= 0,...,361) */
  num.d = u*Iu[i].d + h2.d;
  j = (num.i[HIGH_HALF] & 0x000fffff) >> 4;

  /* Compute w=(u-ui*vj)/(ui*vj) */
  p0=(ONE+(i-75)*DEL_U)*(ONE+(j-180)*DEL_V);
  q=u-p0;   r0=Iu[i].d*Iv[j].d;   w=q*r0;

  /* Evaluate polynomial I */
  polI = w+(a2.d+a3.d*w)*w*w;

  /* Add up everything */
  nln2a = dbl_n*LN2A;
  luai  = Lu[i][0].d;   lubi  = Lu[i][1].d;
  lvaj  = Lv[j][0].d;   lvbj  = Lv[j][1].d;
  EADD(luai,lvaj,sij,ssij)
  EADD(nln2a,sij,A  ,ttij)
  B0 = (((lubi+lvbj)+ssij)+ttij)+dbl_n*LN2B;
  B  = polI+B0;

  /* End stage I, case abs(x-1) >= 0.03 */
  if ((y=A+(B+E1)) == A+(B-E1))  return y;


  /*--- Stage II, the case abs(x-1) > 0.03 */

  /* Improve the accuracy of r0 */
  EMULV(p0,r0,sa,sb,t1,t2,t3,t4,t5)
  t=r0*((ONE-sa)-sb);
  EADD(r0,t,ra,rb)

  /* Compute w */
  MUL2(q,ZERO,ra,rb,w,ww,t1,t2,t3,t4,t5,t6,t7,t8)

  EADD(A,B0,a0,aa0)

  /* Evaluate polynomial III */
  s1 = (c3.d+(c4.d+c5.d*w)*w)*w;
  EADD(c2.d,s1,s2,ss2)
  MUL2(s2,ss2,w,ww,s3,ss3,t1,t2,t3,t4,t5,t6,t7,t8)
  MUL2(s3,ss3,w,ww,s2,ss2,t1,t2,t3,t4,t5,t6,t7,t8)
  ADD2(s2,ss2,w,ww,s3,ss3,t1,t2)
  ADD2(s3,ss3,a0,aa0,a1,aa1,t1,t2)

  /* End stage II, case abs(x-1) >= 0.03 */
  if ((y=a1+(aa1+E3)) == a1+(aa1-E3)) return y;


  /* Final stages. Use multi-precision arithmetic. */
  stage_n:

  for (i=0; i<M; i++) {
    p = pr[i];
    __dbl_mp(x,&mpx,p);  __dbl_mp(y,&mpy,p);
    __mplog(&mpx,&mpy,p);
    __dbl_mp(e[i].d,&mperr,p);
    __add(&mpy,&mperr,&mpy1,p);  __sub(&mpy,&mperr,&mpy2,p);
    __mp_dbl(&mpy1,&y1,p);       __mp_dbl(&mpy2,&y2,p);
    if (y1==y2)   return y1;
  }
  return y1;
}