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 are
11 based on the Xoroshiro and Xorshift 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 most 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, but execute in a time roughly equiva‐
19 lent to one regular iteration per generator bit.
20
21 At the end of this module documentation there are also some niche al‐
22 gorithms to be used without this module's normal plug-in framework
23 API that may be useful for special purposes like short generation time
24 when quality is not essential, for seeding other generators, and such.
25
26 The following algorithms are provided:
27
28 exsss:
29 Xorshift116**, 58 bits precision and period of 2^116-1
30
31 Jump function: equivalent to 2^64 calls
32
33 This is the Xorshift116 generator combined with the StarStar scram‐
34 bler from the 2018 paper by David Blackman and Sebastiano Vigna:
35 Scrambled Linear Pseudorandom Number Generators
36
37 The generator does not need 58-bit rotates so it is faster than the
38 Xoroshiro116 generator, and when combined with the StarStar scram‐
39 bler it does not have any weak low bits like exrop (Xoroshiro116+).
40
41 Alas, this combination is about 10% slower than exrop, but is de‐
42 spite that the default algorithm thanks to its statistical quali‐
43 ties.
44
45 exro928ss:
46 Xoroshiro928**, 58 bits precision and a period of 2^928-1
47
48 Jump function: equivalent to 2^512 calls
49
50 This is a 58 bit version of Xoroshiro1024**, from the 2018 paper by
51 David Blackman and Sebastiano Vigna: Scrambled Linear Pseudorandom
52 Number Generators that on a 64 bit Erlang system executes only
53 about 40% slower than the defaultexsssalgorithm but with much
54 longer period and better statistical properties, but on the flip
55 side a larger state.
56
57 Many thanks to Sebastiano Vigna for his help with the 58 bit adap‐
58 tion.
59
60 exrop:
61 Xoroshiro116+, 58 bits precision and period of 2^116-1
62
63 Jump function: equivalent to 2^64 calls
64
65 exs1024s:
66 Xorshift1024*, 64 bits precision and a period of 2^1024-1
67
68 Jump function: equivalent to 2^512 calls
69
70 exsp:
71 Xorshift116+, 58 bits precision and period of 2^116-1
72
73 Jump function: equivalent to 2^64 calls
74
75 This is a corrected version of the previous default algorithm,
76 that now has been superseded by Xoroshiro116+ (exrop). Since there
77 is no native 58 bit rotate instruction this algorithm executes a
78 little (say < 15%) faster than exrop. See the algorithms' homepage.
79
80 The current default algorithm is exsss (Xorshift116**). If a specific
81 algorithm is required, ensure to always use seed/1 to initialize the
82 state.
83
84 Which algorithm that is the default may change between Erlang/OTP re‐
85 leases, and is selected to be one with high speed, small state and
86 "good enough" statistical properties.
87
88 Undocumented (old) algorithms are deprecated but still implemented so
89 old code relying on them will produce the same pseudo random sequences
90 as before.
91
92 Note:
93 There were a number of problems in the implementation of the now undoc‐
94 umented algorithms, which is why they are deprecated. The new algo‐
95 rithms are a bit slower but do not have these problems:
96
97 Uniform integer ranges had a skew in the probability distribution that
98 was not noticable for small ranges but for large ranges less than the
99 generator's precision the probability to produce a low number could be
100 twice the probability for a high.
101
102 Uniform integer ranges larger than or equal to the generator's preci‐
103 sion used a floating point fallback that only calculated with 52 bits
104 which is smaller than the requested range and therefore were not all
105 numbers in the requested range even possible to produce.
106
107 Uniform floats had a non-uniform density so small values i.e less than
108 0.5 had got smaller intervals decreasing as the generated value ap‐
109 proached 0.0 although still uniformly distributed for sufficiently
110 large subranges. The new algorithms produces uniformly distributed
111 floats on the form N * 2.0^(-53) hence equally spaced.
112
113
114 Every time a random number is requested, a state is used to calculate
115 it and a new state is produced. The state can either be implicit or be
116 an explicit argument and return value.
117
118 The functions with implicit state use the process dictionary variable
119 rand_seed to remember the current state.
120
121 If a process calls uniform/0, uniform/1 or uniform_real/0 without set‐
122 ting a seed first, seed/1 is called automatically with the default al‐
123 gorithm and creates a non-constant seed.
124
125 The functions with explicit state never use the process dictionary.
126
127 Examples:
128
129 Simple use; creates and seeds the default algorithm with a non-constant
130 seed if not already done:
131
132 R0 = rand:uniform(),
133 R1 = rand:uniform(),
134
135 Use a specified algorithm:
136
137 _ = rand:seed(exs928ss),
138 R2 = rand:uniform(),
139
140 Use a specified algorithm with a constant seed:
141
142 _ = rand:seed(exs928ss, {123, 123534, 345345}),
143 R3 = rand:uniform(),
144
145 Use the functional API with a non-constant seed:
146
147 S0 = rand:seed_s(exsss),
148 {R4, S1} = rand:uniform_s(S0),
149
150 Textbook basic form Box-Muller standard normal deviate
151
152 R5 = rand:uniform_real(),
153 R6 = rand:uniform(),
154 SND0 = math:sqrt(-2 * math:log(R5)) * math:cos(math:pi() * R6)
155
156 Create a standard normal deviate:
157
158 {SND1, S2} = rand:normal_s(S1),
159
160 Create a normal deviate with mean -3 and variance 0.5:
161
162 {ND0, S3} = rand:normal_s(-3, 0.5, S2),
163
164 Note:
165 The builtin random number generator algorithms are not cryptographi‐
166 cally strong. If a cryptographically strong random number generator is
167 needed, use something like crypto:rand_seed/0.
168
169
170 For all these generators except exro928ss and exsss the lowest bit(s)
171 has got a slightly less random behaviour than all other bits. 1 bit for
172 exrop (and exsp), and 3 bits for exs1024s. See for example the explana‐
173 tion in the Xoroshiro128+ generator source code:
174
175 Beside passing BigCrush, this generator passes the PractRand test suite
176 up to (and included) 16TB, with the exception of binary rank tests,
177 which fail due to the lowest bit being an LFSR; all other bits pass all
178 tests. We suggest to use a sign test to extract a random Boolean value.
179
180 If this is a problem; to generate a boolean with these algorithms use
181 something like this:
182
183 (rand:uniform(256) > 128) % -> boolean()
184
185 ((rand:uniform(256) - 1) bsr 7) % -> 0 | 1
186
187 For a general range, with N = 1 for exrop, and N = 3 for exs1024s:
188
189 (((rand:uniform(Range bsl N) - 1) bsr N) + 1)
190
191 The floating point generating functions in this module waste the lowest
192 bits when converting from an integer so they avoid this snag.
193
195 builtin_alg() =
196 exsss | exro928ss | exrop | exs1024s | exsp | exs64 |
197 exsplus | exs1024 | dummy
198
199 alg() = builtin_alg() | atom()
200
201 alg_handler() =
202 #{type := alg(),
203 bits => integer() >= 0,
204 weak_low_bits => integer() >= 0,
205 max => integer() >= 0,
206 next :=
207 fun((alg_state()) -> {integer() >= 0, alg_state()}),
208 uniform => fun((state()) -> {float(), state()}),
209 uniform_n =>
210 fun((integer() >= 1, state()) -> {integer() >= 1, state()}),
211 jump => fun((state()) -> state())}
212
213 alg_state() =
214 exsplus_state() |
215 exro928_state() |
216 exrop_state() |
217 exs1024_state() |
218 exs64_state() |
219 dummy_state() |
220 term()
221
222 state() = {alg_handler(), alg_state()}
223
224 Algorithm-dependent state.
225
226 export_state() = {alg(), alg_state()}
227
228 Algorithm-dependent state that can be printed or saved to file.
229
230 seed() =
231 [integer()] | integer() | {integer(), integer(), integer()}
232
233 A seed value for the generator.
234
235 A list of integers sets the generator's internal state directly,
236 after algorithm-dependent checks of the value and masking to the
237 proper word size. The number of integers must be equal to the
238 number of state words in the generator.
239
240 An integer is used as the initial state for a SplitMix64 genera‐
241 tor. The output values of that is then used for setting the gen‐
242 erator's internal state after masking to the proper word size
243 and if needed avoiding zero values.
244
245 A traditional 3-tuple of integers seed is passed through algo‐
246 rithm-dependent hashing functions to create the generator's ini‐
247 tial state.
248
249 exsplus_state()
250
251 Algorithm specific internal state
252
253 exro928_state()
254
255 Algorithm specific internal state
256
257 exrop_state()
258
259 Algorithm specific internal state
260
261 exs1024_state()
262
263 Algorithm specific internal state
264
265 exs64_state()
266
267 Algorithm specific internal state
268
269 dummy_state() = uint58()
270
271 Algorithm specific internal state
272
273 splitmix64_state() = uint64()
274
275 Algorithm specific state
276
277 uint58() = 0..288230376151711743
278
279 0 .. (2^58 - 1)
280
281 uint64() = 0..18446744073709551615
282
283 0 .. (2^64 - 1)
284
285 mwc59_state() = 1..574882961707499518
286
287 1 .. ((16#1ffb072 * 2^29 - 1) - 1)
288
291 bytes(N :: integer() >= 0) -> Bytes :: binary()
292
293 Returns, for a specified integer N >= 0, a binary() with that
294 number of random bytes. Generates as many random numbers as re‐
295 quired using the selected algorithm to compose the binary, and
296 updates the state in the process dictionary accordingly.
297
298 bytes_s(N :: integer() >= 0, State :: state()) ->
299 {Bytes :: binary(), NewState :: state()}
300
301 Returns, for a specified integer N >= 0 and a state, a binary()
302 with that number of random bytes, and a new state. Generates as
303 many random numbers as required using the selected algorithm to
304 compose the binary, and the new state.
305
306 export_seed() -> undefined | export_state()
307
308 Returns the random number state in an external format. To be
309 used with seed/1.
310
311 export_seed_s(State :: state()) -> export_state()
312
313 Returns the random number generator state in an external format.
314 To be used with seed/1.
315
316 jump() -> NewState :: state()
317
318 Returns the state after performing jump calculation to the state
319 in the process dictionary.
320
321 This function generates a not_implemented error exception when
322 the jump function is not implemented for the algorithm specified
323 in the state in the process dictionary.
324
325 jump(State :: state()) -> NewState :: state()
326
327 Returns the state after performing jump calculation to the given
328 state.
329
330 This function generates a not_implemented error exception when
331 the jump function is not implemented for the algorithm specified
332 in the state.
333
334 normal() -> float()
335
336 Returns a standard normal deviate float (that is, the mean is 0
337 and the standard deviation is 1) and updates the state in the
338 process dictionary.
339
340 normal(Mean :: number(), Variance :: number()) -> float()
341
342 Returns a normal N(Mean, Variance) deviate float and updates the
343 state in the process dictionary.
344
345 normal_s(State :: state()) -> {float(), NewState :: state()}
346
347 Returns, for a specified state, a standard normal deviate float
348 (that is, the mean is 0 and the standard deviation is 1) and a
349 new state.
350
351 normal_s(Mean :: number(),
352 Variance :: number(),
353 State0 :: state()) ->
354 {float(), NewS :: state()}
355
356 Returns, for a specified state, a normal N(Mean, Variance) devi‐
357 ate float and a new state.
358
359 seed(AlgOrStateOrExpState ::
360 builtin_alg() | state() | export_state()) ->
361 state()
362
363 seed(Alg :: default) -> state()
364
365 Seeds random number generation with the specifed algorithm and
366 time-dependent data if AlgOrStateOrExpState is an algorithm. Alg
367 = default is an alias for the default algorithm.
368
369 Otherwise recreates the exported seed in the process dictionary,
370 and returns the state. See also export_seed/0.
371
372 seed(Alg :: builtin_alg(), Seed :: seed()) -> state()
373
374 seed(Alg :: default, Seed :: seed()) -> state()
375
376 Seeds random number generation with the specified algorithm and
377 integers in the process dictionary and returns the state. Alg =
378 default is an alias for the default algorithm.
379
380 seed_s(AlgOrStateOrExpState ::
381 builtin_alg() | state() | export_state()) ->
382 state()
383
384 seed_s(Alg :: default) -> state()
385
386 Seeds random number generation with the specifed algorithm and
387 time-dependent data if AlgOrStateOrExpState is an algorithm. Alg
388 = default is an alias for the default algorithm.
389
390 Otherwise recreates the exported seed and returns the state. See
391 also export_seed/0.
392
393 seed_s(Alg :: builtin_alg(), Seed :: seed()) -> state()
394
395 seed_s(Alg :: default, Seed :: seed()) -> state()
396
397 Seeds random number generation with the specified algorithm and
398 integers and returns the state. Alg = default is an alias for
399 the default algorithm.
400
401 uniform() -> X :: float()
402
403 Returns a random float uniformly distributed in the value range
404 0.0 =< X < 1.0 and updates the state in the process dictionary.
405
406 The generated numbers are on the form N * 2.0^(-53), that is;
407 equally spaced in the interval.
408
409 Warning:
410 This function may return exactly 0.0 which can be fatal for cer‐
411 tain applications. If that is undesired you can use (1.0 -
412 rand:uniform()) to get the interval 0.0 < X =< 1.0, or instead
413 use uniform_real/0.
414
415 If neither endpoint is desired you can test and re-try like
416 this:
417
418 my_uniform() ->
419 case rand:uniform() of
420 0.0 -> my_uniform();
421 X -> X
422 end
423 end.
424
425
426 uniform_real() -> X :: float()
427
428 Returns a random float uniformly distributed in the value range
429 DBL_MIN =< X < 1.0 and updates the state in the process dictio‐
430 nary.
431
432 Conceptually, a random real number R is generated from the in‐
433 terval 0 =< R < 1 and then the closest rounded down normalized
434 number in the IEEE 754 Double precision format is returned.
435
436 Note:
437 The generated numbers from this function has got better granu‐
438 larity for small numbers than the regular uniform/0 because all
439 bits in the mantissa are random. This property, in combination
440 with the fact that exactly zero is never returned is useful for
441 algoritms doing for example 1.0 / X or math:log(X).
442
443
444 See uniform_real_s/1 for more explanation.
445
446 uniform(N :: integer() >= 1) -> X :: integer() >= 1
447
448 Returns, for a specified integer N >= 1, a random integer uni‐
449 formly distributed in the value range 1 =< X =< N and updates
450 the state in the process dictionary.
451
452 uniform_s(State :: state()) -> {X :: float(), NewState :: state()}
453
454 Returns, for a specified state, random float uniformly distrib‐
455 uted in the value range 0.0 =< X < 1.0 and a new state.
456
457 The generated numbers are on the form N * 2.0^(-53), that is;
458 equally spaced in the interval.
459
460 Warning:
461 This function may return exactly 0.0 which can be fatal for cer‐
462 tain applications. If that is undesired you can use (1.0 -
463 rand:uniform(State)) to get the interval 0.0 < X =< 1.0, or in‐
464 stead use uniform_real_s/1.
465
466 If neither endpoint is desired you can test and re-try like
467 this:
468
469 my_uniform(State) ->
470 case rand:uniform(State) of
471 {0.0, NewState} -> my_uniform(NewState);
472 Result -> Result
473 end
474 end.
475
476
477 uniform_real_s(State :: state()) ->
478 {X :: float(), NewState :: state()}
479
480 Returns, for a specified state, a random float uniformly dis‐
481 tributed in the value range DBL_MIN =< X < 1.0 and updates the
482 state in the process dictionary.
483
484 Conceptually, a random real number R is generated from the in‐
485 terval 0 =< R < 1 and then the closest rounded down normalized
486 number in the IEEE 754 Double precision format is returned.
487
488 Note:
489 The generated numbers from this function has got better granu‐
490 larity for small numbers than the regular uniform_s/1 because
491 all bits in the mantissa are random. This property, in combina‐
492 tion with the fact that exactly zero is never returned is useful
493 for algoritms doing for example 1.0 / X or math:log(X).
494
495
496 The concept implicates that the probability to get exactly zero
497 is extremely low; so low that this function is in fact guaran‐
498 teed to never return zero. The smallest number that it might re‐
499 turn is DBL_MIN, which is 2.0^(-1022).
500
501 The value range stated at the top of this function description
502 is technically correct, but 0.0 =< X < 1.0 is a better descrip‐
503 tion of the generated numbers' statistical distribution. Except
504 that exactly 0.0 is never returned, which is not possible to ob‐
505 serve statistically.
506
507 For example; for all sub ranges N*2.0^(-53) =< X <
508 (N+1)*2.0^(-53) where 0 =< integer(N) < 2.0^53 the probability
509 is the same. Compare that with the form of the numbers generated
510 by uniform_s/1.
511
512 Having to generate extra random bits for small numbers costs a
513 little performance. This function is about 20% slower than the
514 regular uniform_s/1
515
516 uniform_s(N :: integer() >= 1, State :: state()) ->
517 {X :: integer() >= 1, NewState :: state()}
518
519 Returns, for a specified integer N >= 1 and a state, a random
520 integer uniformly distributed in the value range 1 =< X =< N and
521 a new state.
522
524 This section contains special purpose algorithms that does not use the
525 plug-in framework API, for example for speed reasons.
526
527 Since these algorithms lack the plug-in framework support, generating
528 numbers in a range other than the generator's own generated range may
529 become a problem.
530
531 There are at least 3 ways to do this, assuming that the range is less
532 than the generator's range:
533
534 Modulo:
535 To generate a number V in the range 0..Range-1:
536
537 * Generate a number X.
538
539 *
540 Use V = X rem Range as your value.
541
542 This method uses rem, that is, the remainder of an integer divi‐
543 sion, which is a slow operation.
544
545 Low bits from the generator propagate straight through to the gen‐
546 erated value, so if the generator has got weaknesses in the low
547 bits this method propagates them too.
548
549 If Range is not a divisor of the generator range, the generated
550 numbers have a bias. Example:
551
552 Say the generator generates a byte, that is, the generator range is
553 0..255, and the desired range is 0..99 (Range=100). Then there are
554 3 generator outputs that produce the value 0, that is; 0, 100 and
555 200. But there are only 2 generator outputs that produce the value
556 99, which are; 99 and 199. So the probability for a value V in
557 0..55 is 3/2 times the probability for the other values 56..99.
558
559 If Range is much smaller than the generator range, then this bias
560 gets hard to detect. The rule of thumb is that if Range is smaller
561 than the square root of the generator range, the bias is small
562 enough. Example:
563
564 A byte generator when Range=20. There are 12 (256 div 20) possibil‐
565 ities to generate the highest numbers and one more to generate a
566 number V < 16 (256 rem 20). So the probability is 13/12 for a low
567 number versus a high. To detect that difference with some confi‐
568 dence you would need to generate a lot more numbers than the gener‐
569 ator range, 256 in this small example.
570
571 Truncated multiplication:
572 To generate a number V in the range 0..Range-1, when you have a
573 generator with the range 0..2^Bits-1:
574
575 * Generate a number X.
576
577 *
578 Use V = X*Range bsr Bits as your value.
579
580 If the multiplication X*Range creates a bignum this method becomes
581 very slow.
582
583 High bits from the generator propagate through to the generated
584 value, so if the generator has got weaknesses in the high bits this
585 method propagates them too.
586
587 If Range is not a divisor of the generator range, the generated
588 numbers have a bias, pretty much as for the Modulo method above.
589
590 Shift or mask:
591 To generate a number in the range 0..2^RBits-1, when you have a
592 generator with the range 0..2^Bits:
593
594 * Generate a number X.
595
596 *
597 Use V = X band ((1 bsl RBits)-1) or V = X bsr (Bits-RBits) as
598 your value.
599
600 Masking with band preserves the low bits, and right shifting with
601 bsr preserves the high, so if the generator has got weaknesses in
602 high or low bits; choose the right operator.
603
604 If the generator has got a range that is not a power of 2 and this
605 method is used anyway, it introduces bias in the same way as for
606 the Modulo method above.
607
608 Rejection:
609
610
611 * Generate a number X.
612
613 *
614 If X is in the range, use V = X as your value, otherwise reject
615 it and repeat.
616
617 In theory it is not certain that this method will ever complete,
618 but in practice you ensure that the probability of rejection is
619 low. Then the probability for yet another iteration decreases expo‐
620 nentially so the expected mean number of iterations will often be
621 between 1 and 2. Also, since the base generator is a full length
622 generator, a value that will break the loop must eventually be gen‐
623 erated.
624
625 Chese methods can be combined, such as using the Modulo method and only
626 if the generator value would create bias use Rejection. Or using Shift
627 or mask to reduce the size of a generator value so that Truncated mul‐
628 tiplication will not create a bignum.
629
630 The recommended way to generate a floating point number (IEEE 745 dou‐
631 ble, that has got a 53-bit mantissa) in the range 0..1, that is 0.0 =<
632 V <1.0 is to generate a 53-bit number X and then use V = X * (1.0/((1
633 bsl 53))) as your value. This will create a value on the form N*2^-53
634 with equal probability for every possible N for the range.
635
637 splitmix64_next(AlgState :: integer()) ->
638 {X :: uint64(),
639 NewAlgState :: splitmix64_state()}
640
641 Returns a random 64-bit integer X and a new generator state
642 NewAlgState, according to the SplitMix64 algorithm.
643
644 This generator is used internally in the rand module for seeding
645 other generators since it is of a quite different breed which
646 reduces the probability for creating an accidentally bad seed.
647
648 exsp_next(AlgState :: exsplus_state()) ->
649 {X :: uint58(), NewAlgState :: exsplus_state()}
650
651 Returns a random 58-bit integer X and a new generator state
652 NewAlgState, according to the Xorshift116+ algorithm.
653
654 This is an API function into the internal implementation of the
655 exsp algorithm that enables using it without the overhead of the
656 plug-in framework, which might be useful for time critial appli‐
657 cations. On a typical 64 bit Erlang VM this approach executes in
658 just above 30% (1/3) of the time for the default algorithm
659 through this module's normal plug-in framework.
660
661 To seed this generator use {_, AlgState} = rand:seed_s(exsp) or
662 {_, AlgState} = rand:seed_s(exsp, Seed) with a specific Seed.
663
664 Note:
665 This function offers no help in generating a number on a se‐
666 lected range, nor in generating a floating point number. It is
667 easy to accidentally mess up the fairly good statistical proper‐
668 ties of this generator when doing either. See the recepies at
669 the start of this Niche algorithms API description. Note also
670 the caveat about weak low bits that this generator suffers from.
671 The generator is exported in this form primarily for perfor‐
672 mance.
673
674
675 exsp_jump(AlgState :: exsplus_state()) ->
676 NewAlgState :: exsplus_state()
677
678 Returns a new generator state equivalent of the state after it‐
679 erating over exsp_next/1 2^64 times.
680
681 See the description of jump functions at the top of this module
682 description.
683
684 mwc59(CX0 :: mwc59_state()) -> CX1 :: mwc59_state()
685
686 Returns a new generator state CX1, according to a Multiply With
687 Carry generator, which is an efficient implementation of a Mul‐
688 tiplicative Congruential Generator with a power of 2 multiplier
689 and a prime modulus.
690
691 This generator uses the multiplier 2^32 and the modulus
692 16#7fa6502 * 2^32 - 1, which have been selected, in collabora‐
693 tion with Sebastiano Vigna, to avoid bignum operations and still
694 get good statistical quality. It can be written as:
695 C = CX0 bsr 32
696 X = CX0 band ((1 bsl 32)-1))
697 CX1 = 16#7fa6502 * X + C
698
699 Because the generator uses a multiplier that is a power of 2 it
700 gets statistical flaws for collision tests and birthday spacings
701 tests in 2 and 3 dimensions, and even these caveats apply only
702 to the MWC "digit", that is the low 32 bits (due to the multi‐
703 plier) of the generator state.
704
705 The quality of the output value improves much by using a scram‐
706 bler instead of just taking the low bits. Function mwc59_value32
707 is a fast scrambler that returns a decent 32-bit number. The
708 slightly slower mwc59_value scrambler returns 59 bits of very
709 good quality, and mwc59_float returns a float() of very good
710 quality.
711
712 The low bits of the base generator are surprisingly good, so the
713 lowest 16 bits actually pass fairly strict PRNG tests, despite
714 the generator's weaknesses that lie in the high bits of the
715 32-bit MWC "digit". It is recommended to use rem on the the gen‐
716 erator state, or bit mask extracting the lowest bits to produce
717 numbers in a range 16 bits or less. See the recepies at the
718 start of this Niche algorithms API description.
719
720 On a typical 64 bit Erlang VM this generator executes in below
721 8% (1/13) of the time for the default algorithm in the plug-in
722 framework API of this module. With the mwc59_value32 scrambler
723 the total time becomes 16% (1/6), and with mwc59_value it be‐
724 comes 20% (1/5) of the time for the default algorithm. With
725 mwc59_float the total time is 60% of the time for the default
726 algorithm generating a float().
727
728 Note:
729 This generator is a niche generator for high speed applications.
730 It has a much shorter period than the default generator, which
731 in itself is a quality concern, although when used with the
732 value scramblers it passes strict PRNG tests. The generator is
733 much faster than exsp_next/1 but with a bit lower quality.
734
735
736 mwc59_value32(CX :: mwc59_state()) -> V :: 0..4294967295
737
738 Returns a 32-bit value V from a generator state CX. The genera‐
739 tor state is scrambled using an 8-bit xorshift which masks the
740 statistical imperfecions of the base generator mwc59 enough to
741 produce numbers of decent quality. Still some problems in 2- and
742 3-dimensional birthday spacing and collision tests show through.
743
744 When using this scrambler it is in general better to use the
745 high bits of the value than the low. The lowest 8 bits are of
746 good quality and pass right through from the base generator.
747 They are combined with the next 8 in the xorshift making the low
748 16 good quality, but in the range 16..31 bits there are weaker
749 bits that you do not want to have as the high bits of your gen‐
750 erated values. Therefore it is in general safer to shift out low
751 bits. See the recepies at the start of this Niche algorithms
752 API description.
753
754 For a non power of 2 range less than about 16 bits (to not get
755 too much bias and to avoid bignums) truncated multiplication can
756 be used, which is much faster than using rem: (Range*V) bsr 32.
757
758 mwc59_value(CX :: mwc59_state()) -> V :: 0..576460752303423487
759
760 Returns a 59-bit value V from a generator state CX. The genera‐
761 tor state is scrambled using an 4-bit followed by a 27-bit xor‐
762 shift, which masks the statistical imperfecions of the base gen‐
763 erator mwc59 enough that all 59 bits are of very good quality.
764
765 Be careful to not accidentaly create a bignum when handling the
766 value V.
767
768 It is in general general better to use the high bits from this
769 scrambler than the low. See the recepies at the start of this
770 Niche algorithms API description.
771
772 For a non power of 2 range less than about 29 bits (to not get
773 too much bias and to avoid bignums) truncated multiplication can
774 be used, which is much faster than using rem. Example for range
775 1'000'000'000; the range is 30 bits, we use 29 bits from the
776 generator, adding up to 59 bits, which is not a bignum:
777 (1000000000 * (V bsr (59-29))) bsr 29.
778
779 mwc59_float(CX :: mwc59_state()) -> V :: float()
780
781 Returns the generator value V from a generator state CX, as a
782 float(). The generator state is scrambled as with mwc59_value/1
783 before converted to a float().
784
785 mwc59_seed() -> CX :: mwc59_state()
786
787 mwc59_seed(S :: 0..288230376151711743) -> CX :: mwc59_state()
788
789 Returns a generator state CX. S is hashed to create the genera‐
790 tor state, to avoid that similar seeds create similar sequences.
791
792 Without S, the generator state is created as for seed_s(atom()).
793
794
795
796Ericsson AB stdlib 4.2 rand(3)