/************************************************************** * * lucdwt.c * * Mersenne primality tester prototype source code. * * Updates: * 20 May 97 RDW - fixed win32 compiler warning * 26 Apr 97 RDW - fixed tabs and unix EOL * 20 Apr 97 RDW * 22 Oct 97 REC (Creation) * * c. 1997 Perfectly Scientific, Inc. * All Rights Reserved. * * Compile and run with, e.g.: * * % cc -O lucasDWT.c * % a.out 216091 16384 100 1 * **************************************************************/ /* Include Files */ #include #include #include #include /* definitions */ #define TWOPI (double)(2*3.1415926535897932384626433) #define SQRTHALF (double)(0.707106781186547524400844362104) #define SQRT2 (double)(1.414213562373095048801688724209) #define BITS 16 /* compiler options */ #ifdef _WIN32 #pragma warning( disable : 4127 4706 ) /* disable conditional is constant warning */ #endif /* global variables */ double *cn, *sn, *two_to_phi, *two_to_minusphi, *scrambled; double high,low,highinv,lowinv; int b, c, *permute; /* function prototypes */ void showusage(void); /************************************************************** * * Functions * **************************************************************/ /* rint is not ANSI compatible, so we need a definition for * WIN32 and other platforms with rint. */ double RINT(double x) { return floor(x + 0.5); } void print( double *x, int N ) { int printed = 0; while (N--) { if ((x[N]==0) && (!printed)) continue; printf("%d ",(int)(x[N])); printed=1; } printf("\n"); } void init_scramble_real( int n ) { register int i,j,k,halfn = n>>1; int tmp; for (i=0; i>=1; } j += k; } } void init_fft( int n ) { int j; double e = TWOPI/n; cn = (double *)malloc(sizeof(double)*n); sn = (double *)malloc(sizeof(double)*n); for (j=0;j>1, nminus = n-1, is, id; register int n2, n8, i, j; x = z-1; /* FORTRAN compatibility. */ is = 1; id = 4; do { for (i2=is;i2<=n;i2+=id) { i1 = i2+1; e = x[i2]; x[i2] = e + x[i1]; x[i1] = e - x[i1]; } is = (id<<1)-1; id <<= 2; } while (is>=1) { n2 <<= 1; n4 = n2>>2; n8 = n2>>3; is = 0; id = n2<<1; do { for (i=is;i>1, nminus = n-1, is, id; int n2, i, j; x = z-1; n2 = n<<1; while(nn >>= 1) { is = 0; id = n2; n2 >>= 1; n4 = n2>>2; n8 = n4>>1; do { for (i=is;i>1; register double c, d; b[0] *= b[0]; b[half] *= b[half]; for (k=1;k maxerr) maxerr = err; } *xptr = 0; j = k; bj = bk; xxptr = xptr++; do { if (j==N) j=0; if (j==0) { xxptr = x; bj = 0; w = floor(zz*hiinv); if (sign_flip) *xxptr -= (zz-w*hi); else *xxptr += (zz-w*hi); } else if (j==NminusOne) { w = floor(zz*loinv); if (sign_flip) *xxptr -= (zz-w*lo); else *xxptr += (zz-w*lo); } else if (bj >= c) { w = floor(zz*hiinv); if (sign_flip) *xxptr -= (zz-w*hi); else *xxptr += (zz-w*hi); } else { w = floor(zz*loinv); if (sign_flip) *xxptr -= (zz-w*lo); else *xxptr += (zz-w*lo); } zz = w; ++j; ++xxptr; bj += b; if (bj>=N) bj -= N; } while(zz!=0.0); bk += b; if (bk>=N) bk -= N; } return(maxerr); } void patch( double *x, int N ) { register int j,bj,NminusOne = N-1, carry; register double hi = high, lo = low, highliminv, lowliminv; register double *px = x, xx; double highlim,lowlim, lim, inv, base; carry = 0; highlim = hi*0.5; lowlim = lo*0.5; highliminv =1.0/highlim; lowliminv = 1.0/lowlim; xx = *px + carry; if (xx >= highlim) carry =((int)(xx*highliminv+1))>>1; else if (xx<-highlim) carry = -(((int)(1-xx*highliminv))>>1); else carry = 0; *(px++) = xx - carry*hi; bj = b; for (j=1; j= c) { if (xx >= highlim) carry =((int)(xx*highliminv+1))>>1; else if (xx<-highlim) carry = -(((int)(1-xx*highliminv))>>1); else carry = 0; *px = xx - carry*hi; } else { if (xx >= lowlim) carry =((int)(xx*lowliminv+1))>>1; else if (xx<-lowlim) carry = -(((int)(1-xx*lowliminv))>>1); else carry = 0; *px = xx - carry*lo; } ++px; bj += b; } xx = *px + carry; if (xx >= lowlim) carry = ((int)(xx*lowliminv+1))>>1; else if (xx<-lowlim) carry = -(((int)(1-xx*lowliminv))>>1); else carry = 0; *px = xx - carry*lo; if (carry) { j = 0; bj = 0; px = x; while (carry) { xx = *px + carry; if (j==0) { lim = highlim; inv = highliminv; base = hi; } else if (j==NminusOne) { lim = lowlim; inv = lowliminv; base = lo; } else if ((bj & NminusOne) >= c) { lim = highlim; inv = highliminv; base = hi; } else { lim = lowlim; inv = lowliminv; base = lo; } if (xx>=lim) carry = ((int)(xx*inv+1))>>1; else if (xx<-lim) carry = -(((int)(1-xx*inv))>>1); else carry = 0; *(px++) = xx - carry*base; bj += b; if (++j == N) { j = 0; bj = 0; px = x; } } } } void check_balanced( double *x, int N ) { int j,bj = 0,NminusOne = N-1; double limit, hilim,lolim,*ptrx = x; hilim = high*0.5; lolim = low*0.5; for (j=0; j= c) limit = hilim; else limit = lolim; assert ((*ptrx<=limit) && (*ptrx>=-limit)); ++ptrx; bj+=b; } } double lucas_square( double *x, int N, int error_log ) { register int j, *perm; register double err, *ptrx, *ptry, *ptrmphi; perm = permute; ptry = scrambled; for (j=0; j=c) x[j]+=high; else x[j]+=low; } else if (sudden_death) break; bj+=b; if (++j==N) { sudden_death = 1; j = 0; bj = 0; } } } void printbits( double *x, int q, int N, int totalbits ) { char *bits = (char *) malloc((int) totalbits); int j, k, i, word; j = 0; i = 0; do { k = (int)( ceil((double)q*(j+1)/N) - ceil((double)q*j/N)); if (k>totalbits) k = totalbits; totalbits -= k; word = (int)x[j++]; while(k--) { bits[i++] = (char)('0' + (word & 1)); word>>=1; } } while (totalbits); while (i--) { printf("%c",bits[i]); } printf("\n"); free(bits); } void showusage( void ) { fprintf(stderr,"Usage: lucas [n] [err]\n"); fprintf(stderr," q = Mersenne exponent\n"); fprintf(stderr," N = fft run-length\n"); fprintf(stderr," n = Number of Lucas iterations (or 0 for full test)\n"); fprintf(stderr," err = 1 to report maximum errors\n"); } /************************************************************** * * Main Function * **************************************************************/ void main( int argc, char **argv ) { int q, n, j; double *x, err; int last, errflag=0; if (argc<3) { showusage(); return; } q = (int)atol(argv[1]); last = q-1; n = (int)atol(argv[2]); if (argc>3) { if (atol(argv[3]) > 0) last = (int)atol(argv[3]); if (argc>4) errflag = (int)atol(argv[4]); } x = (double *) malloc(n*sizeof(double)); init_fft(n); init_lucas(q,n); for (j=0;j