/* This program is copyright (c) 2000 by D E Knuth; * you may copy it freely AS LONG AS YOU MAKE ABSOLUTELY NO CHANGES! * You could also change it, but then you must rename the file and * tell people clearly that your version is not the same as mine. * It is explained in Seminumerical Algorithms, 3rd edition, Section 3.6 * (or in the errata to the 2nd edition --- see * http://www-cs-faculty.stanford.edu/~knuth/taocp.html * in the changes to pages 171 and following of Volume 2). */ /* If you find any bugs, please report them immediately to * taocp@cs.stanford.edu * (and you will be rewarded if the bug is genuine). Thanks! */ /************ see the book for explanations and caveats! *******************/ /************ in particular, you need two's complement arithmetic **********/ /* old-style C function declarations appear here for reasons of portability */ #define KK 100 /* the long lag */ #define LL 37 /* the short lag */ #define MM (1L<<30) /* the modulus */ #define mod_diff(x,y) (((x)-(y))&(MM-1)) /* subtraction mod MM */ long ran_x[KK]; /* the generator state */ /* void ran_array(long aa[],int n) */ void ran_array(aa,n) /* put n new random numbers in aa */ long *aa; /* destination */ int n; /* array length (must be at least KK) */ { register int i,j; for (j=0;j=MM) ss-=MM-2; /* cyclic shift 29 bits */ } for (;j0;j--) x[j+j]=x[j]; /* "square" */ for (j=KK+KK-2;j>KK-LL;j-=2) x[KK+KK-1-j]=evenize(x[j]); for (j=KK+KK-2;j>=KK;j--) if(is_odd(x[j])) { x[j-(KK-LL)]=mod_diff(x[j-(KK-LL)],x[j]); x[j-KK]=mod_diff(x[j-KK],x[j]); } if (is_odd(ss)) { /* "multiply by z" */ for (j=KK;j>0;j--) x[j]=x[j-1]; x[0]=x[KK]; /* shift the buffer cyclically */ if (is_odd(x[KK])) x[LL]=mod_diff(x[LL],x[KK]); } if (ss) ss>>=1; else t--; } for (j=0;j=0? *ran_arr_ptr++: ran_arr_cycle()) long ran_arr_cycle() { ran_array(ran_arr_buf,QUALITY); ran_arr_buf[100]=-1; ran_arr_ptr=ran_arr_buf+1; return ran_arr_buf[0]; } int main() { register int m; long a[2009]; ran_start(310952); for (m=0;m<=2009;m++) ran_array(a,1009); printf("%ld\n", a[0]); /* 461390032 */ ran_start(310952); for (m=0;m<=1009;m++) ran_array(a,2009); printf("%ld\n", a[0]); /* 461390032 */ return 0; }