NEURON
nrnran123.cpp
Go to the documentation of this file.
1 #include <cstdint>
2 #include "nrnran123.h"
3 #include <cstdlib>
4 #include <cmath>
5 #include <Random123/philox.h>
6 
7 using RNG = r123::Philox4x32;
8 
9 static RNG::key_type k = {{0}};
10 
12  RNG::ctr_type c;
13  RNG::ctr_type r;
14  char which_;
15 };
16 
17 void nrnran123_set_globalindex(std::uint32_t gix) {
18  k[0] = gix;
19 }
20 
21 /* if one sets the global, one should reset all the stream sequences. */
22 std::uint32_t nrnran123_get_globalindex() {
23  return k[0];
24 }
25 
26 /* deprecated */
27 nrnran123_State* nrnran123_newstream3(std::uint32_t id1, std::uint32_t id2, std::uint32_t id3) {
28  return nrnran123_newstream(id1, id2, id3);
29 }
30 
32  extern int nrnmpi_myid;
33  static std::uint32_t id3{};
34  return nrnran123_newstream(1, nrnmpi_myid, ++id3);
35 }
36 
37 nrnran123_State* nrnran123_newstream(std::uint32_t id1, std::uint32_t id2, std::uint32_t id3) {
38  auto* s = new nrnran123_State;
39  s->c[1] = id3;
40  s->c[2] = id1;
41  s->c[3] = id2;
42  nrnran123_setseq(s, 0, 0);
43  return s;
44 }
45 
47  delete s;
48 }
49 
50 void nrnran123_getseq(nrnran123_State* s, std::uint32_t* seq, char* which) {
51  *seq = s->c[0];
52  *which = s->which_;
53 }
54 
55 void nrnran123_setseq(nrnran123_State* s, std::uint32_t seq, char which) {
56  if (which > 3 || which < 0) {
57  s->which_ = 0;
58  } else {
59  s->which_ = which;
60  }
61  s->c[0] = seq;
62  s->r = philox4x32(s->c, k);
63 }
64 
65 /** @brief seq4which is 34 bit uint encoded as double(seq)*4 + which
66  * More convenient to get and set from interpreter
67 */
68 void nrnran123_setseq(nrnran123_State* s, double seq4which) {
69  if (seq4which < 0.0) {
70  seq4which = 0.0;
71  }
72  if (seq4which > double(0XffffffffffLL)) {
73  seq4which = 0.0;
74  }
75  // at least 64 bits even on 32 bit machine (could be more)
76  unsigned long long x = ((unsigned long long) seq4which) & 0X3ffffffffLL;
77  char which = x & 0X3;
78  uint32_t seq = x >> 2;
79  nrnran123_setseq(s, seq, which);
80 }
81 
82 void nrnran123_getids(nrnran123_State* s, std::uint32_t* id1, std::uint32_t* id2) {
83  *id1 = s->c[2];
84  *id2 = s->c[3];
85 }
86 
88  std::uint32_t* id1,
89  std::uint32_t* id2,
90  std::uint32_t* id3) {
91  *id3 = s->c[1];
92  *id1 = s->c[2];
93  *id2 = s->c[3];
94 }
95 
96 /* Deprecated */
98  std::uint32_t* id1,
99  std::uint32_t* id2,
100  std::uint32_t* id3) {
101  nrnran123_getids(s, id1, id2, id3);
102 }
103 
104 void nrnran123_setids(nrnran123_State* s, std::uint32_t id1, std::uint32_t id2, std::uint32_t id3) {
105  s->c[1] = id3;
106  s->c[2] = id1;
107  s->c[3] = id2;
108 }
109 
111  char which = s->which_;
112  std::uint32_t rval = s->r[which++];
113  if (which > 3) {
114  which = 0;
115  s->c.incr();
116  s->r = philox4x32(s->c, k);
117  }
118  s->which_ = which;
119  return rval;
120 }
121 
123  static const double SHIFT32 = 1.0 / 4294967297.0; /* 1/(2^32 + 1) */
124  auto u = nrnran123_ipick(s);
125  return ((double) u + 1.0) * SHIFT32;
126 }
127 
129  return nrnran123_dblpick(s);
130 }
131 
132 double nrnran123_uniform(nrnran123_State* s, double a, double b) {
133  return a + nrnran123_dblpick(s) * (b - a);
134 }
135 
136 double nrnran123_negexp(nrnran123_State* s, double mean) {
137  /* min 2.3283064e-10 to max 22.18071 (if mean is 1) */
138  return -std::log(nrnran123_dblpick(s)) * mean;
139 }
140 
142  /* min 2.3283064e-10 to max 22.18071 */
143  return -std::log(nrnran123_dblpick(s));
144 }
145 
146 /* At cost of a cached value we could compute two at a time. */
147 /* But that would make it difficult to transfer to coreneuron for t > 0 */
149  double w, x, y;
150  double u1, u2;
151  do {
152  u1 = nrnran123_dblpick(s);
153  u2 = nrnran123_dblpick(s);
154  u1 = 2. * u1 - 1.;
155  u2 = 2. * u2 - 1.;
156  w = (u1 * u1) + (u2 * u2);
157  } while (w > 1);
158 
159  y = std::sqrt((-2. * std::log(w)) / w);
160  x = u1 * y;
161  return x;
162 }
163 
164 double nrnran123_normal(nrnran123_State* s, double mu, double sigma) {
165  return mu + nrnran123_normal(s) * sigma;
166 }
167 
168 nrnran123_array4x32 nrnran123_iran(std::uint32_t seq, std::uint32_t id1, std::uint32_t id2) {
169  return nrnran123_iran3(seq, id1, id2, 0);
170 }
172  std::uint32_t id1,
173  std::uint32_t id2,
174  std::uint32_t id3) {
176  RNG::ctr_type c;
177  c[0] = seq;
178  c[1] = id3;
179  c[2] = id1;
180  c[3] = id2;
181  RNG::ctr_type r = philox4x32(c, k);
182  a.v[0] = r[0];
183  a.v[1] = r[1];
184  a.v[2] = r[2];
185  a.v[3] = r[3];
186  return a;
187 }
Definition: RNG.h:5
double nrnran123_normal(nrnran123_State *s)
Definition: nrnran123.cpp:148
double nrnran123_uniform(nrnran123_State *s)
Definition: nrnran123.cpp:128
void nrnran123_getids(nrnran123_State *s, std::uint32_t *id1, std::uint32_t *id2)
Get stream IDs from Random123 State object.
Definition: nrnran123.cpp:82
void nrnran123_set_globalindex(std::uint32_t gix)
Definition: nrnran123.cpp:17
double nrnran123_negexp(nrnran123_State *s, double mean)
Definition: nrnran123.cpp:136
std::uint32_t nrnran123_get_globalindex()
Definition: nrnran123.cpp:22
nrnran123_array4x32 nrnran123_iran(std::uint32_t seq, std::uint32_t id1, std::uint32_t id2)
Definition: nrnran123.cpp:168
std::uint32_t nrnran123_ipick(nrnran123_State *s)
Definition: nrnran123.cpp:110
nrnran123_array4x32 nrnran123_iran3(std::uint32_t seq, std::uint32_t id1, std::uint32_t id2, std::uint32_t id3)
Definition: nrnran123.cpp:171
nrnran123_State * nrnran123_newstream()
Construct a new Random123 stream based on the philox4x32 generator.
Definition: nrnran123.cpp:31
void nrnran123_deletestream(nrnran123_State *s)
Destroys the given Random123 stream.
Definition: nrnran123.cpp:46
void nrnran123_getids3(nrnran123_State *s, std::uint32_t *id1, std::uint32_t *id2, std::uint32_t *id3)
Definition: nrnran123.cpp:97
double nrnran123_dblpick(nrnran123_State *s)
Definition: nrnran123.cpp:122
static RNG::key_type k
Definition: nrnran123.cpp:9
void nrnran123_setseq(nrnran123_State *s, std::uint32_t seq, char which)
Set a Random123 sequence for a sequnece ID and which selector.
Definition: nrnran123.cpp:55
nrnran123_State * nrnran123_newstream3(std::uint32_t id1, std::uint32_t id2, std::uint32_t id3)
Definition: nrnran123.cpp:27
void nrnran123_setids(nrnran123_State *s, std::uint32_t id1, std::uint32_t id2, std::uint32_t id3)
Definition: nrnran123.cpp:104
void nrnran123_getseq(nrnran123_State *s, std::uint32_t *seq, char *which)
Get sequence number and selector from an nrnran123_State object.
Definition: nrnran123.cpp:50
static int c
Definition: hoc.cpp:169
static const double SHIFT32
Definition: mcran4.cpp:116
sqrt
Definition: extdef.h:3
log
Definition: extdef.h:4
s
Definition: multisend.cpp:521
int nrnmpi_myid
RNG::ctr_type c
Definition: nrnran123.cpp:12
RNG::ctr_type r
Definition: nrnran123.cpp:13
std::uint32_t v[4]
Definition: nrnran123.h:31