00001 00032 #include "util.h" 00033 00034 static char rcsid[] UNUSED = "$Id: random.c,v 1.4 2002/09/10 00:05:33 fabio Exp $"; 00035 00036 /*---------------------------------------------------------------------------*/ 00037 /* Constant declarations */ 00038 /*---------------------------------------------------------------------------*/ 00039 00040 /* Random generator constants. */ 00041 #define MODULUS1 2147483563 00042 #define LEQA1 40014 00043 #define LEQQ1 53668 00044 #define LEQR1 12211 00045 #define MODULUS2 2147483399 00046 #define LEQA2 40692 00047 #define LEQQ2 52774 00048 #define LEQR2 3791 00049 #define STAB_SIZE 64 00050 #define STAB_DIV (1 + (MODULUS1 - 1) / STAB_SIZE) 00051 00052 /*---------------------------------------------------------------------------*/ 00053 /* Type declarations */ 00054 /*---------------------------------------------------------------------------*/ 00055 00056 00057 /*---------------------------------------------------------------------------*/ 00058 /* Structure declarations */ 00059 /*---------------------------------------------------------------------------*/ 00060 00061 00062 /*---------------------------------------------------------------------------*/ 00063 /* Variable declarations */ 00064 /*---------------------------------------------------------------------------*/ 00065 static long utilRand = 0; 00066 static long utilRand2; 00067 static long shuffleSelect; 00068 static long shuffleTable[STAB_SIZE]; 00069 00070 /*---------------------------------------------------------------------------*/ 00071 /* Macro declarations */ 00072 /*---------------------------------------------------------------------------*/ 00073 00074 00077 /*---------------------------------------------------------------------------*/ 00078 /* Static function prototypes */ 00079 /*---------------------------------------------------------------------------*/ 00080 00084 /*---------------------------------------------------------------------------*/ 00085 /* Definition of exported functions */ 00086 /*---------------------------------------------------------------------------*/ 00087 00088 00105 void 00106 util_srandom(long seed) 00107 { 00108 int i; 00109 00110 if (seed < 0) utilRand = -seed; 00111 else if (seed == 0) utilRand = 1; 00112 else utilRand = seed; 00113 utilRand2 = utilRand; 00114 /* Load the shuffle table (after 11 warm-ups). */ 00115 for (i = 0; i < STAB_SIZE + 11; i++) { 00116 long int w; 00117 w = utilRand / LEQQ1; 00118 utilRand = LEQA1 * (utilRand - w * LEQQ1) - w * LEQR1; 00119 utilRand += (utilRand < 0) * MODULUS1; 00120 shuffleTable[i % STAB_SIZE] = utilRand; 00121 } 00122 shuffleSelect = shuffleTable[1 % STAB_SIZE]; 00123 } /* end of util_srandom */ 00124 00142 long 00143 util_random(void) 00144 { 00145 int i; /* index in the shuffle table */ 00146 long int w; /* work variable */ 00147 00148 /* utilRand == 0 if the geneartor has not been initialized yet. */ 00149 if (utilRand == 0) util_srandom(1); 00150 00151 /* Compute utilRand = (utilRand * LEQA1) % MODULUS1 avoiding 00152 ** overflows by Schrage's method. 00153 */ 00154 w = utilRand / LEQQ1; 00155 utilRand = LEQA1 * (utilRand - w * LEQQ1) - w * LEQR1; 00156 utilRand += (utilRand < 0) * MODULUS1; 00157 00158 /* Compute utilRand2 = (utilRand2 * LEQA2) % MODULUS2 avoiding 00159 ** overflows by Schrage's method. 00160 */ 00161 w = utilRand2 / LEQQ2; 00162 utilRand2 = LEQA2 * (utilRand2 - w * LEQQ2) - w * LEQR2; 00163 utilRand2 += (utilRand2 < 0) * MODULUS2; 00164 00165 /* utilRand is shuffled with the Bays-Durham algorithm. 00166 ** shuffleSelect and utilRand2 are combined to generate the output. 00167 */ 00168 00169 /* Pick one element from the shuffle table; "i" will be in the range 00170 ** from 0 to STAB_SIZE-1. 00171 */ 00172 i = shuffleSelect / STAB_DIV; 00173 /* Mix the element of the shuffle table with the current iterate of 00174 ** the second sub-generator, and replace the chosen element of the 00175 ** shuffle table with the current iterate of the first sub-generator. 00176 */ 00177 shuffleSelect = shuffleTable[i] - utilRand2; 00178 shuffleTable[i] = utilRand; 00179 shuffleSelect += (shuffleSelect < 1) * (MODULUS1 - 1); 00180 /* Since shuffleSelect != 0, and we want to be able to return 0, 00181 ** here we subtract 1 before returning. 00182 */ 00183 return(shuffleSelect - 1); 00184 00185 } /* end of util_random */ 00186 00187 00188 /*---------------------------------------------------------------------------*/ 00189 /* Definition of internal functions */ 00190 /*---------------------------------------------------------------------------*/ 00191 00192 00193 /*---------------------------------------------------------------------------*/ 00194 /* Definition of static functions */ 00195 /*---------------------------------------------------------------------------*/ 00196 00197 00198