00001 #ifndef MATH_RANDOM_H
00002 #define MATH_RANDOM_H
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00033 #include <iosfwd>
00034 #include <cassert>
00035 #include <cmath>
00036
00037 #include <glt/config.h>
00038
00039 #include <math/real.h>
00040 #include <math/vector3.h>
00041 #include <math/matrix4.h>
00042
00054 class GltRandomLCG
00055 {
00056 public:
00058 GltRandomLCG(const uint32 seed = 199125);
00060 GltRandomLCG(const GltRandomLCG &rng);
00062 ~GltRandomLCG();
00063
00065 uint32 rand() const;
00067 uint32 max() const;
00068
00070 void seed(const uint32 seed = 199125);
00071
00073 static GltRandomLCG rng;
00074
00076 GltRandomLCG &base() { return *this; }
00078 const GltRandomLCG &base() const { return *this; }
00079
00080 private:
00081
00082 mutable uint32 _idum;
00083
00084 const static int32 a;
00085 const static int32 m;
00086 const static int32 q;
00087 const static int32 r;
00088 };
00089
00111 class GltRandomLFSRMix
00112 {
00113 public:
00115 GltRandomLFSRMix(const uint32 seed1 = 199125,const uint32 seed2 = 90618,const uint32 seed3 = 189419);
00117 GltRandomLFSRMix(const GltRandomLFSRMix &rng);
00119 ~GltRandomLFSRMix();
00120
00122 uint32 rand() const;
00124 uint32 max() const;
00125
00127 static GltRandomLFSRMix rng;
00128
00130 GltRandomLFSRMix &base() { return *this; }
00132 const GltRandomLFSRMix &base() const { return *this; }
00133
00134 private:
00135
00136 mutable uint32 _regA, _regB, _regC;
00137 };
00138
00145 template<class R = GltRandomLFSRMix>
00146 class GltRandomDouble
00147 {
00148 public:
00149
00151 GltRandomDouble(R &random,const double min = 0.0,const double max = 1.0)
00152 : _random(random),
00153 _min(min),
00154 _max(max),
00155 _mult((max-min)/random.max())
00156 {
00157 }
00158
00160 GltRandomDouble(const double min = 0.0,const double max = 1.0)
00161 : _random(R::rng),
00162 _min(min),
00163 _max(max),
00164 _mult((max-min)/R::rng.max())
00165 {
00166 }
00167
00169 GltRandomDouble(const GltRandomDouble<R> &gen)
00170 : _random(gen._random),
00171 _min(gen._min),
00172 _max(gen._max),
00173 _mult(gen._mult)
00174 {
00175 }
00176
00178 ~GltRandomDouble()
00179 {
00180 }
00181
00183 double rand() const
00184 {
00185 return _min + _mult*double(_random.rand());
00186 }
00187
00189 R &base() { return _random; }
00191 const R &base() const { return _random; }
00192
00193 private:
00194
00195 R &_random;
00196 const double _min;
00197 const double _max;
00198 const double _mult;
00199 };
00200
00207 template<class R = GltRandomLFSRMix>
00208 class GltRandomInteger
00209 {
00210 public:
00211
00213 GltRandomInteger(R &random,const uint32 min,const uint32 max)
00214 : _random(random),
00215 _min(min),
00216 _max(double(max)+1.0-1.0e-6),
00217 _mult((double(max)+1.0-1.0e-6-double(min))/random.max())
00218 {
00219 assert(min<max);
00220 assert(max<=random.max());
00221 }
00222
00224 GltRandomInteger(const uint32 min,const uint32 max)
00225 : _random(R::rng),
00226 _min(min),
00227 _max(double(max)+1.0-1.0e-6),
00228 _mult((double(max)+1.0-1.0e-6-double(min))/R::rng.max())
00229 {
00230 assert(min<max);
00231 assert(max<=_random.max());
00232 }
00233
00235 GltRandomInteger(const GltRandomInteger<R> &gen)
00236 : _random(gen._random),
00237 _min(gen._min),
00238 _max(gen._max),
00239 _mult(gen._mult)
00240 {
00241 }
00242
00244 ~GltRandomInteger()
00245 {
00246 }
00247
00249 uint32 rand() const
00250 {
00251 return _min + (uint32) floor(_mult*double(_random.rand()));
00252 }
00253
00255 R &base() { return _random; }
00257 const R &base() const { return _random; }
00258
00259 private:
00260
00261 R &_random;
00262 const uint32 _min;
00263 const double _max;
00264 const double _mult;
00265 };
00266
00293 template<class R = GltRandomLFSRMix>
00294 class GltRandomSphere
00295 {
00296 public:
00297
00299 GltRandomSphere(R &random,const double radius = 1.0)
00300 : _z(random,-1.0,1.0),
00301 _t(random,0,2*M_PI),
00302 _radius(radius)
00303 {
00304 }
00305
00307 GltRandomSphere(const double radius = 1.0)
00308 : _z(R::rng,-1.0,1.0),
00309 _t(R::rng, 0.0,2*M_PI),
00310 _radius(radius)
00311 {
00312 }
00313
00315 GltRandomSphere(const GltRandomSphere<R> &gen)
00316 : _z(gen._z._random),
00317 _t(gen._t._random),
00318 _radius(gen._radius)
00319 {
00320 }
00321
00323 ~GltRandomSphere()
00324 {
00325 }
00326
00328 Vector rand() const
00329 {
00330 const double z = _z.rand();
00331 const double t = _t.rand();
00332 const double r = _radius*sqrt(1.0-z*z);
00333 return Vector(r*cos(t),r*sin(t),_radius*z);
00334 }
00335
00337 R &base() { return _z.base(); }
00339 const R &base() const { return _z.base(); }
00340
00341 private:
00342
00343 GltRandomDouble<R> _z,_t;
00344 const double _radius;
00345 };
00346
00353 template<class R = GltRandomLFSRMix>
00354 class GltRandomOrientation
00355 {
00356 public:
00357
00359 GltRandomOrientation(R &random)
00360 : _s(random), _a(random,0.0,2*M_PI)
00361 {
00362 }
00363
00365 GltRandomOrientation()
00366 : _s(R::rng), _a(R::rng,0.0,2*M_PI)
00367 {
00368 }
00369
00371 GltRandomOrientation(const GltRandomOrientation<R> &gen)
00372 : _s(gen._s), _a(gen._a)
00373 {
00374 }
00375
00377 ~GltRandomOrientation()
00378 {
00379 }
00380
00382 Matrix rand() const
00383 {
00384
00385
00386
00387 const Vector a(_s.rand());
00388
00389
00390
00391 Vector b;
00392
00393 switch (a.dominant())
00394 {
00395 case 0: b = xProduct(a,VectorZ); break;
00396 case 1: b = xProduct(a,VectorZ); break;
00397 case 2: b = xProduct(a,VectorX); break;
00398 }
00399
00400
00401
00402 Vector c(xProduct(b,a));
00403
00404
00405 b.normalize();
00406 c.normalize();
00407
00408
00409
00410 const real angle = _a.rand();
00411 const real sina = sin(angle);
00412 const real cosa = cos(angle);
00413
00414 return matrixOrient
00415 (
00416 a,
00417 sina*b + cosa*c,
00418 cosa*b - sina*c
00419 );
00420 }
00421
00423 R &base() { return _s.base(); }
00425 const R &base() const { return _s.base(); }
00426
00427 private:
00428 GltRandomSphere<R> _s;
00429 GltRandomDouble<R> _a;
00430 };
00431
00432 #endif