void setall(long iseed1,long iseed2) /* ********************************************************************** void setall(long iseed1,long iseed2) SET ALL random number generators Sets the initial seed of generator 1 to ISEED1 and ISEED2. The initial seeds of the other generators are set accordingly, and all generators states are set to these seeds. This is a transcription from Pascal to Fortran of routine Set_Initial_Seed from the paper L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package with Splitting Facilities." ACM Transactions on Mathematical Software, 17:98-111 (1991) Arguments iseed1 -> First of two integer seeds iseed2 -> Second of two integer seeds ********************************************************************** */ { #define numg 32L extern void gsrgs(long getset,long *qvalue); extern void gssst(long getset,long *qset); extern void gscgn(long getset,long *g); extern long Xm1,Xm2,Xa1vw,Xa2vw,Xig1[],Xig2[]; long T1; long g,ocgn; long qrgnin; T1 = 1; /* TELL IGNLGI, THE ACTUAL NUMBER GENERATOR, THAT THIS ROUTINE HAS BEEN CALLED. */ gssst(1,&T1); gscgn(0L,&ocgn); /* Initialize Common Block if Necessary */ gsrgs(0L,&qrgnin); if(!qrgnin) inrgcm(); *Xig1 = iseed1; *Xig2 = iseed2; initgn(-1L); for(g=2; g<=numg; g++) { *(Xig1+g-1) = mltmod(Xa1vw,*(Xig1+g-2),Xm1); *(Xig2+g-1) = mltmod(Xa2vw,*(Xig2+g-2),Xm2); gscgn(1L,&g); initgn(-1L); } gscgn(1L,&ocgn); #undef numg }
void initgn(long isdtyp) /* ********************************************************************** void initgn(long isdtyp) INIT-ialize current G-e-N-erator Reinitializes the state of the current generator This is a transcription from Pascal to Fortran of routine Init_Generator from the paper L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package with Splitting Facilities." ACM Transactions on Mathematical Software, 17:98-111 (1991) Arguments isdtyp -> The state to which the generator is to be set isdtyp = -1 => sets the seeds to their initial value isdtyp = 0 => sets the seeds to the first value of the current block isdtyp = 1 => sets the seeds to the first value of the next block ********************************************************************** */ { #define numg 32L extern void gsrgs(long getset,long *qvalue); extern void gscgn(long getset,long *g); extern long Xm1,Xm2,Xa1w,Xa2w,Xig1[],Xig2[],Xlg1[],Xlg2[],Xcg1[],Xcg2[]; long g; long qrgnin; /* Abort unless random number generator initialized */ gsrgs(0L,&qrgnin); if(qrgnin) goto S10; fprintf(stderr,"%s\n", " INITGN called before random number generator initialized -- abort!"); exit(1); S10: gscgn(0L,&g); if(-1 != isdtyp) goto S20; *(Xlg1+g-1) = *(Xig1+g-1); *(Xlg2+g-1) = *(Xig2+g-1); goto S50; S20: if(0 != isdtyp) goto S30; goto S50; S30: /* do nothing */ if(1 != isdtyp) goto S40; *(Xlg1+g-1) = mltmod(Xa1w,*(Xlg1+g-1),Xm1); *(Xlg2+g-1) = mltmod(Xa2w,*(Xlg2+g-1),Xm2); goto S50; S40: fprintf(stderr,"%s\n","isdtyp not in range in INITGN"); exit(1); S50: *(Xcg1+g-1) = *(Xlg1+g-1); *(Xcg2+g-1) = *(Xlg2+g-1); #undef numg }
long ignlgi(void) /* ********************************************************************** long ignlgi(void) GeNerate LarGe Integer Returns a random integer following a uniform distribution over (1, 2147483562) using the current generator. This is a transcription from Pascal to Fortran of routine Random from the paper L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package with Splitting Facilities." ACM Transactions on Mathematical Software, 17:98-111 (1991) ********************************************************************** */ { #define numg 32L extern void gsrgs(long getset,long *qvalue); extern void gssst(long getset,long *qset); extern void gscgn(long getset,long *g); extern void inrgcm(void); extern long Xm1,Xm2,Xa1,Xa2,Xcg1[],Xcg2[]; extern long Xqanti[]; long ignlgi,curntg,k,s1,s2,z; long qqssd,qrgnin; /* IF THE RANDOM NUMBER PACKAGE HAS NOT BEEN INITIALIZED YET, DO SO. IT CAN BE INITIALIZED IN ONE OF TWO WAYS : 1) THE FIRST CALL TO THIS ROUTINE 2) A CALL TO SETALL. */ gsrgs(0L,&qrgnin); if(!qrgnin) inrgcm(); gssst(0,&qqssd); if(!qqssd) setall(1234567890L,123456789L); /* Get Current Generator */ gscgn(0L,&curntg); s1 = *(Xcg1+curntg-1); s2 = *(Xcg2+curntg-1); k = s1/53668L; s1 = Xa1*(s1-k*53668L)-k*12211; if(s1 < 0) s1 += Xm1; k = s2/52774L; s2 = Xa2*(s2-k*52774L)-k*3791; if(s2 < 0) s2 += Xm2; *(Xcg1+curntg-1) = s1; *(Xcg2+curntg-1) = s2; z = s1-s2; if(z < 1) z += (Xm1-1); if(*(Xqanti+curntg-1)) z = Xm1-z; ignlgi = z; return ignlgi; #undef numg }
void advnst(long k) /* ********************************************************************** void advnst(long k) ADV-a-N-ce ST-ate Advances the state of the current generator by 2^K values and resets the initial seed to that value. This is a transcription from Pascal to Fortran of routine Advance_State from the paper L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package with Splitting Facilities." ACM Transactions on Mathematical Software, 17:98-111 (1991) Arguments k -> The generator is advanced by2^K values ********************************************************************** ** Buttrey note: replaced all exit() calls with return()s -- Jan 2015. ** Also replaced all fprintf's with Rprintf ********************************************************************** */ { #define numg 32L extern void gsrgs(long getset,long *qvalue); extern void gscgn(long getset,long *g); extern long Xm1,Xm2,Xa1,Xa2,Xcg1[],Xcg2[]; static long g,i,ib1,ib2; static long qrgnin; /* Abort unless random number generator initialized */ gsrgs(0L,&qrgnin); if(qrgnin) goto S10; Rprintf(" ADVNST called before random generator initialized - ABORT"); return; S10: gscgn(0L,&g); ib1 = Xa1; ib2 = Xa2; for(i=1; i<=k; i++) { ib1 = mltmod(ib1,ib1,Xm1); ib2 = mltmod(ib2,ib2,Xm2); } setsd(mltmod(ib1,*(Xcg1+g-1),Xm1),mltmod(ib2,*(Xcg2+g-1),Xm2)); /* NOW, IB1 = A1**K AND IB2 = A2**K */ #undef numg }
void setant(long qvalue) /* ********************************************************************** void setant(long qvalue) SET ANTithetic Sets whether the current generator produces antithetic values. If X is the value normally returned from a uniform [0,1] random number generator then 1 - X is the antithetic value. If X is the value normally returned from a uniform [0,N] random number generator then N - 1 - X is the antithetic value. All generators are initialized to NOT generate antithetic values. This is a transcription from Pascal to Fortran of routine Set_Antithetic from the paper L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package with Splitting Facilities." ACM Transactions on Mathematical Software, 17:98-111 (1991) Arguments qvalue -> nonzero if generator G is to generating antithetic values, otherwise zero ********************************************************************** */ { #define numg 32L extern void gsrgs(long getset,long *qvalue); extern void gscgn(long getset,long *g); extern long Xqanti[]; long g; long qrgnin; /* Abort unless random number generator initialized */ gsrgs(0L,&qrgnin); if(qrgnin) goto S10; fprintf(stderr,"%s\n", " SETANT called before random number generator initialized -- abort!"); exit(1); S10: gscgn(0L,&g); Xqanti[g-1] = qvalue; #undef numg }
void setsd(long iseed1,long iseed2) /* ********************************************************************** void setsd(long iseed1,long iseed2) SET S-ee-D of current generator Resets the initial seed of the current generator to ISEED1 and ISEED2. The seeds of the other generators remain unchanged. This is a transcription from Pascal to Fortran of routine Set_Seed from the paper L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package with Splitting Facilities." ACM Transactions on Mathematical Software, 17:98-111 (1991) Arguments iseed1 -> First integer seed iseed2 -> Second integer seed ********************************************************************** */ { #define numg 32L extern void gsrgs(long getset,long *qvalue); extern void gscgn(long getset,long *g); extern long Xig1[],Xig2[]; long g; long qrgnin; /* Abort unless random number generator initialized */ gsrgs(0L,&qrgnin); if(qrgnin) goto S10; fprintf(stderr,"%s\n", " SETSD called before random number generator initialized -- abort!"); exit(1); S10: gscgn(0L,&g); *(Xig1+g-1) = iseed1; *(Xig2+g-1) = iseed2; initgn(-1L); #undef numg }
void getsd(long *iseed1,long *iseed2) /* ********************************************************************** void getsd(long *iseed1,long *iseed2) GET SeeD Returns the value of two integer seeds of the current generator This is a transcription from Pascal to Fortran of routine Get_State from the paper L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package with Splitting Facilities." ACM Transactions on Mathematical Software, 17:98-111 (1991) Arguments iseed1 <- First integer seed of generator G iseed2 <- Second integer seed of generator G ********************************************************************** */ { #define numg 32L extern void gsrgs(long getset,long *qvalue); extern void gscgn(long getset,long *g); extern long Xcg1[],Xcg2[]; long g; long qrgnin; /* Abort unless random number generator initialized */ gsrgs(0L,&qrgnin); if(qrgnin) goto S10; fprintf(stderr,"%s\n", " GETSD called before random number generator initialized -- abort!"); exit(0); S10: gscgn(0L,&g); *iseed1 = *(Xcg1+g-1); *iseed2 = *(Xcg2+g-1); #undef numg }
void apprcirc(long *n, double *Hurst, double *L, int *cum, long *seed1, long *seed2, double *output) { /* function that generates a fractional Brownian motion or fractional */ /* Gaussian noise sample using the approximate circulant method. */ /* Input: *n determines the sample size N by N=2^(*n) */ /* *Hurst the Hurst parameter of the trace */ /* *L the sample is generated on [0,L] */ /* *cum = 0: fractional Gaussian noise is produced */ /* = 1: fractional Brownian motion is produced */ /* *seed1 seed1 for the random generator */ /* *seed2 seed2 for the random generator */ /* Output: *seed1 new seed1 of the random generator */ /* *seed2 new seed2 of the random generator */ /* *output the resulting sample is stored in this array */ long i, N, halfN, generator; double scaling, H; double *pow_spec; double aux; complex *a; halfN = pow(2,*n); H = *Hurst; N = 2*halfN; /* set random generator and seeds */ snorm(); generator = 1; gscgn(1, &generator); setall(*seed1,*seed2); /* allocate memory */ pow_spec = (double*) malloc((halfN+1)*sizeof(double)); /* approximate spectral density */ FGN_spectrum(pow_spec,halfN,H); a = malloc(N*sizeof(complex)); a[0].re = sqrt(2*(pow(N,2*H)-pow(N-1,2*H)))*snorm(); a[0].im = 0.; a[halfN].re = sqrt(2*pow_spec[halfN])*snorm(); a[halfN].im = 0.; for(i=1; i<halfN; i++) { aux = sqrt(pow_spec[i]); a[i].re = aux*snorm(); a[i].im = aux*snorm(); } for(i=halfN+1; i<N; i++) { a[i].re = a[N-i].re; a[i].im = -a[N-i].im; } /* real part of Fourier transform of a_re + i a_im gives sample path */ fft(N,a,1,1.0); /* rescale to obtain a sample of size 2^(*n) on [0,L] */ scaling = pow(*L/halfN,H)/sqrt(2*N); for(i=0;i<halfN;i++) { output[i] = scaling*(a[i].re); if (*cum && i>0) { output[i] += output[i-1]; } } /* store the new random seeds and free memory */ getsd(seed1,seed2); free(pow_spec); free(a); }