Subversion Repositories public iLand

Rev

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