su2hmc
Loading...
Searching...
No Matches
random.c File Reference

Random number generator related routines. More...

#include "coord.h"
#include "errorcodes.h"
#include "par_mpi.h"
#include "random.h"
#include "sizes.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
Include dependency graph for random.c:

Go to the source code of this file.

Macros

#define M_PI   acos(-1)
 \(\pi\) if not defined elsewhere

 

Functions

int ranset (long *seed)
 Dummy seed the ran2 generator.
 
int Par_ranread (char *filename, double *ranval)
 Reads ps from a file Since this function is very similar to Par_sread, I'm not really going to comment it check there if you are confused about things.
 
int Par_ranset (long *seed, int iread)
 Uses the rank to get a new seed. Copying from the FORTRAN description here c create new seeds in range seed to 9*seed c having a range of 0*seed gave an unfortunate pattern c in the underlying value of ds(1) (it was always 10 times bigger c on the last processor). This does not appear to happen with 9.
 
double Par_granf ()
 Generates a random double which is then sent to the other ranks.
 
int Gauss_z (Complex *ps, unsigned int n, const Complex mu, const double sigma)
 Generates a vector of normally distributed random double precision complex numbers using the Box-Muller Method.
 
int Gauss_c (Complex_f *ps, unsigned int n, const Complex_f mu, const float sigma)
 Generates a vector of normally distributed random single precision complex numbers using the Box-Muller Method.
 
int Gauss_d (double *ps, unsigned int n, const double mu, const double sigma)
 Generates a vector of normally distributed random double precision numbers using the Box-Muller Method.
 
int Gauss_f (float *ps, unsigned int n, const float mu, const float sigma)
 Generates a vector of normally distributed random single precision numbers using the Box-Muller Method.
 
double ran2 (long *idum)
 Generates uniformly distributed random double between zero and one as described in numerical recipes. It's also thread-safe for different seeds.
 

Variables

long seed
 RAN2 seed.
 

Detailed Description

Random number generator related routines.

Definition in file random.c.

Macro Definition Documentation

◆ M_PI

#define M_PI   acos(-1)

\(\pi\) if not defined elsewhere

Definition at line 41 of file random.c.

Function Documentation

◆ Gauss_c()

int Gauss_c ( Complex_f * ps,
unsigned int n,
const Complex_f mu,
const float sigma )

Generates a vector of normally distributed random single precision complex numbers using the Box-Muller Method.

Parameters
psThe output array
nThe array length
mumean
sigmavariance
Returns
Zero on success integer error code otherwise

Definition at line 260 of file random.c.

260 {
261 /*
262 * @brief Generates a vector of normally distributed random single precision complex numbers using the Box-Muller Method
263 *
264 * @param ps: The output array
265 * @param n: The array length
266 * @param mu: mean
267 * @param sigma: variance
268 *
269 * @see ran2(), par_dcopy(), gsl_rng_uniform(), vdRngUniform()
270 *
271 * @return Zero on success integer error code otherwise
272 */
273 const char *funcname = "Gauss_z";
274 if(n<=0){
275 fprintf(stderr, "Error %i in %s: Array cannot have length %i.\nExiting...\n\n",
276 ARRAYLEN, funcname, n);
277#if(nproc>1)
278 MPI_Abort(comm,ARRAYLEN);
279#else
280 exit(ARRAYLEN);
281#endif
282 }
283#pragma unroll
284 for(int i=0;i<n;i++){
285 /* Marsaglia Method for fun
286 do{
287 u=sfmt_genrand_real1(sfmt);
288 v=sfmt_genrand_real1(sfmt);
289 r=u*u+v*v;
290 }while(0<r & r<1);
291 r=sqrt(r);
292 r=sqrt(-2.0*log(r)/r)*sigma;
293 ps[i] = mu+u*r + I*(mu+v*r);
294 */
295#ifdef __RANLUX__
296 float r =sigma*sqrt(-2*log(gsl_rng_uniform(ranlux_instd)));
297 float theta=2.0*M_PI*gsl_rng_uniform(ranlux_instd);
298#else
299 float r =sigma*sqrt(-2*log(ran2(&seed)));
300 float theta=2.0*M_PI*ran2(&seed);
301#endif
302 ps[i]=r*(cos(theta)+mu+sin(theta)*I)+mu;
303 }
304 return 0;
305}
#define M_PI
if not defined elsewhere
Definition random.c:41
double ran2(long *idum)
Generates uniformly distributed random double between zero and one as described in numerical recipes....
Definition random.c:440
long seed
RAN2 seed.
Definition random.c:27

