diff options
Diffstat (limited to 'test/math/ieee.c')
-rw-r--r-- | test/math/ieee.c | 4119 |
1 files changed, 0 insertions, 4119 deletions
diff --git a/test/math/ieee.c b/test/math/ieee.c deleted file mode 100644 index 17efea01c..000000000 --- a/test/math/ieee.c +++ /dev/null @@ -1,4119 +0,0 @@ -/* ieee.c - * - * Extended precision IEEE binary floating point arithmetic routines - * - * Numbers are stored in C language as arrays of 16-bit unsigned - * short integers. The arguments of the routines are pointers to - * the arrays. - * - * - * External e type data structure, simulates Intel 8087 chip - * temporary real format but possibly with a larger significand: - * - * NE-1 significand words (least significant word first, - * most significant bit is normally set) - * exponent (value = EXONE for 1.0, - * top bit is the sign) - * - * - * Internal data structure of a number (a "word" is 16 bits): - * - * ei[0] sign word (0 for positive, 0xffff for negative) - * ei[1] biased exponent (value = EXONE for the number 1.0) - * ei[2] high guard word (always zero after normalization) - * ei[3] - * to ei[NI-2] significand (NI-4 significand words, - * most significant word first, - * most significant bit is set) - * ei[NI-1] low guard word (0x8000 bit is rounding place) - * - * - * - * Routines for external format numbers - * - * asctoe( string, e ) ASCII string to extended double e type - * asctoe64( string, &d ) ASCII string to long double - * asctoe53( string, &d ) ASCII string to double - * asctoe24( string, &f ) ASCII string to single - * asctoeg( string, e, prec ) ASCII string to specified precision - * e24toe( &f, e ) IEEE single precision to e type - * e53toe( &d, e ) IEEE double precision to e type - * e64toe( &d, e ) IEEE long double precision to e type - * eabs(e) absolute value - * eadd( a, b, c ) c = b + a - * eclear(e) e = 0 - * 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. - * ediv( a, b, c ) c = b / a - * efloor( a, b ) truncate to integer, toward -infinity - * efrexp( a, exp, s ) extract exponent and significand - * eifrac( e, &l, frac ) e to long integer and e type fraction - * euifrac( e, &l, frac ) e to unsigned long integer and e type fraction - * einfin( e ) set e to infinity, leaving its sign alone - * eldexp( a, n, b ) multiply by 2**n - * emov( a, b ) b = a - * emul( a, b, c ) c = b * a - * eneg(e) e = -e - * eround( a, b ) b = nearest integer value to a - * esub( a, b, c ) c = b - a - * e24toasc( &f, str, n ) single to ASCII string, n digits after decimal - * e53toasc( &d, str, n ) double to ASCII string, n digits after decimal - * e64toasc( &d, str, n ) long double to ASCII string - * etoasc( e, str, n ) e to ASCII string, n digits after decimal - * etoe24( e, &f ) convert e type to IEEE single precision - * etoe53( e, &d ) convert e type to IEEE double precision - * etoe64( e, &d ) convert e type to IEEE long double precision - * ltoe( &l, e ) long (32 bit) integer to e type - * ultoe( &l, e ) unsigned long (32 bit) integer to e type - * eisneg( e ) 1 if sign bit of e != 0, else 0 - * eisinf( e ) 1 if e has maximum exponent (non-IEEE) - * or is infinite (IEEE) - * eisnan( e ) 1 if e is a NaN - * esqrt( a, b ) b = square root of a - * - * - * Routines for internal format numbers - * - * eaddm( ai, bi ) add significands, bi = bi + ai - * ecleaz(ei) ei = 0 - * ecleazs(ei) set ei = 0 but leave its sign alone - * ecmpm( ai, bi ) compare significands, return 1, 0, or -1 - * edivm( ai, bi ) divide significands, bi = bi / ai - * emdnorm(ai,l,s,exp) normalize and round off - * emovi( a, ai ) convert external a to internal ai - * emovo( ai, a ) convert internal ai to external a - * emovz( ai, bi ) bi = ai, low guard word of bi = 0 - * emulm( ai, bi ) multiply significands, bi = bi * ai - * enormlz(ei) left-justify the significand - * eshdn1( ai ) shift significand and guards down 1 bit - * eshdn8( ai ) shift down 8 bits - * eshdn6( ai ) shift down 16 bits - * eshift( ai, n ) shift ai n bits up (or down if n < 0) - * eshup1( ai ) shift significand and guards up 1 bit - * eshup8( ai ) shift up 8 bits - * eshup6( ai ) shift up 16 bits - * esubm( ai, bi ) subtract significands, bi = bi - ai - * - * - * The result is always normalized and rounded to NI-4 word precision - * after each arithmetic operation. - * - * Exception flags are NOT fully supported. - * - * Define INFINITY in mconf.h for support of infinity; otherwise a - * saturation arithmetic is implemented. - * - * Define NANS for support of Not-a-Number items; otherwise the - * arithmetic will never produce a NaN output, and might be confused - * by a NaN input. - * If NaN's are supported, the output of ecmp(a,b) is -2 if - * either a or b is a NaN. This means asking if(ecmp(a,b) < 0) - * may not be legitimate. Use if(ecmp(a,b) == -1) for less-than - * if in doubt. - * Signaling NaN's are NOT supported; they are treated the same - * as quiet NaN's. - * - * Denormals are always supported here where appropriate (e.g., not - * for conversion to DEC numbers). - */ - -/* - * Revision history: - * - * 5 Jan 84 PDP-11 assembly language version - * 2 Mar 86 fixed bug in asctoq() - * 6 Dec 86 C language version - * 30 Aug 88 100 digit version, improved rounding - * 15 May 92 80-bit long double support - * - * Author: S. L. Moshier. - */ - -#include <stdio.h> -/* #include "\usr\include\stdio.h" */ -#include "ehead.h" -#include "mconf.h" - -/* Change UNK into something else. */ -#ifdef UNK -#undef UNK -#define IBMPC 1 -#endif - -/* NaN's require infinity support. */ -#ifdef NANS -#ifndef INFINITY -#define INFINITY -#endif -#endif - -/* This handles 64-bit long ints. */ -#define LONGBITS (8 * sizeof(long)) - -/* Control register for rounding precision. - * This can be set to 80 (if NE=6), 64, 56, 53, or 24 bits. - */ -int rndprc = NBITS; -extern int rndprc; - -void eaddm(), esubm(), emdnorm(), asctoeg(), enan(); -static void toe24(), toe53(), toe64(), toe113(); -void eremain(), einit(), eiremain(); -int ecmpm(), edivm(), emulm(), eisneg(), eisinf(); -void emovi(), emovo(), emovz(), ecleaz(), eadd1(); -void etodec(), todec(), dectoe(); -int eisnan(), eiisnan(); - - - -void einit() -{ -} - -/* -; Clear out entire external format number. -; -; unsigned short x[]; -; eclear( x ); -*/ - -void eclear( x ) -register unsigned short *x; -{ -register int i; - -for( i=0; i<NE; i++ ) - *x++ = 0; -} - - - -/* Move external format number from a to b. - * - * emov( a, b ); - */ - -void emov( a, b ) -register unsigned short *a, *b; -{ -register int i; - -for( i=0; i<NE; i++ ) - *b++ = *a++; -} - - -/* -; Absolute value of external format number -; -; short x[NE]; -; eabs( x ); -*/ - -void eabs(x) -unsigned short x[]; /* x is the memory address of a short */ -{ - -x[NE-1] &= 0x7fff; /* sign is top bit of last word of external format */ -} - - - - -/* -; Negate external format number -; -; unsigned short x[NE]; -; eneg( x ); -*/ - -void eneg(x) -unsigned short x[]; -{ - -#ifdef NANS -if( eisnan(x) ) - return; -#endif -x[NE-1] ^= 0x8000; /* Toggle the sign bit */ -} - - - -/* Return 1 if external format number is negative, - * else return zero. - */ -int eisneg(x) -unsigned short x[]; -{ - -#ifdef NANS -if( eisnan(x) ) - return( 0 ); -#endif -if( x[NE-1] & 0x8000 ) - return( 1 ); -else - return( 0 ); -} - - -/* Return 1 if external format number has maximum possible exponent, - * else return zero. - */ -int eisinf(x) -unsigned short x[]; -{ - -if( (x[NE-1] & 0x7fff) == 0x7fff ) - { -#ifdef NANS - if( eisnan(x) ) - return( 0 ); -#endif - return( 1 ); - } -else - return( 0 ); -} - -/* Check if e-type number is not a number. - */ -int eisnan(x) -unsigned short x[]; -{ - -#ifdef NANS -int i; -/* NaN has maximum exponent */ -if( (x[NE-1] & 0x7fff) != 0x7fff ) - return (0); -/* ... and non-zero significand field. */ -for( i=0; i<NE-1; i++ ) - { - if( *x++ != 0 ) - return (1); - } -#endif -return (0); -} - -/* -; Fill entire number, including exponent and significand, with -; largest possible number. These programs implement a saturation -; value that is an ordinary, legal number. A special value -; "infinity" may also be implemented; this would require tests -; for that value and implementation of special rules for arithmetic -; operations involving inifinity. -*/ - -void einfin(x) -register unsigned short *x; -{ -register int i; - -#ifdef INFINITY -for( i=0; i<NE-1; i++ ) - *x++ = 0; -*x |= 32767; -#else -for( i=0; i<NE-1; i++ ) - *x++ = 0xffff; -*x |= 32766; -if( rndprc < NBITS ) - { - if (rndprc == 113) - { - *(x - 9) = 0; - *(x - 8) = 0; - } - if( rndprc == 64 ) - { - *(x-5) = 0; - } - if( rndprc == 53 ) - { - *(x-4) = 0xf800; - } - else - { - *(x-4) = 0; - *(x-3) = 0; - *(x-2) = 0xff00; - } - } -#endif -} - - - -/* Move in external format number, - * converting it to internal format. - */ -void emovi( a, b ) -unsigned short *a, *b; -{ -register unsigned short *p, *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; -} - - -/* Move internal format number out, - * converting it to external format. - */ -void emovo( a, b ) -unsigned short *a, *b; -{ -register unsigned short *p, *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( b, NBITS ); - return; - } -#endif - einfin(b); - return; - } -#endif -/* skip over guard word */ -++p; -/* move the significand */ -for( i=0; i<NE-1; i++ ) - *q-- = *p++; -} - - - - -/* Clear out internal format number. - */ - -void ecleaz( xi ) -register unsigned short *xi; -{ -register int i; - -for( i=0; i<NI; i++ ) - *xi++ = 0; -} - -/* same, but don't touch the sign. */ - -void ecleazs( xi ) -register unsigned short *xi; -{ -register int i; - -++xi; -for(i=0; i<NI-1; i++) - *xi++ = 0; -} - - - - -/* Move internal format number from a to b. - */ -void emovz( a, b ) -register unsigned short *a, *b; -{ -register int i; - -for( i=0; i<NI-1; i++ ) - *b++ = *a++; -/* clear low guard word */ -*b = 0; -} - -/* Return nonzero if internal format number is a NaN. - */ - -int eiisnan (x) -unsigned short x[]; -{ -int i; - -if( (x[E] & 0x7fff) == 0x7fff ) - { - for( i=M+1; i<NI; i++ ) - { - if( x[i] != 0 ) - return(1); - } - } -return(0); -} - -#ifdef INFINITY -/* Return nonzero if internal format number is infinite. */ - -static int -eiisinf (x) - unsigned short x[]; -{ - -#ifdef NANS - if (eiisnan (x)) - return (0); -#endif - if ((x[E] & 0x7fff) == 0x7fff) - return (1); - return (0); -} -#endif - -/* -; Compare significands of numbers in internal format. -; Guard words are included in the comparison. -; -; unsigned short a[NI], b[NI]; -; cmpm( a, b ); -; -; for the significands: -; returns +1 if a > b -; 0 if a == b -; -1 if a < b -*/ -int ecmpm( a, b ) -register unsigned short *a, *b; -{ -int i; - -a += M; /* skip up to significand area */ -b += M; -for( i=M; i<NI; i++ ) - { - if( *a++ != *b++ ) - goto difrnt; - } -return(0); - -difrnt: -if( *(--a) > *(--b) ) - return(1); -else - return(-1); -} - - -/* -; Shift significand down by 1 bit -*/ - -void eshdn1(x) -register unsigned short *x; -{ -register unsigned short bits; -int i; - -x += M; /* point to significand area */ - -bits = 0; -for( i=M; i<NI; i++ ) - { - if( *x & 1 ) - bits |= 1; - *x >>= 1; - if( bits & 2 ) - *x |= 0x8000; - bits <<= 1; - ++x; - } -} - - - -/* -; Shift significand up by 1 bit -*/ - -void eshup1(x) -register unsigned short *x; -{ -register unsigned short bits; -int i; - -x += NI-1; -bits = 0; - -for( i=M; i<NI; i++ ) - { - if( *x & 0x8000 ) - bits |= 1; - *x <<= 1; - if( bits & 2 ) - *x |= 1; - bits <<= 1; - --x; - } -} - - - -/* -; Shift significand down by 8 bits -*/ - -void eshdn8(x) -register unsigned short *x; -{ -register unsigned short newbyt, oldbyt; -int i; - -x += M; -oldbyt = 0; -for( i=M; i<NI; i++ ) - { - newbyt = *x << 8; - *x >>= 8; - *x |= oldbyt; - oldbyt = newbyt; - ++x; - } -} - -/* -; Shift significand up by 8 bits -*/ - -void eshup8(x) -register unsigned short *x; -{ -int i; -register unsigned short newbyt, oldbyt; - -x += NI-1; -oldbyt = 0; - -for( i=M; i<NI; i++ ) - { - newbyt = *x >> 8; - *x <<= 8; - *x |= oldbyt; - oldbyt = newbyt; - --x; - } -} - -/* -; Shift significand up by 16 bits -*/ - -void eshup6(x) -register unsigned short *x; -{ -int i; -register unsigned short *p; - -p = x + M; -x += M + 1; - -for( i=M; i<NI-1; i++ ) - *p++ = *x++; - -*p = 0; -} - -/* -; Shift significand down by 16 bits -*/ - -void eshdn6(x) -register unsigned short *x; -{ -int i; -register unsigned short *p; - -x += NI-1; -p = x + 1; - -for( i=M; i<NI-1; i++ ) - *(--p) = *(--x); - -*(--p) = 0; -} - -/* -; Add significands -; x + y replaces y -*/ - -void eaddm( x, y ) -unsigned short *x, *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( x, y ) -unsigned short *x, *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; - } -} - - -/* Divide significands */ - -static unsigned short equot[NI] = {0}; /* was static */ - -#if 0 -int edivm( den, num ) -unsigned short den[], num[]; -{ -int i; -register unsigned short *p, *q; -unsigned short j; - -p = &equot[0]; -*p++ = num[0]; -*p++ = num[1]; - -for( i=M; i<NI; i++ ) - { - *p++ = 0; - } - -/* Use faster compare and subtraction if denominator - * has only 15 bits of significance. - */ -p = &den[M+2]; -if( *p++ == 0 ) - { - for( i=M+3; i<NI; i++ ) - { - if( *p++ != 0 ) - goto fulldiv; - } - if( (den[M+1] & 1) != 0 ) - goto fulldiv; - eshdn1(num); - eshdn1(den); - - p = &den[M+1]; - q = &num[M+1]; - - for( i=0; i<NBITS+2; i++ ) - { - if( *p <= *q ) - { - *q -= *p; - j = 1; - } - else - { - j = 0; - } - eshup1(equot); - equot[NI-2] |= j; - eshup1(num); - } - goto divdon; - } - -/* The number of quotient bits to calculate is - * NBITS + 1 scaling guard bit + 1 roundoff bit. - */ -fulldiv: - -p = &equot[NI-2]; -for( i=0; i<NBITS+2; i++ ) - { - if( ecmpm(den,num) <= 0 ) - { - esubm(den, num); - j = 1; /* quotient bit = 1 */ - } - else - j = 0; - eshup1(equot); - *p |= j; - eshup1(num); - } - -divdon: - -eshdn1( equot ); -eshdn1( equot ); - -/* 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( a, b ) -unsigned short a[], b[]; -{ -unsigned short *p, *q; -int i, j, k; - -equot[0] = b[0]; -equot[1] = b[1]; -for( i=M; i<NI; i++ ) - equot[i] = 0; - -p = &a[NI-2]; -k = NBITS; -while( *p == 0 ) /* significand is not supposed to be all zero */ - { - eshdn6(a); - k -= 16; - } -if( (*p & 0xff) == 0 ) - { - eshdn8(a); - k -= 8; - } - -q = &equot[NI-1]; -j = 0; -for( i=0; i<k; i++ ) - { - if( *p & 1 ) - eaddm(b, equot); -/* remember if there were any nonzero bits shifted out */ - if( *q & 1 ) - j |= 1; - eshdn1(a); - eshdn1(equot); - } - -for( i=0; i<NI; i++ ) - b[i] = equot[i]; - -/* return flag for lost nonzero bits */ -return(j); -} - -#else - -/* Multiply significand of e-type number b -by 16-bit quantity a, e-type result to c. */ - -void m16m( a, b, c ) -unsigned short a; -unsigned short b[], 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( den, num ) -unsigned short den[], num[]; -{ -int i; -register unsigned short *p; -unsigned long tnum; -unsigned short j, tdenm, tquot; -unsigned short tprod[NI+1]; - -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 * 0xffffL) < 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 ); - } - } -/* - if( ecmpm( tprod, num ) > 0 ) - { - eshow( "tprod", tprod ); - eshow( "num ", num ); - printf( "tnum = %08lx, tden = %04x, tquot = %04x\n", - tnum, den[M+1], tquot ); - } -*/ - esubm( tprod, num ); -/* - if( ecmpm( num, den ) >= 0 ) - { - eshow( "num ", num ); - eshow( "den ", den ); - printf( "tnum = %08lx, tden = %04x, tquot = %04x\n", - tnum, den[M+1], tquot ); - } -*/ - 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( a, b ) -unsigned short a[], b[]; -{ -unsigned short *p, *q; -unsigned short pprod[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 ); -} - - -/* -eshow(str, x) -char *str; -unsigned short *x; -{ -int i; - -printf( "%s ", str ); -for( i=0; i<NI; i++ ) - printf( "%04x ", *x++ ); -printf( "\n" ); -} -*/ -#endif - - - -/* - * 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 "exp" is the biased exponent, which may be negative. - * the exponent field of "s" is ignored but is replaced by - * "exp" as adjusted by normalization and rounding. - * - * Input "rcntrl" is the rounding control. - */ - -static int rlast = -1; -static int rw = 0; -static unsigned short rmsk = 0; -static unsigned short rmbit = 0; -static unsigned short rebit = 0; -static int re = 0; -static unsigned short rbit[NI] = {0,0,0,0,0,0,0,0}; - -void emdnorm( s, lost, subflg, exp, rcntrl ) -unsigned short s[]; -int lost; -int subflg; -long exp; -int rcntrl; -{ -int i, j; -unsigned short r; - -/* Normalize */ -j = enormlz( s ); - -/* a blank significand could mean either zero or infinity. */ -#ifndef INFINITY -if( j > NBITS ) - { - ecleazs( s ); - return; - } -#endif -exp -= j; -#ifndef INFINITY -if( exp >= 32767L ) - goto overf; -#else -if( (j > NBITS) && (exp < 32767L) ) - { - ecleazs( s ); - return; - } -#endif -if( exp < 0L ) - { - if( exp > (long )(-NBITS-1) ) - { - j = (int )exp; - 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; -/* Set up rounding parameters if the control register changed. */ -if( rndprc != rlast ) - { - ecleaz( rbit ); - switch( rndprc ) - { - default: - case NBITS: - rw = NI-1; /* low guard word */ - rmsk = 0xffff; - rmbit = 0x8000; - rebit = 1; - re = rw - 1; - break; - case 113: - rw = 10; - rmsk = 0x7fff; - rmbit = 0x4000; - rebit = 0x8000; - re = rw; - break; - case 64: - rw = 7; - rmsk = 0xffff; - rmbit = 0x8000; - rebit = 1; - re = rw-1; - break; -/* For DEC arithmetic */ - case 56: - rw = 6; - rmsk = 0xff; - rmbit = 0x80; - rebit = 0x100; - re = rw; - break; - case 53: - rw = 6; - rmsk = 0x7ff; - rmbit = 0x0400; - rebit = 0x800; - re = rw; - break; - case 24: - rw = 4; - rmsk = 0xff; - rmbit = 0x80; - rebit = 0x100; - re = rw; - break; - } - rbit[re] = rebit; - rlast = rndprc; - } - -/* 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( (exp <= 0) && (rndprc != NBITS) ) -#else -if( (exp <= 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; -if( (r & rmbit) != 0 ) - { - if( r == rmbit ) - { - if( lost == 0 ) - { /* round to even */ - if( (s[re] & rebit) == 0 ) - goto mddone; - } - else - { - if( subflg != 0 ) - goto mddone; - } - } - eaddm( rbit, s ); - } -mddone: -#if IBMPC -if( (exp <= 0) && (rndprc != NBITS) ) -#else -if( (exp <= 0) && (rndprc != 64) && (rndprc != NBITS) ) -#endif - { - eshup1(s); - } -if( s[2] != 0 ) - { /* overflow on roundoff */ - eshdn1(s); - exp += 1; - } -mdfin: -s[NI-1] = 0; -if( exp >= 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; - if( rndprc == 24 ) - { - s[5] = 0; - s[6] = 0; - } - } -#endif - return; - } -if( exp < 0 ) - s[1] = 0; -else - s[1] = (unsigned short )exp; -} - - - -/* -; Subtract external format numbers. -; -; unsigned short a[NE], b[NE], c[NE]; -; esub( a, b, c ); c = b - a -*/ - -static int subflg = 0; - -void esub( a, b, c ) -unsigned short *a, *b, *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( c, NBITS ); - return; - } -#endif -subflg = 1; -eadd1( a, b, c ); -} - - -/* -; Add. -; -; unsigned short a[NE], b[NE], c[NE]; -; eadd( a, b, c ); c = b + a -*/ -void eadd( a, b, c ) -unsigned short *a, *b, *c; -{ - -#ifdef NANS -/* NaN plus anything is a NaN. */ -if( eisnan(a) ) - { - emov(a,c); - return; - } -if( eisnan(b) ) - { - emov(b,c); - return; - } -/* Infinity minus infinity is a NaN. - * Test for adding infinities of opposite signs. - */ -if( eisinf(a) && eisinf(b) - && ((eisneg(a) ^ eisneg(b)) != 0) ) - { - mtherr( "eadd", DOMAIN ); - enan( c, NBITS ); - return; - } -#endif -subflg = 0; -eadd1( a, b, c ); -} - -void eadd1( a, b, c ) -unsigned short *a, *b, *c; -{ -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( subflg ) - 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; - } |