struct MParith { void mpadd(VecUchar_O &w, VecUchar_I &u, VecUchar_I &v) { Int j,n=u.size(),m=v.size(),p=w.size(); Int n_min=MIN(n,m),p_min=MIN(n_min,p-1); Uint ireg=0; for (j=p_min-1;j>=0;j--) { ireg=u[j]+v[j]+hibyte(ireg); w[j+1]=lobyte(ireg); } w[0]=hibyte(ireg); if (p > p_min+1) for (j=p_min+1;j=0;j--) { ireg=255+u[j]-v[j]+hibyte(ireg); w[j]=lobyte(ireg); } is=hibyte(ireg)-1; if (p > p_min) for (j=p_min;j=0;j--) { ireg=u[j]+hibyte(ireg); if (j+1 < p) w[j+1]=lobyte(ireg); } w[0]=hibyte(ireg); for (j=n+1;j=0;j--) { ireg=u[j]*iv+hibyte(ireg); if (j < p-1) w[j+1]=lobyte(ireg); } w[0]=hibyte(ireg); for (j=n+1;j p_min) for (j=p_min;j=0;j--) { ireg=255-u[j]+hibyte(ireg); u[j]=lobyte(ireg); } } void mpmov(VecUchar_O &u, VecUchar_I &v) { Int j,n=u.size(),m=v.size(),n_min=MIN(n,m); for (j=0;j n_min) for(j=n_min;j> 8) & 0xff);} void mpmul(VecUchar_O &w, VecUchar_I &u, VecUchar_I &v); void mpinv(VecUchar_O &u, VecUchar_I &v); void mpdiv(VecUchar_O &q, VecUchar_O &r, VecUchar_I &u, VecUchar_I &v); void mpsqrt(VecUchar_O &w, VecUchar_O &u, VecUchar_I &v); void mp2dfr(VecUchar_IO &a, string &s); string mppi(const Int np); }; void MParith::mpmul(VecUchar_O &w, VecUchar_I &u, VecUchar_I &v) { const Doub RX=256.0; Int j,nn=1,n=u.size(),m=v.size(),p=w.size(),n_max=MAX(m,n); Doub cy,t; while (nn < n_max) nn <<= 1; nn <<= 1; VecDoub a(nn,0.0),b(nn,0.0); for (j=0;j=0;j--) { t=b[j]/(nn >> 1)+cy+0.5; cy=Uint(t/RX); b[j]=t-cy*RX; } if (cy >= RX) throw("cannot happen in mpmul"); for (j=0;j=0;j--) { fv *= BI; fv += v[j]; } fu=1.0/fv; for (j=0;j n) throw("Divisor longer than dividend in mpdiv"); mm=m+MACC; VecUchar 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) throw("MACC too small in mpdiv"); for (i=0;im) for (i=m;i=0;j--) { fv *= BI; fv += v[j]; } fu=1.0/sqrt(fv); for (j=0;j