References M_PI, ran2(), and seed.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Gauss_d()

int Gauss_d ( double * ps,
unsigned int n,
const double mu,
const double sigma )

Generates a vector of normally distributed random double precision numbers using the Box-Muller Method.

Parameters
psThe output array
nThe array length
mumean
sigmavariance
Returns
Zero on success integer error code otherwise

Definition at line 306 of file random.c.

306 {
307 /*
308 * @brief Generates a vector of normally distributed random double precision numbers using the Box-Muller Method
309 *
310 * @param ps: The output array
311 * @param n: The array length
312 * @param mu: mean
313 * @param sigma: variance
314 *
315 * @see ran2(), par_dcopy(), gsl_rng_uniform(), vdRngUniform()
316 *
317 * @return Zero on success integer error code otherwise
318 */
319 const char *funcname = "Gauss_z";
320 //The FORTRAN Code had two different Gauss Routines. gaussp having unit
321 //mean and variance and gauss0 where the variance would appear to be 1/sqrt(2)
322 //(Since we multiply by sqrt(-ln(r)) instead of sqrt(-2ln(r)) )
323 if(n<=0){
324 fprintf(stderr, "Error %i in %s: Array cannot have length %i.\nExiting...\n\n",
325 ARRAYLEN, funcname, n);
326#if(nproc>1)
327 MPI_Abort(comm,ARRAYLEN);
328#else
329 exit(ARRAYLEN);
330#endif
331 }
332 int i;
333 double r, u, v;
334 //If n is odd we calculate the last index seperately and the rest in pairs
335 if(n%2==1){
336 n--;
337#ifdef __RANLUX__
338 r=2.0*M_PI*gsl_rng_uniform(ranlux_instd);
339 ps[n]=sqrt(-2*log(gsl_rng_uniform(ranlux_instd)))*cos(r);
340#else
341 r=2.0*M_PI*ran2(&seed);
342 ps[n]=sqrt(-2*log(ran2(&seed)))*cos(r);
343#endif
344 }
345 for(i=0;i<n;i+=2){
346 /* Marsaglia Method for fun
347 do{
348 u=sfmt_genrand_real1(sfmt);
349 v=sfmt_genrand_real1(sfmt);
350 r=u*u+v*v;
351 }while(0<r & r<1);
352 r=sqrt(r);
353 r=sqrt(-2.0*log(r)/r)*sigma;
354 ps[i] = mu+u*r;
355 ps[i+1]=mu+v*r;
356 */
357#ifdef __RANLUX__
358 u=sqrt(-2*log(gsl_rng_uniform(ranlux_instd)))*sigma;
359 r=2.0*M_PI*gsl_rng_uniform(ranlux_instd);
360#else
361 u=sqrt(-2*log(ran2(&seed)))*sigma;
362 r=2.0*M_PI*ran2(&seed);
363#endif
364 ps[i]=u*cos(r)+mu;
365 ps[i+1]=u*sin(r)+mu;
366 }
367 return 0;
368}

References M_PI, ran2(), and seed.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Gauss_f()

int Gauss_f ( float * ps,
unsigned int n,
const float mu,
const float sigma )

Generates a vector of normally distributed random single precision numbers using the Box-Muller Method.

Parameters
psThe output array
nThe array length
mumean
sigmavariance
Returns
Zero on success integer error code otherwise

Definition at line 369 of file random.c.

