/*	esqrt.c		*/
/* Square root check routine, done by long division. */
/* by Stephen L. Moshier. */


#include "mconf.h"
#include "ehead.h"

void emovi(), emovo(), ecleaz(), emdnorm(), eaddm(), esubm();
int ecmpm();
static unsigned short rndbit[NI] = {0,0,0,0,0,0,0,1,0};

void esqrt( x, y )
short *x, *y;
{
unsigned short temp[NI], num[NI], sq[NI], xx[NI];
int i, j, k, n;
long m, exp;

/* Check for arg <= 0 */
i = ecmp( x, ezero );
if( i <= 0 )
	{
	eclear(y);
	if( i < 0 )
		mtherr( "esqrt", DOMAIN );
	return;
	}

/* Bring in the arg and renormalize if it is denormal. */
emovi( x, xx );
m = (long )xx[1]; /* local long word exponent */
if( m == 0 )
	m -= enormlz( xx );

/* Divide exponent by 2 */
m -= 0x3ffe;
exp = (unsigned short )( (m / 2) + 0x3ffe );

/* Adjust if exponent odd */
if( (m & 1) != 0 )
	{
	if( m > 0 )
		exp += 1;
	eshdn1( xx );
	}

ecleaz( sq );
ecleaz( num );
n = 8; /* get 8 bits of result per inner loop */

for( j=0; j<(2*NE-2); j++ )
	{
/* bring in next word of arg */
	if( j < NE )
		num[NI-1] = xx[j+3];
/* Do additional bit on last outer loop, for roundoff. */
	if( j == (2*NE-3) )
		n = 9;
	for( i=0; i<n; i++ )
		{
/* Next 2 bits of arg */
		eshup1( num );
		eshup1( num );
/* Shift up answer */
		eshup1( sq );
/* Make trial divisor */
		for( k=0; k<NI; k++ )
			temp[k] = sq[k];
		eshup1( temp );
		eaddm( rndbit, temp );
/* Subtract and insert answer bit if it goes in */
		if( ecmpm( temp, num ) <= 0 )
			{
			esubm( temp, num );
			sq[NI-2] |= 1;
			}
		}
	}

exp -= 1; /* Adjust for extra, roundoff loop done. */

/* Sticky bit = 1 if the remainder is nonzero. */
k = 0;
for( i=3; i<NI; i++ )
	k |= (int )num[i];

/* Renormalize and round off. */
emdnorm( sq, k, 0, exp, 64 );
emovo( sq, y );
}
