/******************************************************************************/
/* */
/* N-WORD SQUARE ROOT */
/* 04/05/14 (dkc) */
/* */
/******************************************************************************/
void addn(unsigned int *a, unsigned int *b, unsigned int n);
void subn(unsigned int *a, unsigned int *b, unsigned int n);
void shiftn(unsigned int *a, unsigned int *b, unsigned int shift, unsigned
int n);
void setn(unsigned int *a, unsigned int b, unsigned int n);
unsigned int normn(unsigned int *a, unsigned int n);
unsigned int orn(unsigned int *a, unsigned int n);
void lshiftn(unsigned int *a, unsigned int *b, unsigned int shift, unsigned
int n);
void copyn(unsigned int *a, unsigned int *b, unsigned int n);
//
unsigned int sqrtn(unsigned int num, unsigned int *R, unsigned int m) {
unsigned int count,o;
unsigned int B[64],N[64],T[64],U[64];
if (m>64)
return(0);
//
// unsigned int res=0;
// unsigned int bit=1<<30;
// while (bit>num)
// bit>>=2;
// while (bit!=0) {
// if (num>=res+bit) {
// num-=res+bit;
// res=(res>>1)+bit;
// }
// else
// res>>=1;
// bit>>=2;
// }
//
setn(R,0,m); // res=0
setn(B,0,m);
B[0]=1<<30; // bit=1<<30
setn(N,num,m);
count=normn(N,m);
count=count-1;
if ((count&1)!=0)
count=count-1;
lshiftn(N,T,count,m);
copyn(T,N,m);
o=orn(B,m);
while (o!=0) {
copyn(R,T,m);
addn(B,T,m); // res+bit
copyn(T,U,m); // save res+bit
subn(N,U,m); // num-(res+bit)
if ((U[0]&0x80000000)==0) {
copyn(U,N,m); // num-=res+bit
shiftn(R,R,1,m); // res>>1
addn(B,R,m); // res=(res>>1)+bit
}
else
shiftn(R,R,1,m); // res>>1
shiftn(B,B,2,m); // bit=bit>>2
o=orn(B,m);
}
shiftn(R,R,count/2-m*16+32,m);
return(1);
}