Loading...
Searching...
No Matches
RandomNumbers.cpp
Go to the documentation of this file.
1/*
2** This file is part of eOn.
3**
4** SPDX-License-Identifier: BSD-3-Clause
5**
6** Copyright (c) 2010--present, eOn Development Team
7** All rights reserved.
8**
9** Repo:
10** https://github.com/TheochemUI/eOn
11*/
12#include "eon/RandomNumbers.h"
13
14#include <cmath>
15
16namespace {
17struct Ran2State {
18 long seed{-1};
19 long seed2{123456789};
20 long iy{0};
21 long iv[eonc::NTAB]{};
22};
23
24// Parallel replica exchange (and any other std::thread MD) used to race on
25// the process-wide ran2 tables. Each C++ thread owns a stream.
26thread_local Ran2State tls;
27} // namespace
28
29double eonc::rng::random(long newSeed) {
30 auto &st = tls;
31 if (newSeed) {
32 st.seed = -newSeed;
33 }
34 int j;
35 long k;
36 double temp;
37 if (st.seed <= 0) {
38 if (-(st.seed) < 1)
39 st.seed = 3;
40 else
41 st.seed = -(st.seed);
42 st.seed2 = (st.seed);
43 for (j = NTAB + 7; j >= 0; j--) {
44 k = (st.seed) / IQ1;
45 st.seed = IA1 * (st.seed - k * IQ1) - k * IR1;
46 if (st.seed < 0)
47 st.seed += IM1;
48 if (j < NTAB)
49 st.iv[j] = st.seed;
50 }
51 st.iy = st.iv[0];
52 }
53 k = (st.seed) / IQ1;
54 st.seed = IA1 * (st.seed - k * IQ1) - k * IR1;
55 if (st.seed < 0)
56 st.seed += IM1;
57 k = st.seed2 / IQ2;
58 st.seed2 = IA2 * (st.seed2 - k * IQ2) - k * IR2;
59 if (st.seed2 < 0)
60 st.seed2 += IM2;
61 j = int(st.iy / NDIV);
62 st.iy = st.iv[j] - st.seed2;
63 st.iv[j] = st.seed;
64 if (st.iy < 1)
65 st.iy += IMM1;
66 if ((temp = double(AM * st.iy)) > RNMX)
67 return RNMX;
68 else
69 return temp;
70}
71
72double eonc::rng::randomDouble() { return (random()); }
73
74double eonc::rng::randomDouble(int max) {
75 double dmax = double(max);
76 return (dmax * randomDouble());
77}
78
79double eonc::rng::randomDouble(long max) {
80 double dmax = double(max);
81 return (dmax * randomDouble());
82}
83
84double eonc::rng::randomDouble(double dmax) { return (dmax * randomDouble()); }
85
86long eonc::rng::randomInt(int lower, int upper) {
87 return lround((upper - lower) * randomDouble() + lower);
88}
89
90double eonc::rng::gaussRandom(double avg, double std) {
91 double r = 2, v1, v2, l, result;
92 while (r >= 1.0 || r < 1e-300) {
93 v1 = 2.0 * randomDouble() - 1.0;
94 v2 = 2.0 * randomDouble() - 1.0;
95 r = v1 * v1 + v2 * v2;
96 }
97 l = v1 * sqrt(-2.0 * ::log(r) / r);
98 result = avg + std * l;
99 return (result);
100}
double random(long newSeed=0)
long randomInt(int lower, int upper)
double randomDouble()
double gaussRandom(double avg, double std)
constexpr double AM
constexpr int NDIV
constexpr long IA2
constexpr long IR2
constexpr long IQ1
constexpr int NTAB
constexpr long IA1
constexpr long IQ2
constexpr long IM1
constexpr long IMM1
constexpr long IM2
constexpr long IR1
constexpr double RNMX