00001 /* SimData: Data Infrastructure for Simulations 00002 * Copyright (C) 2002, 2003 Mark Rose <tm2@stm.lbl.gov> 00003 * 00004 * This file is part of SimData. 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00019 */ 00020 00021 00047 #ifndef __SIMDATA_RANDOM_H__ 00048 #define __SIMDATA_RANDOM_H__ 00049 00050 00051 #include <cmath> 00052 #include <SimData/Ref.h> 00053 #include <SimData/Export.h> 00054 00055 00056 NAMESPACE_SIMDATA 00057 00058 00060 // Random Number Generators 00061 00062 namespace rng { // random number generators 00063 00110 class SIMDATA_EXPORT MT19937 { 00111 static const int N = 624; /* Period parameters */ 00112 static const int M = 397; 00113 00114 // most significant w-r bits 00115 static const unsigned long UPPER_MASK = 0x80000000UL; 00116 00117 // least significant r bits 00118 static const unsigned long LOWER_MASK = 0x7fffffffUL; 00119 00120 // state 00121 unsigned long _mt[N]; 00122 int _mti; 00123 00124 static inline unsigned long MAGIC(unsigned long y) { 00125 return (((y)&0x1) ? 0x9908b0dfUL : 0); 00126 } 00127 00130 void update(); 00131 00137 inline unsigned long generate() { 00138 if (_mti >= N) update(); // generate N words at one time 00139 unsigned long k = _mt[_mti]; 00140 k ^= (k >> 11); 00141 k ^= (k << 7) & 0x9d2c5680UL; 00142 k ^= (k << 15) & 0xefc60000UL; 00143 k ^= (k >> 18); 00144 _mti++; 00145 return k; 00146 } 00147 00148 public: 00151 struct State { 00152 unsigned long _mt[N]; 00153 int _mti; 00154 }; 00155 00158 inline std::string getName() const { return "Mersenne Twister (MT19937)"; } 00159 00162 MT19937() { setSeed(0); } 00163 00170 template <typename T> 00171 inline T uniformInt(T lower, T upper) { 00172 return lower + static_cast<T>(unit() * (upper-lower)); 00173 } 00174 00177 template <typename T> 00178 inline T uniformInt(T upper) { 00179 return uniformInt(static_cast<T>(0), upper); 00180 } 00181 00184 inline double unit() { 00185 return generate() / 4294967296.0 ; 00186 }; 00187 00190 inline double uniform(double lower, double upper) { 00191 return lower + unit() * (upper-lower); 00192 } 00193 00198 void setSeed(unsigned long int s); 00199 00204 void getState(State &state) const; 00205 00211 void setState(State const &state); 00212 }; 00213 00214 00215 00216 00285 class SIMDATA_EXPORT Taus2 { 00286 // state 00287 unsigned long int _s1, _s2, _s3; 00288 00289 static const unsigned long int MASK = 0xffffffffUL; 00290 00291 inline static unsigned long int LCG(unsigned long int n) { 00292 return ((69069 * n) & 0xffffffffUL); 00293 } 00294 00295 inline static unsigned long int TAUSWORTHE(unsigned long int s, 00296 unsigned long int a, 00297 unsigned long int b, 00298 unsigned long int c, 00299 unsigned long int d) { 00300 return (((s &c) <<d) &MASK) ^ ((((s <<a) &MASK)^s) >>b); 00301 } 00302 00306 inline unsigned long generate() { 00307 _s1 = TAUSWORTHE(_s1, 13, 19, 4294967294UL, 12); 00308 _s2 = TAUSWORTHE(_s2, 2, 25, 4294967288UL, 4); 00309 _s3 = TAUSWORTHE(_s3, 3, 11, 4294967280UL, 17); 00310 return (_s1 ^ _s2 ^ _s3); 00311 } 00312 public: 00315 struct State { 00316 unsigned long int _s1, _s2, _s3; 00317 }; 00318 00321 inline std::string getName() const { return "Tausworthe (Taus2)"; } 00322 00325 Taus2() { setSeed(0); } 00326 00333 template <typename T> 00334 inline T uniformInt(T lower, T upper) { 00335 return lower + static_cast<T>(unit() * (upper-lower)); 00336 } 00337 00340 template <typename T> 00341 inline T uniformInt(T upper) { 00342 return uniformInt(static_cast<T>(0), upper); 00343 } 00344 00347 inline double unit() { 00348 return generate() / 4294967296.0 ; 00349 }; 00350 00353 inline double uniform(double lower, double upper) { 00354 return lower + unit() * (upper-lower); 00355 } 00356 00361 void setSeed(unsigned long int s); 00362 00367 void getState(State &state) const; 00368 00374 void setState(State const &state); 00375 }; 00376 00377 00378 } // namespace rng 00379 00380 00381 00383 // Random Number Generator Wrappers 00384 00387 class SIMDATA_EXPORT RandomInterface { 00388 protected: 00391 struct _State: Referenced { }; 00392 public: 00393 typedef Ref<_State> State; 00394 typedef unsigned long int SeedType; 00395 00396 virtual ~RandomInterface(); 00397 00400 virtual void setSeed(SeedType seed)=0; 00401 00404 virtual State getState() const=0; 00405 00408 virtual void setState(State const &state)=0; 00409 00412 virtual std::string getName() const=0; 00413 }; 00414 00415 00418 class SIMDATA_EXPORT RandomNumberGeneratorInterface: public RandomInterface { 00419 public: 00422 virtual double unit()=0; 00423 00426 virtual double uniform(double lower, double upper)=0; 00427 00430 virtual long uniformInt(long lower, long upper)=0; 00431 00434 virtual long uniformInt(long upper)=0; 00435 00438 virtual unsigned long uniformUInt(unsigned long lower, unsigned long upper)=0; 00439 00442 virtual unsigned long uniformUInt(unsigned long upper)=0; 00443 }; 00444 00453 template <class RNG> 00454 class RandomNumberGenerator: public RandomNumberGeneratorInterface { 00455 00458 struct RNGState: _State { 00459 typename RNG::State _state; 00460 }; 00461 RNG _gen; 00462 public: 00467 virtual void setSeed(SeedType seed); 00468 00473 virtual State getState() const; 00474 00480 virtual void setState(State const &); 00481 00484 virtual double unit(); 00485 00488 virtual double uniform(double, double); 00489 00496 virtual long uniformInt(long lower, long upper); 00497 00500 virtual long uniformInt(long upper); 00501 00508 virtual unsigned long uniformUInt(unsigned long lower, unsigned long upper); 00509 00512 virtual unsigned long uniformUInt(unsigned long upper); 00513 00516 virtual std::string getName() const; 00517 00523 inline RNG *operator->() { return &_gen; } 00524 }; 00525 00526 00527 template <class RNG> 00528 RandomInterface::State RandomNumberGenerator<RNG>::getState() const { 00529 RNGState *rng_state = new RNGState; 00530 _gen.getState(rng_state->_state); 00531 return rng_state; 00532 } 00533 00534 template <class RNG> 00535 void RandomNumberGenerator<RNG>::setState(RandomInterface::State const &state) { 00536 Ref<RNGState> rng_state = state; 00537 _gen.setState(rng_state->_state); 00538 } 00539 00540 template <class RNG> 00541 void RandomNumberGenerator<RNG>::setSeed(RandomInterface::SeedType seed) { 00542 _gen.setSeed(seed); 00543 } 00544 00545 template <class RNG> 00546 double RandomNumberGenerator<RNG>::unit() { 00547 return _gen.unit(); 00548 } 00549 00550 template <class RNG> 00551 double RandomNumberGenerator<RNG>::uniform(double low, double high) { 00552 return _gen.uniform(low, high); 00553 } 00554 00555 template <class RNG> 00556 long RandomNumberGenerator<RNG>::uniformInt(long low, long high) { 00557 return _gen.uniformInt(low, high); 00558 } 00559 00560 template <class RNG> 00561 long RandomNumberGenerator<RNG>::uniformInt(long high) { 00562 return _gen.uniformInt(high); 00563 } 00564 00565 template <class RNG> 00566 unsigned long RandomNumberGenerator<RNG>::uniformUInt(unsigned long low, unsigned long high) { 00567 return _gen.uniformInt(low, high); 00568 } 00569 00570 template <class RNG> 00571 unsigned long RandomNumberGenerator<RNG>::uniformUInt(unsigned long high) { 00572 return _gen.uniformInt(high); 00573 } 00574 00575 template <class RNG> 00576 std::string RandomNumberGenerator<RNG>::getName() const { 00577 return _gen.getName(); 00578 } 00579 00580 00582 // Random Distributions 00583 00584 namespace rd { // random distributions 00585 00588 class SIMDATA_EXPORT Gauss { 00589 rng::Taus2 _gen; 00590 double _mean, _sigma; 00591 double _x; 00592 bool _odd; 00593 public: 00594 00597 struct State { 00598 rng::Taus2::State _state; 00599 double _mean, _sigma, _x; 00600 bool _odd; 00601 }; 00602 00605 std::string getName() const { return "Gaussian (Gauss)"; } 00606 00612 Gauss(double mean=0.0, double sigma=0.0): _mean(mean), _sigma(sigma), _odd(true) {} 00613 00619 inline void setDistribution(double mean, double sigma) { 00620 _mean = mean; 00621 _sigma = sigma; 00622 } 00623 00626 inline double getMean() const { return _mean; } 00627 00630 inline double getSigma() const { return _sigma; } 00631 00634 double sample(); 00635 00640 inline void setSeed(unsigned long int seed) { _gen.setSeed(seed); _odd = true; } 00641 00648 void getState(State &) const; 00649 00656 void setState(State const &); 00657 }; 00658 00659 00660 extern SIMDATA_EXPORT double BoxMueller(RandomNumberGeneratorInterface &_gen, double _mean, double _sigma); 00661 00662 } // namespace rd 00663 00664 00665 00667 // Random Distribution Wrappers 00668 00669 00672 class SIMDATA_EXPORT RandomDistributionInterface: public RandomInterface { 00673 public: 00676 virtual double sample()=0; 00677 }; 00678 00679 00680 00687 template <class RD> 00688 class RandomDistribution: public RandomDistributionInterface { 00691 struct RDState: _State { 00692 typename RD::State _state; 00693 }; 00694 RD _dist; 00695 public: 00698 double sample(); 00699 00704 virtual void setSeed(SeedType seed); 00705 00710 virtual State getState() const; 00711 00717 virtual void setState(State const &); 00718 00721 virtual std::string getName() const; 00722 00728 inline RD *operator->() { return &_dist; } 00729 }; 00730 00731 00732 template <class RD> 00733 double RandomDistribution<RD>::sample() { 00734 return _dist.sample(); 00735 } 00736 00737 template <class RD> 00738 RandomInterface::State RandomDistribution<RD>::getState() const { 00739 RDState *rd_state = new RDState; 00740 _dist.getState(rd_state->_state); 00741 return rd_state; 00742 } 00743 00744 template <class RD> 00745 void RandomDistribution<RD>::setState(RandomInterface::State const &state) { 00746 Ref<RDState> rd_state = state; 00747 _dist.setState(rd_state->_state); 00748 } 00749 00750 template <class RD> 00751 void RandomDistribution<RD>::setSeed(RandomInterface::SeedType s) { 00752 _dist.setSeed(s); 00753 } 00754 00755 template <class RD> 00756 std::string RandomDistribution<RD>::getName() const { 00757 return _dist.getName(); 00758 } 00759 00760 00761 00762 00763 namespace random { // generators and distributions 00764 typedef RandomDistribution<rd::Gauss> Gauss; 00765 typedef RandomNumberGenerator<rng::MT19937> MersenneTwister; 00766 typedef RandomNumberGenerator<rng::Taus2> Taus2; 00767 typedef Taus2 Standard; 00768 } 00769 00770 00773 extern SIMDATA_EXPORT random::Taus2 g_Random; 00774 00775 00776 NAMESPACE_SIMDATA_END // simdata 00777 00778 #endif // __SIMDATA_RANDOM_H__ 00779
|
SimData version pre-0.4.0. For more information on SimData, visit the SimData Homepage. Generated on Tue Oct 14 12:06:39 2003, using Doxygen 1.2.18. |