LibRan  0.1
Pseudo-random number distribution generator
urand.c
Go to the documentation of this file.
1 static const char AUTHOR[]="@(#)urand 06/02/94 1.3 R.K.Owen,PhD";
2 static const char RCSID[]="$Id: urand.c 106 2002-02-10 08:02:39Z rk $";
3 /*
4  * Copyright 2019 R.K. Owen, Ph.D.
5  * License see lgpl.md (Gnu Lesser General Public License)
6  */
69 #ifdef __cplusplus
70 extern "C" {
71 #endif
72 
73 #include "config.h"
74 #include "libran.h" /* LR_obj, LR_val */
75 #include <string.h> /* strcmp */
76 
77 /* global variables */
78 /* random sequence values */
79 /*
80 int lr_iy = 0, lr_iy0 = 0;
81 long lr_ly = 0, lr_ly0 = 0;
82 */
83 float lr_fscale, lr_fhalfm;
84 double lr_dscale, lr_dhalfm;
85 int lr_ia = 0, lr_ic = 0, lr_imc = 0;
86 long lr_la = 0, lr_lc = 0, lr_lmc = 0;
87 
88 #define SQRT3 1.7320508075688772935
89 #define PI 3.141592653589793238462643
90 
91 void _set_rand(void) {
92  extern float lr_fscale, lr_fhalfm;
93  extern double lr_dscale, lr_dhalfm;
94  extern int lr_ia, lr_ic, lr_imc;
95  extern long lr_la, lr_lc, lr_lmc;
96 
97  lr_fhalfm = (float) LR_IRAND_IMAX2;
98  lr_dhalfm = (double) LR_IRAND_LMAX2;
99 
100 /* COMPUTE MULTIPLIER AND INCREMENT FOR LINEAR CONGRUENTIAL METHOD */
101  lr_ia = ((int) (lr_fhalfm * PI / 32.) << 3) + 5;
102  lr_ic = ((int) (lr_fhalfm * (.5 - SQRT3 / 6.)) << 1) + 1;
103  lr_imc = (LR_IRAND_IMAX2 - lr_ic) + LR_IRAND_IMAX2;
104  lr_la = ((long) (lr_dhalfm * PI / 32.) << 3) + 5;
105  lr_lc = ((long) (lr_dhalfm * (.5 - SQRT3 / 6.)) << 1) + 1;
106  lr_lmc = (LR_IRAND_LMAX2 - lr_lc) + LR_IRAND_LMAX2;
107 
108 /* SCALE FACTOR FOR CONVERTING TO FLOATING POINT */
109  lr_fscale = .5 / lr_fhalfm;
110  lr_dscale = .5 / lr_dhalfm;
111 }
112 
121 int LR_irand(LR_obj *o) {
122  /* extern int lr_iy, lr_iy0; */
123  extern float lr_fscale, lr_fhalfm;
124  extern int lr_ia, lr_ic, lr_imc;
125 
126 /* IF FIRST ENTRY, COMPUTE URAND CONSTANTS */
127  if (lr_ia == 0) _set_rand();
128 
129 /* COMPUTE NEXT RANDOM NUMBER */
130  o->iy.i *= lr_ia;
131 /* THE FOLLOWING STATEMENT IS FOR COMPUTERS WHICH DO NOT ALLOW */
132 /* INTEGER OVERFLOW ON ADDITION */
133 #ifndef LR_NOINTOVF
134  if (o->iy.i > lr_imc) {
135 #ifdef LR_ISUB
136  o->iy.i -= LR_IRAND_IMAX2;
137  o->iy.i -= LR_IRAND_IMAX2;
138 #elif defined LR_NOISUB
139  o->iy.i ^= LR_IRAND_INOT;
140 #else
141 # error "Need either LR_ISUB or LR_NOISUB to be defined"
142 #endif
143  }
144 #endif
145  o->iy.i += lr_ic;
146 
147 /* THE FOLLOWING STATEMENT IS FOR COMPUTERS WHERE THE */
148 /* WORD LENGTH FOR ADDITION IS GREATER THAN FOR MULTIPLICATION */
149 #ifndef NOADDMULT
150  if (
151 # ifdef LR_IDIV
152  (o->iy.i/2)
153 # elif defined LR_NOIDIV
154  (o->iy.i >> 1)
155 # else
156 # error "Need either LR_IDIV or LR_NOIDIV to be defined"
157 # endif
158  > LR_IRAND_IMAX2) {
159 # ifdef LR_ISUB
160  o->iy.i -= LR_IRAND_IMAX2;
161  o->iy.i -= LR_IRAND_IMAX2;
162 # elif defined LR_NOISUB
163  o->iy.i ^= LR_IRAND_INOT;
164 # else
165 # error "Need either LR_ISUB or LR_NOISUB to be defined"
166 # endif
167  }
168 #endif
169 
170 /* THE FOLLOWING STATEMENT IS FOR COMPUTERS WHERE INTEGER */
171 /* OVERFLOW AFFECTS THE SIGN BIT */
172  if (o->iy.i < 0) {
173 #ifdef LR_IADD
174  o->iy.i += LR_IRAND_IMAX2;
175  o->iy.i += LR_IRAND_IMAX2;
176 #elif defined LR_NOIADD
177  o->iy.i ^= LR_IRAND_INOT;
178 #else
179 # error "Need either LR_IADD or LR_NOIADD to be defined"
180 #endif
181  }
182  return o->iy.i;
183 }
184 
193 float LR_frand(LR_obj *o) {
194  /* extern int lr_iy; */
195  extern float lr_fscale;
196 
197 /* COMPUTE NEXT RANDOM NUMBER */
198  LR_irand(o);
199 
200  return (float) (o->iy.i) * lr_fscale;
201 }
202 
212 void LR_isetseed(LR_obj *o, int X) {
213  /* extern int lr_iy, lr_iy0; */
214  extern int lr_ia;
215 
216 /* IF FIRST ENTRY, COMPUTE URAND CONSTANTS */
217  if (lr_ia == 0) _set_rand();
218 
219  o->iy.i = o->iy0.i = X;
220 }
221 
231  /* extern int lr_iy0; */
232  return o->iy0.i;
233 }
234 
244  /* extern int lr_iy; */
245  return o->iy.i;
246 }
247 
256 float LR_fgetrand(LR_obj *o) {
257  /* extern int lr_iy; */
258  extern float lr_fscale;
259  return (float) (o->iy.i) * lr_fscale;
260 }
261 
270 long LR_lrand(LR_obj *o) {
271  /* extern long lr_ly, lr_ly0; */
272  extern double lr_dscale, lr_dhalfm;
273  extern long lr_la, lr_lc, lr_lmc;
274 
275 /* IF FIRST ENTRY, COMPUTE URAND CONSTANTS */
276  if (lr_la == 0) _set_rand();
277 
278 /* COMPUTE NEXT RANDOM NUMBER */
279  o->iy.l *= lr_la;
280 /* THE FOLLOWING STATEMENT IS FOR COMPUTERS WHICH DO NOT ALLOW */
281 /* INTEGER OVERFLOW ON ADDITION */
282 #ifndef LR_NOINTOVF
283  if (o->iy.l > lr_lmc) {
284 #ifdef LR_ISUB
285  o->iy.l -= LR_IRAND_LMAX2;
286  o->iy.l -= LR_IRAND_LMAX2;
287 #elif defined LR_NOISUB
288  o->iy.l ^= LR_IRAND_LNOT;
289 #else
290 # error "Need either LR_ISUB or LR_NOISUB to be defined"
291 #endif
292  }
293 #endif
294  o->iy.l += lr_lc;
295 
296 /* THE FOLLOWING STATEMENT IS FOR COMPUTERS WHERE THE */
297 /* WORD LENGTH FOR ADDITION IS GREATER THAN FOR MULTIPLICATION */
298 #ifndef NOADDMULT
299  if (
300 #ifdef LR_IDIV
301  (o->iy.l/2)
302 #elif defined LR_NOIDIV
303  (o->iy.l >> 1)
304 #else
305 # error "Need either LR_IDIV or LR_NOIDIV to be defined"
306 #endif
307  > LR_IRAND_LMAX2) {
308 #ifdef LR_ISUB
309  o->iy.l -= LR_IRAND_LMAX2;
310  o->iy.l -= LR_IRAND_LMAX2;
311 #elif defined LR_NOISUB
312  o->iy.l ^= LR_IRAND_LNOT;
313 #else
314 # error "Need either LR_ISUB or LR_NOISUB to be defined"
315 #endif
316  }
317 #endif
318 
319 /* THE FOLLOWING STATEMENT IS FOR COMPUTERS WHERE INTEGER */
320 /* OVERFLOW AFFECTS THE SIGN BIT */
321  if (o->iy.l < 0) {
322 #ifdef LR_LADD
323  o->iy.l += LR_IRAND_LMAX2;
324  o->iy.l += LR_IRAND_LMAX2;
325 #elif defined LR_NOLADD
326  o->iy.l ^= LR_IRAND_LNOT;
327 #else
328 # error "Need either LR_LADD or LR_NOIADD to be defined"
329 #endif
330  }
331  return o->iy.l;
332 }
333 
342 double LR_drand(LR_obj *o) {
343  /* extern long lr_ly; */
344  extern double lr_dscale;
345 
346 /* COMPUTE NEXT RANDOM NUMBER */
347  LR_lrand(o);
348 
349  return (double) (o->iy.l) * lr_dscale;
350 }
351 
361 void LR_lsetseed(LR_obj *o, long X) {
362  /* extern long lr_ly, lr_ly0; */
363  extern long lr_la;
364 
365 /* IF FIRST ENTRY, COMPUTE URAND CONSTANTS */
366  if (lr_la == 0) _set_rand();
367 
368  o->iy.l = o->iy0.l = X;
369 }
370 
379 long LR_lgetseed(LR_obj *o) {
380  /* extern long lr_ly0; */
381  return o->iy0.l;
382 }
383 
392 long LR_lgetrand(LR_obj *o) {
393  /* extern long lr_ly; */
394  return o->iy.l;
395 }
396 
405 double LR_dgetrand(LR_obj *o) {
406  /* extern long lr_ly; */
407  extern double lr_dscale;
408  return (double) (o->iy.l) * lr_dscale;
409 }
410 
422 int LR_igetval(char *val) {
423  if (!strcmp(val, "LR_IRAND_IMAX2"))
424  return LR_IRAND_IMAX2;
425  else if (!strcmp(val, "LR_IRAND_IMAX"))
426  return LR_IRAND_IMAX;
427  else if (!strcmp(val, "LR_IRAND_INOT"))
428  return LR_IRAND_INOT;
429  return 0;
430 }
431 
443 long LR_lgetval(char *val) {
444  if (!strcmp(val, "LR_IRAND_LMAX2"))
445  return LR_IRAND_LMAX2;
446  else if (!strcmp(val, "LR_IRAND_LMAX"))
447  return LR_IRAND_LMAX;
448  else if (!strcmp(val, "LR_IRAND_LNOT"))
449  return LR_IRAND_LNOT;
450  return 0;
451 }
452 
464 float LR_fgetval(char *val) {
465  if (!strcmp(val, "LR_FEPS"))
466  return LR_FEPS;
467  else if (!strcmp(val, "LR_FSQEPS"))
468  return LR_FSQEPS;
469  return 0;
470 }
471 
483 double LR_dgetval(char *val) {
484  if (!strcmp(val, "LR_DEPS"))
485  return LR_DEPS;
486  else if (!strcmp(val, "LR_DSQEPS"))
487  return LR_DSQEPS;
488  return 0;
489 }
490 
491 #ifdef __cplusplus
492 }
493 #endif
double LR_dgetval(char *val)
LR_dgetval(char *val) - return the configure value.
Definition: urand.c:483
LR_val iy
Definition: libran.h:148
float LR_fgetrand(LR_obj *o)
LR_fgetrand(LR_obj *) - get the current pseudo-random number.
Definition: urand.c:256
long LR_lgetval(char *val)
LR_lgetval(char *val) - return the configure value.
Definition: urand.c:443
long LR_lgetseed(LR_obj *o)
LR_lgetseed(LR_obj *) - get the current seed.
Definition: urand.c:379
#define LR_IRAND_LMAX
LibRan IRAND max long value.
Definition: config.h:137
double LR_drand(LR_obj *o)
LR_drand(LR_obj *) - returns double in range [0.0,1.0)
Definition: urand.c:342
long LR_lgetrand(LR_obj *o)
LR_lgetrand(LR_obj *) - get the current pseudo-random number.
Definition: urand.c:392
float LR_frand(LR_obj *o)
LR_frand(LR_obj *) - returns float in range [0.0,1.0)
Definition: urand.c:193
#define LR_IRAND_LNOT
LibRan IRAND long NOT max (in hex)
Definition: config.h:143
#define LR_IRAND_IMAX2
LibRan IRAND half max int value.
Definition: config.h:149
#define LR_IRAND_INOT
LibRan IRAND int NOT max (in hex)
Definition: config.h:161
int i
Definition: libran.h:85
double LR_dgetrand(LR_obj *o)
LR_dgetrand(LR_obj *) - get the current pseudo-random number.
Definition: urand.c:405
int LR_igetseed(LR_obj *o)
LR_igetseed(LR_obj *) - get the current seed.
Definition: urand.c:230
#define LR_FEPS
LibRan float machine epsilon.
Definition: config.h:167
int LR_igetrand(LR_obj *o)
LR_igetrand(LR_obj *) - get the current pseudo-random number.
Definition: urand.c:243
#define LR_IRAND_IMAX
LibRan IRAND max int value.
Definition: config.h:155
#define LR_FSQEPS
LibRan float sqrt machine epsilon.
Definition: config.h:173
long l
Definition: libran.h:84
void LR_lsetseed(LR_obj *o, long X)
LR_lsetseed(LR_obj *, long X) - set the seed to X.
Definition: urand.c:361
LR_val iy0
Definition: libran.h:149
int LR_igetval(char *val)
LR_igetval(char *val) - return the configure value.
Definition: urand.c:422
int LR_irand(LR_obj *o)
LR_irand(LR_obj *) - returns int in range [0,LR_IRAND_IMAX].
Definition: urand.c:121
Generated by the configuration step.
#define LR_DSQEPS
LibRan double sqrt machine epsilon.
Definition: config.h:185
#define LR_DEPS
LibRan double machine epsilon.
Definition: config.h:179
float LR_fgetval(char *val)
LR_fgetval(char *val) - return the configure value.
Definition: urand.c:464
The LibRan common header file.
long LR_lrand(LR_obj *o)
LR_lrand(LR_obj *) - returns long in range [0,LR_IRAND_LMAX].
Definition: urand.c:270
void LR_isetseed(LR_obj *o, int X)
LR_isetseed(LR_obj *, int X) - set the seed to X.
Definition: urand.c:212
the fundamental LibRan random variate distribution object
Definition: libran.h:134
#define LR_IRAND_LMAX2
LibRan IRAND half max long value.
Definition: config.h:131