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