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