void NR::mpdiv(Vec_O_UCHR &q, Vec_O_UCHR &r, Vec_I_UCHR &u, Vec_I_UCHR &v) { const int MACC=1; int i,is,mm; int n=u.size(); int m=v.size(); int p=r.size(); int n_min=MIN(m,p); if (m > n) nrerror("Divisor longer than dividend in mpdiv"); mm=m+MACC; Vec_UCHR s(mm),rr(mm),ss(mm+1),qq(n-m+1),t(n); mpinv(s,v); mpmul(rr,s,u); mpsad(ss,rr,1); mplsh(ss); mplsh(ss); mpmov(qq,ss); mpmov(q,qq); mpmul(t,qq,v); mplsh(t); mpsub(is,t,u,t); if (is != 0) nrerror("MACC too small in mpdiv"); for (i=0;i<n_min;i++) r[i]=t[i+n-m]; if (p>m) for (i=m;i<p;i++) r[i]=0; }
void mpdivmodfixfix(Mpint *q, Mpint *r, Mpint *n, Mpint *d) { int i, ns, ds; ns = n->neg; ds = d->neg; n->neg = 0; d->neg = 0; mpmovefixfix(r, n); mpmovecfix(q, 0); // shift denominator until it // is larger than numerator for(i=0; i<Mpprec*Mpscale; i++) { if(mpcmp(d, r) > 0) break; mplsh(d); } // if it never happens // denominator is probably zero if(i >= Mpprec*Mpscale) { q->ovf = 1; r->ovf = 1; n->neg = ns; d->neg = ds; yyerror("set ovf in mpdivmodfixfix"); return; } // shift denominator back creating // quotient a bit at a time // when done the remaining numerator // will be the remainder for(; i>0; i--) { mplsh(q); mprsh(d); if(mpcmp(d, r) <= 0) { mpaddcfix(q, 1); mpsubfixfix(r, d); } } n->neg = ns; d->neg = ds; r->neg = ns; q->neg = ns^ds; }
void NR::mp2dfr(Vec_IO_UCHR &a, string &s) { const unsigned int IAZ=48; int j,m; int n=a.size(); m=int(2.408*n); mplsh(a); for (j=0; j<m; j++) { mpsmu(a,a,10); s += a[0]+IAZ; mplsh(a); } }
void mpsqrt(unsigned char w[], unsigned char u[], unsigned char v[], int n, int m) { void mplsh(unsigned char u[], int n); void mpmov(unsigned char u[], unsigned char v[], int n); void mpmul(unsigned char w[], unsigned char u[], unsigned char v[], int n, int m); void mpneg(unsigned char u[], int n); void mpsdv(unsigned char w[], unsigned char u[], int n, int iv, int *ir); int i,ir,j,mm; float fu,fv; unsigned char *r,*s; r=cvector(1,n<<1); s=cvector(1,n<<1); mm=IMIN(m,MF); fv=(float) v[mm]; for (j=mm-1;j>=1;j--) { fv *= BI; fv += v[j]; } fu=1.0/sqrt(fv); for (j=1;j<=n;j++) { i=(int) fu; u[j]=(unsigned char) i; fu=256.0*(fu-i); } for (;;) { mpmul(r,u,u,n,n); mplsh(r,n); mpmul(s,r,v,n,IMIN(m,n)); mplsh(s,n); mpneg(s,n); s[1] -= 253; mpsdv(s,s,n,2,&ir); for (j=2;j<n;j++) { if (s[j]) { mpmul(r,s,u,n,n); mpmov(u,&r[1],n); break; } } if (j<n) continue; mpmul(r,u,v,n,IMIN(m,n)); mpmov(w,&r[1],n); free_cvector(s,1,n<<1); free_cvector(r,1,n<<1); return; } }
void mp2dfr(unsigned char a[], unsigned char s[], int n, int *m) { void mplsh(unsigned char u[], int n); void mpsmu(unsigned char w[], unsigned char u[], int n, int iv); int j; *m=(int) (2.408*n); for (j=1;j<=(*m);j++) { mpsmu(a,a,n,10); s[j]=a[1]+IAZ; mplsh(a,n); } }
void mpmulfixfix(Mpint *a, Mpint *b) { int i, j, na, nb; long *a1, x; Mpint s, q; if(a->ovf || b->ovf) { yyerror("ovf in mpmulfixfix"); a->ovf = 1; return; } // pick the smaller // to test for bits na = mplen(a); nb = mplen(b); if(na > nb) { mpmovefixfix(&s, a); a1 = &b->a[0]; na = nb; } else { mpmovefixfix(&s, b); a1 = &a->a[0]; } s.neg = 0; mpmovecfix(&q, 0); for(i=0; i<na; i++) { x = *a1++; for(j=0; j<Mpscale; j++) { if(x & 1) mpaddfixfix(&q, &s); mplsh(&s); x >>= 1; } } q.neg = a->neg ^ b->neg; mpmovefixfix(a, &q); if(a->ovf) yyerror("set ovf in mpmulfixfix"); }
// shift left by s (or right by -s) void mpshiftfix(Mpint *a, int s) { if(s >= 0) { while(s >= Mpscale) { mplshw(a); s -= Mpscale; } while(s > 0) { mplsh(a); s--; } } else { s = -s; while(s >= Mpscale) { mprshw(a); s -= Mpscale; } while(s > 0) { mprsh(a); s--; } } }