/** * This file has no copyright assigned and is placed in the Public Domain. * This file is part of the mingw-w64 runtime package. * No warranty is given; refer to the file DISCLAIMER.PD within this package. */ #include "cephes_emath.h" /* * The constants are for 64 bit precision. */ /* Move in external format number, * converting it to internal format. */ void __emovi(const short unsigned int * __restrict__ a, short unsigned int * __restrict__ b) { register const unsigned short *p; register unsigned short *q; int i; q = b; p = a + (NE-1); /* point to last word of external number */ /* get the sign bit */ if (*p & 0x8000) *q++ = 0xffff; else *q++ = 0; /* get the exponent */ *q = *p--; *q++ &= 0x7fff; /* delete the sign bit */ #ifdef INFINITY if ((*(q - 1) & 0x7fff) == 0x7fff) { #ifdef NANS if (__eisnan(a)) { *q++ = 0; for (i = 3; i < NI; i++ ) *q++ = *p--; return; } #endif for (i = 2; i < NI; i++) *q++ = 0; return; } #endif /* clear high guard word */ *q++ = 0; /* move in the significand */ for (i = 0; i < NE - 1; i++ ) *q++ = *p--; /* clear low guard word */ *q = 0; } /* ; Add significands ; x + y replaces y */ void __eaddm(const short unsigned int * __restrict__ x, short unsigned int * __restrict__ y) { register unsigned long a; int i; unsigned int carry; x += NI - 1; y += NI - 1; carry = 0; for (i = M; i < NI; i++) { a = (unsigned long)(*x) + (unsigned long)(*y) + carry; if (a & 0x10000) carry = 1; else carry = 0; *y = (unsigned short)a; --x; --y; } } /* ; Subtract significands ; y - x replaces y */ void __esubm(const short unsigned int * __restrict__ x, short unsigned int * __restrict__ y) { unsigned long a; int i; unsigned int carry; x += NI - 1; y += NI - 1; carry = 0; for (i = M; i < NI; i++) { a = (unsigned long)(*y) - (unsigned long)(*x) - carry; if (a & 0x10000) carry = 1; else carry = 0; *y = (unsigned short)a; --x; --y; } } /* Multiply significand of e-type number b by 16-bit quantity a, e-type result to c. */ static void __m16m(short unsigned int a, short unsigned int * __restrict__ b, short unsigned int * __restrict__ c) { register unsigned short *pp; register unsigned long carry; unsigned short *ps; unsigned short p[NI]; unsigned long aa, m; int i; aa = a; pp = &p[NI - 2]; *pp++ = 0; *pp = 0; ps = &b[NI - 1]; for(i = M + 1; i < NI; i++) { if (*ps == 0) { --ps; --pp; *(pp - 1) = 0; } else { m = (unsigned long) aa * *ps--; carry = (m & 0xffff) + *pp; *pp-- = (unsigned short)carry; carry = (carry >> 16) + (m >> 16) + *pp; *pp = (unsigned short)carry; *(pp - 1) = carry >> 16; } } for (i = M; i < NI; i++) c[i] = p[i]; } /* Divide significands. Neither the numerator nor the denominator is permitted to have its high guard word nonzero. */ int __edivm(short unsigned int * __restrict__ den, short unsigned int * __restrict__ num) { int i; register unsigned short *p; unsigned long tnum; unsigned short j, tdenm, tquot; unsigned short tprod[NI + 1]; unsigned short equot[NI]; p = &equot[0]; *p++ = num[0]; *p++ = num[1]; for (i = M; i < NI; i++) { *p++ = 0; } __eshdn1(num); tdenm = den[M + 1]; for (i = M; i < NI; i++) { /* Find trial quotient digit (the radix is 65536). */ tnum = (((unsigned long) num[M]) << 16) + num[M + 1]; /* Do not execute the divide instruction if it will overflow. */ if ((tdenm * 0xffffUL) < tnum) tquot = 0xffff; else tquot = tnum / tdenm; /* Prove that the divide worked. */ /* tcheck = (unsigned long)tquot * tdenm; if (tnum - tcheck > tdenm) tquot = 0xffff; */ /* Multiply denominator by trial quotient digit. */ __m16m(tquot, den, tprod); /* The quotient digit may have been overestimated. */ if (__ecmpm(tprod, num) > 0) { tquot -= 1; __esubm(den, tprod); if(__ecmpm(tprod, num) > 0) { tquot -= 1; __esubm(den, tprod); } } __esubm(tprod, num); equot[i] = tquot; __eshup6(num); } /* test for nonzero remainder after roundoff bit */ p = &num[M]; j = 0; for (i = M; i < NI; i++) { j |= *p++; } if (j) j = 1; for (i = 0; i < NI; i++) num[i] = equot[i]; return ( (int)j ); } /* Multiply significands */ int __emulm(const short unsigned int * __restrict__ a, short unsigned int * __restrict__ b) { const unsigned short *p; unsigned short *q; unsigned short pprod[NI]; unsigned short equot[NI]; unsigned short j; int i; equot[0] = b[0]; equot[1] = b[1]; for (i = M; i < NI; i++) equot[i] = 0; j = 0; p = &a[NI - 1]; q = &equot[NI - 1]; for (i = M + 1; i < NI; i++) { if (*p == 0) { --p; } else { __m16m(*p--, b, pprod); __eaddm(pprod, equot); } j |= *q; __eshdn6(equot); } for (i = 0; i < NI; i++) b[i] = equot[i]; /* return flag for lost nonzero bits */ return ( (int)j ); } /* * Normalize and round off. * * The internal format number to be rounded is "s". * Input "lost" indicates whether the number is exact. * This is the so-called sticky bit. * * Input "subflg" indicates whether the number was obtained * by a subtraction operation. In that case if lost is nonzero * then the number is slightly smaller than indicated. * * Input "expo" is the biased exponent, which may be negative. * the exponent field of "s" is ignored but is replaced by * "expo" as adjusted by normalization and rounding. * * Input "rcntrl" is the rounding control. * * Input "rnprc" is precison control (64 or NBITS). */ void __emdnorm(short unsigned int *s, int lost, int subflg, int expo, int rcntrl, int rndprc) { int i, j; unsigned short r; int rw = NI-1; /* low guard word */ int re = NI-2; const unsigned short rmsk = 0xffff; const unsigned short rmbit = 0x8000; #if NE == 6 unsigned short rbit[NI] = {0,0,0,0,0,0,0,1,0}; #else unsigned short rbit[NI] = {0,0,0,0,0,0,0,0,0,0,0,1,0}; #endif /* Normalize */ j = __enormlz(s); /* a blank significand could mean either zero or infinity. */ #ifndef INFINITY if (j > NBITS) { __ecleazs(s); return; } #endif expo -= j; #ifndef INFINITY if (expo >= 32767L) goto overf; #else if ((j > NBITS) && (expo < 32767L)) { __ecleazs(s); return; } #endif if (expo < 0L) { if (expo > (long)(-NBITS - 1)) { j = (int)expo; i = __eshift(s, j); if (i) lost = 1; } else { __ecleazs(s); return; } } /* Round off, unless told not to by rcntrl. */ if (rcntrl == 0) goto mdfin; if (rndprc == 64) { rw = 7; re = 6; rbit[NI - 2] = 0; rbit[6] = 1; } /* Shift down 1 temporarily if the data structure has an implied * most significant bit and the number is denormal. * For rndprc = 64 or NBITS, there is no implied bit. * But Intel long double denormals lose one bit of significance even so. */ #if IBMPC if ((expo <= 0) && (rndprc != NBITS)) #else if ((expo <= 0) && (rndprc != 64) && (rndprc != NBITS)) #endif { lost |= s[NI - 1] & 1; __eshdn1(s); } /* Clear out all bits below the rounding bit, * remembering in r if any were nonzero. */ r = s[rw] & rmsk; if (rndprc < NBITS) { i = rw + 1; while (i < NI) { if( s[i] ) r |= 1; s[i] = 0; ++i; } } s[rw] &= (rmsk ^ 0xffff); if ((r & rmbit) != 0) { if (r == rmbit) { if (lost == 0) { /* round to even */ if ((s[re] & 1) == 0) goto mddone; } else { if (subflg != 0) goto mddone; } } __eaddm(rbit, s); } mddone: #if IBMPC if ((expo <= 0) && (rndprc != NBITS)) #else if ((expo <= 0) && (rndprc != 64) && (rndprc != NBITS)) #endif { __eshup1(s); } if (s[2] != 0) { /* overflow on roundoff */ __eshdn1(s); expo += 1; } mdfin: s[NI - 1] = 0; if (expo >= 32767L) { #ifndef INFINITY overf: #endif #ifdef INFINITY s[1] = 32767; for (i = 2; i < NI - 1; i++ ) s[i] = 0; #else s[1] = 32766; s[2] = 0; for (i = M + 1; i < NI - 1; i++) s[i] = 0xffff; s[NI - 1] = 0; if ((rndprc < 64) || (rndprc == 113)) s[rw] &= (rmsk ^ 0xffff); #endif return; } if (expo < 0) s[1] = 0; else s[1] = (unsigned short)expo; } /* ; Multiply. ; ; unsigned short a[NE], b[NE], c[NE]; ; emul( a, b, c ); c = b * a */ void __emul(const short unsigned int *a, const short unsigned int *b, short unsigned int *c) { unsigned short ai[NI], bi[NI]; int i, j; long lt, lta, ltb; #ifdef NANS /* NaN times anything is the same NaN. */ if (__eisnan(a)) { __emov(a, c); return; } if (__eisnan(b)) { __emov(b, c); return; } /* Zero times infinity is a NaN. */ if ((__eisinf(a) && __eiiszero(b)) || (__eisinf(b) && __eiiszero(a))) { mtherr( "emul", DOMAIN); __enan_NBITS(c); return; } #endif /* Infinity times anything else is infinity. */ #ifdef INFINITY if (__eisinf(a) || __eisinf(b)) { if (__eisneg(a) ^ __eisneg(b)) *(c + (NE-1)) = 0x8000; else *(c + (NE-1)) = 0; __einfin(c); return; } #endif __emovi(a, ai); __emovi(b, bi); lta = ai[E]; ltb = bi[E]; if (ai[E] == 0) { for (i = 1; i < NI - 1; i++) { if (ai[i] != 0) { lta -= __enormlz( ai ); goto mnzer1; } } __eclear(c); return; } mnzer1: if (bi[E] == 0) { for (i = 1; i < NI - 1; i++) { if (bi[i] != 0) { ltb -= __enormlz(bi); goto mnzer2; } } __eclear(c); return; } mnzer2: /* Multiply significands */ j = __emulm(ai, bi); /* calculate exponent */ lt = lta + ltb - (EXONE - 1); __emdnorm(bi, j, 0, lt, 64, NBITS); /* calculate sign of product */ if (ai[0] == bi[0]) bi[0] = 0; else bi[0] = 0xffff; __emovo(bi, c); } /* move out internal format to ieee long double */ void __toe64(short unsigned int *a, short unsigned int *b) { register unsigned short *p, *q; unsigned short i; #ifdef NANS if (__eiisnan(a)) { __enan_64(b); return; } #endif #ifdef IBMPC /* Shift Intel denormal significand down 1. */ if (a[E] == 0) __eshdn1(a); #endif p = a; #ifdef MIEEE q = b; #else q = b + 4; /* point to output exponent */ #if 1 /* NOTE: if data type is 96 bits wide, clear the last word here. */ *(q + 1)= 0; #endif #endif /* combine sign and exponent */ i = *p++; #ifdef MIEEE if (i) *q++ = *p++ | 0x8000; else *q++ = *p++; *q++ = 0; #else if (i) *q-- = *p++ | 0x8000; else *q-- = *p++; #endif /* skip over guard word */ ++p; /* move the significand */ #ifdef MIEEE for (i = 0; i < 4; i++) *q++ = *p++; #else #ifdef INFINITY if (__eiisinf(a)) { /* Intel long double infinity. */ *q-- = 0x8000; *q-- = 0; *q-- = 0; *q = 0; return; } #endif for (i = 0; i < 4; i++) *q-- = *p++; #endif } /* Compare two e type numbers. * * unsigned short a[NE], b[NE]; * ecmp( a, b ); * * returns +1 if a > b * 0 if a == b * -1 if a < b * -2 if either a or b is a NaN. */ int __ecmp(const short unsigned int * __restrict__ a, const short unsigned int * __restrict__ b) { unsigned short ai[NI], bi[NI]; register unsigned short *p, *q; register int i; int msign; #ifdef NANS if (__eisnan (a) || __eisnan (b)) return (-2); #endif __emovi(a, ai); p = ai; __emovi(b, bi); q = bi; if (*p != *q) { /* the signs are different */ /* -0 equals + 0 */ for (i = 1; i < NI - 1; i++) { if (ai[i] != 0) goto nzro; if (bi[i] != 0) goto nzro; } return (0); nzro: if (*p == 0) return (1); else return (-1); } /* both are the same sign */ if (*p == 0) msign = 1; else msign = -1; i = NI - 1; do { if (*p++ != *q++) { goto diff; } } while (--i > 0); return (0); /* equality */ diff: if ( *(--p) > *(--q) ) return (msign); /* p is bigger */ else return (-msign); /* p is littler */ } /* ; Shift significand ; ; Shifts significand area up or down by the number of bits ; given by the variable sc. */ int __eshift(short unsigned int *x, int sc) { unsigned short lost; unsigned short *p; if (sc == 0) return (0); lost = 0; p = x + NI - 1; if (sc < 0) { sc = -sc; while (sc >= 16) { lost |= *p; /* remember lost bits */ __eshdn6(x); sc -= 16; } while (sc >= 8) { lost |= *p & 0xff; __eshdn8(x); sc -= 8; } while (sc > 0) { lost |= *p & 1; __eshdn1(x); sc -= 1; } } else { while (sc >= 16) { __eshup6(x); sc -= 16; } while (sc >= 8) { __eshup8(x); sc -= 8; } while (sc > 0) { __eshup1(x); sc -= 1; } } if (lost) lost = 1; return ( (int)lost ); } /* ; normalize ; ; Shift normalizes the significand area pointed to by argument ; shift count (up = positive) is returned. */ int __enormlz(short unsigned int *x) { register unsigned short *p; int sc; sc = 0; p = &x[M]; if (*p != 0) goto normdn; ++p; if (*p & 0x8000) return (0); /* already normalized */ while (*p == 0) { __eshup6(x); sc += 16; /* With guard word, there are NBITS+16 bits available. * return true if all are zero. */ if (sc > NBITS) return (sc); } /* see if high byte is zero */ while ((*p & 0xff00) == 0) { __eshup8(x); sc += 8; } /* now shift 1 bit at a time */ while ((*p & 0x8000) == 0) { __eshup1(x); sc += 1; if (sc > (NBITS + 16)) { mtherr( "enormlz", UNDERFLOW); return (sc); } } return (sc); /* Normalize by shifting down out of the high guard word of the significand */ normdn: if (*p & 0xff00) { __eshdn8(x); sc -= 8; } while (*p != 0) { __eshdn1(x); sc -= 1; if (sc < -NBITS) { mtherr("enormlz", OVERFLOW); return (sc); } } return (sc); } /* Move internal format number out, * converting it to external format. */ void __emovo(const short unsigned int * __restrict__ a, short unsigned int * __restrict__ b) { register const unsigned short *p; register unsigned short *q; unsigned short i; p = a; q = b + (NE - 1); /* point to output exponent */ /* combine sign and exponent */ i = *p++; if (i) *q-- = *p++ | 0x8000; else *q-- = *p++; #ifdef INFINITY if (*(p - 1) == 0x7fff) { #ifdef NANS if (__eiisnan(a)) { __enan_NBITS(b); return; } #endif __einfin(b); return; } #endif /* skip over guard word */ ++p; /* move the significand */ for (i = 0; i < NE - 1; i++) *q-- = *p++; } #if USE_LDTOA void __eiremain(short unsigned int *den, short unsigned int *num, short unsigned int *equot ) { long ld, ln; unsigned short j; ld = den[E]; ld -= __enormlz(den); ln = num[E]; ln -= __enormlz(num); __ecleaz(equot); while (ln >= ld) { if(__ecmpm(den,num) <= 0) { __esubm(den, num); j = 1; } else { j = 0; } __eshup1(equot); equot[NI - 1] |= j; __eshup1(num); ln -= 1; } __emdnorm( num, 0, 0, ln, 0, NBITS ); } void __eadd1(const short unsigned int * __restrict__ a, const short unsigned int * __restrict__ b, short unsigned int * __restrict__ c, int subflg) { unsigned short ai[NI], bi[NI], ci[NI]; int i, lost, j, k; long lt, lta, ltb; #ifdef INFINITY if (__eisinf(a)) { __emov(a, c); if( subflg ) __eneg(c); return; } if (__eisinf(b)) { __emov(b, c); return; } #endif __emovi(a, ai); __emovi(b, bi); if (sub) ai[0] = ~ai[0]; /* compare exponents */ lta = ai[E]; ltb = bi[E]; lt = lta - ltb; if (lt > 0L) { /* put the larger number in bi */ __emovz(bi, ci); __emovz(ai, bi); __emovz(ci, ai); ltb = bi[E]; lt = -lt; } lost = 0; if (lt != 0L) { if (lt < (long)(-NBITS - 1)) goto done; /* answer same as larger addend */ k = (int)lt; lost = __eshift(ai, k); /* shift the smaller number down */ } else { /* exponents were the same, so must compare significands */ i = __ecmpm(ai, bi); if (i == 0) { /* the numbers are identical in magnitude */ /* if different signs, result is zero */ if (ai[0] != bi[0]) { __eclear(c); return; } /* if same sign, result is double */ /* double denomalized tiny number */ if ((bi[E] == 0) && ((bi[3] & 0x8000) == 0)) { __eshup1( bi ); goto done; } /* add 1 to exponent unless both are zero! */ for (j = 1; j < NI - 1; j++) { if (bi[j] != 0) { /* This could overflow, but let emovo take care of that. */ ltb += 1; break; } } bi[E] = (unsigned short )ltb; goto done; } if (i > 0) { /* put the larger number in bi */ __emovz(bi, ci); __emovz(ai, bi); __emovz(ci, ai); } } if (ai[0] == bi[0]) { __eaddm(ai, bi); subflg = 0; } else { __esubm(ai, bi); subflg = 1; } __emdnorm(bi, lost, subflg, ltb, 64, NBITS); done: __emovo(bi, c); } /* y = largest integer not greater than x * (truncated toward minus infinity) * * unsigned short x[NE], y[NE] * * efloor( x, y ); */ void __efloor(short unsigned int *x, short unsigned int *y) { register unsigned short *p; int e, expon, i; unsigned short f[NE]; const unsigned short bmask[] = { 0xffff, 0xfffe, 0xfffc, 0xfff8, 0xfff0, 0xffe0, 0xffc0, 0xff80, 0xff00, 0xfe00, 0xfc00, 0xf800, 0xf000, 0xe000, 0xc000, 0x8000, 0x0000, }; __emov(x, f); /* leave in external format */ expon = (int) f[NE - 1]; e = (expon & 0x7fff) - (EXONE - 1); if (e <= 0) { __eclear(y); goto isitneg; } /* number of bits to clear out */ e = NBITS - e; __emov(f, y); if (e <= 0) return; p = &y[0]; while (e >= 16) { *p++ = 0; e -= 16; } /* clear the remaining bits */ *p &= bmask[e]; /* truncate negatives toward minus infinity */ isitneg: if ((unsigned short)expon & (unsigned short)0x8000) { for (i = 0; i < NE - 1; i++) { if (f[i] != y[i]) { __esub( __eone, y, y ); break; } } } } /* ; Subtract external format numbers. ; ; unsigned short a[NE], b[NE], c[NE]; ; esub( a, b, c ); c = b - a */ void __esub(const short unsigned int * a, const short unsigned int * b, short unsigned int * c) { #ifdef NANS if (__eisnan(a)) { __emov (a, c); return; } if ( __eisnan(b)) { __emov(b, c); return; } /* Infinity minus infinity is a NaN. * Test for subtracting infinities of the same sign. */ if (__eisinf(a) && __eisinf(b) && ((__eisneg (a) ^ __eisneg (b)) == 0)) { mtherr("esub", DOMAIN); __enan_NBITS( c ); return; } #endif __eadd1(a, b, c, 1); } /* ; Divide. ; ; unsigned short a[NI], b[NI], c[NI]; ; ediv( a, b, c ); c = b / a */ void __ediv(const short unsigned int *a, const short unsigned int *b, short unsigned int *c) { unsigned short ai[NI], bi[NI]; int i; long lt, lta, ltb; #ifdef NANS /* Return any NaN input. */ if (__eisnan(a)) { __emov(a, c); return; } if (__eisnan(b)) { __emov(b, c); return; } /* Zero over zero, or infinity over infinity, is a NaN. */ if ((__eiszero(a) && __eiszero(b)) || (__eisinf (a) && __eisinf (b))) { mtherr("ediv", DOMAIN); __enan_NBITS( c ); return; } #endif /* Infinity over anything else is infinity. */ #ifdef INFINITY if (__eisinf(b)) { if (__eisneg(a) ^ __eisneg(b)) *(c + (NE - 1)) = 0x8000; else *(c + (NE - 1)) = 0; __einfin(c); return; } if (__eisinf(a)) { __eclear(c); return; } #endif __emovi(a, ai); __emovi(b, bi); lta = ai[E]; ltb = bi[E]; if (bi[E] == 0) { /* See if numerator is zero. */ for (i = 1; i < NI - 1; i++) { if (bi[i] != 0) { ltb -= __enormlz(bi); goto dnzro1; } } __eclear(c); return; } dnzro1: if (ai[E] == 0) { /* possible divide by zero */ for (i = 1; i < NI - 1; i++) { if (ai[i] != 0) { lta -= __enormlz(ai); goto dnzro2; } } if (ai[0] == bi[0]) *(c + (NE - 1)) = 0; else *(c + (NE - 1)) = 0x8000; __einfin(c); mtherr("ediv", SING); return; } dnzro2: i = __edivm(ai, bi); /* calculate exponent */ lt = ltb - lta + EXONE; __emdnorm(bi, i, 0, lt, 64, NBITS); /* set the sign */ if (ai[0] == bi[0]) bi[0] = 0; else bi[0] = 0Xffff; __emovo(bi, c); } void __e64toe(short unsigned int *pe, short unsigned int *y) { unsigned short yy[NI]; unsigned short *p, *q, *e; int i; e = pe; p = yy; for (i = 0; i < NE - 5; i++) *p++ = 0; #ifdef IBMPC for (i = 0; i < 5; i++) *p++ = *e++; #endif #ifdef DEC for (i = 0; i < 5; i++) *p++ = *e++; #endif #ifdef MIEEE p = &yy[0] + (NE - 1); *p-- = *e++; ++e; for (i = 0; i < 4; i++) *p-- = *e++; #endif #ifdef IBMPC /* For Intel long double, shift denormal significand up 1 -- but only if the top significand bit is zero. */ if ((yy[NE - 1] & 0x7fff) == 0 && (yy[NE - 2] & 0x8000) == 0) { unsigned short temp[NI + 1]; __emovi(yy, temp); __eshup1(temp); __emovo(temp,y); return; } #endif #ifdef INFINITY /* Point to the exponent field. */ p = &yy[NE - 1]; if (*p == 0x7fff) { #ifdef NANS #ifdef IBMPC for (i = 0; i < 4; i++) { if ((i != 3 && pe[i] != 0) /* Check for Intel long double infinity pattern. */ || (i == 3 && pe[i] != 0x8000)) { __enan_NBITS(y); return; } } #else for (i = 1; i <= 4; i++) { if (pe[i] != 0) { __enan_NBITS(y); return; } } #endif #endif /* NANS */ __eclear(y); __einfin(y); if (*p & 0x8000) __eneg(y); return; } #endif p = yy; q = y; for (i = 0; i < NE; i++) *q++ = *p++; } #endif /* USE_LDTOA */