source: Sophya/trunk/SophyaLib/BaseTools/randr48.cc@ 3855

Last change on this file since 3855 was 3838, checked in by ansari, 15 years ago

MAJ commentaires pour doxygen, passage methode Next() en pure virtual (=0), Reza 09/08/2010

File size: 9.2 KB
Line 
1#include "machdefs.h"
2#include <math.h>
3#include <stdlib.h>
4#include <string.h>
5#include "thsafeop.h"
6#include "fiondblock.h"
7
8#include "randr48.h"
9
10namespace SOPHYA {
11
12/*!
13 \class DR48RandGen
14 \ingroup BaseTools
15 \brief Implementation of the RandomGeneratorInterface class using drand48() functions
16
17 Its PPF handler can be used to save the complete state of the class and the underlying
18 random number generator used.
19
20 \sa SOPHYA::ObjFileIO<ThSDR48RandGen>
21
22*/
23
24static bool dr48_first = true;
25DR48RandGen::DR48RandGen()
26{
27 if (dr48_first) {
28 Next(); dr48_first=false;
29 }
30}
31
32DR48RandGen::DR48RandGen(long int seed)
33{
34 srand48(seed);
35 dr48_first=false;
36}
37
38DR48RandGen::~DR48RandGen()
39{
40}
41
42void DR48RandGen::ShowRandom()
43{
44 cout<<"RandomGenerator is DR48RandGen"<<endl;
45}
46
47void DR48RandGen::SetSeed(long int seed)
48{
49 srand48(seed);
50}
51
52void DR48RandGen::SetSeed(uint_2 seed[3])
53{
54 seed48(seed);
55}
56void DR48RandGen::GetSeed(uint_2 seed[3])
57{
58 uint_2 *p, seed_dummy[3] = {0,0,0};
59 p = seed48(seed_dummy);
60 memcpy(seed,p,3*sizeof(uint_2));
61 // on re-initialise a ce qui etait avant
62 seed48(seed);
63}
64
65r_8 DR48RandGen::Next()
66{
67 return drand48();
68}
69
70void DR48RandGen::AutoInit(int lp)
71{
72 vector<uint_2> seed;
73 GenerateSeedVector(0,seed,lp);
74 uint_2 s[3] = {seed[0],seed[1],seed[2]};
75 SetSeed(s);
76}
77
78//------------------------------------------------------------
79//------------------------------------------------------------
80//------------------------------------------------------------
81/*!
82 \class ThSDR48RandGen
83 \ingroup BaseTools
84 \brief Thread-safe version of DR48RandGen random number generator using drand48() functions.
85
86
87 Several instances of this class can be used in different threads without the risk of
88 corrupting the internal state of the drand48() generator. However, in multi-thread applications,
89 there is no guarantee to obtain the same sequence of numbers in each thread.
90 Its PPF handler can be used to save the complete state of the class and the underlying
91 random number generator (drand48() which is used.
92
93 \sa SOPHYA::ObjFileIO<ThSDR48RandGen>
94
95 \code
96 // A.1- Create a thread safe generator based on drand48()
97 ThSDR48RandGen rg;
98 // A.2- Auto initilize its state (using the system time)
99 rg.AutoInit();
100 // A.3- compute and print a smal sequence of random numbers
101 int N = 10;
102 for(int i=0; i<N; i++)
103 cout << " I=" << i << " rand_flat01= " << rg.Flat01() << " rand.gaussian= " << rg.Gaussian() << endl;
104 // A.4- Save the generator state for subsequent use
105 POutPersist po("rg.ppf");
106 po << rg;
107 // A.5- compute and print a second sequence of random numbers
108 for(int i=0; i<N; i++)
109 cout << "++ I=" << i+N << " rand_flat01= " << rg.Flat01() << " rand.gaussian= " << rg.Gaussian() << endl;
110
111 ... In another program :
112
113 // B.1- Create and initialize the generator from the previously saved state
114 ThSDR48RandGen rgr;
115 PInPersist pin("rg.ppf");
116 pin >> rgr;
117 int N = 10;
118 // B.2- Compute and print a sequence of random number, should be compared to the sequance A.5
119 for(int i=0; i<N; i++)
120 cout << "-- I=" << i << " rand_flat01= " << rgr.Flat01() << " rand.gaussian= " << rgr.Gaussian() << endl;
121
122
123 \endcode
124*/
125
126// Objet statique global pour gestion de lock entre threads
127static ThSafeOp* ths_rand = NULL;
128
129/*!
130 \brief Constructor with optional specification of the internal buffer size and thread-safety flag
131
132 The behaviour of the base class DR48RandGen can be reproduced by specifying tsafe=false
133 \param n : an internal buffer of size n is created and filled through block calls to drand48()
134 \param tsafe : if false, creates a non thread-safe generator
135*/
136
137ThSDR48RandGen::ThSDR48RandGen(size_t n, bool tsafe)
138{
139 if (ths_rand == NULL) ths_rand = new ThSafeOp;
140 if (tsafe) { // thread-safe
141 fg_nothrsafe = false;
142 if (n < 1) n = 1024;
143 rseq_.ReSize(n, false);
144 idx_ = n;
145 }
146 else { // NOT thread-safe
147 fg_nothrsafe = true;
148 idx_ = 1;
149 }
150}
151
152ThSDR48RandGen::ThSDR48RandGen(ThSDR48RandGen const & rg)
153{
154 if (ths_rand == NULL) ths_rand = new ThSafeOp;
155 if (!rg.fg_nothrsafe) { // thread-safe
156 fg_nothrsafe = false;
157 rseq_.ReSize(rg.rseq_.Size(), false);
158 idx_ = rseq_.Size();
159 }
160 else { // NOT thread-safe
161 fg_nothrsafe = true;
162 idx_ = 1;
163 }
164}
165
166
167ThSDR48RandGen::~ThSDR48RandGen(void)
168{
169 // rien a faire
170}
171
172void ThSDR48RandGen::SetBuffSize(size_t n)
173// redimensionnement du buffer
174{
175 if(fg_nothrsafe) return;
176 if (n < 1) n = 1024;
177 rseq_.ReSize(n, false);
178 idx_ = n;
179}
180
181
182void ThSDR48RandGen::ShowRandom()
183{
184 cout<<"RandomGenerator is ThSDR48RandGen("<<rseq_.Size()<<","<<!fg_nothrsafe<<")"<<endl;
185}
186
187void ThSDR48RandGen::SetSeed(long int seed)
188{
189 if (ths_rand == NULL) ths_rand = new ThSafeOp;
190 ths_rand->lock();
191 DR48RandGen::SetSeed(seed);
192 ths_rand->unlock();
193 return;
194}
195
196void ThSDR48RandGen::SetSeed(uint_2 seed[3])
197{
198 if (ths_rand == NULL) ths_rand = new ThSafeOp;
199 ths_rand->lock();
200 SetSeed_P(seed);
201 ths_rand->unlock();
202}
203
204void ThSDR48RandGen::GetSeed(uint_2 seed[3])
205{
206 if (ths_rand == NULL) ths_rand = new ThSafeOp;
207 ths_rand->lock();
208 GetSeed_P(seed);
209 ths_rand->unlock();
210 return;
211}
212
213void ThSDR48RandGen::SetSeed_P(uint_2 seed[3])
214{
215 DR48RandGen::SetSeed(seed);
216}
217
218void ThSDR48RandGen::GetSeed_P(uint_2 seed[3])
219{
220 DR48RandGen::GetSeed(seed);
221}
222
223void ThSDR48RandGen::AutoInit(int lp)
224{
225 vector<uint_2> seed;
226 GenerateSeedVector(0,seed,lp);
227 uint_2 s[3] = {seed[0],seed[1],seed[2]};
228 SetSeed(s);
229}
230
231
232void ThSDR48RandGen::GenSeq(void)
233{
234 ths_rand->lock();
235 for(size_t k=0; k<rseq_.Size(); k++) rseq_(k) = drand48();
236 ths_rand->unlock();
237 idx_ = 0;
238}
239
240r_8 ThSDR48RandGen::Next()
241{
242 if (rseq_.Size() == 0) return drand48();
243 else {
244 if(idx_==rseq_.Size()) GenSeq();
245 return(rseq_(idx_++));
246 }
247}
248
249//----------------------------------------------------------
250// Classe pour la gestion de persistance
251// ObjFileIO<DR48RandGen>
252//----------------------------------------------------------
253
254/* --Methode-- */
255DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
256void ObjFileIO<DR48RandGen>::WriteSelf(POutPersist& s) const
257{
258 if (dobj == NULL)
259 throw NullPtrError("ObjFileIO<DR48RandGen>::WriteSelf() dobj=NULL");
260 uint_2 seed[3];
261 dobj->GetSeed(seed);
262 s.Put(seed,3);
263 return;
264}
265
266/* --Methode-- */
267DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
268void ObjFileIO<DR48RandGen>::ReadSelf(PInPersist& s)
269{
270 uint_2 seed[3];
271 s.Get(seed,3);
272 if(dobj == NULL) dobj = new DR48RandGen();
273 dobj->SetSeed(seed);
274 return;
275}
276
277//----------------------------------------------------------
278// Classe pour la gestion de persistance
279// ObjFileIO<ThSDR48RandGen>
280//----------------------------------------------------------
281
282/* --Methode-- */
283DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
284void ObjFileIO<ThSDR48RandGen>::WriteSelf(POutPersist& s) const
285{
286 if (dobj == NULL)
287 throw NullPtrError("ObjFileIO<ThSDR48RandGen>::WriteSelf() dobj=NULL");
288 ths_rand->lock(); // thread-safety
289 uint_4 itab[6];
290 //itab : [0]: version, [1,2,3] = srand48 state/seed , [4,5] = reserved for future use
291 itab[0] = 1;
292 // On recupere et on ecrit ds le PPF l'etat du generateur aleatoire
293 uint_2 seed_16v[3];
294 dobj->GetSeed_P(seed_16v);
295 for(int i=0; i<3; i++) itab[i+1] = seed_16v[i];
296 itab[4] = 0;
297 s.Put(itab, 6);
298 uint_8 sz = dobj->rseq_.Size();
299 s.Put(sz); // Taille du tableau intermediaire
300 uint_8 ix = dobj->idx_;
301 s.Put(ix); // valeur de l'index
302
303 if (dobj->rseq_.Size() > 0) s << dobj->rseq_; // On ecrit le tableau (NDataBlock) si necessaire
304 ths_rand->unlock(); // thread-safety
305 return;
306}
307
308/* --Methode-- */
309DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
310void ObjFileIO<ThSDR48RandGen>::ReadSelf(PInPersist& s)
311{
312 uint_4 itab[6];
313 //itab : [0]: version, [1,2,3] = srand48 state/seed , [4] = reserved for future use
314 s.Get(itab, 6);
315 uint_8 sz,ix;
316 s.Get(sz); // Taille du tableau intermediaire
317 s.Get(ix); // Taille du tableau intermediaire
318
319 if (dobj == NULL) dobj = new ThSDR48RandGen(sz, (sz>0)?true:false);
320 dobj->idx_ = ix;
321 if (sz > 0) {
322 s >> dobj->rseq_; // On lit le tableau (NDataBlock) si necessaire
323 dobj->fg_nothrsafe = false;
324 }
325 else { // Objet lu est NON thread-safe, taille_tableau rseq_ = 0
326 dobj->fg_nothrsafe = true;
327 if (dobj->rseq_.Size() > 0) dobj->rseq_.Dealloc();
328 }
329 // On initialise l'etat du generateur aleatoire avec les valeurs lues
330 uint_2 seed_16v[3];
331 //NON ? pourquoi faire GetSeed ? : dobj->GetSeed_P(seed_16v);
332 for(int i=0; i<3; i++) seed_16v[i] = itab[i+1];
333 dobj->SetSeed(seed_16v);
334 return;
335}
336
337// ---------------------------------------------------------
338#ifdef __CXX_PRAGMA_TEMPLATES__
339#pragma define_template ObjFileIO<DR48RandGen>
340#endif
341
342#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
343template class ObjFileIO<DR48RandGen>;
344#endif
345
346// ---------------------------------------------------------
347#ifdef __CXX_PRAGMA_TEMPLATES__
348#pragma define_template ObjFileIO<ThSDR48RandGen>
349#endif
350
351#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
352template class ObjFileIO<ThSDR48RandGen>;
353#endif
354// ---------------------------------------------------------
355
356
357} /* namespace SOPHYA */
Note: See TracBrowser for help on using the repository browser.