00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <limits.h>
00019 #include <math.h>
00020 #include <stdio.h>
00021 #include <stdlib.h>
00022 #include <string.h>
00023
00024 #include "zigrandom.h"
00025 #include "zignor.h"
00026
00027 #ifdef __cplusplus
00028 extern "C" {
00029 #endif
00030
00031
00032 static double DRanNormalTail(double dMin, int iNegative)
00033 {
00034 double x, y;
00035 do
00036 { x = log(DRanU()) / dMin;
00037 y = log(DRanU());
00038 } while (-2 * y < x * x);
00039 return iNegative ? x - dMin : dMin - x;
00040 }
00041
00042 #define ZIGNOR_C 128
00043 #define ZIGNOR_R 3.442619855899
00044
00045 #define ZIGNOR_V 9.91256303526217e-3
00046
00047
00048
00049 static double s_adZigX[ZIGNOR_C + 1], s_adZigR[ZIGNOR_C];
00050
00051 static void zigNorInit(int iC, double dR, double dV)
00052 {
00053 int i; double f;
00054
00055 f = exp(-0.5 * dR * dR);
00056 s_adZigX[0] = dV / f;
00057 s_adZigX[1] = dR;
00058 s_adZigX[iC] = 0;
00059
00060 for (i = 2; i < iC; ++i)
00061 {
00062 s_adZigX[i] = sqrt(-2 * log(dV / s_adZigX[i - 1] + f));
00063 f = exp(-0.5 * s_adZigX[i] * s_adZigX[i]);
00064 }
00065 for (i = 0; i < iC; ++i)
00066 s_adZigR[i] = s_adZigX[i + 1] / s_adZigX[i];
00067 }
00068 double DRanNormalZig(void)
00069 {
00070 unsigned int i;
00071 double x, u, f0, f1;
00072
00073 for (;;)
00074 {
00075 u = 2 * DRanU() - 1;
00076 i = IRanU() & 0x7F;
00077
00078 if (fabs(u) < s_adZigR[i])
00079 return u * s_adZigX[i];
00080
00081 if (i == 0)
00082 return DRanNormalTail(ZIGNOR_R, u < 0);
00083
00084 x = u * s_adZigX[i];
00085 f0 = exp(-0.5 * (s_adZigX[i] * s_adZigX[i] - x * x) );
00086 f1 = exp(-0.5 * (s_adZigX[i+1] * s_adZigX[i+1] - x * x) );
00087 if (f1 + DRanU() * (f0 - f1) < 1.0)
00088 return x;
00089 }
00090 }
00091
00092 #define ZIGNOR_STORE 64 * 4
00093 static unsigned int s_auiZigTmp[ZIGNOR_STORE / 4];
00094 static unsigned int s_auiZigBox[ZIGNOR_STORE];
00095 static double s_adZigRan[ZIGNOR_STORE + ZIGNOR_STORE / 4];
00096 static int s_cZigStored = 0;
00097
00098 double DRanNormalZigVec(void)
00099 {
00100 unsigned int i, j, k;
00101 double x, u, f0, f1;
00102
00103 for (;;)
00104 {
00105 if (s_cZigStored == 0)
00106 {
00107 RanVecIntU(s_auiZigTmp, ZIGNOR_STORE / 4);
00108 RanVecU(s_adZigRan, ZIGNOR_STORE);
00109 for (j = k = 0; j < ZIGNOR_STORE; j += 4, ++k)
00110 {
00111 i = s_auiZigTmp[k]; s_auiZigBox[j + 0] = i & 0x7F;
00112 i >>= 8; s_auiZigBox[j + 1] = i & 0x7F;
00113 i >>= 8; s_auiZigBox[j + 2] = i & 0x7F;
00114 i >>= 8; s_auiZigBox[j + 3] = i & 0x7F;
00115 s_adZigRan[j + 0] = 2 * s_adZigRan[j + 0] - 1;
00116 s_adZigRan[j + 1] = 2 * s_adZigRan[j + 1] - 1;
00117 s_adZigRan[j + 2] = 2 * s_adZigRan[j + 2] - 1;
00118 s_adZigRan[j + 3] = 2 * s_adZigRan[j + 3] - 1;
00119 }
00120 s_cZigStored = j;
00121 }
00122 --s_cZigStored;
00123
00124 u = s_adZigRan[s_cZigStored];
00125 i = s_auiZigBox[s_cZigStored];
00126
00127 if (fabs(u) < s_adZigR[i])
00128 return u * s_adZigX[i];
00129
00130 if (i == 0)
00131 return DRanNormalTail(ZIGNOR_R, u < 0);
00132
00133 x = u * s_adZigX[i];
00134 f0 = exp(-0.5 * (s_adZigX[i] * s_adZigX[i] - x * x) );
00135 f1 = exp(-0.5 * (s_adZigX[i + 1] * s_adZigX[i + 1] - x * x) );
00136 if (f1 + DRanU() * (f0 - f1) < 1.0)
00137 return x;
00138 }
00139 }
00140
00141 void RanNormalSetSeedZig(int *piSeed, int cSeed)
00142 {
00143 zigNorInit(ZIGNOR_C, ZIGNOR_R, ZIGNOR_V);
00144 RanSetSeed(piSeed, cSeed);
00145 }
00146 void RanNormalSetSeedZigVec(int *piSeed, int cSeed)
00147 {
00148 s_cZigStored = 0;
00149 RanNormalSetSeedZig(piSeed, cSeed);
00150 }
00151
00152
00153
00154 #define ZIGNOR_INVM M_RAN_INVM32
00155
00156 static unsigned int s_aiZigRm[ZIGNOR_C];
00157 static double s_adZigXm[ZIGNOR_C + 1];
00158
00159 static void zig32NorInit(int iC, double dR, double dV)
00160 {
00161 int i; double f, m31 = ZIGNOR_INVM * 2;
00162
00163 f = exp(-0.5 * dR * dR);
00164 s_adZigXm[0] = dV / f;
00165 s_adZigXm[1] = dR;
00166 s_adZigXm[iC] = 0;
00167
00168 for (i = 2; i < iC; ++i)
00169 {
00170 s_adZigXm[i] = sqrt(-2 * log(dV / s_adZigXm[i - 1] + f));
00171 f = exp(-0.5 * s_adZigXm[i] * s_adZigXm[i]);
00172 }
00173
00174 for (i = 0; i < iC; ++i)
00175 s_aiZigRm[i] = (unsigned int)
00176 ( (s_adZigXm[i + 1] / s_adZigXm[i]) / m31 );
00177 for (i = 0; i <= iC; ++i)
00178 s_adZigXm[i] *= m31;
00179 }
00180 double DRanNormalZig32(void)
00181 {
00182 unsigned int i;
00183 int u;
00184 double x, y, f0, f1;
00185
00186 for (;;)
00187 {
00188 u = (int)IRanU();
00189 i = IRanU() & 0x7F;
00190 if ((unsigned int)abs(u) < s_aiZigRm[i])
00191 return u * s_adZigXm[i];
00192
00193 if (i == 0)
00194 return DRanNormalTail(ZIGNOR_R, u < 0);
00195
00196 x = u * s_adZigXm[i];
00197 y = 0.5 * s_adZigXm[i] / ZIGNOR_INVM; f0 = exp(-0.5 * (y * y - x * x) );
00198 y = 0.5 * s_adZigXm[i + 1] / ZIGNOR_INVM; f1 = exp(-0.5 * (y * y - x * x) );
00199 if (f1 + IRanU() * ZIGNOR_INVM * (f0 - f1) < 1.0)
00200 return x;
00201 }
00202 }
00203 #define ZIGNOR32_STORE 64 * 4
00204 static unsigned int s_auiZig32Ran[ZIGNOR32_STORE];
00205 static unsigned int s_auiZig32Box[ZIGNOR32_STORE];
00206 static int s_cZig32Stored = 0;
00207
00208 double DRanNormalZig32Vec(void)
00209 {
00210 unsigned int i, j, k;
00211 int u;
00212 double x, y, f0, f1;
00213
00214 for (;;)
00215 {
00216 if (s_cZig32Stored == 0)
00217 {
00218 RanVecIntU(s_auiZig32Ran, ZIGNOR32_STORE / 4);
00219 for (j = k = 0; j < ZIGNOR32_STORE; j += 4, ++k)
00220 {
00221 i = s_auiZig32Ran[k]; s_auiZig32Box[j+0] = i & 0x7F;
00222 i >>= 8; s_auiZig32Box[j+1] = i & 0x7F;
00223 i >>= 8; s_auiZig32Box[j+2] = i & 0x7F;
00224 i >>= 8; s_auiZig32Box[j+3] = i & 0x7F;
00225 }
00226 RanVecIntU(s_auiZig32Ran, ZIGNOR32_STORE);
00227 s_cZig32Stored = j;
00228 }
00229 --s_cZig32Stored;
00230
00231 u = (int)s_auiZig32Ran[s_cZig32Stored];
00232 i = s_auiZig32Box[s_cZig32Stored];
00233
00234 if ((unsigned int)abs(u) < s_aiZigRm[i])
00235 return u * s_adZigXm[i];
00236
00237 if (i == 0)
00238 return DRanNormalTail(ZIGNOR_R, u < 0);
00239
00240 x = u * s_adZigXm[i];
00241 y = 0.5 * s_adZigXm[i] / ZIGNOR_INVM;
00242 f0 = exp(-0.5 * (y * y - x * x) );
00243 y = 0.5 * s_adZigXm[i + 1] / ZIGNOR_INVM;
00244 f1 = exp(-0.5 * (y * y - x * x) );
00245 if (f1 + IRanU() * ZIGNOR_INVM * (f0 - f1) < 1.0)
00246 return x;
00247 }
00248 }
00249 void RanNormalSetSeedZig32(int *piSeed, int cSeed)
00250 {
00251 zig32NorInit(ZIGNOR_C, ZIGNOR_R, ZIGNOR_V);
00252 RanSetSeed(piSeed, cSeed);
00253 }
00254 void RanNormalSetSeedZig32Vec(int *piSeed, int cSeed)
00255 {
00256 s_cZig32Stored = 0;
00257 RanNormalSetSeedZig32(piSeed, cSeed);
00258 }
00259
00260
00261
00262 double DRanQuanNormalZig(void)
00263 {
00264 return DProbNormal(DRanNormalZig());
00265 }
00266 double DRanQuanNormalZigVec(void)
00267 {
00268 return DProbNormal(DRanNormalZigVec());
00269 }
00270 double DRanQuanNormalZig32(void)
00271 {
00272 return DProbNormal(DRanNormalZig32());
00273 }
00274 double DRanQuanNormalZig32Vec(void)
00275 {
00276 return DProbNormal(DRanNormalZig32Vec());
00277 }
00278
00279
00280 #ifdef __cplusplus
00281 }
00282 #endif