Statistics
| Branch: | Revision:

root / src / sim / cmersennetwister.cc @ 08285dff

History | View | Annotate | Download (4.24 KB)

1 01873262 Georg Kunz
//==========================================================================
2
//  CMERSENNETWISTER.CC - part of
3
//                 OMNeT++/OMNEST
4
//              Discrete System Simulation in C++
5
//
6
// Contents:
7
//   class cMersenneTwister
8
//
9
//==========================================================================
10
11
/*--------------------------------------------------------------*
12
  Copyright (C) 2002-2008 Andras Varga
13
  Copyright (C) 2006-2008 OpenSim Ltd.
14

15
  This file is distributed WITHOUT ANY WARRANTY. See the file
16
  `license' for details on this and other legal matters.
17
*--------------------------------------------------------------*/
18
19
#include "cenvir.h"
20
#include "simutil.h"
21
#include "cexception.h"
22
#include "cmersennetwister.h"
23
#include "cmessage.h"
24
#include "cconfigoption.h"
25
26
USING_NAMESPACE
27
28
29
Register_Class(cMersenneTwister);
30
31
Register_PerRunConfigOption(CFGID_SEED_N_MT, "seed-%-mt", CFG_INT, NULL, "When Mersenne Twister is selected as random number generator (default): seed for RNG number k. (Substitute k for '%' in the key.)");
32
Register_PerRunConfigOption(CFGID_SEED_N_MT_P, "seed-%-mt-p%", CFG_INT, NULL, "With parallel simulation: When Mersenne Twister is selected as random number generator (default): seed for RNG number k in partition number p. (Substitute k for the first '%' in the key, and p for the second.)");
33
Register_GlobalConfigOption(CFGID_MERSENNE_SEED_GENERATOR_SEED, "seed-generator-seed", CFG_INT, "0", "The initial Seed for the Seed generator.");
34
35
36
void cMersenneTwister::initializeAsMaster(int runNumber, int rngId, int numRngs,
37
                int parsimProcId, int parsimNumPartitions, cConfiguration *cfg) {
38
39
        unsigned long seedValue = cfg->getAsInt(CFGID_MERSENNE_SEED_GENERATOR_SEED);
40
41
        //
42
        // use runNumber etc. as usual if the user does not supply a special
43
        // seed for the seed generator.
44
        //
45
        //If default Value was returned
46
        if (seedValue == 0) {
47
                initialize(runNumber, rngId, numRngs, parsimProcId,
48
                                parsimNumPartitions, cfg);
49
                return;
50
        }
51
52
        seed(seedValue);
53
}
54
55
void cMersenneTwister::initialize(int seedSet, int rngId, int numRngs,
56
                                  int parsimProcId, int parsimNumPartitions,
57
                                  cConfiguration *cfg)
58
{
59
    char key[40], key2[40];
60
    sprintf(key, "seed-%d-mt", rngId);
61
    sprintf(key2, "seed-%d-mt-p%d", rngId, parsimProcId);
62
63
    unsigned long seed;
64
    if (parsimNumPartitions>1)
65
    {
66
        // with parallel simulation, every partition should get distinct streams
67
        const char *value = cfg->getConfigValue(key2);
68
        if (value!=NULL)
69
        {
70
            seed = cConfiguration::parseLong(value, 0);
71
        }
72
        else
73
        {
74
            if (cfg->getConfigValue(key)!=NULL)
75
                ev << "Warning: cMersenneTwister: ignoring config key " << key << "=<seed>"
76
                   << " for parallel simulation -- please use partition-specific variant "
77
                   << key2 << "=<seed>\n";
78
            seed = (seedSet*numRngs + rngId)*MAX_PARSIM_PARTITIONS + parsimProcId;
79
        }
80
    }
81
    else
82
    {
83
        const char *value = cfg->getConfigValue(key);
84
        if (value!=NULL)
85
            seed = cConfiguration::parseLong(value, 0);
86
        else
87
            seed = seedSet*numRngs + rngId;
88
    }
89
90
    // use the following number as seed, and hope that all seed values
91
    // are well apart in the 2^19937-long sequence (it should hold if
92
    // someone did the work of testing the initialization routine).
93
    rng.seed(seed);
94
}
95
96
void cMersenneTwister::selfTest()
97
{
98
    rng.seed(1);
99
    for (int i=0; i<10000; i++)
100
        intRand();
101
    if (intRand()!=2915232614UL)
102
        throw cRuntimeError("cMersenneTwister: selfTest() failed, please report this problem!");
103
}
104
105
unsigned long cMersenneTwister::intRand()
106
{
107
    numDrawn++;
108
    return rng.randInt();
109
}
110
111
unsigned long cMersenneTwister::intRandMax()
112
{
113
    return 0xffffffffUL; // 2^32-1
114
}
115
116
unsigned long cMersenneTwister::intRand(unsigned long n)
117
{
118
    numDrawn++;
119
    return rng.randInt(n-1);
120
}
121
122
double cMersenneTwister::doubleRand()
123
{
124
    numDrawn++;
125
    return rng.randExc();
126
}
127
128
double cMersenneTwister::doubleRandNonz()
129
{
130
    numDrawn++;
131
    return rng.randDblExc();
132
}
133
134
double cMersenneTwister::doubleRandIncl1()
135
{
136
    numDrawn++;
137
    return rng.rand();
138
}
139
140
void cMersenneTwister::seed(unsigned long seed)
141
{
142
    rng.seed(seed);
143
}