double r8_uni_01() /******************************************************************************/ /* Purpose: R8_UNI_01 returns a uniform random double in [0,1]. Discussion: This procedure returns a random floating point number from a uniform distribution over (0,1), not including the endpoint values, using the current random number generator. Licensing: This code is distributed under the GNU LGPL license. Modified: 05 August 2013 Author: Original Pascal version by Pierre L'Ecuyer, Serge Cote. C version by John Burkardt. Reference: Pierre LEcuyer, Serge Cote, Implementing a Random Number Package with Splitting Facilities, ACM Transactions on Mathematical Software, Volume 17, Number 1, March 1991, pages 98-111. Parameters: Output, double R8_UNI_01, a uniform random value in [0,1]. */ { int i; double value; /* Check whether the package must be initialized. */ if (!initialized_get()) { initialize(); } /* Get a random integer. */ i = i4_uni(); /* Scale it to [0,1]. */ value = (double) (i) * 4.656613057E-10; return value; }
void get_state ( int *cg1, int *cg2 ) /******************************************************************************/ /* Purpose: GET_STATE returns the state of the current generator. Licensing: This code is distributed under the GNU LGPL license. Modified: 30 March 2013 Author: Original Pascal version by Pierre L'Ecuyer, Serge Cote. C version by John Burkardt. Reference: Pierre LEcuyer, Serge Cote, Implementing a Random Number Package with Splitting Facilities, ACM Transactions on Mathematical Software, Volume 17, Number 1, March 1991, pages 98-111. Parameters: Output, int *CG1, *CG2, the CG values for the current generator. */ { int g; /* Check whether the package must be initialized. */ if ( ! initialized_get ( ) ) { printf ( "\n" ); printf ( "GET_STATE - Note:\n" ); printf ( " Initializing RNGLIB package.\n" ); initialize ( ); } /* Get the current generator index. */ g = cgn_get ( ); /* Retrieve the seed values for this generator. */ cg_get ( g, cg1, cg2 ); return; }
void advance_state(int k) /******************************************************************************/ /* Purpose: ADVANCE_STATE advances the state of the current generator. Discussion: This procedure advances the state of the current generator by 2^K values and resets the initial seed to that value. Licensing: This code is distributed under the GNU LGPL license. Modified: 30 March 2013 Author: Original Pascal version by Pierre L'Ecuyer, Serge Cote. C version by John Burkardt. Reference: Pierre LEcuyer, Serge Cote, Implementing a Random Number Package with Splitting Facilities, ACM Transactions on Mathematical Software, Volume 17, Number 1, March 1991, pages 98-111. Parameters: Input, int K, indicates that the generator is to be advanced by 2^K values. 0 <= K. */ { const int a1 = 40014; const int a2 = 40692; int b1; int b2; int cg1; int cg2; int g; int i; const int m1 = 2147483563; const int m2 = 2147483399; if (k < 0) { fprintf(stderr, "\n"); fprintf(stderr, "ADVANCE_STATE - Fatal error!\n"); fprintf(stderr, " Input exponent K is out of bounds.\n"); exit(1); } /* Check whether the package must be initialized. */ if (!initialized_get()) { initialize(); } /* Get the current generator index. */ g = cgn_get(); b1 = a1; b2 = a2; for (i = 1; i <= k; k++) { b1 = multmod(b1, b1, m1); b2 = multmod(b2, b2, m2); } cg_get(g, &cg1, &cg2); cg1 = multmod(b1, cg1, m1); cg2 = multmod(b2, cg2, m2); cg_set(g, cg1, cg2); return; }
void init_generator(int t) /******************************************************************************/ /* Purpose: INIT_GENERATOR sets the state of generator G to initial, last or new seed. Licensing: This code is distributed under the GNU LGPL license. Modified: 01 April 2013 Author: Original Pascal version by Pierre L'Ecuyer, Serge Cote. C version by John Burkardt. Reference: Pierre LEcuyer, Serge Cote, Implementing a Random Number Package with Splitting Facilities, ACM Transactions on Mathematical Software, Volume 17, Number 1, March 1991, pages 98-111. Parameters: Input, int T, the seed type: 0, use the seed chosen at initialization time. 1, use the last seed. 2, use a new seed set 2^30 values away. */ { const int a1_w = 1033780774; const int a2_w = 1494757890; int cg1; int cg2; int g; int ig1; int ig2; int lg1; int lg2; const int m1 = 2147483563; const int m2 = 2147483399; /* Check whether the package must be initialized. */ if (!initialized_get()) { initialize(); } /* Get the current generator index. */ g = cgn_get(); /* 0: restore the initial seed. */ if (t == 0) { ig_get(g, &ig1, &ig2); lg1 = ig1; lg2 = ig2; lg_set(g, lg1, lg2); } /* 1: restore the last seed. */ else if (t == 1) { lg_get(g, &lg1, &lg2); } /* 2: advance to a new seed. */ else if (t == 2) { lg_get(g, &lg1, &lg2); lg1 = multmod(a1_w, lg1, m1); lg2 = multmod(a2_w, lg2, m2); lg_set(g, lg1, lg2); } else { fprintf(stderr, "\n"); fprintf(stderr, "INIT_GENERATOR - Fatal error!\n"); fprintf(stderr, " Input parameter T out of bounds.\n"); exit(1); } /* Store the new seed. */ cg1 = lg1; cg2 = lg2; cg_set(g, cg1, cg2); return; }
int i4_uni() /******************************************************************************/ /* Purpose: I4_UNI generates a random positive integer. Discussion: This procedure returns a random integer following a uniform distribution over (1, 2147483562) using the current generator. The original name of this function was "random()", but this conflicts with a standard library function name in C. Licensing: This code is distributed under the GNU LGPL license. Modified: 05 August 2013 Author: Original Pascal version by Pierre L'Ecuyer, Serge Cote. C version by John Burkardt. Reference: Pierre LEcuyer, Serge Cote, Implementing a Random Number Package with Splitting Facilities, ACM Transactions on Mathematical Software, Volume 17, Number 1, March 1991, pages 98-111. Parameters: Output, int I4_UNI, the random integer. */ { const int a1 = 40014; const int a2 = 40692; int cg1; int cg2; int g; int k; const int m1 = 2147483563; const int m2 = 2147483399; int value; int z; /* Check whether the package must be initialized. */ if (!initialized_get()) { initialize(); } /* Get the current generator index. */ g = cgn_get(); /* Retrieve the current seeds. */ cg_get(g, &cg1, &cg2); /* Update the seeds. */ k = cg1 / 53668; cg1 = a1 * (cg1 - k * 53668) - k * 12211; if (cg1 < 0) { cg1 = cg1 + m1; } k = cg2 / 52774; cg2 = a2 * (cg2 - k * 52774) - k * 3791; if (cg2 < 0) { cg2 = cg2 + m2; } /* Store the updated seeds. */ cg_set(g, cg1, cg2); /* Form the random integer. */ z = cg1 - cg2; if (z < 1) { z = z + m1 - 1; } /* If the generator is antithetic, reflect the value. */ value = antithetic_get(); if (value) { z = m1 - z; } return z; }
void set_seed(int cg1, int cg2) /******************************************************************************/ /* Purpose: SET_SEED resets the initial seed and the state of generator G. Licensing: This code is distributed under the GNU LGPL license. Modified: 01 April 2013 Author: Original Pascal version by Pierre L'Ecuyer, Serge Cote. C version by John Burkardt. Reference: Pierre LEcuyer, Serge Cote, Implementing a Random Number Package with Splitting Facilities, ACM Transactions on Mathematical Software, Volume 17, Number 1, March 1991, pages 98-111. Parameters: Input, int CG1, CG2, the CG values for generator G. 1 <= CG1 < 2147483563 1 <= CG2 < 2147483399 */ { int g; //int i; const int m1 = 2147483563; const int m2 = 2147483399; int t; if (cg1 < 1 || m1 <= cg1) { fprintf(stderr, "\n"); fprintf(stderr, "SET_SEED - Fatal error!\n"); fprintf(stderr, " Input parameter CG1 out of bounds.\n"); exit(1); } if (cg2 < 1 || m2 <= cg2) { fprintf(stderr, "\n"); fprintf(stderr, "SET_SEED - Fatal error!\n"); fprintf(stderr, " Input parameter CG2 out of bounds.\n"); exit(1); } /* Check whether the package must be initialized. */ if (!initialized_get()) { initialize(); } /* Retrieve the current generator index. */ g = cgn_get(); /* Set the seeds. */ cg_set(g, cg1, cg2); /* Initialize the generator. */ t = 0; init_generator(t); return; }
void set_initial_seed(int ig1, int ig2) /******************************************************************************/ /* Purpose: SET_INITIAL_SEED resets the initial seed and state for all generators. Licensing: This code is distributed under the GNU LGPL license. Modified: 28 March 2013 Author: Original Pascal version by Pierre L'Ecuyer, Serge Cote. C version by John Burkardt. Reference: Pierre LEcuyer, Serge Cote, Implementing a Random Number Package with Splitting Facilities, ACM Transactions on Mathematical Software, Volume 17, Number 1, March 1991, pages 98-111. Parameters: Input, int IG1, IG2, the initial seed values for the first generator. 1 <= IG1 < 2147483563 1 <= IG2 < 2147483399 */ { const int a1_vw = 2082007225; const int a2_vw = 784306273; int g; const int g_max = 32; //int i; const int m1 = 2147483563; const int m2 = 2147483399; int t; if (ig1 < 1 || m1 <= ig1) { fprintf(stderr, "\n"); fprintf(stderr, "SET_INITIAL_SEED - Fatal error!\n"); fprintf(stderr, " Input parameter IG1 out of bounds.\n"); exit(1); } if (ig2 < 1 || m2 <= ig2) { fprintf(stderr, "\n"); fprintf(stderr, "SET_INITIAL_SEED - Fatal error!\n"); fprintf(stderr, " Input parameter IG2 out of bounds.\n"); exit(1); } /* Because INITIALIZE calls SET_INITIAL_SEED, it's not easy to correct the error that arises if SET_INITIAL_SEED is called before INITIALIZE. So don't bother trying. */ if (!initialized_get()) { printf("\n"); printf("SET_INITIAL_SEED - Fatal error!\n"); printf(" The RNGLIB package has not been initialized.\n"); exit(1); } /* Set the initial seed, then initialize the first generator. */ g = 0; cgn_set(g); ig_set(g, ig1, ig2); t = 0; init_generator(t); /* Now do similar operations for the other generators. */ for (g = 1; g < g_max; g++) { cgn_set(g); ig1 = multmod(a1_vw, ig1, m1); ig2 = multmod(a2_vw, ig2, m2); ig_set(g, ig1, ig2); init_generator(t); } /* Now choose the first generator. */ g = 0; cgn_set(g); return; }