/* * * Copyright (C) 2010 - DIGITEO - Michael Baudin * Copyright (C) 2004 - Bruno Pincon * Copyright (C) Luc Devroye * Copyright (C) Pierre Lecuyer * * PURPOSE * uniform random number generator developed by Pierre * Lecuyer based on a clever and tested combination of * two linear congruential sequences * * s1 <- a1*s1 mod m1 , a1 = 40014, m1 = 2147483563 * s2 <- a2*s2 mod m2 , a2 = 40692, m2 = 2147483399 * * output <- s1-s2 mod (m1 - 1) * * so output is in [0, 2147483561], period about 2.3 10^18 * * The state is given by (s1, s2). In case of a user * modification of the state we must have : * * s1 in [1, m1-1] * s2 in [1, m2-1] * * ORIGIN * The basic code is provided at the Luc Devroye 's home page. * Modifications by Bruno Pincon (in particular added routines * to set and get the state, and modify the generator to get * exactly s1-s2 mod (m1 - 1) for "coherence" with the others * generators : provides numbers in [0, MaxRngInt(generator)] * (see NOTE some lines after) * */ #include <math.h> #include "localization.h" #include "sciprint.h" #include "others_generators.h" /* initial default state (seeds) : */ static int s1 = 1234567890 ; static int s2 = 123456789 ; unsigned long int clcg2(void) { register int k, z; /* s1 = a1*s1 mod m1 (Schrage 's method) */ k = s1 / 53668; s1 = 40014 * (s1 % 53668) - k * 12211; if (s1 < 0) { s1 += 2147483563; } /* s2 = a2*s2 mod m2 (Schrage 's method) */ k = s2 / 52774; s2 = 40692 * (s2 % 52774) - k * 3791; if (s2 < 0) { s2 += 2147483399; } /* final step : z = s1-s2 mod m1-1 */ z = s1 - s2; /* here z is in [2-m2,m1-2] */ if (z < 0) { z += 2147483562; } /* NOTE : in the original implementation the final test is : * if (z < 1) z += 2147483562; * * which is not exactly z = s1-s2 mod (m1 - 1) * * This is also why it is different from the version used by * randlib. */ return( (unsigned int) z ); } int set_state_clcg2(double g1, double g2) { if ( g1 == floor(g1) && g2 == floor(g2) && 1 <= g1 && g1 <= 2147483562 && 1 <= g2 && g2 <= 2147483398 ) { s1 = (int) g1; s2 = (int) g2; return ( 1 ); } else { sciprint(_("\nBad seeds for clcg2, must be integers with s1 in [1, 2147483562]\n and s2 in [1, 2147483398]\n")); return ( 0 ); } } void get_state_clcg2(double g[]) { g[0] = (double) s1; g[1] = (double) s2; }