source: Sophya/trunk/SophyaLib/BaseTools/stsrand.cc@ 3392

Last change on this file since 3392 was 3389, checked in by cmv, 18 years ago

intro classe RandomGenerator , cmv+rz 22/11/2007

File size: 5.8 KB
Line 
1#include "stsrand.h"
2#include "thsafeop.h"
3#include "srandgen.h"
4#include "fiondblock.h"
5#include <math.h>
6
7namespace SOPHYA {
8
9/*!
10 \class RandomGenerator
11 \ingroup BaseTools
12 This class is a thread-safe random number generator.
13 Its PPF handler can be used to save the complete state of the class and the underlying
14 random number generator used.
15
16 \sa SOPHYA::ObjFileIO<RandomGenerator>
17
18*/
19
20// Objet statique global pour gestion de lock entre threads
21static ThSafeOp* ths_rand = NULL;
22
23RandomGenerator::RandomGenerator(size_t n, bool tsafe)
24{
25 if (ths_rand == NULL) ths_rand = new ThSafeOp;
26 if (tsafe) { // thread-safe
27 fg_nothrsafe = false;
28 if (n < 1) n = 1024;
29 rseq_.ReSize(n, false);
30 idx_ = n;
31 }
32 else { // NOT thread-safe
33 fg_nothrsafe = true;
34 idx_ = 1;
35 }
36}
37
38RandomGenerator::RandomGenerator(RandomGenerator const & rg)
39{
40 if (ths_rand == NULL) ths_rand = new ThSafeOp;
41 if (!rg.fg_nothrsafe) { // thread-safe
42 fg_nothrsafe = false;
43 rseq_.ReSize(rg.rseq_.Size(), false);
44 idx_ = rseq_.Size();
45 }
46 else { // NOT thread-safe
47 fg_nothrsafe = true;
48 idx_ = 1;
49 }
50}
51
52
53RandomGenerator::~RandomGenerator(void)
54{
55 // rien a faire
56}
57
58void RandomGenerator::AutoInit(int lp)
59{
60 if (ths_rand == NULL) ths_rand = new ThSafeOp;
61 ths_rand->lock();
62 if(lp) cout << "RandomGenerator::AutoInit() : Calling Auto_Ini_Ranf() ..." << endl;
63 Auto_Ini_Ranf(lp); // Faut-il faire copier/coller du code Auto_Ini_Ranf() ici ?
64 ths_rand->unlock();
65}
66
67void RandomGenerator::Init(long seed_val, int lp)
68{
69 if (ths_rand == NULL) ths_rand = new ThSafeOp;
70 if(lp) cout << "RandomGenerator::Init(long seed=" << seed_val << ")" << endl;
71 ths_rand->lock();
72 srand48(seed_val);
73 ths_rand->unlock();
74 return;
75}
76
77void RandomGenerator::Init(unsigned short seed_16v[3], int lp)
78{
79 if (ths_rand == NULL) ths_rand = new ThSafeOp;
80 if(lp) cout << "RandomGenerator::Init(u_short seed_16v[3]=" << seed_16v[0]
81 << "," << seed_16v[1] << "," << seed_16v[2] << ")" << endl;
82 ths_rand->lock();
83 Init_P(seed_16v);
84 ths_rand->unlock();
85}
86
87void RandomGenerator::GetSeed(unsigned short seed_16v[3], int lp)
88{
89 if (ths_rand == NULL) ths_rand = new ThSafeOp;
90 ths_rand->lock();
91 GetSeed_P(seed_16v);
92 ths_rand->unlock();
93 if(lp) cout << "RandomGenerator::GetSeed(u_short seed_16v[3]=" << seed_16v[0]
94 << "," << seed_16v[1] << "," << seed_16v[2] << ")" << endl;
95 return;
96}
97
98void RandomGenerator::Init_P(unsigned short seed_16v[3])
99{
100 seed48(seed_16v);
101}
102
103void RandomGenerator::GetSeed_P(unsigned short seed_16v[3])
104{
105 unsigned short seed[3] = {0,0,0};
106 unsigned short *p;
107 p = seed48(seed);
108 memcpy(seed_16v,p,3*sizeof(unsigned short));
109 /* on re-initialise a ce qui etait avant */
110 seed48(seed_16v);
111 return;
112}
113
114r_8 RandomGenerator::Gaussian()
115{
116 r_8 A=Next();
117 while (A==0.) A=Next();
118 return sqrt(-2.*log(A))*cos(2.*M_PI*Next());
119}
120
121
122uint_8 RandomGenerator::Poisson(double mu,double mumax)
123{
124 double pp,ppi,x;
125
126 if((mumax>0.)&&(mu>=mumax)) {
127 pp = sqrt(mu);
128 while( (x=pp*Gaussian()) < -mu );
129 return (uint_8)(mu+x+0.5);
130 }
131 else {
132 uint_8 n;
133 ppi = pp = exp(-mu);
134 x = Next();
135 n = 0;
136 while (x > ppi) {
137 n++;
138 pp = mu*pp/(double)n;
139 ppi += pp;
140 }
141 return n;
142 }
143 return 0; // pas necessaire ?
144}
145
146void RandomGenerator::GenSeq(void)
147{
148 ths_rand->lock();
149 for(size_t k=0; k<rseq_.Size(); k++) rseq_(k) = drand48();
150 ths_rand->unlock();
151 idx_ = 0;
152}
153
154//----------------------------------------------------------
155// Classe pour la gestion de persistance
156// ObjFileIO<RandomGenerator>
157//----------------------------------------------------------
158
159/* --Methode-- */
160DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
161void ObjFileIO<RandomGenerator>::WriteSelf(POutPersist& s) const
162{
163 if (dobj == NULL)
164 throw NullPtrError("ObjFileIO<RandomGenerator>::WriteSelf() dobj=NULL");
165 ths_rand->lock(); // thread-safety
166 uint_4 itab[6];
167 //itab : [0]: version, [1,2,3] = srand48 state/seed , [4,5] = reserved for future use
168 itab[0] = 1;
169 // On recupere et on ecrit ds le PPF l'etat du generateur aleatoire
170 unsigned short seed_16v[3];
171 dobj->GetSeed_P(seed_16v);
172 for(int i=0; i<3; i++) itab[i+1] = seed_16v[i];
173 itab[4] = 0;
174 s.Put(itab, 6);
175 uint_8 sz = dobj->rseq_.Size();
176 s.Put(sz); // Taille du tableau intermediaire
177 uint_8 ix = dobj->idx_;
178 s.Put(ix); // valeur de l'index
179
180 if (dobj->rseq_.Size() > 0) s << dobj->rseq_; // On ecrit le tableau (NDataBlock) si necessaire
181 ths_rand->unlock(); // thread-safety
182 return;
183}
184
185/* --Methode-- */
186DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
187void ObjFileIO<RandomGenerator>::ReadSelf(PInPersist& s)
188{
189 uint_4 itab[6];
190 //itab : [0]: version, [1,2,3] = srand48 state/seed , [4] = reserved for future use
191 s.Get(itab, 6);
192 uint_8 sz,ix;
193 s.Get(sz); // Taille du tableau intermediaire
194 s.Get(ix); // Taille du tableau intermediaire
195
196 if (dobj == NULL) dobj = new RandomGenerator(sz, (sz>0)?true:false);
197 dobj->idx_ = ix;
198 if (sz > 0) {
199 s >> dobj->rseq_; // On lit le tableau (NDataBlock) si necessaire
200 dobj->fg_nothrsafe = false;
201 }
202 else { // Objet lu est NON thread-safe, taille_tableau rseq_ = 0
203 dobj->fg_nothrsafe = true;
204 if (dobj->rseq_.Size() > 0) dobj->rseq_.Dealloc();
205 }
206 // On initialise l'etat du generateur aleatoire avec les valeurs lues
207 unsigned short seed_16v[3];
208 dobj->GetSeed_P(seed_16v);
209 for(int i=0; i<3; i++) seed_16v[i] = itab[i+1];
210 dobj->Init(seed_16v, 0);
211 return;
212}
213
214// ---------------------------------------------------------
215#ifdef __CXX_PRAGMA_TEMPLATES__
216#pragma define_template ObjFileIO<RandomGenerator>
217#endif
218
219#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
220template class ObjFileIO<RandomGenerator>;
221#endif
222// ---------------------------------------------------------
223
224} /* namespace SOPHYA */
225
Note: See TracBrowser for help on using the repository browser.