/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifdef SOLARIS #define RF_INLINE_MACROS 1 #endif static const double TwoTo16=65536.0; static const double TwoToMinus16=1.0/65536.0; static const double Zero=0.0; static const double TwoTo32=65536.0*65536.0; static const double TwoToMinus32=1.0/(65536.0*65536.0); #ifdef RF_INLINE_MACROS double upper32(double); double lower32(double, double); double mod(double, double, double); void i16_to_d16_and_d32x4(const double * /*1/(2^16)*/, const double * /* 2^16*/, const double * /* 0 */, double * /*result16*/, double * /* result32 */, float * /*source - should be unsigned int* converted to float* */); #else #ifdef MP_USE_FLOOR #include #else #define floor(d) ((double)((unsigned long long)(d))) #endif static double upper32(double x) { return floor(x*TwoToMinus32); } static double lower32(double x, double y) { return x-TwoTo32*floor(x*TwoToMinus32); } static double mod(double x, double oneoverm, double m) { return x-m*floor(x*oneoverm); } #endif static void cleanup(double *dt, int from, int tlen) { int i; double tmp,tmp1,x,x1; tmp=tmp1=Zero; /* original code ** for(i=2*from;i<2*tlen-2;i++) { x=dt[i]; dt[i]=lower32(x,Zero)+tmp1; tmp1=tmp; tmp=upper32(x); } dt[tlen-2]+=tmp1; dt[tlen-1]+=tmp; **end original code ***/ /* new code ***/ for(i=2*from;i<2*tlen;i+=2) { x=dt[i]; x1=dt[i+1]; dt[i]=lower32(x,Zero)+tmp; dt[i+1]=lower32(x1,Zero)+tmp1; tmp=upper32(x); tmp1=upper32(x1); } /** end new code **/ } void conv_d16_to_i32(unsigned int *i32, double *d16, long long *tmp, int ilen) { int i; long long t, t1, a, b, c, d; t1=0; a=(long long)d16[0]; b=(long long)d16[1]; for(i=0; i>32); d=(long long)d16[2*i+3]; t1+=(b&0xffff)<<16; t+=(b>>16)+(t1>>32); i32[i]=(unsigned int)t1; t1=t; a=c; b=d; } t1+=(unsigned int)a; t=(a>>32); t1+=(b&0xffff)<<16; i32[i]=(unsigned int)t1; } void conv_i32_to_d32(double *d32, unsigned int *i32, int len) { int i; #pragma pipeloop(0) for(i=0;i>16); } } void conv_i32_to_d32_and_d16(double *d32, double *d16, unsigned int *i32, int len) { int i = 0; unsigned int a; #pragma pipeloop(0) #ifdef RF_INLINE_MACROS for(;i>16); } } void adjust_montf_result(unsigned int *i32, unsigned int *nint, int len) { long long acc; int i; if(i32[len]>0) i=-1; else { for(i=len-1; i>=0; i--) { if(i32[i]!=nint[i]) break; } } if((i<0)||(i32[i]>nint[i])) { acc=0; for(i=0;i>32; } } } /* ** the lengths of the input arrays should be at least the following: ** result[nlen+1], dm1[nlen], dm2[2*nlen+1], dt[4*nlen+2], dn[nlen], nint[nlen] ** all of them should be different from one another ** */ void mont_mulf_noconv(unsigned int *result, double *dm1, double *dm2, double *dt, double *dn, unsigned int *nint, int nlen, double dn0) { int i, j, jj; int tmp; double digit, m2j, nextm2j, a, b; double *dptmp, *pdm1, *pdm2, *pdn, *pdtj, pdn_0, pdm1_0; pdm1=&(dm1[0]); pdm2=&(dm2[0]); pdn=&(dn[0]); pdm2[2*nlen]=Zero; if (nlen!=16) { for(i=0;i<4*nlen+2;i++) dt[i]=Zero; a=dt[0]=pdm1[0]*pdm2[0]; digit=mod(lower32(a,Zero)*dn0,TwoToMinus16,TwoTo16); pdtj=&(dt[0]); for(j=jj=0;j<2*nlen;j++,jj++,pdtj++) { m2j=pdm2[j]; a=pdtj[0]+pdn[0]*digit; b=pdtj[1]+pdm1[0]*pdm2[j+1]+a*TwoToMinus16; pdtj[1]=b; #pragma pipeloop(0) for(i=1;i