00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <limits.h>
00025 #include <math.h>
00026 #include <stdio.h>
00027 #include <string.h>
00028
00029 #include "zigrandom.h"
00030
00031 #ifdef __cplusplus
00032 extern "C" {
00033 #endif
00034
00035
00036 void GetInitialSeeds(unsigned int auiSeed[], int cSeed,
00037 unsigned int uiSeed, unsigned int uiMin)
00038 {
00039 int i;
00040 unsigned int s = uiSeed;
00041
00042 for (i = 0; i < cSeed; )
00043 {
00044 s = 1664525 * s + 1013904223;
00045 if (s <= uiMin)
00046 continue;
00047 auiSeed[i] = s;
00048 ++i;
00049 }
00050 }
00051
00052
00053
00054
00055 #define MWC_R 256
00056 #define MWC_A LIT_UINT64(809430660)
00057 #define MWC_AI 809430660
00058 #define MWC_C 362436
00059 static unsigned int s_uiStateMWC = MWC_R - 1;
00060 static unsigned int s_uiCarryMWC = MWC_C;
00061 static unsigned int s_auiStateMWC[MWC_R];
00062
00063 void RanSetSeed_MWC8222(int *piSeed, int cSeed)
00064 {
00065 s_uiStateMWC = MWC_R - 1;
00066 s_uiCarryMWC = MWC_C;
00067
00068 if (cSeed == MWC_R)
00069 {
00070 int i;
00071 for (i = 0; i < MWC_R; ++i)
00072 {
00073 s_auiStateMWC[i] = (unsigned int)piSeed[i];
00074 }
00075 }
00076 else
00077 {
00078 GetInitialSeeds(s_auiStateMWC, MWC_R, piSeed && cSeed ? piSeed[0] : 0, 0);
00079 }
00080 }
00081 unsigned int IRan_MWC8222(void)
00082 {
00083 UINT64 t;
00084
00085 s_uiStateMWC = (s_uiStateMWC + 1) & (MWC_R - 1);
00086 t = MWC_A * s_auiStateMWC[s_uiStateMWC] + s_uiCarryMWC;
00087 s_uiCarryMWC = (unsigned int)(t >> 32);
00088 s_auiStateMWC[s_uiStateMWC] = (unsigned int)t;
00089 return (unsigned int)t;
00090 }
00091 double DRan_MWC8222(void)
00092 {
00093 UINT64 t;
00094
00095 s_uiStateMWC = (s_uiStateMWC + 1) & (MWC_R - 1);
00096 t = MWC_A * s_auiStateMWC[s_uiStateMWC] + s_uiCarryMWC;
00097 s_uiCarryMWC = (unsigned int)(t >> 32);
00098 s_auiStateMWC[s_uiStateMWC] = (unsigned int)t;
00099 return RANDBL_32new(t);
00100 }
00101 void VecIRan_MWC8222(unsigned int *auiRan, int cRan)
00102 {
00103 UINT64 t;
00104 unsigned int carry = s_uiCarryMWC, status = s_uiStateMWC;
00105
00106 for (; cRan > 0; --cRan, ++auiRan)
00107 {
00108 status = (status + 1) & (MWC_R - 1);
00109 t = MWC_A * s_auiStateMWC[status] + carry;
00110 *auiRan = s_auiStateMWC[status] = (unsigned int)t;
00111 carry = (unsigned int)(t >> 32);
00112 }
00113 s_uiCarryMWC = carry;
00114 s_uiStateMWC = status;
00115 }
00116 void VecDRan_MWC8222(double *adRan, int cRan)
00117 {
00118 UINT64 t;
00119 unsigned int carry = s_uiCarryMWC, status = s_uiStateMWC;
00120
00121 for (; cRan > 0; --cRan, ++adRan)
00122 {
00123 status = (status + 1) & (MWC_R - 1);
00124 t = MWC_A * s_auiStateMWC[status] + carry;
00125 s_auiStateMWC[status] = (unsigned int)t;
00126 *adRan = RANDBL_32new(t);
00127 carry = (unsigned int)(t >> 32);
00128 }
00129 s_uiCarryMWC = carry;
00130 s_uiStateMWC = status;
00131 }
00132
00133
00134
00135
00136 static int s_cNormalInStore = 0;
00137
00138 static DRANFUN s_fnDRanu = DRan_MWC8222;
00139 static IRANFUN s_fnIRanu = IRan_MWC8222;
00140 static IVECRANFUN s_fnVecIRanu = VecIRan_MWC8222;
00141 static DVECRANFUN s_fnVecDRanu = VecDRan_MWC8222;
00142 static RANSETSEEDFUN s_fnRanSetSeed = RanSetSeed_MWC8222;
00143
00144 double DRanU(void)
00145 {
00146 return (*s_fnDRanu)();
00147 }
00148 unsigned int IRanU(void)
00149 {
00150 return (*s_fnIRanu)();
00151 }
00152 void RanVecIntU(unsigned int *auiRan, int cRan)
00153 {
00154 (*s_fnVecIRanu)(auiRan, cRan);
00155 }
00156 void RanVecU(double *adRan, int cRan)
00157 {
00158 (*s_fnVecDRanu)(adRan, cRan);
00159 }
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 void RanSetSeed(int *piSeed, int cSeed)
00173 {
00174 s_cNormalInStore = 0;
00175 (*s_fnRanSetSeed)(piSeed, cSeed);
00176 }
00177 void RanSetRan(const char *sRan)
00178 {
00179 s_cNormalInStore = 0;
00180 if (strcmp(sRan, "MWC8222") == 0)
00181 {
00182 s_fnDRanu = DRan_MWC8222;
00183 s_fnIRanu = IRan_MWC8222;
00184 s_fnVecIRanu = VecIRan_MWC8222;
00185 s_fnRanSetSeed = RanSetSeed_MWC8222;
00186 }
00187 else
00188 {
00189 s_fnDRanu = NULL;
00190 s_fnIRanu = NULL;
00191 s_fnVecIRanu = NULL;
00192 s_fnRanSetSeed = NULL;
00193 }
00194 }
00195 static unsigned int IRanUfromDRanU(void)
00196 {
00197 return (unsigned int)(UINT_MAX * (*s_fnDRanu)());
00198 }
00199 static double DRanUfromIRanU(void)
00200 {
00201 return RANDBL_32new( (*s_fnIRanu)() );
00202 }
00203 void RanSetRanExt(DRANFUN DRanFun, IRANFUN IRanFun, IVECRANFUN IVecRanFun,
00204 DVECRANFUN DVecRanFun, RANSETSEEDFUN RanSetSeedFun)
00205 {
00206 s_fnDRanu = DRanFun ? DRanFun : DRanUfromIRanU;
00207 s_fnIRanu = IRanFun ? IRanFun : IRanUfromDRanU;
00208 s_fnVecIRanu = IVecRanFun;
00209 s_fnVecDRanu = DVecRanFun;
00210 s_fnRanSetSeed = RanSetSeedFun;
00211 }
00212
00213
00214
00215
00216 #define POLARBLOCK(u1, u2, d) \
00217 do \
00218 { u1 = (*s_fnDRanu)(); u1 = 2 * u1 - 1;\
00219 u2 = (*s_fnDRanu)(); u2 = 2 * u2 - 1;\
00220 d = u1 * u1 + u2 * u2; \
00221 } while (d >= 1); \
00222 d = sqrt( (-2.0 / d) * log(d) ); \
00223 u1 *= d; u2 *= d
00224
00225 static double s_dNormalInStore;
00226
00227 double DRanNormalPolar(void)
00228 {
00229 double d, u1;
00230
00231 if (s_cNormalInStore)
00232 u1 = s_dNormalInStore, s_cNormalInStore = 0;
00233 else
00234 {
00235 POLARBLOCK(u1, s_dNormalInStore, d);
00236 s_cNormalInStore = 1;
00237 }
00238
00239 return u1;
00240 }
00241
00242 #define FPOLARBLOCK(u1, u2, d) \
00243 do \
00244 { u1 = (float)((*s_fnDRanu)()); u1 = 2 * u1 - 1;\
00245 u2 = (float)((*s_fnDRanu)()); u2 = 2 * u2 - 1;\
00246 d = u1 * u1 + u2 * u2; \
00247 } while (d >= 1); \
00248 d = sqrt( (-2.0 / d) * log(d) ); \
00249 u1 *= d; u2 *= d
00250
00251 static float s_fNormalInStore;
00252 double FRanNormalPolar(void)
00253 {
00254 float d, u1;
00255
00256 if (s_cNormalInStore)
00257 u1 = s_fNormalInStore, s_cNormalInStore = 0;
00258 else
00259 {
00260 POLARBLOCK(u1, s_fNormalInStore, d);
00261 s_cNormalInStore = 1;
00262 }
00263
00264 return (double)u1;
00265 }
00266
00267
00268
00269 static double dProbN(double x, int fUpper)
00270 {
00271 double p; double y; int fnegative = 0;
00272
00273 if (x < 0)
00274 x = -x, fnegative = 1, fUpper = !fUpper;
00275 else if (x == 0)
00276 return 0.5;
00277
00278 if ( !(x <= 8 || (fUpper && x <= 37) ) )
00279 return (fUpper) ? 0 : 1;
00280
00281 y = x * x / 2;
00282
00283 if (x <= 1.28)
00284 {
00285 p = 0.5 - x * (0.398942280444 - 0.399903438504 * y /
00286 (y + 5.75885480458 - 29.8213557808 /
00287 (y + 2.62433121679 + 48.6959930692 /
00288 (y + 5.92885724438))));
00289 }
00290 else
00291 {
00292 p = 0.398942280385 * exp(-y) /
00293 (x - 3.8052e-8 + 1.00000615302 /
00294 (x + 3.98064794e-4 + 1.98615381364 /
00295 (x - 0.151679116635 + 5.29330324926 /
00296 (x + 4.8385912808 - 15.1508972451 /
00297 (x + 0.742380924027 + 30.789933034 /
00298 (x + 3.99019417011))))));
00299 }
00300 return (fUpper) ? p : 1 - p;
00301 }
00302 double DProbNormal(double x)
00303 {
00304 return dProbN(x, 0);
00305 }
00306 double DRanQuanNormal(void)
00307 {
00308 return DProbNormal(DRanNormalPolar());
00309 }
00310 double FRanQuanNormal(void)
00311 {
00312 return DProbNormal(FRanNormalPolar());
00313 }
00314
00315
00316 #ifdef __cplusplus
00317 }
00318 #endif