home *** CD-ROM | disk | FTP | other *** search
- /* qflt.c
- * QFLOAT
- *
- * Extended precision floating point routines
- *
- * asctoq( string, q ) ascii string to q type
- * dtoq( &d, q ) DEC double precision to q type
- * etoq( &d, q ) IEEE double precision to q type
- * ltoq( &l, q ) long integer to q type
- * qabs(q) absolute value
- * qadd( a, b, c ) c = b + a
- * qclear(q) q = 0
- * qcmp( a, b ) compare a to b
- * qdiv( a, b, c ) c = b / a
- * qifrac( x, &l, frac ) x to integer part l and q type fraction
- * qinfin( x ) set x to infinity, leaving its sign alone
- * qmov( a, b ) b = a
- * qmul( a, b, c ) c = b * a
- * qmuli( a, b, c ) c = b * a, a has only 16 significant bits
- * qneg(q) q = -q
- * qnrmlz(q) adjust exponent and mantissa
- * qsub( a, b, c ) c = b - a
- * qtoasc( a, s, n ) q to ASCII string, n digits after decimal
- * qtod( q, &d ) convert q type to DEC double precision
- * qtoe( q, &d ) convert q type to IEEE double precision
- *
- * Data structure of the number (a "word" is 16 bits)
- *
- * sign word (0 for positive, -1 for negative)
- * exponent (0x4001 for 1.0)
- * high guard word (always zero after normalization)
- * N-1 mantissa words (most significant word first,
- * most significant bit is set)
- *
- * Numbers are stored in C language as arrays. All routines
- * use pointers to the arrays as arguments.
- *
- * The result is always normalized after each arithmetic operation.
- * All arithmetic results are chopped. No rounding is performed except
- * on conversion to double precision.
- */
-
- /*
- * Revision history:
- *
- * SLM, 5 Jan 84 PDP-11 assembly language version
- * SLM, 2 Mar 86 fixed bug in asctoq()
- * SLM, 6 Dec 86 C language version
- *
- */
-
- #include "mconf.h"
- #include "qhead.h"
-
- /* number of 16 bit words in mantissa area */
- /*define N 10*/
- /* max number of decimal digits in conversion */
- /*define NDEC 46*/
- /* number of bits of precision */
- /*define NBITS (OMG-1)*16*/
- /* array index of the exponent */
- #define E 1
- /* array index of first mantissa word */
- #define M 2
-
- /* Define 1 for sticky bit rounding */
- #define STICKY 0
-
- /* accumulators */
- static short ac1[NQ+1] = {0};
- static short ac2[NQ+1] = {0};
- static short ac3[NQ+1] = {0};
- static short ac4[NQ+1] = {0};
- /* shift count register */
- static int SC = 0;
-
- extern short qzero[], qone[];
-
-
- /*
- ; Absolute value
- ;
- ; short q[NQ];
- ; qabs( q );
- */
-
- qabs(x)
- short *x; /* x is the memory address of a short */
- {
-
- *x = 0; /* sign is first word of array */
- }
-
-
-
-
- /*
- ; Negate
- ;
- ; short q[NQ];
- ; qneg( q );
- */
-
- qneg(x)
- short *x;
- {
-
- *x = ~(*x); /* complement the sign */
- }
-
- /*
- ; convert long (32-bit) integer to q type
- ;
- ; long l;
- ; short q[NQ];
- ; ltoq( &l, q );
- ; note &l is the memory address of l
- */
-
- ltoq( lp, y )
- long *lp; /* lp is the memory address of a long integer */
- short *y; /* y is the address of a short */
- {
- register short *p, *q; /* use processor registers if possible */
- long ll;
-
- qclear( ac1 );
- ll = *lp; /* local copy of lp */
- if( ll < 0 )
- {
- ll = -ll; /* make it positive */
- ac1[0] = -1; /* put correct sign in the q type number */
- }
-
- /* move the long integer to ac1 mantissa area */
- p = &ac1[M];
- *p++ = ll >> 16;
- *p = ll;
- /*
- * q = (short *)≪
- * #if DEC
- * p = &ac1[M];
- * *p++ = *q++;
- * #endif
- * #if IBMPC
- * p = &ac1[M+1];
- * *p-- = *q++;
- * #endif
- * *p = *q;
- */
- ac1[E] = 040020; /* exponent if normalize shift count were 0 */
- ac1[NQ] = 0;
- if( normlz( ac1 ) ) /* normalize the mantissa */
- qclear( ac1 ); /* it was zero */
- else
- ac1[E] -= SC; /* else subtract shift count from exponent */
- qmov( ac1, y ); /* output the answer */
- }
-
- /*
- ; convert DEC double precision to q type
- ; double d;
- ; short q[NQ];
- ; dtoq( &d, q );
- */
- dtoq( d, y )
- short *d;
- short *y;
- {
- register short r, *p;
-
- qclear(y); /* start with a zero */
- p = y; /* point to our number */
- r = *d; /* get DEC exponent word */
- if( *d < 0 )
- *p = -1; /* fill in our sign */
- ++p; /* bump pointer to our exponent word */
- r &= 0x7fff; /* strip the sign bit */
- if( r == 0 ) /* answer = 0 if high order DEC word = 0 */
- return;
-
-
- r >>= 7; /* shift exponent word down 7 bits */
- r -= 0200; /* subtract DEC exponent offset */
- r += 040000; /* add our q type exponent offset */
- *p++ = r; /* to form our exponent */
-
- r = *d++; /* now do the high order mantissa */
- r &= 0177; /* strip off the DEC exponent and sign bits */
- r |= 0200; /* the DEC understood high order mantissa bit */
- *p++ = r; /* put result in our high guard word */
-
- *p++ = *d++; /* fill in the rest of our mantissa */
- *p++ = *d++;
- *p = *d;
-
- shdn8(y); /* shift our mantissa down 8 bits */
- }
-
- /*
- ; convert q type to DEC double precision
- ; double d;
- ; short q[NQ];
- ; qtod( q, &d );
- */
-
- qtod( x, d )
- short *x, *d;
- {
- register short r;
- int i, j;
-
- *d = 0;
- if( *x < 0 )
- *d = 0100000;
- qmovz( x, ac1 );
- r = ac1[E];
- if( r < 037600 )
- goto zout;
- i = ac1[M+4];
- if( (i & 0200) != 0 )
- {
- if( (i & 0377) == 0200 )
- {
- if( (i & 0400) != 0 )
- {
- /* check all less significant bits */
- for( j=M+5; j<=NQ; j++ )
- {
- if( ac1[j] != 0 )
- goto yesrnd;
- }
- }
- goto nornd;
- }
- yesrnd:
- qclear( ac2 );
- ac2[ M+4 ] = 0200;
- ac2[NQ] = 0;
- addm( ac2, ac1 );
- normlz(ac1);
- r -= SC;
- }
-
- nornd:
-
- r -= 040000;
- r += 0200;
- if( r < 0 )
- {
- zout:
- *d++ = 0;
- *d++ = 0;
- *d++ = 0;
- *d++ = 0;
- return;
- }
- if( r >= 0377 )
- {
- *d++ = 077777;
- *d++ = -1;
- *d++ = -1;
- *d++ = -1;
- return;
- }
- r &= 0377;
- r <<= 7;
- shup8( ac1 );
- ac1[M] &= 0177;
- r |= ac1[M];
- *d++ |= r;
- *d++ = ac1[M+1];
- *d++ = ac1[M+2];
- *d++ = ac1[M+3];
- }
-
- /*
- ; Find integer and fractional parts
-
- ; long i;
- ; short x[NQ], frac[NQ];
- ; qifrac( x, &i, frac );
- */
-
- qifrac( x, i, frac )
- short *x;
- long *i;
- short *frac;
- {
- register short *p;
-
- qmovz( x, ac1 );
- SC = ac1[E] - 040000;
- if( SC <= 0 )
- {
- /* if exponent <= 0, integer = 0 and argument is fraction */
- *i = 0L;
- qmov( ac1, frac );
- return;
- }
- if( SC > 31 )
- {
- /*
- ; long integer overflow: output large integer
- ; and correct fraction
- */
- *i = 0x7fffffff;
- shift( ac1 );
- goto lab10;
- }
-
- if( SC > 16 )
- {
- /*
- ; shift more than 16 bits: shift up SC-16, output the integer,
- ; then complete the shift to get the fraction.
- */
- SC -= 16;
- shift( ac1 );
- *i = ((unsigned long )ac1[M] << 16) | (unsigned short )ac1[M+1];
- /*
- * p = (short *)i;
- * #ifdef DEC
- * *p++ = ac1[M];
- * *p++ = ac1[M+1];
- * #else
- * *p++ = ac1[M+1];
- * *p++ = ac1[M];
- * #endif
- */
- shup16( ac1 );
- goto lab10;
- }
-
- /* shift not more than 16 bits */
- shift( ac1 );
- *i = ac1[M] & 0xffff;
-
- lab10:
- if( x[0] )
- *i = -(*i);
- ac1[0] = 0;
- ac1[E] = 040000;
- ac1[M] = 0;
- if( normlz(ac1) )
- qclear( ac1 );
- else
- ac1[E] -= SC;
-
- qmov( ac1, frac );
- }
-
-
- /*
- ; subtract
- ;
- ; short a[NQ], b[NQ], c[NQ];
- ; qsub( a, b, c ); c = b - a
- */
-
- static short subflg = 0;
-
- qsub( a, b, c )
- short *a, *b, *c;
- {
-
- subflg = 1;
- qadd1( a, b, c );
- }
-
-
- /*
- ; add
- ;
- ; short a[NQ], b[NQ], c[NQ];
- ; qadd( a, b, c ); c = b + a
- */
-
- qadd( a, b, c )
- short *a, *b, *c;
- {
-
- subflg = 0;
- qadd1( a, b, c );
- }
-
- qadd1( a, b, c )
- short *a, *b, *c;
- {
- long lt;
- int i;
- #if STICKY
- int lost;
- #endif
-
- qmovz( a, ac1 );
- qmovz( b, ac2 );
- if( subflg )
- ac1[0] = ~ac1[0];
-
- /* compare exponents */
- SC = ac1[E] - ac2[E];
- if( SC > 0 )
- { /* put the larger number in ac2 */
- qmovz( ac2, ac3 );
- qmov( ac1, ac2 );
- qmov( ac3, ac1 );
- SC = -SC;
- }
-
- #if STICKY
- lost = 0;
- #endif
- if( SC != 0 )
- {
- if( SC < -NBITS-1 )
- goto done; /* answer same as larger addend */
- #if STICKY
- lost = shift( ac1, SC ); /* shift the smaller number down */
- #else
- shift( ac1, SC ); /* shift the smaller number down */
- #endif
- }
- else
- {
- /* exponents were the same, so must compare mantissae */
- i = cmpm( ac1, ac2 );
- if( i == 0 )
- { /* the numbers are identical */
- /* if different signs, result is zero */
- if( ac1[0] != ac2[0] )
- goto underf;
- /* if exponents zero, result is zero */
- if( ac1[E] == 0 )
- goto underf;
- /* if same sign, result is double */
- ac2[E] += 1;
- goto done;
- }
- if( i > 0 )
- { /* put the larger number in ac2 */
- qmovz( ac2, ac3 );
- qmov( ac1, ac2 );
- qmov( ac3, ac1 );
- }
- }
-
- if( ac1[0] == ac2[0] )
- {
- addm( ac1, ac2 );
- subflg = 0;
- }
- else
- {
- subm( ac1, ac2 );
- subflg = 1;
- }
- if( normlz(ac2) )
- goto underf;
-
- lt = (long )ac2[E] - SC;
- if( lt > 32767 )
- goto overf;
- if( lt < 0 )
- {
- /* mtherr( "qadd", UNDERFLOW );*/
- goto underf;
- }
- ac2[E] = lt;
-
- /* round off */
- i = ac2[NQ] & 0xffff;
- if( i & 0x8000 )
- {
- #if STICKY
- if( i == 0x8000 )
- {
- if( lost == 0 )
- {
- /* Critical case, round to even */
- if( (ac2[NQ-1] & 1) == 0 )
- goto done;
- }
- else
- {
- if( subflg != 0 )
- goto done;
- }
- }
- #else
- if( subflg != 0 )
- goto done;
- #endif
-
- qclear( ac1 );
- ac1[NQ] = 0;
- ac1[NQ-1] = 1;
- addm( ac1, ac2 );
- normlz(ac2);
- if( SC )
- {
- lt = (long )ac2[E] - SC;
- if( lt > 32767 )
- goto overf;
- ac2[E] = lt;
- }
- }
- done:
- qmov( ac2, c );
- return;
-
- underf:
- qclear(c);
- return;
-
- overf:
- mtherr( "qadd", OVERFLOW );
- qinfin(c);
- return;
- }
-
- /*
- ; divide
- ;
- ; short a[NQ], b[NQ], c[NQ];
- ; qdiv( a, b, c ); c = b / a
- */
- /* for Newton iteration version:
- * extern short qtwo[];
- * static short qt[NQ] = {0};
- * static short qu[NQ] = {0};
- */
- qdiv( a, b, c )
- short *a, *b, *c;
- {
- int ctr, i;
- long lt;
- double da;
-
- if( b[E] == 0 )
- {
- qclear(c); /* numerator is zero */
- return;
- }
-
- if( a[E] == 0 )
- { /* divide by zero */
- qinfin(c);
- mtherr( "qdiv", SING );
- return;
- }
- qmovz( b, ac3 );
- divm( a, ac3 );
- /* calculate exponent */
- lt = (long )ac3[E] - (long )a[E];
- ac3[E] = lt;
- ac3[NQ] = 0;
- normlz(ac3);
- /* Newton iteration version */
- lt = lt - SC + 16386L;
- /* Taylor series version */
- /*lt = lt - SC + 16385L;*/
- ac3[E] = lt;
-
- if( a[0] == b[0] )
- ac3[0] = 0;
- else
- ac3[0] = -1;
-
- qmov( ac3, c );
- }
-
- /*
- ; multiply
- ;
- ; short a[NQ], b[NQ], c[NQ];
- ; qmul( a, b, c ); c = b * a
- */
- qmul( a, b, c )
- short *a, *b, *c;
- {
- register short *p;
- register int ctr;
- long lt;
-
- if( (a[E] == 0) || (b[E] == 0) )
- {
- qclear(c);
- return;
- }
- /* detect multiplication by small integer a */
- if( a[4] == 0 )
- {
- p = &a[5];
- for( ctr=5; ctr<NQ; ctr++ )
- {
- if( *p++ != 0 )
- goto nota;
- }
- qmov( b, ac3 );
- mulin( a, ac3 );
- lt = (long)a[E] + (long )ac3[E] - 32768L;
- goto mulcon;
- }
-
- nota:
- /* detect multiplication by small integer b */
- if( b[4] == 0 )
- {
- p = &b[5];
- for( ctr=5; ctr<NQ; ctr++ )
- {
- if( *p++ != 0 )
- goto notb;
- }
- qmov( a, ac3 );
- mulin( b, ac3 );
- lt = (long)b[E] + (long )ac3[E] - 32768L;
- goto mulcon;
- }
-
- notb:
-
- qmov( a, ac3 );
- mulm( b, ac3 );
- lt = (long)b[E] + (long )ac3[E] - 32768L;
-
- mulcon:
- /* calculate sign of product */
- if( b[0] == a[0] )
- ac3[0] = 0;
- else
- ac3[0] = -1;
-
- if( lt > 32767 )
- goto overf;
- ac3[E] = lt;
- ac3[NQ] = 0;
- if( normlz(ac3) )
- goto underf;
- lt = lt - SC + 16384L;
- if( lt > 32767 )
- goto overf;
- if( lt < 0 )
- goto underf;
- ac3[E] = lt;
- qmov( ac3, c );
- return;
-
- underf:
- qclear(c);
- return;
-
- overf:
- qinfin(c);
- mtherr( "qmul", OVERFLOW );
- return;
- }
-
-
-
-
- /* Multiply, a has at most 16 significant bits */
-
- qmuli( a, b, c )
- short *a, *b, *c;
- {
- int ctr;
- long lt;
-
- if( (a[E] == 0) || (b[E] == 0) )
- {
- qclear(c);
- return;
- }
-
- qmov( b, ac3 );
- mulin( a, ac3 );
-
- /* calculate sign of product */
- if( b[0] == a[0] )
- ac3[0] = 0;
- else
- ac3[0] = -1;
-
- /* calculate exponent */
- lt = (long)ac3[E] + (long )a[E] - 32768L;
- if( lt > 32767 )
- goto overf;
- ac3[E] = lt;
- ac3[NQ] = 0;
- if( normlz(ac3) )
- goto underf;
- lt = lt - SC + 16384L;
- if( lt > 32767 )
- goto overf;
- if( lt < 0 )
- goto underf;
- ac3[E] = lt;
- qmov( ac3, c );
- return;
-
- underf:
- qclear(c);
- return;
-
- overf:
- qinfin(c);
- mtherr( "qmuli", OVERFLOW );
- return;
- }
-
-
-
-
- /*
- ; Compare mantissas
- ;
- ; short a[NQ], b[NQ];
- ; cmpm( a, b );
- ;
- ; for the mantissas:
- ; returns +1 if a > b
- ; 0 if a == b
- ; -1 if a < b
- */
-
- cmpm( a, b )
- register unsigned short *a, *b;
- {
- int i;
-
- a += 2; /* skip up to mantissa area */
- b += 2;
- for( i=0; i<OMG; i++ )
- {
- if( *a++ != *b++ )
- goto difrnt;
- }
- return(0);
-
- difrnt:
- if( *(--a) > *(--b) )
- return(1);
- else
- return(-1);
- }
-
- /*
- ; shift mantissa
- ;
- ; Shifts mantissa area up or down by the number of bits
- ; given by the variable SC.
- */
-
- shift( x )
- short *x;
- {
- short *p;
- #if STICKY
- int lost;
- #endif
-
- if( SC == 0 )
- {
- #if STICKY
- return(0);
- #else
- return;
- #endif
- }
-
- #if STICKY
- lost = 0;
- #endif
- if( SC < 0 )
- {
- p = x + NQ;
- SC = -SC;
- while( SC >= 16 )
- {
- #if STICKY
- lost |= *p;
- #endif
- shdn16(x);
- SC -= 16;
- }
-
- while( SC >= 8 )
- {
- #if STICKY
- lost |= *p & 0xff;
- #endif
- shdn8(x);
- SC -= 8;
- }
-
- while( SC > 0 )
- {
- #if STICKY
- lost |= *p & 1;
- #endif
- shdn1(x);
- SC -= 1;
- }
- }
- else
- {
- while( SC >= 16 )
- {
- shup16(x);
- SC -= 16;
- }
-
- while( SC >= 8 )
- {
- shup8(x);
- SC -= 8;
- }
-
- while( SC > 0 )
- {
- shup1(x);
- SC -= 1;
- }
- }
- #if STICKY
- return( lost );
- #endif
- }
-
- /*
- ; normalize
- ;
- ; shift normalizes the mantissa area pointed to by R1
- ; shift count (up = positive) returned in SC
- */
-
- normlz(x)
- short x[];
- {
- register short *p;
-
- SC = 0;
- p = &x[M];
- if( *p != 0 )
- goto normdn;
- ++p;
- if( *p < 0 )
- return(0); /* already normalized */
-
- while( *p == 0 )
- {
- shup16(x);
- SC += 16;
- /* With guard word, there are NBITS+16 bits available.
- * return true if all are zero.
- */
- if( SC > NBITS )
- return(1);
- }
-
- /* see if high byte is zero */
- while( (*p & 0xff00) == 0 )
- {
- shup8(x);
- SC += 8;
- }
- /* now shift 1 bit at a time */
-
- while( *p > 0)
- {
- shup1(x);
- SC += 1;
- /*
- if( SC > NBITS )
- {
- printf( "normlz error\n");
- return(0);
- }
- */
- }
- return(0);
-
- /* normalize by shifting down out of the high guard word
- of the mantissa */
-
- normdn:
-
- if( *p & 0xff00 )
- {
- shdn8(x);
- SC -= 8;
- }
- while( *p != 0 )
- {
- shdn1(x);
- SC -= 1;
- /*
- if( SC < -NBITS )
- {
- printf( "low normlz error\n");
- return(0);
- }
- */
- }
- return(0);
- }
-
- /*
- ; Clear out entire number, including sign and exponent, pointed
- ; to by x
- ;
- ; short x[];
- ; qclear( x );
- */
-
- qclear( x )
- register short *x;
- {
- register int i;
-
- for( i=0; i<NQ; i++ )
- *x++ = 0;
- }
-
- /*
- ; Fill entire number, including exponent and mantissa, with
- ; largest possible number.
- */
-
- qinfin(x)
- register short *x;
- {
- register int i;
-
- ++x; /* skip over the sign */
- *x++ = 0x7fff;
- *x++ = 0;
- for( i=0; i<OMG-1; i++ )
- *x++ = 0xffff;
- }
-
- /* normalization program */
- qnrmlz(x)
- short *x; /* x is the memory address of a short */
- {
-
- qmovz( x, ac1 );
- normlz( ac1 ); /* shift normalize the mantissa */
- ac1[E] -= SC; /* subtract the shift count from the exponent */
- qmov( ac1, x );
- }
-
-
-
-
- /*
- ; Convert IEEE double precision to Q type
- ; double d;
- ; short q[N+2];
- ; etoq( &d, q );
- */
-
- etoq( e, y )
- short *e, *y;
- {
- #ifdef DEC
- dtoq(e,y);
- #else
- register short r;
- register short *p;
- short yy[NQ+1];
- int denorm;
-
-
- denorm = 0; /* flag if denormalized number */
- qclear(yy);
- yy[NQ] = 0;
-
- #ifdef MIEEE
-
- #endif
-
-
- #ifdef IBMPC
- e += 3;
- #endif
-
- /*
- r = *e & 0x7fff;
- if( r == 0 )
- return;
- */
-
- r = *e;
- yy[0] = 0;
- if( r < 0 )
- yy[0] = -1;
-
- yy[M] = (r & 0x0f) | 0x10;
- r &= ~0x800f; /* strip sign and 4 mantissa bits */
- r >>= 4;
- /* If zero exponent, then the mantissa is denormalized.
- * So, take back the understood high mantissa bit. */
- if( r == 0 )
- {
- denorm = 1;
- yy[M] &= ~0x10;
- }
- r += 040001 - 01777;
- yy[E] = r;
- p = &yy[M+1];
- #ifdef MIEEE
- ++e;
- *p++ = *e++;
- *p++ = *e++;
- *p++ = *e++;
- #endif
- #ifdef IBMPC
- *p++ = *(--e);
- *p++ = *(--e);
- *p++ = *(--e);
- #endif
- SC = -5;
- shift(yy);
- if( denorm )
- { /* if zero exponent, then normalize the mantissa */
- if( normlz( yy ) )
- qclear(yy);
- else
- yy[E] -= SC-1;
- }
- qmov( yy, y );
- /* not DEC */
- #endif
- }
-
- /*
- ; Q type to IEEE double precision
- ; double d;
- ; short q[N+2];
- ; qtoe( q, &d );
- */
- qtoe( x, e )
- short *x, *e;
- {
- #ifdef DEC
- qtod(x,e);
- #else
- short i, j, k;
- register short *p;
-
-
- #ifdef MIEEE
-
- #endif
- #ifdef IBMPC
- e += 3;
- #endif
-
-
- *e = 0; /* output high order */
- p = &ac1[0];
- qmovz( x, p );
- if( *p++ < 0 )
- *e = 0x8000; /* output sign bit */
-
- normlz(ac1);
- *p -= SC;
-
- i = *p++ -(040001 - 01777); /* adjust exponent for offsets */
-
- /* Handle denormalized small numbers.
- * The tiniest number represented appears to be 2**-1074.
- */
- if( i <= 0 )
- {
- if( i > -53 )
- {
- SC = i - 1;
- shift( ac1 );
- i = 0;
- }
- else
- {
- /*ozero:*/
- #ifdef MIEEE
- ++e;
- *e++ = 0;
- *e++ = 0;
- *e++ = 0;
- #endif
- #ifdef IBMPC
- *(--e) = 0;
- *(--e) = 0;
- *(--e) = 0;
- #endif
- return;
- }
- }
-
- /* round off to nearest or even */
- k = ac1[M+4];
- if( (k & 0x400) != 0 )
- {
- if( (k & 0x07ff) == 0x400 )
- {
- if( (k & 0x800) != 0 )
- {
- /* check all less significant bits */
- for( j=M+5; j<=NQ; j++ )
- {
- if( ac1[j] != 0 )
- goto yesrnd;
- }
- }
- goto nornd;
- }
- yesrnd:
- qclear( ac2 );
- ac2[NQ] = 0;
- ac2[M+4] = 0x800;
- addm( ac2, ac1 );
- if( ac1[2] )
- {
- shdn1(ac1);
- i += 1;
- }
- if( (i == 0) && (ac1[3] & 0x8000) )
- i += 1;
- }
-
- nornd:
-
- if( i > 2047 )
- { /* Saturate at largest number less than infinity. */
- mtherr( "qtoe", OVERFLOW );
- *e |= 0x7fef;
- #ifdef MIEEE
- ++e;
- *e++ = 0xffff;
- *e++ = 0xffff;
- *e++ = 0xffff;
- #endif
- #ifdef IBMPC
- *(--e) = 0xffff;
- *(--e) = 0xffff;
- *(--e) = 0xffff;
- #endif
- return;
- }
-
-
- i <<= 4;
- SC = 5;
- shift( ac1 );
- i |= *p++ & 0x0f; /* *p = ac1[M] */
- *e |= i; /* high order output already has sign bit set */
- #ifdef MIEEE
- ++e;
- *e++ = *p++;
- *e++ = *p++;
- *e++ = *p++;
- #endif
- #ifdef IBMPC
- *(--e) = *p++;
- *(--e) = *p++;
- *(--e) = *p;
- #endif
- /* not DEC */
- #endif
- }
-
-
-
- /* qtoasc.c */
- /* Convert q type number to ASCII string */
-
- /*include "qhead.h"*/
-
- #define NTEN 12
-
- #if NQ < 13
- #define NTT 12
- static short qtens[NTEN+1][NTT] = {
- /* 4096 */
- {0x0000,0x7527,0x0000,0xc460,0x5202,0x8a20,0x979a,0xc94c,
- 0x153f,0x804a,0x4a92,0x6576,},
- /* 2048 */
- {0x0000,0x5a94,0x0000,0x9e8b,0x3b5d,0xc53d,0x5de4,0xa74d,
- 0x28ce,0x329a,0xce52,0x6a32,},
- /* 1024 */
- {0x0000,0x4d4a,0x0000,0xc976,0x7586,0x8175,0x0c17,0x650d,
- 0x3d28,0xf18b,0x50ce,0x526c,},
- /* 512 */
- {0x0000,0x46a5,0x0000,0xe319,0xa0ae,0xa60e,0x91c6,0xcc65,
- 0x5c54,0xbc50,0x58f8,0x9c66,},
- /* 256 */
- {0x0000,0x4353,0x0000,0xaa7e,0xebfb,0x9df9,0xde8d,0xddbb,
- 0x901b,0x98fe,0xeab7,0x851e,},
- /* 128 */
- {0x0000,0x41aa,0x0000,0x93ba,0x47c9,0x80e9,0x8cdf,0xc66f,
- 0x336c,0x36b1,0x0137,0x0235,},
- /* 64 */
- {0x0000,0x40d5,0x0000,0xc278,0x1f49,0xffcf,0xa6d5,0x3cbf,
- 0x6b71,0xc76b,0x25fb,0x50f8,},
- /* 32 */
- {0000000,0040153,0000000,0116705,0126650,0025560,
- 0132635,0170040,0000000,0000000,0000000,0000000,},
- /* 16 */
- {0000000,0040066,0000000,0107033,0144677,0002000,
- 0000000,0000000,0000000,0000000,0000000,0000000,},
- /* 8 */
- {0000000,0040033,0000000,0137274,0020000,0000000,
- 0000000,0000000,0000000,0000000,0000000,0000000,},
- /* 4 */
- {0000000,0040016,0000000,0116100,0000000,0000000,
- 0000000,0000000,0000000,0000000,0000000,0000000,},
- /* 2 */
- {0000000,0040007,0000000,0144000,0000000,0000000,
- 0000000,0000000,0000000,0000000,0000000,0000000,},
- /* 1 */
- {0000000,0040004,0000000,0120000,0000000,0000000,
- 0000000,0000000,0000000,0000000,0000000,0000000,},
- };
-
- static short qmtens[NTEN+1][NTT] = {
- /* -4096 */
- {0x0000,0x0ada,0x0000,0xa6dd,0x04c8,0xd2ce,0x9fde,0x2de3,
- 0x8123,0xa1c3,0xcffc,0x2030,},
- /* -2048 */
- {0x0000,0x256d,0x0000,0xceae,0x534f,0x3436,0x2de4,0x4925,
- 0x12d4,0xf2ea,0xd2cb,0x8264,},
- /* -1024 */
- {0x0000,0x32b7,0x0000,0xa2a6,0x82a5,0xda57,0xc0bd,0x87a6,
- 0x0158,0x6bd3,0xf698,0xf53f,},
- /* -512 */
- {0x0000,0x395c,0x0000,0x9049,0xee32,0xdb23,0xd21c,0x7132,
- 0xd332,0xe3f2,0x04d4,0xe731,},
- /* -256 */
- {0x0000,0x3cae,0x0000,0xc031,0x4325,0x637a,0x1939,0xfa91,
- 0x1155,0xfefb,0x5308,0xa23e,},
- /* -128 */
- {0x0000,0x3e57,0x0000,0xddd0,0x467c,0x64bc,0xe4a0,0xac7c,
- 0xb3f6,0xd05d,0xdbde,0xe26d,},
- /* -64 */
- {0x0000,0x3f2c,0x0000,0xa87f,0xea27,0xa539,0xe9a5,0x3f23,
- 0x98d7,0x47b3,0x6224,0x2a20,},
- /* -32 */
- {0x0000,0x3f96,0x0000,0xcfb1,0x1ead,0x4539,0x94ba,0x67de,
- 0x18ed,0xa581,0x4af2,0x0b5b,},
- /* -16 */
- {0x0000,0x3fcb,0x0000,0xe695,0x94be,0xc44d,0xe15b,0x4c2e,
- 0xbe68,0x7989,0xa9b3,0xbf71,},
- /* -8 */
- {0x0000,0x3fe6,0x0000,0xabcc,0x7711,0x8461,0xcefc,0xfdc2,
- 0x0d2b,0x36ba,0x7c3d,0x3d4d,},
- /* -4 */
- {0x0000,0x3ff3,0x0000,0xd1b7,0x1758,0xe219,0x652b,0xd3c3,
- 0x6113,0x404e,0xa4a8,0xc155,},
- /* -2 */
- {0x0000,0x3ffa,0x0000,0xa3d7,0x0a3d,0x70a3,0xd70a,0x3d70,
- 0xa3d7,0x0a3d,0x70a3,0xd70a,},
- /* -1 */
- {0x0000,0x3ffd,0x0000,0xcccc,0xcccc,0xcccc,0xcccc,0xcccc,
- 0xcccc,0xcccc,0xcccc,0xcccd,},
- };
-
- #else
-
- #define NTT 24
- static short qtens[NTEN+1][NTT] = {
- /* 4096 */
- {0x0000,0x7527,0x0000,0xc460,0x5202,0x8a20,0x979a,0xc94c,
- 0x153f,0x804a,0x4a92,0x6576,0x1fb2,0x444e,0x2267,0xdd5c,
- 0xf7c9,0x45f2,0x2a3f,0xfff0,0xd1d2,0xe184,0x69b1,0xea39,},
- /* 2048 */
- {0x0000,0x5a94,0x0000,0x9e8b,0x3b5d,0xc53d,0x5de4,0xa74d,
- 0x28ce,0x329a,0xce52,0x6a31,0x97bb,0xebe3,0x034f,0x7715,
- 0x4ce2,0xbcba,0x1964,0x8b21,0xc11e,0xb962,0xb1b6,0x1b94,},
- /* 1024 */
- {0x0000,0x4d4a,0x0000,0xc976,0x7586,0x8175,0x0c17,0x650d,
- 0x3d28,0xf18b,0x50ce,0x526b,0x9882,0x7524,0x9b0f,0xd6f4,
- 0xb6d2,0x7bd1,0xc61c,0x2530,0x69a5,0xc329,0xf9af,0x4a9c,},
- /* 512 */
- {0x0000,0x46a5,0x0000,0xe319,0xa0ae,0xa60e,0x91c6,0xcc65,
- 0x5c54,0xbc50,0x58f8,0x9c65,0x8398,0x1d13,0x4cba,0x422d,
- 0x38ea,0x3584,0xcde4,0x0b9a,0x1d7d,0x634d,0xf2d8,0x74a2,},
- /* 256 */
- {0x0000,0x4353,0x0000,0xaa7e,0xebfb,0x9df9,0xde8d,0xddbb,
- 0x901b,0x98fe,0xeab7,0x851e,0x4cbf,0x3de2,0xf98a,0xae78,
- 0x0c7f,0xea81,0xc788,0x5a6b,0x43a2,0xa6c4,0x95b8,0xccd6,},
- /* 128 */
- {0x0000,0x41aa,0x0000,0x93ba,0x47c9,0x80e9,0x8cdf,0xc66f,
- 0x336c,0x36b1,0x0137,0x0234,0xf3fd,0x7b08,0xdd39,0x0bc3,
- 0xc54e,0x3f40,0xf7e6,0x424b,0xa54f,0x8040,0x0000,0x0000,},
- /* 64 */
- {0x0000,0x40d5,0x0000,0xc278,0x1f49,0xffcf,0xa6d5,0x3cbf,
- 0x6b71,0xc76b,0x25fb,0x50f8,0x0800,0x0000,0x0000,0x0000,
- 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,},
- /* 32 */
- {0000000,0040153,0000000,0116705,0126650,0025560,
- 0132635,0170040,0000000,0000000,0000000,0000000,
- 0000000,0000000,0000000,0000000,0000000,0000000,
- 0000000,0000000,0000000,0000000,0000000,0000000,},
- /* 16 */
- {0000000,0040066,0000000,0107033,0144677,0002000,
- 0000000,0000000,0000000,0000000,0000000,0000000,
- 0000000,0000000,0000000,0000000,0000000,0000000,
- 0000000,0000000,0000000,0000000,0000000,0000000,},
- /* 8 */
- {0000000,0040033,0000000,0137274,0020000,0000000,
- 0000000,0000000,0000000,0000000,0000000,0000000,
- 0000000,0000000,0000000,0000000,0000000,0000000,
- 0000000,0000000,0000000,0000000,0000000,0000000,},
- /* 4 */
- {0000000,0040016,0000000,0116100,0000000,0000000,
- 0000000,0000000,0000000,0000000,0000000,0000000,
- 0000000,0000000,0000000,0000000,0000000,0000000,
- 0000000,0000000,0000000,0000000,0000000,0000000,},
- /* 2 */
- {0000000,0040007,0000000,0144000,0000000,0000000,
- 0000000,0000000,0000000,0000000,0000000,0000000,
- 0000000,0000000,0000000,0000000,0000000,0000000,
- 0000000,0000000,0000000,0000000,0000000,0000000,},
- /* 1 */
- {0000000,0040004,0000000,0120000,0000000,0000000,
- 0000000,0000000,0000000,0000000,0000000,0000000,
- 0000000,0000000,0000000,0000000,0000000,0000000,
- 0000000,0000000,0000000,0000000,0000000,0000000,},
- };
-
- static short qmtens[NTEN+1][NTT] = {
- /* -4096 */
- {0x0000,0x0ada,0x0000,0xa6dd,0x04c8,0xd2ce,0x9fde,0x2de3,
- 0x8123,0xa1c3,0xcffc,0x2030,0x5d02,0x44e0,0x91ba,0x5e2d,
- 0x7403,0x972f,0x6f2b,0x04e6,0x63ac,0x16d5,0x1215,0x9834,},
- /* -2048 */
- {0x0000,0x256d,0x0000,0xceae,0x534f,0x3436,0x2de4,0x4925,
- 0x12d4,0xf2ea,0xd2cb,0x8263,0xca5c,0xbc77,0x4bd9,0x71aa,
- 0xd590,0x46c7,0x4249,0xdddd,0xc0df,0xbb0d,0x6f2c,0x0584,},
- /* -1024 */
- {0x0000,0x32b7,0x0000,0xa2a6,0x82a5,0xda57,0xc0bd,0x87a6,
- 0x0158,0x6bd3,0xf698,0xf53e,0x94d1,0xb235,0x7c32,0xc0ea,
- 0xff37,0x55a2,0xddcd,0x5191,0xa70f,0x9e33,0x9aa9,0x6270,},
- /* -512 */
- {0x0000,0x395c,0x0000,0x9049,0xee32,0xdb23,0xd21c,0x7132,
- 0xd332,0xe3f2,0x04d4,0xe731,0x7d62,0x209b,0x6a93,0xd4c9,
- 0x4a9d,0xa069,0x3e0c,0xfefd,0xe89b,0x01e5,0x1068,0xe0e4,},
- /* -256 */
- {0x0000,0x3cae,0x0000,0xc031,0x4325,0x637a,0x1939,0xfa91,
- 0x1155,0xfefb,0x5308,0xa23e,0x2ed2,0x7766,0xe8cc,0x9b03,
- 0x5377,0x08b1,0x648f,0x7a73,0x0e52,0xe6e7,0x4360,0x55f4,},
- /* -128 */
- {0x0000,0x3e57,0x0000,0xddd0,0x467c,0x64bc,0xe4a0,0xac7c,
- 0xb3f6,0xd05d,0xdbde,0xe26c,0xa606,0x3461,0xfffa,0x4ed7,
- 0x75fc,0x49f2,0x7952,0xf2f3,0xa45f,0x9009,0xf3c9,0xee49,},
- /* -64 */
- {0x0000,0x3f2c,0x0000,0xa87f,0xea27,0xa539,0xe9a5,0x3f23,
- 0x98d7,0x47b3,0x6224,0x2a1f,0xee40,0xd90a,0xab31,0x0e12,
- 0x8b5d,0x938c,0xfb3f,0x6f20,0x3147,0x025d,0x1129,0xe492,},
- /* -32 */
- {0x0000,0x3f96,0x0000,0xcfb1,0x1ead,0x4539,0x94ba,0x67de,
- 0x18ed,0xa581,0x4af2,0x0b5b,0x1aa0,0x28cc,0xd99e,0x59e3,
- 0x38e3,0x87ad,0x8e28,0x5676,0x0892,0x1621,0x96af,0x3c7f,},
- /* -16 */
- {0x0000,0x3fcb,0x0000,0xe695,0x94be,0xc44d,0xe15b,0x4c2e,
- 0xbe68,0x7989,0xa9b3,0xbf71,0x6c1a,0xdd27,0xf085,0x23cc,
- 0xd348,0x4db6,0x70aa,0xd6e0,0x12cf,0x7fa7,0xcf42,0x8583,},
- /* -8 */
- {0x0000,0x3fe6,0x0000,0xabcc,0x7711,0x8461,0xcefc,0xfdc2,
- 0x0d2b,0x36ba,0x7c3d,0x3d4d,0x3d75,0x8161,0x697c,0x7068,
- 0xf3b4,0x6d2f,0x8350,0x5705,0x755f,0xd37a,0x3b04,0x8dd9,},
- /* -4 */
- {0x0000,0x3ff3,0x0000,0xd1b7,0x1758,0xe219,0x652b,0xd3c3,
- 0x6113,0x404e,0xa4a8,0xc154,0xc985,0xf06f,0x6944,0x6738,
- 0x1d7d,0xbf48,0x7fcb,0x923a,0x29c7,0x79a6,0xb50b,0x0f28,},
- /* -2 */
- {0x0000,0x3ffa,0x0000,0xa3d7,0x0a3d,0x70a3,0xd70a,0x3d70,
- 0xa3d7,0x0a3d,0x70a3,0xd70a,0x3d70,0xa3d7,0x0a3d,0x70a3,
- 0xd70a,0x3d70,0xa3d7,0x0a3d,0x70a3,0xd70a,0x3d70,0xa3d7,},
- /* -1 */
- {0x0000,0x3ffd,0x0000,0xcccc,0xcccc,0xcccc,0xcccc,0xcccc,
- 0xcccc,0xcccc,0xcccc,0xcccc,0xcccc,0xcccc,0xcccc,0xcccc,
- 0xcccc,0xcccc,0xcccc,0xcccc,0xcccc,0xcccc,0xcccc,0xcccd,},
- };
- #endif
-
-
-
- qtoasc( q, string, ndigs )
- short q[];
- char *string;
- int ndigs;
- {
- long digit;
- short x[NTT], xt[NTT];
- short *p, *r, *ten, *tenth;
- short sign;
- int i, k, expon;
- char *s, *ss;
-
- qmov( q, x );
- sign = x[0];
- x[0] = 0;
- expon = 0;
- ten = &qtens[NTEN][0];
-
- i = qcmp( qone, x );
- if( i == 0 )
- goto isone;
- if( x[1] == 0 )
- {
- qclear( x );
- goto isone;
- }
-
- if( i < 0 )
- {
- k = 4096;
- p = &qtens[0][0];
- qmov( qone, ac4 );
- qmov( x, xt );
- while( qcmp( ten, x ) <= 0 )
- {
- if( qcmp( p, xt ) <= 0 )
- {
- qdiv( p, xt, xt );
- qmul( p, ac4, ac4 );
- expon += k;
- }
- k >>= 1;
- if( k == 0 )
- break;
- p += NTT;
- }
- qdiv( ac4, x, x );
- }
- else
- {
- k = -4096;
- p = &qmtens[0][0];
- r = &qtens[0][0];
- tenth = &qmtens[NTEN][0];
- while( qcmp( tenth, x ) > 0 )
- {
- if( qcmp( p, x ) >= 0 )
- {
- qmul( r, x, x );
- expon += k;
- }
- k /= 2;
- /* Prevent infinite loop due to arithmetic error: */
- if( k == 0 )
- break;
- p += NTT;
- r += NTT;
- }
- qmuli( ten, x, x );
- expon -= 1;
- }
-
- isone:
- qifrac( x, &digit, x );
- /* The following check handles numbers very close to 10**(2**n)
- * when there is a mistake due to arithmetic error.
- */
- if( digit >= 10 )
- {
- qdiv( ten, x, x );
- expon += 1;
- digit = 1;
- }
- s = string;
- if( sign < 0 )
- *s++ = '-';
- else
- *s++ = ' ';
- *s++ = (char )digit + 060;
- *s++ = '.';
- if( ndigs < 0 )
- ndigs = 0;
- if( ndigs > NDEC )
- ndigs = NDEC;
- for( k=0; k<ndigs; k++ )
- {
- qmuli( ten, x, x );
- qifrac( x, &digit, x );
- *s++ = (char )digit + 060;
- }
-
- *s = '\0'; /* mark end of string */
- ss = s;
-
- /* round off the ASCII string */
-
- qmuli( ten, x, x );
- qifrac( x, &digit, x );
- if( digit > 4 )
- {
- /* Check for critical rounding case */
- if( digit == 5 )
- {
- if( qcmp( x, qzero ) != 0 )
- goto roun; /* round to nearest */
- if( (*(s-1) & 1) == 0 )
- goto doexp; /* round to even */
- }
- roun:
- --s;
- k = *s & 0x7f;
- /* Carry out to most significant digit? */
- if( k == '.' )
- {
- --s;
- k = *s & 0x7f;
- k += 1;
- *s = k;
- /* Most significant digit rounds to 10? */
- if( k > '9' )
- {
- *s = '1';
- expon += 1;
- }
- goto doexp;
- }
- /* Round up and carry out from less significant digits. */
- k += 1;
- *s = k;
- if( k > '9' )
- {
- *s = '0';
- goto roun;
- }
- }
-
- doexp:
-
- sprintf( ss, "E%d\0", expon );
- }
-
-
- /* short a[NQ], b[NQ];
- * qcmp( a, b )
- *
- * returns +1 if a > b
- * 0 if a == b
- * -1 if a < b
- */
-
- qcmp( p, q )
- register unsigned short *p, *q;
- {
- unsigned short r[NQ];
- register int i;
- int msign;
-
- if( ( *(p+1) <= NBITS) && ( *(q+1) <= NBITS ) )
- {
- qsub( q, p, r );
- if( r[E] == 0 )
- return( 0 );
- if( r[0] == 0 )
- return( 1 );
- return( -1 );
- }
-
- if( *p != *q )
- { /* the signs are different */
- if( *p == 0 )
- return( 1 );
- else
- return( -1 );
- }
-
- /* both are the same sign */
- if( *p == 0 )
- msign = 1;
- else
- msign = -1;
-
- i = NQ;
- 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 */
- }
-
-
-
- /*
- ; ASCTOQ
- ; ASCTOQ.MAC LATEST REV: 11 JAN 84
- ; SLM, 3 JAN 78
- ;
- ; Convert ASCII string to quadruple precision floating point
- ;
- ; Numeric input is free field decimal number
- ; with max of 15 digits with or without
- ; decimal point entered as ASCII from teletype.
- ; Entering E after the number followed by a second
- ; number causes the second number to be interpreted
- ; as a power of 10 to be multiplied by the first number
- ; (i.e., "scientific" notation).
- ;
- ; Usage:
- ; asctoq( string, q );
- */
-
- /*if NQ < 13*/
- /*static short qten[NTT] = {0,040004,0,0120000,0,0,0,0,0,0,0,0};*/
-
- static short qten[24] = {
- 0,040004,0,0120000,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0
- };
-
-
- asctoq( s, y )
- char *s;
- short *y;
- {
- short yy[NQ+1], qt[NQ];
- int esign, nsign, decflg, sgnflg, nexp, exp, prec;
- short *p;
-
-
- nsign = 0;
- decflg = 0;
- sgnflg = 0;
- nexp = 0;
- exp = 0;
- prec = 0;
- qclear( yy );
- yy[NQ] = 0;
-
- nxtcom:
- if( (*s >= '0') && (*s <= '9') )
- {
- if( (prec == 0) && (decflg == 0) && (*s == '0') )
- goto donchr;
- if( prec < NDEC )
- {
- if( decflg )
- nexp += 1; /* count digits after decimal point */
- shup1( yy ); /* multiply current number by 10 */
- qmovz( yy, ac2 );
- shup1( ac2 );
- shup1( ac2 );
- addm( ac2, yy );
- qclear( ac2 );
- ac2[OMG+1] = *s - '0';
- addm( ac2, yy );
- }
- prec += 1;
- goto donchr;
- }
-
- switch( *s )
- {
- case ' ':
- break;
- case 'E':
- case 'e':
- goto expnt;
- case '.': /* decimal point */
- if( decflg )
- goto error;
- ++decflg;
- break;
- case '-':
- nsign = -1;
- case '+':
- if( sgnflg )
- goto error;
- ++sgnflg;
- break;
- case '\0':
- /* For Microware OS-9 operating system: */
- #ifndef OSK
- case '\n':
- #endif
- case '\r':
- goto daldone;
- default:
- error:
- printf( "asctoq conversion error\n" );
- qclear(y);
- return;
- }
- donchr:
- ++s;
- goto nxtcom;
-
-
- /* EXPONENT INTERPRETATION */
- expnt:
-
- esign = 1;
- exp = 0;
- ++s;
- /* check for + or - */
- if( *s == '-' )
- {
- esign = -1;
- ++s;
- }
- if( *s == '+' )
- ++s;
- while( (*s >= '0') && (*s <= '9') )
- {
- exp *= 10;
- exp += *s++ - '0';
- }
- if( esign < 0 )
- exp = -exp;
-
- daldone:
- nexp = exp - nexp;
-
- if( normlz(yy) )
- {
- qclear(y);
- return;
- }
-
- yy[E] = 040000 + NBITS - SC;
- qmov( yy, y );
- y[0] = nsign;
-
- /* multiply or divide by 10**NEXP */
- if( nexp == 0 )
- goto aexit;
- esign = 0;
- if( nexp < 0 )
- {
- esign = -1;
- nexp = -nexp;
- }
-
- p = &qtens[NTEN][0];
- exp = 1;
- qmov( qone, qt );
-
- do
- {
- if( exp & nexp )
- qmul( p, qt, qt );
- exp <<= 1;
- p -= NQ;
- }
- while( exp < 8192 );
-
- if( esign < 0 )
- qdiv( qt, y, y );
- else
- qmul( qt, y, y );
- aexit:
- return;
- }
-
-