18#include "mdb_thread.h"
29extern double dlaran_(integer *seed);
30extern double dlaran_oag(integer *seed,
long increment);
32#define MAX_RAND_INT (1.0 * RAND_MAX)
34static MDB_THREAD_LOCK rand_lock = MDB_THREAD_LOCK_INITIALIZER;
36void mdbmth_lock_rand(
void) {
37 mdb_thread_lock(&rand_lock);
40void mdbmth_unlock_rand(
void) {
41 mdb_thread_unlock(&rand_lock);
44int mdbmth_rand_unlocked(
void) {
48void mdbmth_srand_unlocked(
unsigned int seed) {
52double mdbmth_rand_fraction_unlocked(
void) {
53 return (
double)mdbmth_rand_unlocked() / ((double)RAND_MAX + 1.0);
56int mdbmth_locked_rand(
void) {
59 value = mdbmth_rand_unlocked();
64void mdbmth_locked_srand(
unsigned int seed) {
66 mdbmth_srand_unlocked(seed);
70double mdbmth_locked_rand_fraction(
void) {
73 value = mdbmth_rand_fraction_unlocked();
87 return (
float)(mdbmth_locked_rand() / MAX_RAND_INT);
99 return (lo + ((hi - lo) * mdbmth_locked_rand()) / MAX_RAND_INT);
107 mdbmth_locked_srand((
unsigned int)time(NULL));
120void r_theta_rand(
double *r,
double *theta,
double r_min,
double r_max) {
121 double area, sqr_r_min;
123 *theta =
rdrand(0.0, PIx2);
124 sqr_r_min = sqr(r_min);
125 area =
rdrand(0.0, sqr(r_max) - sqr_r_min);
126 *r = sqrt(area + sqr_r_min);
129static short inhibitPermute = 0;
130static MDB_THREAD_LOCK inhibitPermuteLock = MDB_THREAD_LOCK_INITIALIZER;
142 mdb_thread_lock(&inhibitPermuteLock);
144 inhibitPermute = state;
145 currentState = inhibitPermute;
146 mdb_thread_unlock(&inhibitPermuteLock);
160 long offset = input0 % 1000;
165 unsigned long bitMask[32] = {
200 mdb_thread_lock(&inhibitPermuteLock);
201 inhibit = inhibitPermute;
202 mdb_thread_unlock(&inhibitPermuteLock);
208 for (i = 0; i < 31; i++) {
209 newValue += (input & bitMask[i]) ? bitMask[(i + offset) % 31] : 0;
211 if (newValue == input0) {
214 for (i = 0; i < 31; i++) {
215 newValue += (input & bitMask[i]) ? bitMask[(i + offset) % 31] : 0;
231 static MDB_THREAD_LOCAL
short initialized = 0;
232 static MDB_THREAD_LOCAL integer seed[4] = {0, 0, 0, 0};
234 if (!initialized || iseed < 0) {
243 iseed = (iseed / 2) * 2 + 1;
244 seed[3] = (iseed & 4095);
245 seed[2] = (iseed >>= 12) & 4095;
246 seed[1] = (iseed >>= 12) & 4095;
247 seed[0] = (iseed >>= 12) & 4095;
251 bomb(
"random_1 not properly initialized", NULL);
263 static MDB_THREAD_LOCAL
short initialized = 0;
264 static MDB_THREAD_LOCAL integer seed[4] = {0, 0, 0, 0};
266 if (!initialized || iseed < 0) {
270 seed[3] = ((iseed & 4095) / 2) * 2 + 1;
271 seed[2] = (iseed >>= 12) & 4095;
272 seed[1] = (iseed >>= 12) & 4095;
273 seed[0] = (iseed >>= 12) & 4095;
277 bomb(
"random_2 not properly initialized", NULL);
289 static MDB_THREAD_LOCAL
short initialized = 0;
290 static MDB_THREAD_LOCAL integer seed[4] = {0, 0, 0, 0};
292 if (!initialized || iseed < 0) {
296 seed[3] = ((iseed & 4095) / 2) * 2 + 1;
297 seed[2] = (iseed >>= 12) & 4095;
298 seed[1] = (iseed >>= 12) & 4095;
299 seed[0] = (iseed >>= 12) & 4095;
303 bomb(
"random_3 not properly initialized", NULL);
315 static MDB_THREAD_LOCAL
short initialized = 0;
316 static MDB_THREAD_LOCAL integer seed[4] = {0, 0, 0, 0};
318 if (!initialized || iseed < 0) {
322 seed[3] = ((iseed & 4095) / 2) * 2 + 1;
323 seed[2] = (iseed >>= 12) & 4095;
324 seed[1] = (iseed >>= 12) & 4095;
325 seed[0] = (iseed >>= 12) & 4095;
329 bomb(
"random_4 not properly initialized", NULL);
341 static MDB_THREAD_LOCAL
short initialized = 0;
342 static MDB_THREAD_LOCAL integer seed[4] = {0, 0, 0, 0};
344 if (!initialized || iseed < 0) {
348 seed[3] = ((iseed & 4095) / 2) * 2 + 1;
349 seed[2] = (iseed >>= 12) & 4095;
350 seed[1] = (iseed >>= 12) & 4095;
351 seed[0] = (iseed >>= 12) & 4095;
355 bomb(
"random_5 not properly initialized", NULL);
367 static MDB_THREAD_LOCAL
short initialized = 0;
368 static MDB_THREAD_LOCAL integer seed[4] = {0, 0, 0, 0};
370 if (!initialized || iseed < 0) {
374 seed[3] = ((iseed & 4095) / 2) * 2 + 1;
375 seed[2] = (iseed >>= 12) & 4095;
376 seed[1] = (iseed >>= 12) & 4095;
377 seed[0] = (iseed >>= 12) & 4095;
381 bomb(
"random_6 not properly initialized", NULL);
396double gauss_rn(
long iseed,
double (*urandom)(
long iseed1)) {
397 static MDB_THREAD_LOCAL
long valueSaved = 0;
398 static MDB_THREAD_LOCAL
double savedValue;
399 double urn1, urn2, sine, cosine, factor;
404 urn1 = (*urandom)(0);
405 urn2 = (*urandom)(0);
406 factor = sqrt(-2 * log(urn1));
407 cosine = cos(PIx2 * urn2);
408 sine = sin(PIx2 * urn2);
409 savedValue = factor * cosine;
415 return factor * sine;
434 double mean,
double sigma,
435 double limit_in_sigmas,
437 double (*urandom)(
long iseed)) {
440 if (limit_in_sigmas <= 0)
441 return (mean + sigma *
gauss_rn(0, urandom));
443 limit = limit_in_sigmas;
446 }
while (FABS(value) > limit);
447 return (sigma * value + mean);
462 double u1, u2, z = 0;
469 for (i = j = 0; i < points; i++) {
470 u1 = 2 * (data[i] - 0.5);
475#if defined(vxWorks) || defined(__rtems__)
476 fprintf(stderr,
"erf function is not implemented on this architecture\n");
479 z =
zeroNewton(erf, u2, 0.5, 1e-6, 500, 1e-12);
482 if (limit <= 0 || data[j] < limit) {
496int randomizeOrderCmp(
const void *p1,
const void *p2) {
501 if ((diff = rh1->randomValue - rh2->randomValue) > 0)
520long randomizeOrder(
char *ptr,
long size,
long length,
long iseed,
double (*urandom)(
long iseed1)) {
527 if (!(rh = malloc(
sizeof(*rh) * length)))
533 for (i = 0; i < length; i++)
537 for (i = 0; i < length; i++) {
538 if (!(rh[i].buffer = malloc(size))) {
544 memcpy(rh[i].buffer, ptr + i * size, size);
545 rh[i].randomValue = (*urandom)(0);
547 qsort((
void *)rh, length,
sizeof(*rh), randomizeOrderCmp);
549 for (i = 0; i < length; i++) {
550 memcpy(ptr + i * size, rh[i].buffer, size);
567 static MDB_THREAD_LOCAL
short initialized = 0;
568 static MDB_THREAD_LOCAL integer seed[4] = {0, 0, 0, 0};
570 if (!initialized || iseed < 0) {
573 seed[3] = ((iseed & 4095) / 2) * 2 + 1;
574 seed[2] = (iseed >>= 12) & 4095;
575 seed[1] = (iseed >>= 12) & 4095;
576 seed[0] = (iseed >>= 12) & 4095;
580 fprintf(stderr,
"random_oag not properly initialized\n");
597double gauss_rn_oag(
long iseed,
long increment,
double (*urandom)(
long iseed1,
long increment)) {
598 double urn1, urn2, sine, factor;
602 increment = ((increment - 1) * 2) + 1;
603 urn1 = (*urandom)(iseed, increment);
604 urn2 = (*urandom)(0, 1);
605 factor = sqrt(-2 * log(urn1));
606 sine = sin(PIx2 * urn2);
607 return factor * sine;
623 double mean,
double sigma,
624 double limit_in_sigmas,
627 double (*urandom)(
long iseed,
long increment)) {
631 if (limit_in_sigmas <= 0)
632 return (mean + sigma *
gauss_rn_oag(0, increment, urandom));
634 limit = limit_in_sigmas;
639 if (FABS(value) <= limit)
641 }
while ((FABS(value) > limit) || (i < increment));
643 return (sigma * value + mean);
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
double random_5(long iseed)
Similar to random_4(), provides another independent random sequence.
long permuteSeedBitOrder(long input0)
Permute the bit order of a seed value to improve randomness.
double random_1(long iseed)
Generate a uniform random double in [0,1] using a custom seed initialization.
double gauss_rn(long iseed, double(*urandom)(long iseed1))
Generate a Gaussian-distributed random number with mean 0 and sigma 1.
double random_6(long iseed)
Similar to random_5(), provides another independent random sequence.
void r_theta_rand(double *r, double *theta, double r_min, double r_max)
Generate a random point (r, θ) within an annulus defined by [r_min, r_max].
double gauss_rn_lim_oag(double mean, double sigma, double limit_in_sigmas, long increment, double(*urandom)(long iseed, long increment))
Generate a Gaussian-distributed random number with mean, sigma, and optional cutoff using oag RNG.
float drand(long dummy)
Generate a uniform random float in [0,1].
long convertSequenceToGaussianDistribution(double *data, long points, double limit)
Convert a sequence of uniformly distributed [0,1] values into a Gaussian-distributed sequence.
short inhibitRandomSeedPermutation(short state)
Enable or disable permutation of seed bits for random number generators.
double gauss_rn_oag(long iseed, long increment, double(*urandom)(long iseed1, long increment))
Generate a Gaussian-distributed random number using the random_oag approach.
double random_oag(long iseed, long increment)
Generate a uniform random double in [0,1] using a seed and increment, optimized for certain applicati...
double random_3(long iseed)
Similar to random_2(), provides another independent random sequence.
double random_4(long iseed)
Similar to random_3(), provides another independent random sequence.
long randomizeOrder(char *ptr, long size, long length, long iseed, double(*urandom)(long iseed1))
Randomize the order of an array of elements.
double rdrand(double lo, double hi)
Generate a uniform random double in [lo, hi].
double dlaran_oag(integer *seed, long increment)
Advance the DLARAN seed and return a random number.
double random_2(long iseed)
Similar to random_1(), provides a separate random sequence with its own seed handling.
double gauss_rn_lim(double mean, double sigma, double limit_in_sigmas, double(*urandom)(long iseed))
Generate a Gaussian-distributed random number with specified mean, sigma, and optional cutoff.
double dlaran_(integer *seed)
Generates a random number using the DLARAN algorithm.
double zeroNewton(double(*fn)(double x), double value, double x_i, double dx, long n_passes, double _zero)
Finds the zero of a function using Newton's method with numerical derivative computation.