Rev 1221 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
707 | werner | 1 | /******************************************************************************************** |
2 | ** iLand - an individual based forest landscape and disturbance model |
||
3 | ** http://iland.boku.ac.at |
||
4 | ** Copyright (C) 2009- Werner Rammer, Rupert Seidl |
||
5 | ** |
||
6 | ** This program is free software: you can redistribute it and/or modify |
||
7 | ** it under the terms of the GNU General Public License as published by |
||
8 | ** the Free Software Foundation, either version 3 of the License, or |
||
9 | ** (at your option) any later version. |
||
10 | ** |
||
11 | ** This program is distributed in the hope that it will be useful, |
||
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
14 | ** GNU General Public License for more details. |
||
15 | ** |
||
16 | ** You should have received a copy of the GNU General Public License |
||
17 | ** along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
18 | ********************************************************************************************/ |
||
19 | |||
20 | #ifndef RANDOMGENERATOR_H |
||
21 | #define RANDOMGENERATOR_H |
||
705 | werner | 22 | #include <cstdlib> |
23 | #include <math.h> |
||
706 | werner | 24 | #include <time.h> |
705 | werner | 25 | |
757 | werner | 26 | #define RANDOMGENERATORSIZE 500000 |
758 | werner | 27 | #define RANDOMGENERATORROTATIONS 0 |
757 | werner | 28 | // a new set of numbers is generated for every 5*500000 = 2.500.000 numbers |
707 | werner | 29 | class RandomGenerator |
705 | werner | 30 | { |
31 | public: |
||
707 | werner | 32 | enum ERandomGenerators { ergMersenneTwister, ergWellRNG512, ergXORShift96, ergFastRandom }; |
757 | werner | 33 | RandomGenerator() { seed(0); setGeneratorType(ergMersenneTwister); } |
707 | werner | 34 | /// set the type of the random generator that should be used. |
758 | werner | 35 | static void setGeneratorType(const ERandomGenerators gen) { mGeneratorType = gen; mRotationCount=RANDOMGENERATORROTATIONS+1;mIndex=0;mRefillCounter=0; } |
36 | static void debugState(int &rIndex, int &rGeneration, int &rRefillCount) { rIndex = mIndex; rGeneration = mRotationCount; rRefillCount = mRefillCounter; } |
||
1002 | werner | 37 | static int debugNRandomNumbers() { return mIndex + RANDOMGENERATORSIZE*mRotationCount + (RANDOMGENERATORROTATIONS+1)*RANDOMGENERATORSIZE*mRefillCounter; } |
707 | werner | 38 | /// call this function to check if we need to create new random numbers. |
39 | /// this function is not reentrant! (e.g. call every year in the model) |
||
757 | werner | 40 | static void checkGenerator() { if (mRotationCount>RANDOMGENERATORROTATIONS) { refill(); } } |
707 | werner | 41 | static void setup(const ERandomGenerators gen, const unsigned oneSeed) { setGeneratorType(gen); seed(oneSeed); checkGenerator(); } |
42 | /// set a random generator seed. If oneSeed is 0, then a random number (provided by system time) is used as initial seed. |
||
43 | static void seed(const unsigned oneSeed); |
||
705 | werner | 44 | /// get a random value from [0., 1.] |
707 | werner | 45 | static inline double rand() { return next() * (1.0/4294967295.0); } |
46 | static inline double rand(const double max_value) { return max_value * rand(); } |
||
705 | werner | 47 | /// get a random integer in [0,2^32-1] |
707 | werner | 48 | static inline unsigned long randInt(){ return next(); } |
49 | static inline unsigned long randInt(const int max_value) { return max_value>0?randInt()%max_value:0; } |
||
705 | werner | 50 | /// Access to nonuniform random number distributions |
707 | werner | 51 | static inline double randNorm( const double mean, const double stddev ); |
52 | |||
705 | werner | 53 | private: |
757 | werner | 54 | static inline unsigned long next() { ++mIndex; if (mIndex>RANDOMGENERATORSIZE) { mRotationCount++; mIndex=0; checkGenerator(); } return mBuffer[mIndex]; } |
707 | werner | 55 | static unsigned int mBuffer[RANDOMGENERATORSIZE+5]; |
56 | static int mIndex; |
||
57 | static int mRotationCount; |
||
758 | werner | 58 | static int mRefillCounter; |
707 | werner | 59 | static ERandomGenerators mGeneratorType; |
60 | static void refill(); |
||
61 | }; |
||
705 | werner | 62 | |
707 | werner | 63 | /// ****************************************** |
64 | /// Global access functions for random numbers |
||
65 | /// ****************************************** |
||
705 | werner | 66 | |
67 | |||
707 | werner | 68 | /// nrandom returns a random number from [p1, p2] -> p2 is a possible result! |
69 | inline double nrandom(const double& p1, const double& p2) |
||
705 | werner | 70 | { |
707 | werner | 71 | return p1 + RandomGenerator::rand(p2-p1); |
72 | //return p1 + (p2-p1)*(rand()/double(RAND_MAX)); |
||
705 | werner | 73 | } |
707 | werner | 74 | /// returns a random number in [0,1] (i.e.="1" is a possible result!) |
75 | inline double drandom() |
||
705 | werner | 76 | { |
707 | werner | 77 | return RandomGenerator::rand(); |
78 | //return rand()/double(RAND_MAX); |
||
705 | werner | 79 | } |
1164 | werner | 80 | /// return a random number from "from" to "to" (excluding 'to'.), i.e. irandom(3,6) results in 3, 4 or 5. |
707 | werner | 81 | inline int irandom(int from, int to) |
82 | { |
||
83 | return from + RandomGenerator::randInt(to-from); |
||
84 | //return from + rand()%(to-from); |
||
85 | } |
||
705 | werner | 86 | |
707 | werner | 87 | |
88 | |||
89 | |||
90 | inline double RandomGenerator::randNorm( const double mean, const double stddev ) |
||
705 | werner | 91 | { |
92 | // Return a real number from a normal (Gaussian) distribution with given |
||
93 | // mean and standard deviation by polar form of Box-Muller transformation |
||
94 | double x, y, r; |
||
95 | do |
||
96 | { |
||
97 | x = 2.0 * rand() - 1.0; |
||
98 | y = 2.0 * rand() - 1.0; |
||
99 | r = x * x + y * y; |
||
100 | } |
||
101 | while ( r >= 1.0 || r == 0.0 ); |
||
102 | double s = sqrt( -2.0 * log(r) / r ); |
||
103 | return mean + x * s * stddev; |
||
104 | } |
||
105 | |||
707 | werner | 106 | |
107 | |||
108 | |||
109 | |||
110 | |||
111 | |||
112 | |||
113 | #endif // RANDOMGENERATOR_H |