| Bsoft 2.0.5 Bernard's software package

random_numbers.cpp
Go to the documentation of this file.
1
9 #include "Vector3.h"
10 #include "utilities.h"
11
12 // Declaration of global variables
13 extern int verbose; // Level of output to the screen
14 int randseed(0); // Flag to indicate if a random seed has been generated
15
22 long get_rand_max()
23 {
24 long i, rand_max(32767);
25
26 for ( i=0; i<100; i++ )
27 if ( random() > rand_max ) rand_max = 2147483647;
28
29 return rand_max;
30 }
31
32 double irm(1.0L/get_rand_max());
33
41 long random_seed()
42 {
43 if ( randseed ) return 1;
44
45 srandom(getpid());
46
47 randseed = 1;
48
49 return 1;
50 }
51
52 int random_array_uniform_chunk(float* r, long start, long end, double min, double range)
53 {
54 for ( long i=start; i<end; i++ )
55 r[i] = random()*range + min;
56
57 return 0;
58 }
59
76 float* random_array_uniform(long n, double min, double max)
77 {
78 float* r = new float[n];
79
80 double range = (max - min)/get_rand_max();
81
82 if ( verbose & VERB_FULL ) {
83 cout << "Generating a random series with a uniform distribution:" << endl;
84 cout << "Size: " << n << endl;
85 cout << "Minimum & maximum: " << min << " " << max << endl;
86 }
87
88 random_seed();
89
90 long chunk_size = get_chunk_size(n);
91
92 #ifdef HAVE_GCD
93 dispatch_apply((n - 1)/chunk_size + 1, dispatch_get_global_queue(0, 0), ^(size_t i){
94 long start = i*chunk_size;
95 long end = start + chunk_size;
96 if ( end > n ) end = n;
97 random_array_uniform_chunk(r, start, end, min, range);
98 });
99 #else
100 #pragma omp parallel for
101 for ( long i=0; i<n; i+=chunk_size ) {
102 long end = i + chunk_size;
103 random_array_uniform_chunk(r, i, end, min, range);
104 }
105 #endif
106
107 return r;
108 }
109
123 double random_gaussian(double avg, double stdev)
124 {
125 if ( verbose & VERB_FULL ) {
126 cout << "Generating a random value with a gaussian distribution:" << endl;
127 cout << "Avg and std: " << avg << " " << stdev << endl;
128 }
129
130 double r;
131
132 r = -2*log(random()*irm);
133
134 if ( r > 0 ) r = avg + stdev*sqrt(r)*cos(TWOPI*(random()*irm));
135 else r = avg;
136
137 if ( verbose & VERB_FULL )
138 cout << "Random value: " << r << endl;
139
140 return r;
141 }
142
143 int random_array_gaussian_chunk(float* r, long start, long end, double avg, double stdev)
144 {
145 double v;
146
147 // cout << start << tab << end << endl;
148
149 for ( long i=start; i<end; i++ ) {
150 v = -2*log(random()*irm);
151 if ( v > 0 )
152 r[i] = avg + stdev*sqrt(v)*cos(TWOPI*random()*irm);
153 }
154
155 return 0;
156 }
157
172 float* random_array_gaussian(long n, double avg, double stdev)
173 {
174 float* r = new float[n];
175
176 if ( verbose & VERB_FULL ) {
177 cout << "Generating a random series with a gaussian distribution:" << endl;
178 cout << "Size: " << n << endl;
179 cout << "Avg and std: " << avg << " " << stdev << endl;
180 }
181
182 random_seed();
183
184 long chunk_size = get_chunk_size(n);
185
186 #ifdef HAVE_GCD
187 dispatch_apply((n - 1)/chunk_size + 1, dispatch_get_global_queue(0, 0), ^(size_t i){
188 long start = i*chunk_size;
189 long end = start + chunk_size;
190 if ( end > n ) end = n;
191 random_array_gaussian_chunk(r, start, end, avg, stdev);
192 });
193 #else
194 #pragma omp parallel for
195 for ( long i=0; i<n; i+=chunk_size ) {
196 long end = i + chunk_size;
197 if ( end > n ) end = n;
198 random_array_gaussian_chunk(r, i, end, avg, stdev);
199 }
200 #endif
201
202 return r;
203 }
204
221 double random_poisson(double avg)
222 {
223 double r = 0;
224
225 if ( avg <= 0 ) return r;
226
227 double sq, lnavg, g, t, y(0);
228
229 if ( avg < 12.0 ) {
230 g = exp(-avg);
231 for ( r = -1, t = 1; t > g; r++ ) t *= random()*irm;
232 } else {
233 sq = sqrt(2.0*avg);
234 lnavg = log(avg);
235 g = avg*lnavg - lgamma(avg + 1.0L);
236 do {
237 for ( r = -1; r < 0; ) {
238 y = tan(M_PI*irm*random());
239 r = sq*y + avg;
240 }
241 r = floor(r);
242 t = 0.9*(1 + y*y)*exp(r*lnavg - lgamma(r + 1.0L) - g);
243 } while ( random()*irm > t );
244 }
245
246 return r;
247 }
248
249 int random_array_poisson_chunk(float* r, long start, long end, double avg)
250 {
251 long i;
252 double sq, lnavg, g, t, y;
253
254 if ( avg < 12.0 ) {
255 g = exp(-avg);
256 for ( i=start; i<end; i++ )
257 for ( r[i] = -1, t = 1; t > g; r[i]++ ) t *= random()*irm;
258 } else {
259 sq = sqrt(2.0*avg);
260 lnavg = log(avg);
261 g = avg*lnavg - lgamma(avg + 1.0L);
262 for ( i=start; i<end; i++ ) {
263 do {
264 for ( r[i] = -1; r[i] < 0; ) {
265 y = tan(M_PI*irm*random());
266 r[i] = sq*y + avg;
267 }
268 r[i] = floor(r[i]);
269 t = 0.9*(1 + y*y)*exp(r[i]*lnavg - lgamma(r[i] + 1.0L) - g);
270 } while ( random()*irm > t );
271 }
272 }
273
274 return 0;
275 }
276
296 float* random_array_poisson(int n, double avg)
297 {
298 float* r = new float[n];
299
300 if ( avg <= 0 ) return r;
301
302 random_seed();
303
304 long chunk_size = get_chunk_size(n);
305
306 #ifdef HAVE_GCD
307 dispatch_apply((n - 1)/chunk_size + 1, dispatch_get_global_queue(0, 0), ^(size_t i){
308 long start = i*chunk_size;
309 long end = start + chunk_size;
310 if ( end > n ) end = n;
311 random_array_poisson_chunk(r, start, end, avg);
312 });
313 #else
314 #pragma omp parallel for
315 for ( long i=0; i<n; i+=chunk_size ) {
316 long end = i + chunk_size;
317 random_array_poisson_chunk(r, i, end, avg);
318 }
319 #endif
320
321 return r;
322 }
323
338 double random_logistical(double avg, double stdev)
339 {
340 double r, rand_max = get_rand_max();
341 double prefac = stdev/GOLDEN;
342
343 if ( verbose & VERB_FULL ) {
344 cout << "Generating a value with a logistical differential distribution:" << endl;
345 cout << "Avg, std and range: " << avg << " " << stdev << endl;
346 }
347
348 r = avg + prefac*log(rand_max/(random()+1.0L) - 1);
349
350 return r;
351 }
352
353 int random_array_logistical_chunk(float* r, long start, long end, double avg, double stdev)
354 {
355 double rand_max = get_rand_max();
356 double prefac = stdev/GOLDEN;
357
358 for ( long i=start; i<end; i++ )
359 r[i] = avg + prefac*log(rand_max/(random()+1.0L) - 1);
360
361 return 0;
362 }
363
379 float* random_array_logistical(long n, double avg, double stdev)
380 {
381 float* r = new float[n];
382
383 if ( verbose & VERB_FULL ) {
384 cout << "Generating a random series with a logistical differential distribution:" << endl;
385 cout << "Size: " << n << endl;
386 cout << "Avg, std and range: " << avg << " " << stdev << endl;
387 }
388
389 random_seed();
390
391 long chunk_size = get_chunk_size(n);
392
393 #ifdef HAVE_GCD
394 dispatch_apply((n - 1)/chunk_size + 1, dispatch_get_global_queue(0, 0), ^(size_t i){
395 long start = i*chunk_size;
396 long end = start + chunk_size;
397 if ( end > n ) end = n;
398 random_array_logistical_chunk(r, start, end, avg, stdev);
399 });
400 #else
401 #pragma omp parallel for
402 for ( long i=0; i<n; i+=chunk_size ) {
403 long end = i + chunk_size;
404 random_array_logistical_chunk(r, i, end, avg, stdev);
405 }
406 #endif
407
408 return r;
409 }
410
419 Vector3<double> vector3_random_unit_sphere()
420 {
421 Vector3<double> vec;
422
423 vec[0] = random_gaussian(0, 1);
424 vec[1] = random_gaussian(0, 1);
425 vec[2] = random_gaussian(0, 1);
426 vec.normalize();
427
428 return vec;
429 }
430
440 Vector3<double> vector3_random(const double min, const double max)
441 {
442 Vector3<double> vec;
443 double range = (max - min)/get_rand_max();
444
445 vec[0] = random()*range + min;
446 vec[1] = random()*range + min;
447 vec[2] = random()*range + min;
448
449 return vec;
450 }
451
462 Vector3<double> vector3_random(Vector3<double> min, Vector3<double> max)
463 {
464 Vector3<double> vec;
465 Vector3<double> range = (max - min) / get_rand_max();
466
467 vec[0] = random()*range[0] + min[0];
468 vec[1] = random()*range[1] + min[1];
469 vec[2] = random()*range[2] + min[2];
470
471 return vec;
472 }
473
483 Vector3<double> vector3_random(const double length)
484 {
485 Vector3<double> vec = vector3_random_unit_sphere();
486
487 vec *= random()*length/get_rand_max();
488
489 return vec;
490 }
491
502 Vector3<double> vector3_random_gaussian(double avg, double stdev)
503 {
504 Vector3<double> vec = vector3_random_unit_sphere();
505 double amp = random_gaussian(avg, stdev);
506
507 vec *= amp;
508
509 return vec;
510 }
511
522 Vector3<double> vector3_xy_random_gaussian(double avg, double stdev)
523 {
524 Vector3<double> vec;
525 double amp = random_gaussian(avg, stdev);
526
527 vec[0] = random_gaussian(0, 1);
528 vec[1] = random_gaussian(0, 1);
529 vec.normalize();
530 vec *= amp;
531
532 return vec;
533 }
534
535
536 double halton_number(long i, long b)
537 {
538 double r(0), f(1);
539
540 while ( i > 0 ) {
541 f /= b;
542 r += f * (i%b);
543 i /= b;
544 }
545
546 return r;
547 }
548
558 double* halton_sequence(long n, long b)
559 {
560 long i;
561 double* r = new double[n];
562
563 for ( i=0; i<n; i++ )
564 r[i] = halton_number(i, b);
565
566 return r;
567 }
568
vector3_random
Vector3< double > vector3_random(const double min, const double max)
Generates a random vector within a defined cube.
Definition: random_numbers.cpp:440
Vector3::normalize
double normalize()
Definition: Vector3.h:236
halton_number
double halton_number(long i, long b)
Definition: random_numbers.cpp:536
vector3_random_gaussian
Vector3< double > vector3_random_gaussian(double avg, double stdev)
Generates a random vector within a random gaussian-distributed length.
Definition: random_numbers.cpp:502
utilities.h
Header file for general utilities.
halton_sequence
double * halton_sequence(long n, long b)
Generates a Halton sequence.
Definition: random_numbers.cpp:558
random_array_gaussian_chunk
int random_array_gaussian_chunk(float *r, long start, long end, double avg, double stdev)
Definition: random_numbers.cpp:143
random_array_uniform
float * random_array_uniform(long n, double min, double max)
Generates a series with a uniform random distribution.
Definition: random_numbers.cpp:76
GOLDEN
#define GOLDEN
Definition: utilities.h:81
get_chunk_size
size_t get_chunk_size(size_t datasize)
Returns the chunk size per thread.
Definition: utilities.cpp:645
randseed
int randseed(0)
random_array_uniform_chunk
int random_array_uniform_chunk(float *r, long start, long end, double min, double range)
Definition: random_numbers.cpp:52
M_PI
#define M_PI
Definition: utilities.h:59
random_array_logistical_chunk
int random_array_logistical_chunk(float *r, long start, long end, double avg, double stdev)
Definition: random_numbers.cpp:353
length
double length(vector< T > v)
Definition: Vector3.h:528
irm
double irm(1.0L/get_rand_max())
verbose
int verbose
random_array_poisson_chunk
int random_array_poisson_chunk(float *r, long start, long end, double avg)
Definition: random_numbers.cpp:249
random_array_logistical
float * random_array_logistical(long n, double avg, double stdev)
Generates an array with a logistical random distribution.
Definition: random_numbers.cpp:379
random_seed
long random_seed()
Gets a random seed and sets the flag.
Definition: random_numbers.cpp:41
get_rand_max
long get_rand_max()
Finds the maximum random number for a system.
Definition: random_numbers.cpp:22
random_gaussian
double random_gaussian(double avg, double stdev)
Generates a value with a gaussian random distribution.
Definition: random_numbers.cpp:123
Vector3< double >
Vector3.h
Class for 3-value vectors.
random_logistical
double random_logistical(double avg, double stdev)
Generates a value with a logistical random distribution.
Definition: random_numbers.cpp:338
random_array_gaussian
float * random_array_gaussian(long n, double avg, double stdev)
Generates a series with a gaussian random distribution of values.
Definition: random_numbers.cpp:172
random_array_poisson
float * random_array_poisson(int n, double avg)
Generates a series with a poisson random distribution of values.
Definition: random_numbers.cpp:296
vector3_random_unit_sphere
Vector3< double > vector3_random_unit_sphere()
Generates a random vector on the unit sphere.
Definition: random_numbers.cpp:419
VERB_FULL
#define VERB_FULL
Definition: utilities.h:109
random_poisson
double random_poisson(double avg)
Generates a value deviating from the average based on a poisson distribution.
Definition: random_numbers.cpp:221
TWOPI
#define TWOPI
Definition: utilities.h:68
vector3_xy_random_gaussian
Vector3< double > vector3_xy_random_gaussian(double avg, double stdev)
Generates a random vector within a random gaussian-distributed length in the xy plane.
Definition: random_numbers.cpp:522