|
|
1.1 ! root 1: #include "mp.h" ! 2: msqrt(a,b,r) mint *a,*b,*r; ! 3: { mint x,junk,y; ! 4: int j; ! 5: x.len=junk.len=y.len=0; ! 6: if(a->len<0) fatal("msqrt: neg arg"); ! 7: if(a->len==0) ! 8: { b->len=0; ! 9: r->len=0; ! 10: return(0); ! 11: } ! 12: if(a->len%2==1) x.len=(1+a->len)/2; ! 13: else x.len=1+a->len/2; ! 14: x.val=xalloc(x.len,"msqrt"); ! 15: for(j=0;j<x.len;x.val[j++]=0); ! 16: if(a->len%2==1) x.val[x.len-1]=0400; ! 17: else x.val[x.len-1]=1; ! 18: xfree(b); ! 19: xfree(r); ! 20: loop: ! 21: mdiv(a,&x,&y,&junk); ! 22: xfree(&junk); ! 23: madd(&x,&y,&y); ! 24: sdiv(&y,2,&y,(short *)&j); ! 25: if(mcmp(&x,&y)>0) ! 26: { xfree(&x); ! 27: move(&y,&x); ! 28: xfree(&y); ! 29: goto loop; ! 30: } ! 31: xfree(&y); ! 32: move(&x,b); ! 33: mult(&x,&x,&x); ! 34: msub(a,&x,r); ! 35: xfree(&x); ! 36: return(r->len); ! 37: } ! 38: ! 39: /* pathology: n<= 0 => r=rem=0, num <= 0, r=rem=0 */ ! 40: /* this is a lazy implementation, assuming n>=3 => root is a legal double */ ! 41: mroot(n, num, r, rem) ! 42: mint *num, *r, *rem; ! 43: { extern double log(), exp(); ! 44: double z; ! 45: int i; ! 46: static mint *xn, *xn1, *top, *bot; ! 47: static init; ! 48: if(!init++) { ! 49: xn = itom(0), xn1 = itom(0), top = itom(0), bot = itom(0); ! 50: } ! 51: if(n < 0 || num->len <= 0) { ! 52: msub(r, r, r); ! 53: move(r, rem); ! 54: return; ! 55: } ! 56: if(n == 1) { ! 57: move(num, r); ! 58: msub(rem, rem, rem); ! 59: return; ! 60: } ! 61: if(n == 2) { ! 62: msqrt(num, r, rem); ! 63: return; ! 64: } ! 65: /* compute approx bigger than root */ ! 66: for(z = 0, i = 0; i < num->len; i++) ! 67: z = z/32768 + num->val[i]; ! 68: /* num = z * 2^15*(len-1) */ ! 69: z = exp((log(z) + 15*(num->len-1)*log(2.))/n); ! 70: z = 1.01 * z + 1; /* make sure it is bigger than root */ ! 71: dtom(z, r); ! 72: /* ((n-1)*x^n+num)/(n*x^(n-1))*/ ! 73: for(;;) { ! 74: rpow(r, n - 1, xn1); ! 75: mult(r, xn1, xn); ! 76: imult(n-1, xn, top); ! 77: madd(top, num, top); ! 78: imult(n, xn1, bot); ! 79: mdiv(top, bot, xn1, rem); ! 80: switch(mcmp(xn1, r)) { ! 81: case -1: ! 82: move(xn1, r); ! 83: continue; ! 84: case 0: ! 85: move(xn1, r); ! 86: msub(num, xn, rem); ! 87: return; ! 88: case 1: /* since r was too large to start with */ ! 89: msub(num, xn, rem); ! 90: return; ! 91: } ! 92: } ! 93: } ! 94: ! 95: static ! 96: imult(n, a, b) ! 97: mint *a, *b; ! 98: { mint *x; ! 99: x = itom(n); ! 100: mult(x, a, b); ! 101: msub(x, x,x); ! 102: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.