369 {
370 /*
371 * @brief Generates a vector of normally distributed random single precision numbers using the Box-Muller Method
372 *
373 * @param ps: The output array
374 * @param n: The array length
375 * @param mu: mean
376 * @param sigma: variance
377 *
378 * @see ran2(), par_dcopy(), gsl_rng_uniform(), vdRngUniform()
379 *
380 * @return Zero on success integer error code otherwise
381 */
382 const char *funcname = "Gauss_z";
383 //The FORTRAN Code had two different Gauss Routines. gaussp having unit
384 //mean and variance and gauss0 where the variance would appear to be 1/sqrt(2)
385 //(Since we multiply by sqrt(-ln(r)) instead of sqrt(-2ln(r)) )
386 if(n<=0){
387 fprintf(stderr, "Error %i in %s: Array cannot have length %i.\nExiting...\n\n",
388 ARRAYLEN, funcname, n);
389#if(nproc>1)
390 MPI_Abort(comm,ARRAYLEN);
391#else
392 exit(ARRAYLEN);
393#endif
394 }
395 int i;
396 float r, u, v;
397 //If n is odd we calculate the last index seperately and the rest in pairs
398 if(n%2==1){
399 n--;
400#ifdef __RANLUX__
401 r=2.0*M_PI*gsl_rng_uniform(ranlux_instd);
402 ps[n]=sqrt(-2*log(gsl_rng_uniform(ranlux_instd)))*cos(r);
403#else
404 r=2.0*M_PI*ran2(&seed);
405 ps[n]=sqrt(-2*log(ran2(&seed)))*cos(r);
406#endif
407 }
408#ifdef __RANLUX__
409 r=2.0*M_PI*gsl_rng_uniform(ranlux_instd);
410 ps[n]=sqrt(-2*log(gsl_rng_uniform(ranlux_instd)))*cos(r);
411#else
412 r=2.0*M_PI*ran2(&seed);
413 ps[n]=sqrt(-2*log(ran2(&seed)))*cos(r);
414#endif
415 for(i=0;i<n;i+=2){
416 /* Marsaglia Method for fun
417 do{
418 u=sfmt_genrand_real1(sfmt);
419 v=sfmt_genrand_real1(sfmt);
420 r=u*u+v*v;
421 }while(0<r & r<1);
422 r=sqrt(r);
423 r=sqrt(-2.0*log(r)/r)*sigma;
424 ps[i] = mu+u*r;
425 ps[i+1]=mu+v*r;
426 */
427#ifdef __RANLUX__
428 u=sqrt(-2*log(gsl_rng_uniform(ranlux_instd)))*sigma;
429 r=2.0*M_PI*gsl_rng_uniform(ranlux_instd);
430#else
431 u=sqrt(-2*log(ran2(&seed)))*sigma;
432 r=2.0*M_PI*ran2(&seed);
433#endif
434 ps[i]=u*cos(r)+mu;
435 ps[i+1]=u*sin(r)+mu;
436 }
437 return 0;
438}

References M_PI, ran2(), and seed.

Here is the call graph for this function:

◆ Gauss_z()

int Gauss_z ( Complex * ps,
unsigned int n,
const Complex mu,
const double sigma )

Generates a vector of normally distributed random double precision complex numbers using the Box-Muller Method.

Parameters
psThe output array
nThe array length
mumean
sigmavariance
Returns
Zero on success integer error code otherwise

Definition at line 214 of file random.c.

