home *** CD-ROM | disk | FTP | other *** search
- /* qsqrta.c */
- /* Square root check routine, done by long division. */
- /* Copyright (C) 1984-1988 by Stephen L. Moshier. */
-
-
- #include "qhead.h"
- #include "mconf.h"
-
- extern unsigned short qzero[], qone[];
- static unsigned short rndbit[NQ+1] = {0};
- static short rndset = 0;
-
- int qsqrt( x, y )
- short *x, *y;
- {
- unsigned short temp[NQ+1], num[NQ+1], sq[NQ+1], xx[NQ+1];
- int i, j, k, n;
- long m, exp;
-
- if( rndset == 0 )
- {
- qclear( rndbit );
- rndbit[NQ] = 0;
- rndbit[NQ-1] = 1;
- rndset = 1;
- }
- /* Check for arg <= 0 */
- /*i = qcmp( x, qzero );*/
- if( x[1] == 0 )
- goto iszero;
- if( x[0] != 0 )
- {
- mtherr( "qsqrt", DOMAIN );
- iszero:
- qclear(y);
- return;
- }
-
- /* Bring in the arg and renormalized if it is denormal. */
- qmovz( x, xx );
- m = xx[1]; /* local long word exponent */
- /*
- if( m == 0 )
- m -= normlz( xx );
- */
- /* Divide exponent by 2 */
- m -= 0x4000;
- exp = (unsigned short )( (m / 2) + 0x4000 );
-
- /* Adjust if exponent odd */
- if( (m & 1) != 0 )
- {
- if( m > 0 )
- exp += 1;
- shdn1( xx );
- }
-
- qclear( sq );
- sq[NQ] = 0;
- qclear( num );
- num[NQ] = 0;
- n = 8;
-
- for( j=0; j<2*NQ-6; j++ )
- {
- /* bring in next word of arg */
- if( j < NQ-3 )
- num[NQ] = xx[j+3];
- /* Do additional bit on last outer loop, for roundoff. */
- if( j == 2*NQ-7 )
- n = 9;
- for( i=0; i<n; i++ )
- {
- /* Next 2 bits of arg */
- shup1( num );
- shup1( num );
- /* Shift up answer */
- shup1( sq );
- /* Make trial divisor */
- for( k=0; k<=NQ; k++ )
- temp[k] = sq[k];
- shup1( temp );
- addm( rndbit, temp );
- /* Subtract and insert answer bit if it goes in */
- if( cmpm( temp, num ) <= 0 )
- {
- subm( temp, num );
- sq[NQ-1] |= 1;
- }
- }
- }
-
- exp -= 1; /* Adjust for extra, roundoff loop done. */
- sq[1] = exp;
-
- /* Sticky bit = 1 if the remainder is nonzero. */
- k = 0;
- for( i=3; i<=NQ; i++ )
- k |= num[i];
-
- /* Renormalize and round off. */
- mdnorm( sq, k );
- qmov( sq, y );
- }
-