1rand(3) Erlang Module Definition rand(3)
2
3
4
6 rand - Pseudo random number generation.
7
9 This module provides a pseudo random number generator. The module con‐
10 tains a number of algorithms. The uniform distribution algorithms use
11 the xoroshiro116+ and xorshift1024* algorithms by Sebastiano Vigna.
12 The normal distribution algorithm uses the Ziggurat Method by
13 Marsaglia and Tsang on top of the uniform distribution algorithm.
14
15 For some algorithms, jump functions are provided for generating non-
16 overlapping sequences for parallel computations. The jump functions
17 perform calculations equivalent to perform a large number of repeated
18 calls for calculating new states.
19
20 The following algorithms are provided:
21
22 exrop:
23 Xoroshiro116+, 58 bits precision and period of 2^116-1
24
25 Jump function: equivalent to 2^64 calls
26
27 exs1024s:
28 Xorshift1024*, 64 bits precision and a period of 2^1024-1
29
30 Jump function: equivalent to 2^512 calls
31
32 exsp:
33 Xorshift116+, 58 bits precision and period of 2^116-1
34
35 Jump function: equivalent to 2^64 calls
36
37 This is a corrected version of the previous default algorithm, that
38 now has been superseded by Xoroshiro116+ (exrop). Since there is no
39 native 58 bit rotate instruction this algorithm executes a little
40 (say < 15%) faster than exrop. See the algorithms' homepage.
41
42 The default algorithm is exrop (Xoroshiro116+). If a specific algorithm
43 is required, ensure to always use seed/1 to initialize the state.
44
45 Undocumented (old) algorithms are deprecated but still implemented so
46 old code relying on them will produce the same pseudo random sequences
47 as before.
48
49 Note:
50 There were a number of problems in the implementation of the now undoc‐
51 umented algorithms, which is why they are deprecated. The new algo‐
52 rithms are a bit slower but do not have these problems:
53
54 Uniform integer ranges had a skew in the probability distribution that
55 was not noticable for small ranges but for large ranges less than the
56 generator's precision the probability to produce a low number could be
57 twice the probability for a high.
58
59 Uniform integer ranges larger than or equal to the generator's preci‐
60 sion used a floating point fallback that only calculated with 52 bits
61 which is smaller than the requested range and therefore were not all
62 numbers in the requested range even possible to produce.
63
64 Uniform floats had a non-uniform density so small values i.e less than
65 0.5 had got smaller intervals decreasing as the generated value
66 approached 0.0 although still uniformly distributed for sufficiently
67 large subranges. The new algorithms produces uniformly distributed
68 floats on the form N * 2.0^(-53) hence equally spaced.
69
70
71 Every time a random number is requested, a state is used to calculate
72 it and a new state is produced. The state can either be implicit or be
73 an explicit argument and return value.
74
75 The functions with implicit state use the process dictionary variable
76 rand_seed to remember the current state.
77
78 If a process calls uniform/0, uniform/1 or uniform_real/0 without set‐
79 ting a seed first, seed/1 is called automatically with the default
80 algorithm and creates a non-constant seed.
81
82 The functions with explicit state never use the process dictionary.
83
84 Examples:
85
86 Simple use; creates and seeds the default algorithm with a non-constant
87 seed if not already done:
88
89 R0 = rand:uniform(),
90 R1 = rand:uniform(),
91
92 Use a specified algorithm:
93
94 _ = rand:seed(exs1024s),
95 R2 = rand:uniform(),
96
97 Use a specified algorithm with a constant seed:
98
99 _ = rand:seed(exs1024s, {123, 123534, 345345}),
100 R3 = rand:uniform(),
101
102 Use the functional API with a non-constant seed:
103
104 S0 = rand:seed_s(exrop),
105 {R4, S1} = rand:uniform_s(S0),
106
107 Textbook basic form Box-Muller standard normal deviate
108
109 R5 = rand:uniform_real(),
110 R6 = rand:uniform(),
111 SND0 = math:sqrt(-2 * math:log(R5)) * math:cos(math:pi() * R6)
112
113 Create a standard normal deviate:
114
115 {SND1, S2} = rand:normal_s(S1),
116
117 Create a normal deviate with mean -3 and variance 0.5:
118
119 {ND0, S3} = rand:normal_s(-3, 0.5, S2),
120
121 Note:
122 The builtin random number generator algorithms are not cryptographi‐
123 cally strong. If a cryptographically strong random number generator is
124 needed, use something like crypto:rand_seed/0.
125
126
127 For all these generators the lowest bit(s) has got a slightly less ran‐
128 dom behaviour than all other bits. 1 bit for exrop (and exsp), and 3
129 bits for exs1024s. See for example the explanation in the
130 Xoroshiro128+ generator source code:
131
132 Beside passing BigCrush, this generator passes the PractRand test suite
133 up to (and included) 16TB, with the exception of binary rank tests,
134 which fail due to the lowest bit being an LFSR; all other bits pass all
135 tests. We suggest to use a sign test to extract a random Boolean value.
136
137 If this is a problem; to generate a boolean use something like this:
138
139 (rand:uniform(16) > 8)
140
141 And for a general range, with N = 1 for exrop, and N = 3 for exs1024s:
142
143 (((rand:uniform(Range bsl N) - 1) bsr N) + 1)
144
145 The floating point generating functions in this module waste the lowest
146 bits when converting from an integer so they avoid this snag.
147
149 builtin_alg() =
150 exs64 | exsplus | exsp | exs1024 | exs1024s | exrop
151
152 alg() = builtin_alg() | atom()
153
154 alg_handler() =
155 #{type := alg(),
156 bits => integer() >= 0,
157 weak_low_bits => integer() >= 0,
158 max => integer() >= 0,
159 next :=
160 fun((alg_state()) -> {integer() >= 0, alg_state()}),
161 uniform => fun((state()) -> {float(), state()}),
162 uniform_n =>
163 fun((integer() >= 1, state()) -> {integer() >= 1, state()}),
164 jump => fun((state()) -> state())}
165
166 alg_state() =
167 exs64_state() |
168 exsplus_state() |
169 exs1024_state() |
170 exrop_state() |
171 term()
172
173 state() = {alg_handler(), alg_state()}
174
175 Algorithm-dependent state.
176
177 export_state() = {alg(), alg_state()}
178
179 Algorithm-dependent state that can be printed or saved to file.
180
181 exs64_state()
182
183 Algorithm specific internal state
184
185 exsplus_state()
186
187 Algorithm specific internal state
188
189 exs1024_state()
190
191 Algorithm specific internal state
192
193 exrop_state()
194
195 Algorithm specific internal state
196
198 export_seed() -> undefined | export_state()
199
200 Returns the random number state in an external format. To be
201 used with seed/1.
202
203 export_seed_s(State :: state()) -> export_state()
204
205 Returns the random number generator state in an external format.
206 To be used with seed/1.
207
208 jump() -> NewState :: state()
209
210 Returns the state after performing jump calculation to the state
211 in the process dictionary.
212
213 This function generates a not_implemented error exception when
214 the jump function is not implemented for the algorithm specified
215 in the state in the process dictionary.
216
217 jump(State :: state()) -> NewState :: state()
218
219 Returns the state after performing jump calculation to the given
220 state.
221
222 This function generates a not_implemented error exception when
223 the jump function is not implemented for the algorithm specified
224 in the state.
225
226 normal() -> float()
227
228 Returns a standard normal deviate float (that is, the mean is 0
229 and the standard deviation is 1) and updates the state in the
230 process dictionary.
231
232 normal(Mean :: number(), Variance :: number()) -> float()
233
234 Returns a normal N(Mean, Variance) deviate float and updates the
235 state in the process dictionary.
236
237 normal_s(State :: state()) -> {float(), NewState :: state()}
238
239 Returns, for a specified state, a standard normal deviate float
240 (that is, the mean is 0 and the standard deviation is 1) and a
241 new state.
242
243 normal_s(Mean :: number(),
244 Variance :: number(),
245 State0 :: state()) ->
246 {float(), NewS :: state()}
247
248 Returns, for a specified state, a normal N(Mean, Variance) devi‐
249 ate float and a new state.
250
251 seed(AlgOrStateOrExpState ::
252 builtin_alg() | state() | export_state()) ->
253 state()
254
255 Seeds random number generation with the specifed algorithm and
256 time-dependent data if AlgOrStateOrExpState is an algorithm.
257
258 Otherwise recreates the exported seed in the process dictionary,
259 and returns the state. See also export_seed/0.
260
261 seed(Alg :: builtin_alg(),
262 Seed :: {integer(), integer(), integer()}) ->
263 state()
264
265 Seeds random number generation with the specified algorithm and
266 integers in the process dictionary and returns the state.
267
268 seed_s(AlgOrStateOrExpState ::
269 builtin_alg() | state() | export_state()) ->
270 state()
271
272 Seeds random number generation with the specifed algorithm and
273 time-dependent data if AlgOrStateOrExpState is an algorithm.
274
275 Otherwise recreates the exported seed and returns the state. See
276 also export_seed/0.
277
278 seed_s(Alg :: builtin_alg(),
279 Seed :: {integer(), integer(), integer()}) ->
280 state()
281
282 Seeds random number generation with the specified algorithm and
283 integers and returns the state.
284
285 uniform() -> X :: float()
286
287 Returns a random float uniformly distributed in the value range
288 0.0 =< X < 1.0 and updates the state in the process dictionary.
289
290 The generated numbers are on the form N * 2.0^(-53), that is;
291 equally spaced in the interval.
292
293 Warning:
294 This function may return exactly 0.0 which can be fatal for cer‐
295 tain applications. If that is undesired you can use (1.0 -
296 rand:uniform()) to get the interval 0.0 < X =< 1.0, or instead
297 use uniform_real/0.
298
299 If neither endpoint is desired you can test and re-try like
300 this:
301
302 my_uniform() ->
303 case rand:uniform() of
304 0.0 -> my_uniform();
305 X -> X
306 end
307 end.
308
309
310 uniform_real() -> X :: float()
311
312 Returns a random float uniformly distributed in the value range
313 DBL_MIN =< X < 1.0 and updates the state in the process dictio‐
314 nary.
315
316 Conceptually, a random real number R is generated from the
317 interval 0 =< R < 1 and then the closest rounded down normalized
318 number in the IEEE 754 Double precision format is returned.
319
320 Note:
321 The generated numbers from this function has got better granu‐
322 larity for small numbers than the regular uniform/0 because all
323 bits in the mantissa are random. This property, in combination
324 with the fact that exactly zero is never returned is useful for
325 algoritms doing for example 1.0 / X or math:log(X).
326
327
328 See uniform_real_s/1 for more explanation.
329
330 uniform(N :: integer() >= 1) -> X :: integer() >= 1
331
332 Returns, for a specified integer N >= 1, a random integer uni‐
333 formly distributed in the value range 1 =< X =< N and updates
334 the state in the process dictionary.
335
336 uniform_s(State :: state()) -> {X :: float(), NewState :: state()}
337
338 Returns, for a specified state, random float uniformly distrib‐
339 uted in the value range 0.0 =< X < 1.0 and a new state.
340
341 The generated numbers are on the form N * 2.0^(-53), that is;
342 equally spaced in the interval.
343
344 Warning:
345 This function may return exactly 0.0 which can be fatal for cer‐
346 tain applications. If that is undesired you can use (1.0 -
347 rand:uniform(State)) to get the interval 0.0 < X =< 1.0, or
348 instead use uniform_real_s/1.
349
350 If neither endpoint is desired you can test and re-try like
351 this:
352
353 my_uniform(State) ->
354 case rand:uniform(State) of
355 {0.0, NewState} -> my_uniform(NewState);
356 Result -> Result
357 end
358 end.
359
360
361 uniform_real_s(State :: state()) ->
362 {X :: float(), NewState :: state()}
363
364 Returns, for a specified state, a random float uniformly dis‐
365 tributed in the value range DBL_MIN =< X < 1.0 and updates the
366 state in the process dictionary.
367
368 Conceptually, a random real number R is generated from the
369 interval 0 =< R < 1 and then the closest rounded down normalized
370 number in the IEEE 754 Double precision format is returned.
371
372 Note:
373 The generated numbers from this function has got better granu‐
374 larity for small numbers than the regular uniform_s/1 because
375 all bits in the mantissa are random. This property, in combina‐
376 tion with the fact that exactly zero is never returned is useful
377 for algoritms doing for example 1.0 / X or math:log(X).
378
379
380 The concept implicates that the probability to get exactly zero
381 is extremely low; so low that this function is in fact guaran‐
382 teed to never return zero. The smallest number that it might
383 return is DBL_MIN, which is 2.0^(-1022).
384
385 The value range stated at the top of this function description
386 is technically correct, but 0.0 =< X < 1.0 is a better descrip‐
387 tion of the generated numbers' statistical distribution. Except
388 that exactly 0.0 is never returned, which is not possible to
389 observe statistically.
390
391 For example; for all sub ranges N*2.0^(-53) =< X <
392 (N+1)*2.0^(-53) where 0 =< integer(N) < 2.0^53 the probability
393 is the same. Compare that with the form of the numbers generated
394 by uniform_s/1.
395
396 Having to generate extra random bits for small numbers costs a
397 little performance. This function is about 20% slower than the
398 regular uniform_s/1
399
400 uniform_s(N :: integer() >= 1, State :: state()) ->
401 {X :: integer() >= 1, NewState :: state()}
402
403 Returns, for a specified integer N >= 1 and a state, a random
404 integer uniformly distributed in the value range 1 =< X =< N and
405 a new state.
406
407
408
409Ericsson AB stdlib 3.8.2.1 rand(3)