214 {
215 /*
216 * @brief Generates a vector of normally distributed random double precision complex numbers using the Box-Muller Method
217 *
218 * @param ps: The output array
219 * @param n: The array length
220 * @param mu: mean
221 * @param sigma: variance
222 *
223 * @see ran2(), par_dcopy(), gsl_rng_uniform(), vdRngUniform()
224 *
225 * @return Zero on success integer error code otherwise
226 */
227 const char *funcname = "Gauss_z";
228 if(n<=0){
229 fprintf(stderr, "Error %i in %s: Array cannot have length %i.\nExiting...\n\n",
230 ARRAYLEN, funcname, n);
231#if(nproc>1)
232 MPI_Abort(comm,ARRAYLEN);
233#else
234 exit(ARRAYLEN);
235#endif
236 }
237#pragma unroll
238 for(int i=0;i<n;i++){
239 /* Marsaglia Method for fun
240 do{
241 u=sfmt_genrand_real1(sfmt);
242 v=sfmt_genrand_real1(sfmt);
243 r=u*u+v*v;
244 }while(0<r & r<1);
245 r=sqrt(r);
246 r=sqrt(-2.0*log(r)/r)*sigma;
247 ps[i] = mu+u*r + I*(mu+v*r);
248 */
249#ifdef __RANLUX__
250 double r =sigma*sqrt(-2*log(gsl_rng_uniform(ranlux_instd)));
251 double theta=2.0*M_PI*gsl_rng_uniform(ranlux_instd);
252#else
253 double r =sigma*sqrt(-2*log(ran2(&seed)));
254 double theta=2.0*M_PI*ran2(&seed);
255#endif
256 ps[i]=r*(cos(theta)+sin(theta)*I)+mu;
257 }
258 return 0;
259}

References M_PI, ran2(), and seed.

Here is the call graph for this function:

◆ Par_granf()

double Par_granf ( )

Generates a random double which is then sent to the other ranks.

Returns
the random number generated

Definition at line 190 of file random.c.

190 {
191 /*
192 * @brief Generates a random double which is then sent to the other ranks
193 *
194 * @see ran2(), par_dcopy(), gsl_rng_uniform(), vdRngUniform()
195 *
196 * @return the random number generated
197 */
198 const char *funcname = "Par_granf";
199 double ran_val=0;
200 if(!rank){
201#if (defined USE_RAN2||(!defined __INTEL_MKL__&&!defined __RANLUX__))
202 ran_val = ran2(&seed);
203#elif defined __RANLUX__
204 ran_val = gsl_rng_uniform(ranlux_instd);
205#else
206 vdRngUniform(VSL_RNG_METHOD_UNIFORM_STD_ACCURATE, stream, 1, &ran_val, 0,1);
207#endif
208 }
209#if(nproc>1)
210 Par_dcopy(&ran_val);
211#endif
212 return ran_val;
213}
int Par_dcopy(double *dval)
Broadcasts a double to the other processes.
int rank
The MPI rank.
Definition par_mpi.c:22

References Par_dcopy(), ran2(), rank, and seed.

Here is the call graph for this function:

◆ Par_ranread()

int Par_ranread ( char * filename,
double * ranval )

Reads ps from a file Since this function is very similar to Par_sread, I'm not really going to comment it check there if you are confused about things.

Parameters
filenameThe name of the file we're reading from
ranvalThe destination for the file's contents
Returns
Zero on success, integer error code otherwise

Definition at line 88 of file random.c.

88 {
89 /*
90 * @brief Reads ps from a file
91 * Since this function is very similar to Par_sread, I'm not really going to comment it
92 * check there if you are confused about things.
93 *
94 * @param *filename: The name of the file we're reading from
95 * @param ps: The destination for the file's contents
96 *
97 * @return Zero on success, integer error code otherwise
98 */
99 const char *funcname = "Par_psread";
100 FILE *dest;
101 if(!rank){
102 if(!(dest = fopen(filename, "rb"))){
103 fprintf(stderr, "Error %i in %s: Failed to open %s.\nExiting...\n\n", OPENERROR, funcname, filename);
104#if(nproc>1)
105 MPI_Abort(comm,OPENERROR);
106#else
107 exit(OPENERROR);
108#endif
109
110 }
111 fread(&ranval, sizeof(ranval), 1, dest);
112 fclose(dest);
113 }
114#if(nproc>1)
115 Par_dcopy(ranval);
116#endif
117 return 0;
118}

References Par_dcopy(), and rank.

Here is the call graph for this function:

◆ Par_ranset()

int Par_ranset ( long * seed,
int iread )

