00001 #ifndef GAMMA_RND_H_INC
00002 #define GAMMA_RND_H_INC
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <math.h>
00012 #include <stdio.h>
00013 #include <time.h>
00014
00015 #include "Gamma/gen.h"
00016 #include "Gamma/mem.h"
00017 #include "Gamma/scl.h"
00018 #include "Gamma/Conversion.h"
00019 #include "Gamma/Types.h"
00020
00021 #define TEM template <class T>
00022
00023 namespace gam{
00024
00025
00026 namespace rnd{
00027 namespace{
00028 static bool initSeed = false;
00029 static uint32_t mSeedPush[4];
00030 static gen::RMulAdd<uint32_t> seedGen(1664525, 1013904223);
00031 }
00032
00034 static uint32_t getSeed(){
00035 if(!initSeed){ seedGen.val = time(NULL); initSeed = true; }
00036 return seedGen();
00037 }
00038
00039 }
00040
00041
00043
00049 struct RNGLinCon : public gen::RMulAdd<uint32_t>{
00050
00051 RNGLinCon(){ val=rnd::getSeed(); type(0); }
00052
00054 RNGLinCon(uint32_t seed): gen::RMulAdd<uint32_t>(1,0,seed){ type(0); }
00055
00057
00060 void type(int v){
00061 switch(v){
00062 case 1: mul = 2147001325; add = 715136305; break;
00063 default:mul = 1664525; add = 1013904223;
00064 }
00065 }
00066 };
00067
00068
00069
00071
00074 struct RNGMulLinCon : public gen::RMul<uint32_t>{
00075
00076 RNGMulLinCon(){ val=rnd::getSeed(); type(0); }
00077
00079 RNGMulLinCon(uint32_t seed): gen::RMul<uint32_t>(1,seed){ type(0); }
00080
00082
00085 void type(int v){
00086 switch(v){
00087 default: mul = 69069;
00088 }
00089 }
00090 };
00091
00092
00093
00095
00102 class RNGTaus{
00103 public:
00104 RNGTaus(){ (*this) = rnd::getSeed(); }
00105
00107 RNGTaus(uint32_t seed);
00108
00109 uint32_t s1, s2, s3, s4;
00110
00111 uint32_t operator()();
00112 void operator = (uint32_t seed);
00113 void seed(uint32_t s1, uint32_t s2, uint32_t s3, uint32_t s4);
00114
00115 private:
00116 void iterate();
00117 };
00118
00119
00120
00122
00155
00156 namespace rnd{
00157
00159
00162 TEM T& cond(T& v, const T& va, const T& vb, float pab, float pba);
00163
00165 TEM T geom(int n, T mul, T start=1, float p=0.5);
00166
00168 TEM T neg(T val, float prob=0.5f);
00169
00171 TEM const T& pick(const T& val1, const T& val2, float prob=0.5f);
00172
00174 TEM bool prob(T& rng, float p=0.5f);
00175
00177 bool prob(float p=0.5f);
00178 bool prob(double p);
00179
00181
00184 bool prob(char c);
00185
00186 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00187 #define FUNCS(name)\
00188 TEM T name(T bound2, T bound1 = 0);\
00189 TEM void name(T * dst, uint32_t len);\
00190 TEM void name(T * dst, uint32_t len, T bound2, T bound1 = 0);\
00191 TEM void name(T * dst, uint32_t len, T * src, uint32_t srcLen);\
00192 TEM float name##_float(T & rng);
00193
00194
00195 FUNCS(add2) FUNCS(add2I) FUNCS(add3) FUNCS(binS) FUNCS(lin) FUNCS(mul2)
00196 FUNCS(pow2) FUNCS(pow3) FUNCS(uni) FUNCS(uniS)
00197
00198 #undef FUNCS
00199 #endif
00200
00202
00205 void push(uint32_t seed=0);
00206 void pop();
00207
00209 TEM void permute(T * arr, uint32_t len);
00210
00212 float quan(uint32_t q);
00213
00215 TEM T quanOct(uint32_t q, T o);
00216
00218 void seed(uint32_t value=0);
00219
00221 TEM void set(T * arr, uint32_t len, uint32_t num, T val=1);
00222
00224 TEM void thin(T * arr, uint32_t len, float prob=0.5f);
00225
00227 TEM T uniExc(const T& exc, const T& max, const T& min=T(0));
00228
00230
00233 TEM uint32_t weighted(T * weights, uint32_t num, T weightsSum=(T)1);
00234
00235 static RNGTaus gen(rnd::getSeed());
00236 }
00237
00238
00239
00240
00241
00242
00243
00244 inline RNGTaus::RNGTaus(uint32_t sd){ (*this) = sd; }
00245
00246 inline uint32_t RNGTaus::operator()(){
00247 iterate();
00248 return s1 ^ s2 ^ s3 ^ s4;
00249 }
00250
00251 inline void RNGTaus::operator=(uint32_t s){
00252 gen::RMulAdd<uint32_t> g(1664525, 1013904223, s);
00253 g.val = s; g();
00254 seed(g(), g(), g(), g());
00255 }
00256
00257 inline void RNGTaus::seed(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t v4){
00258
00259 v1 & 0xffffffe ? s1 = v1 : s1 = ~v1;
00260 v2 & 0xffffff8 ? s2 = v2 : s2 = ~v2;
00261 v3 & 0xffffff0 ? s3 = v3 : s3 = ~v3;
00262 v4 & 0xfffff80 ? s4 = v4 : s4 = ~v4;
00263 }
00264
00265 inline void RNGTaus::iterate(){
00266 s1 = ((s1 & 0xfffffffe) << 18) ^ (((s1 << 6) ^ s1) >> 13);
00267 s2 = ((s2 & 0xfffffff8) << 2) ^ (((s2 << 2) ^ s2) >> 27);
00268 s3 = ((s3 & 0xfffffff0) << 7) ^ (((s3 << 13) ^ s3) >> 21);
00269 s4 = ((s4 & 0xffffff80) << 13) ^ (((s4 << 3) ^ s4) >> 12);
00270 }
00271
00272
00273
00274 namespace rnd{
00275
00276 #define R uni_float(rng)
00277 TEM inline float add2_float(T& rng){ return (R + R) * 0.5f; }
00278 TEM inline float add3_float(T& rng){ return (R + R + R) * 0.33333333333f; }
00279 TEM inline float lin_float(T& rng){ float r = R; float s = R; return r < s ? r : s; }
00280 TEM inline float mul2_float(T& rng){ return R * R; }
00281 TEM inline float pow2_float(T& rng){ float r = R; return r * r; }
00282 TEM inline float pow3_float(T& rng){ float r = R; return r * r * r; }
00283
00284 TEM inline float add2I_float(T & rng){
00285 float r = add2_float(rng) + 0.5f;
00286 return (r < 1.f) ? r : r - 1.f;
00287 }
00288 #undef R
00289
00290 TEM inline float uni_float(T& rng){ return uintToUnit<float>(rng()); }
00291 TEM inline float uniS_float(T& rng){ return uintToUnitS<float>(rng()); }
00292
00293 TEM inline float binS_float(T & rng){
00294 uint32_t r = rng() & MaskSign<float>() | Expo1<float>();
00295 return punUF(r);
00296 }
00297
00298 TEM inline T & cond(T& v, const T& va, const T& vb, float pab, float pba){
00299 if(v == va) v = pick(vb, va, pba);
00300 else if(v == vb) v = pick(va, vb, pab);
00301 return v;
00302 }
00303
00304 template <class RNG>
00305 float gaussian(RNG& rng = rnd::gen){
00306 float x1, x2, w, y1, y2;
00307
00308 do{
00309 x1 = uniS_float(rng);
00310 x2 = uniS_float(rng);
00311 w = x1 * x1 + x2 * x2;
00312 } while( w >= 1.f );
00313
00314 w = sqrt((-2.f * ::log(w)) / w);
00315 y1 = x1 * w;
00316 y2 = x2 * w;
00317 return y1;
00318 }
00319
00320 TEM inline T geom(int n, T mul, T start, float p){
00321 for(; n>0; --n){
00322 if(prob(p)) break;
00323 start *= mul;
00324 }
00325 return start;
00326 }
00327
00328 TEM inline T neg(T v, float p){ return prob(p) ? -v : v; }
00329 TEM inline const T & pick(const T & v1, const T & v2, float p){ return prob(p) ? v1 : v2; }
00330 TEM inline bool prob(T& rng, float p){ return uni_float(rng) < p; }
00331 inline bool prob(float p){ return prob(gen, p); }
00332
00333 inline bool prob(double p){ return prob((float)p); }
00334
00335 inline bool prob(char c){
00336 if(c>'7'||c=='/') return true;
00337 if(c<'1') return false;
00338 return prob((c-48) * 0.125f);
00339 }
00340
00341 #define LOOP(n) for(uint32_t i=0;i<n;++i)
00342
00343 TEM inline void set(T * arr, uint32_t len, uint32_t num, T val){
00344 LOOP(num){ arr[rnd::uni(len)] = val; }
00345 }
00346
00347 TEM inline void permute(T * arr, uint32_t len){
00348 LOOP(len-1){ mem::swap(arr[i], arr[rnd::uni(len, i)]); }
00349 }
00350
00351 inline float quan(uint32_t q){ return uni(q) / (float)q; }
00352
00353 TEM inline T quanOct(uint32_t q, T o){ return quan(q) * o + o; }
00354
00355 TEM inline void thin(T * arr, uint32_t len, float p){
00356 LOOP(len){ if(prob(p)) arr[i]=T(0); }
00357 }
00358
00359 TEM inline T uniExc(const T& exc, const T& max, const T& min){
00360 T r=exc; while(exc==r){ r=uni(max,min); } return r;
00361 }
00362
00363 #define DEF(rnd_t, fnc)\
00364 TEM inline T fnc(T b2, T b1){\
00365 return (T)( (rnd_t)b1 + fnc##_##rnd_t(gen) * (rnd_t)(b2-b1) );\
00366 }\
00367 TEM inline void fnc(T * dst, uint32_t len){\
00368 LOOP(len){ dst[i] = (T) fnc##_##rnd_t (gen); }\
00369 }\
00370 TEM inline void fnc(T * dst, uint32_t len, T bound2, T bound1){\
00371 rnd_t b1 = (rnd_t)bound1;\
00372 rnd_t df = (rnd_t)bound2 - b1;\
00373 LOOP(len){ dst[i] = (T)(b1 + fnc##_##rnd_t(gen) * df); }\
00374 }\
00375 TEM inline void fnc(T * dst, uint32_t len, T * src, uint32_t srcLen){\
00376 LOOP(len){ dst[i] = src[rnd::fnc(srcLen)]; }\
00377 }
00378 DEF(float, add2) DEF(float, add2I) DEF(float, add3) DEF(float, lin)
00379 DEF(float, mul2) DEF(float, pow2 ) DEF(float, pow3) DEF(float, uni)
00380 DEF(float, uniS)
00381 #undef DEF
00382
00383 #undef LOOP
00384
00385 inline void push(uint32_t seedA){
00386 mSeedPush[0] = gen.s1;
00387 mSeedPush[1] = gen.s2;
00388 mSeedPush[2] = gen.s3;
00389 mSeedPush[3] = gen.s4;
00390 if(seedA) seed(seedA);
00391 }
00392 inline void pop(){
00393 gen.s1 = mSeedPush[0];
00394 gen.s2 = mSeedPush[1];
00395 gen.s3 = mSeedPush[2];
00396 gen.s4 = mSeedPush[3];
00397 }
00398
00399 inline void seed(uint32_t value){
00400 gen = value ? value : getSeed();
00401 }
00402
00403 TEM uint32_t weighted(T * weights, uint32_t num, T weightsSum){
00404 if(0 == num--) return 0;
00405 T probSum = weights[0];
00406 T rnd = (T)(uni_float(gen) * (float)weightsSum);
00407
00408 if(rnd < probSum) return 0;
00409
00410 for(uint32_t i=1; i<num; ++i){
00411 probSum += weights[i];
00412 if(rnd < probSum) return i;
00413 }
00414 return num;
00415 }
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438 }
00439 }
00440
00441 #undef TEM
00442
00443 #endif