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
00019
00020
00021
00022
00023
00024 #ifndef __VCG_RandomGenerator
00025 #define __VCG_RandomGenerator
00026
00027 #include <vcg/math/base.h>
00028
00029 namespace vcg {
00030 namespace math {
00031
00037 class RandomGenerator
00038 {
00039
00040
00041 public:
00042
00043 RandomGenerator(){}
00044
00045 virtual ~RandomGenerator()
00046 {}
00047
00048
00049 public:
00050
00052 virtual void initialize(unsigned int seed)=0;
00053
00055 virtual unsigned int generate(unsigned int limit)=0;
00056
00058 virtual double generate01()=0;
00059
00061 virtual double generate01closed()=0;
00062
00064 virtual double generate01open()=0;
00065 virtual double generateRange(double minV, double maxV) { return minV+(maxV-minV)*generate01(); }
00066
00067 };
00068
00072 template <class ScalarType, class GeneratorType>
00073 vcg::Point3<ScalarType> GenerateBarycentricUniform(GeneratorType &rnd)
00074 {
00075 vcg::Point3<ScalarType> interp;
00076 interp[1] = rnd.generate01();
00077 interp[2] = rnd.generate01();
00078 if(interp[1] + interp[2] > 1.0)
00079 {
00080 interp[1] = 1.0 - interp[1];
00081 interp[2] = 1.0 - interp[2];
00082 }
00083
00084 assert(interp[1] + interp[2] <= 1.0);
00085 interp[0]=1.0-(interp[1] + interp[2]);
00086 return interp;
00087 }
00088
00090 template <class ScalarType, class GeneratorType>
00091 vcg::Point3<ScalarType> GeneratePointInBox3Uniform(GeneratorType &rnd, const Box3<ScalarType> &bb)
00092 {
00093 return Point3<ScalarType>(
00094 (ScalarType) rnd.generateRange(double(bb.min[0]),double(bb.max[0])),
00095 (ScalarType) rnd.generateRange(double(bb.min[1]),double(bb.max[1])),
00096 (ScalarType) rnd.generateRange(double(bb.min[2]),double(bb.max[2]))
00097 );
00098 }
00099
00111 template <class ScalarType, class GeneratorType>
00112 vcg::Point3<ScalarType> GeneratePointOnUnitSphereUniform(GeneratorType &rnd)
00113 {
00114 vcg::Point3<ScalarType> p;
00115 double x,y,s;
00116 do
00117 {
00118 x = 2.0*rnd.generate01()-1.0;
00119 y = 2.0*rnd.generate01()-1.0;
00120 s = x*x+y*y;
00121 } while (s>1);
00122 p[0]= ScalarType(2 * x * sqrt(1-s));
00123 p[1]= ScalarType(2 * y * sqrt(1-s));
00124 p[2]= ScalarType(1-2*s);
00125 return p;
00126 }
00127
00129 template <class ScalarType, class GeneratorType>
00130 vcg::Point3<ScalarType> GeneratePointInUnitBallUniform(GeneratorType &rnd)
00131 {
00132 vcg::Point3<ScalarType> p;
00133 while(1)
00134 {
00135 p.Import(Point3d(0.5-rnd.generate01(),0.5-rnd.generate01(),0.5-rnd.generate01()));
00136 if(SquaredNorm(p)<=0.25){
00137 p*=2;
00138 return p;
00139 }
00140 }
00141 }
00142
00143
00156 class SubtractiveRingRNG : public RandomGenerator
00157 {
00158
00159
00160 private:
00161
00162
00163 unsigned int _M_table[55];
00164 size_t _M_index1;
00165 size_t _M_index2;
00166
00167
00168 public:
00169
00170
00171 SubtractiveRingRNG(int default_seed=161803398u)
00172 {
00173 initialize(default_seed);
00174 }
00175
00176 virtual ~SubtractiveRingRNG()
00177 {}
00178
00179
00180 public:
00181
00183 void initialize(unsigned int seed)
00184 {
00185 unsigned int __k = 1;
00186 _M_table[54] = seed;
00187 size_t __i;
00188 for (__i = 0; __i < 54; __i++)
00189 {
00190 size_t __ii = (21 * (__i + 1) % 55) - 1;
00191 _M_table[__ii] = __k;
00192 __k = seed - __k;
00193 seed = _M_table[__ii];
00194 }
00195 for (int __loop = 0; __loop < 4; __loop++)
00196 {
00197 for (__i = 0; __i < 55; __i++)
00198 _M_table[__i] = _M_table[__i] - _M_table[(1 + __i + 30) % 55];
00199 }
00200 _M_index1 = 0;
00201 _M_index2 = 31;
00202 }
00203
00205 unsigned int generate(unsigned int limit= 0xffffffffu)
00206 {
00207 _M_index1 = (_M_index1 + 1) % 55;
00208 _M_index2 = (_M_index2 + 1) % 55;
00209 _M_table[_M_index1] = _M_table[_M_index1] - _M_table[_M_index2];
00210 return _M_table[_M_index1] % limit;
00211 }
00212
00214 double generate01()
00215 {
00216 const unsigned int lmt = 0xffffffffu;
00217 unsigned int number = generate(lmt);
00218 return static_cast<double>(number) / static_cast<double>(lmt);
00219 }
00220
00222 double generate01closed()
00223 {
00224 const unsigned int lmt = 0xffffffffu;
00225 unsigned int number = generate(lmt);
00226 return static_cast<double>(number) / static_cast<double>(0xfffffffEu);
00227 }
00228
00230 double generate01open()
00231 {
00232 const unsigned int lmt = 0xffffffffu;
00233 unsigned int number = generate(lmt);
00234 return (static_cast<double>(number) + 0.5) * (1.0/static_cast<double>(lmt));
00235 }
00236
00237 };
00238
00250 class MarsenneTwisterRNG : public RandomGenerator
00251 {
00252
00253
00254 private:
00255
00256 static const int N = 624;
00257 static const int M = 397;
00258 static const unsigned int MATRIX_A = 0x9908b0dfu;
00259 static const unsigned int UPPER_MASK = 0x80000000u;
00260 static const unsigned int LOWER_MASK = 0x7fffffffu;
00261
00262
00263 private:
00264
00265
00266 unsigned int mt[N];
00267 int mti;
00268
00269
00270 public:
00271
00272
00273 MarsenneTwisterRNG()
00274 {
00275 initialize(5489u);
00276 }
00277
00278 MarsenneTwisterRNG(unsigned int seed)
00279 {
00280 initialize(seed);
00281 }
00282
00283 virtual ~MarsenneTwisterRNG()
00284 {}
00285
00286
00287
00288 public:
00289
00291 void initialize(unsigned int seed)
00292 {
00293 mt[0]= seed & 0xffffffffu;
00294 for (mti=1; mti<N; mti++)
00295 {
00296 mt[mti] = (1812433253u * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
00297
00298
00299
00300
00301 mt[mti] &= 0xffffffffu;
00302
00303 }
00304 }
00305
00312 void initializeByArray(unsigned int init_key[], int key_length)
00313 {
00314 int i, j, k;
00315 initialize(19650218u);
00316 i=1; j=0;
00317 k = (N>key_length ? N : key_length);
00318 for (; k; k--)
00319 {
00320 mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525u)) + init_key[j] + j;
00321 mt[i] &= 0xffffffffu;
00322 i++; j++;
00323
00324 if (i>=N)
00325 {
00326 mt[0] = mt[N-1];
00327 i=1;
00328 }
00329
00330 if (j>=key_length) j=0;
00331 }
00332
00333 for (k=N-1; k; k--)
00334 {
00335 mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941u)) - i;
00336 mt[i] &= 0xffffffffu;
00337 i++;
00338 if (i>=N)
00339 {
00340 mt[0] = mt[N-1];
00341 i=1;
00342 }
00343 }
00344
00345 mt[0] = 0x80000000u;
00346 }
00347
00348 unsigned int generate(unsigned int limit)
00349 {
00350 return generate()%limit;
00351 }
00352
00358 unsigned int generate()
00359 {
00360 unsigned int y;
00361 static unsigned int mag01[2]={0x0u, MATRIX_A};
00362
00363
00364 if (mti >= N)
00365 {
00366 int kk;
00367
00368 for (kk=0;kk<N-M;kk++)
00369 {
00370 y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
00371 mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1u];
00372 }
00373
00374 for (;kk<N-1;kk++)
00375 {
00376 y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
00377 mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1u];
00378 }
00379
00380 y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
00381 mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1u];
00382
00383 mti = 0;
00384 }
00385
00386 y = mt[mti++];
00387
00388
00389 y ^= (y >> 11);
00390 y ^= (y << 7) & 0x9d2c5680u;
00391 y ^= (y << 15) & 0xefc60000u;
00392 y ^= (y >> 18);
00393
00394 return y;
00395 }
00396
00398 double generate01closed()
00399 {
00400 return generate()*(1.0/4294967295.0);
00401 }
00402
00404 double generate01()
00405 {
00406 return generate()*(1.0/4294967296.0);
00407 }
00408
00410 double generate01open()
00411 {
00412 return (((double)generate()) + 0.5)*(1.0/4294967296.0);
00413 }
00414
00416 template <class PointType>
00417 void generateBarycentric(PointType &p){
00418 p[1] = this->generate01();
00419 p[2] = this->generate01();
00420
00421 if(p[1] + p[2] > 1.0){
00422 p[1] = 1.0 - p[1];
00423 p[2] = 1.0 - p[2];
00424 }
00425 p[0]=1.0-(p[1] + p[2]);
00426 }
00427 };
00428
00429
00430
00431
00432
00433
00434
00435
00436 inline double box_muller(RandomGenerator &generator, double m, double s)
00437 {
00438 double x1, x2, w, y1;
00439 static double y2;
00440 static int use_last = 0;
00441 static RandomGenerator *last_generator = 0;
00442 if(last_generator != &generator)
00443 use_last = 0;
00444 last_generator = &generator;
00445 if (use_last){
00446 y1 = y2;
00447 use_last = 0;
00448 } else {
00449 do {
00450 x1 = 2.0 * generator.generate01closed() - 1.0;
00451 x2 = 2.0 * generator.generate01closed() - 1.0;
00452 w = x1 * x1 + x2 * x2;
00453 } while ( w >= 1.0 );
00454 w = sqrt( (-2.0 * log( w ) ) / w );
00455 y1 = x1 * w;
00456 y2 = x2 * w;
00457 use_last = 1;
00458 }
00459 return( m + y1 * s );
00460 }
00461 }
00462 }
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499 #endif