clcg2.c

Go to the documentation of this file.
00001 /*  
00002  *  PURPOSE
00003  *     uniform random number generator developed by Pierre 
00004  *     Lecuyer based on a clever and tested combination of 
00005  *     two linear congruential sequences
00006  *
00007  *        s1 <- a1*s1 mod m1 ,  a1 = 40014, m1 = 2147483563
00008  *        s2 <- a2*s2 mod m2 ,  a2 = 40692, m2 = 2147483399
00009  *
00010  *        output <-  s1-s2 mod (m1 - 1)  
00011  *
00012  *        so output is in [0, 2147483561], period about 2.3 10^18
00013  *
00014  *        The state is given by (s1, s2). In case of a user
00015  *        modification of the state we must have :
00016  * 
00017  *              s1 in [1, m1-1]
00018  *              s2 in [1, m2-1]
00019  *
00020  *  ORIGIN
00021  *     The basic code is provided at the Luc Devroye 's home page.
00022  *     Modifications by Bruno Pincon (in particular added routines 
00023  *     to set and get the state, and modify the generator to get 
00024  *     exactly  s1-s2 mod (m1 - 1) for "coherence" with the others 
00025  *     generators : provides numbers in [0, MaxRngInt(generator)] 
00026  *     (see NOTE some lines after)
00027  *
00028  */
00029 
00030 #include "machine.h" 
00031 #include <math.h>
00032 #include "sciprint.h"
00033 
00034 /* initial default state (seeds) : */
00035 static long s1 = 1234567890 ;
00036 static long s2 = 123456789  ;
00037 
00038 unsigned long clcg2()
00039 {
00040   register long k,z;
00041 
00042   /*  s1 = a1*s1 mod m1  (Schrage 's method)  */
00043   k= s1 /53668;
00044   s1 =40014*(s1%53668)-k*12211;
00045   if (s1 < 0) s1 += 2147483563;
00046 
00047   /*  s2 = a2*s2 mod m2  (Schrage 's method)  */
00048   k=s2/52774;
00049   s2=40692*(s2%52774)-k*3791;
00050   if (s2 < 0) s2 += 2147483399;
00051 
00052   /* final step : z = s1-s2 mod m1-1  */
00053   z = s1 - s2;  /* here z is in [2-m2,m1-2] */
00054   if (z < 0) z += 2147483562;
00055 
00056   /* NOTE : in the  original implementation the final test is :
00057    *     if (z < 1) z += 2147483562;
00058    * 
00059    *   which is not exactly  z = s1-s2 mod (m1 - 1)
00060    *
00061    *   This is also why it is different from the version used by
00062    *   randlib.
00063    */
00064   
00065   return( (unsigned long) z );
00066 }
00067 
00068 int set_state_clcg2(double g1, double g2)
00069 {
00070   
00071   if ( g1 == floor(g1) && g2 == floor(g2)  && 
00072        1 <= g1 && g1 <= 2147483562    &&
00073        1 <= g2 && g2 <= 2147483398 )
00074     {
00075       s1 = (long) g1;
00076       s2 = (long) g2;
00077       return ( 1 );
00078     }
00079   else
00080     {
00081       sciprint("\n\r bad seeds for clcg2, must be integers with  s1 in [1, 2147483562]");
00082       sciprint("\n\r                                        and  s2 in [1, 2147483398]\n\r");
00083       return ( 0 );
00084     }
00085 }
00086 
00087 void get_state_clcg2(double g[])
00088 {
00089   g[0] = (double) s1;
00090   g[1] = (double) s2;
00091 }
00092 

Generated on Sun Mar 4 15:03:59 2007 for Scilab [trunk] by  doxygen 1.5.1