1284 lines
21 KiB
C
1284 lines
21 KiB
C
/**
|
|
* 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 >= 32767)
|
|
goto overf;
|
|
#else
|
|
if ((j > NBITS) && (expo < 32767))
|
|
{
|
|
__ecleazs(s);
|
|
return;
|
|
}
|
|
#endif
|
|
if (expo < 0)
|
|
{
|
|
if (expo > (-NBITS - 1))
|
|
{
|
|
j = 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 >= 32767)
|
|
{
|
|
#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 */
|