Uses the rank to get a new seed. Copying from the FORTRAN description here c create new seeds in range seed to 9*seed c having a range of 0*seed gave an unfortunate pattern c in the underlying value of ds(1) (it was always 10 times bigger c on the last processor). This does not appear to happen with 9.

Parameters
seedThe seed from the rank in question.
ireadDo we read from file or not. Don't remember why it's here as it's not used
Returns
Zero on success, integer error code otherwise

Definition at line 135 of file random.c.

171{
172 const char *funcname = "Par_ranset";
173 //If we're not using the master thread, we need to change the seed
174#ifdef _DEBUG
175 printf("Master seed: %i\t",*seed);
176#endif
177 if(rank)
178 *seed *= 1.0f+8.0f*(float)rank/(float)(size-1);
179#ifdef _DEBUG
180 printf("Rank: %i\tSeed %i\n",rank, *seed);
181#endif
182 //Next we set the seed using ranset
183 //This is one of the really weird FORTRAN 66-esque functions with ENTRY points, so good luck!
184#if (defined __INTEL_MKL__||defined __RANLUX__)
185 return ranset(seed);
186#else
187 return 0;
188#endif
189}
int size
The number of MPI ranks in total.
Definition par_mpi.c:22
int ranset(long *seed)
Dummy seed the ran2 generator.
Definition random.c:74

References rank, ranset(), seed, and size.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ran2()

double ran2 ( long * idum)

Generates uniformly distributed random double between zero and one as described in numerical recipes. It's also thread-safe for different seeds.

Parameters
idumPointer to the seed
Returns
The random double between zero and one

Definition at line 440 of file random.c.

440 {
441 /*
442 * @brief Generates uniformly distributed random double between zero and one as
443 * described in numerical recipes. It's also thread-safe for different seeds.
444 *
445 * @param idum: Pointer to the seed
446 *
447 * @return The random double between zero and one
448 *
449 */
450 long k;
451 int j;
452 static long idum2=123456789;
453 static long iy=0;
454 static long iv[NTAB];
456#pragma omp threadprivate(idum2, iy, iv)
457 //No worries
458 double temp;
459
460 if (*idum <= 0) {
461 if (-(*idum) < 1) *idum=1;
462 else *idum = -(*idum);
463 {
464 idum2=(*idum);
465
466 for(j=NTAB+7;j>=0;j--) {
467 k=(*idum)/IQ1;
468 *idum=IA1*(*idum-k*IQ1)-k*IR1;
469 if (*idum < 0) *idum += IM1;
470 if (j < NTAB)
471 iv[j] = *idum;
472 }
473 iy=iv[0];
474 }
475 }
476 k=(*idum)/IQ1;
477 *idum=IA1*(*idum-k*IQ1)-k*IR1;
478 if (*idum < 0) *idum += IM1;
479 k=idum2/IQ2;
480 idum2=IA2*(idum2-k*IQ2)-k*IR2;
481
482 if (idum2 < 0) idum2 += IM2; j=iy/NDIV;
483 iy=iv[j]-idum2;
484 iv[j] = *idum;
485 if (iy < 1) iy += IMM1;
486 if ((temp=AM*iy) > RNMX)
487 return RNMX;
488
489 else return temp;
490
491}
Here is the caller graph for this function:

◆ ranset()

int ranset ( long * seed)
inline

Dummy seed the ran2 generator.

Parameters
seedpointer to seed
Returns
0

Definition at line 74 of file random.c.

76{
77#ifdef __RANLUX__
78 ranlux_instd=gsl_rng_alloc(gsl_rng_ranlxd2);
79 gsl_rng_set(ranlux_instd,*seed);
80 return 0;
81#elif (defined __INTEL_MKL__&& !defined USE_RAN2)
82 vslNewStream( &stream, VSL_BRNG_MT19937, *seed );
83 return 0;
84#else
85 return 0;
86#endif
87}

References seed.

Here is the caller graph for this function:

Variable Documentation

◆ seed

long seed

RAN2 seed.

Definition at line 27 of file random.c.