1  package frost.math
 2  
 3  ====================================================================================================
 4  Provices methods for calculating pseudorandom numbers. Implementations of `Random` generally need
 5  only implement the [int64()] method, with all other methods having default implementations.
 6  ====================================================================================================
 7  interface Random {
 8      ================================================================================================
 9      Provides an automatically-seeded implementation of the default random number generator. The
10      precise algorithm chosen may be system- and version-dependent and is not guaranteed to remain
11      consistent over time. Calling `Random.default()` multiple times within a single run of a program
12      may return instances which all return the same sequence; generally, you should only call this
13      method once per run of a given program.
14      ================================================================================================
15      @class
16      function default():Random {
17          return XorShift128Plus(Timer().elapsed().asInt64)
18      }
19  
20      ============================================================================
21      Returns a random `Bit` (either `true` or `false` with 50% odds of each).
22  
23      @returns a random bit
24      ============================================================================
25      @default
26      method bit():Bit {
27          def test := self.int64()
28          return test && 1 != 0
29      }
30   
31      ================================================================================================
32      Returns a random number between [Int32.MIN] and [Int32.MAX], inclusive.
33      ================================================================================================
34      @default
35      method int32():Int32 {
36          return int64().asInt32
37      }
38  
39      ================================================================================================
40      Returns a random number between [Int64.MIN] and [Int64.MAX], inclusive.
41      ================================================================================================
42      method int64():Int64
43  
44      ================================================================================================
45      Returns a random `Int` between `0` and `n - 1`, inclusive. For example, `int(6)` is equivalent
46      to rolling a standard six-sided die, with return value between `0` and `5`.
47      
48      @param n the range of possible values to generate
49      @returns a random number between `0` and `n - 1`
50      ================================================================================================
51      @default
52      @pre(n >= 1)
53      @post(@return >= 0 & @return < n)
54      method int(n:Int):Int {
55          if n = 1 {
56              return 0
57          }
58  
59          def min := -n % n
60          loop {
61              def x := int64().asInt
62              if x >= min {
63                  return x % n
64              }
65          }
66      }
67  
68      ================================================================================================
69      Returns a random, uniformly distributed `Real32` between `0` (inclusive) and `1` (exclusive).
70      
71      @returns a random `Real32`
72      ================================================================================================
73      @default
74      @post(@return >= 0 & @return < 1)
75      method real32():Real32 {
76          return (int32().asUInt32 >> 8) / (1 << 24)
77      }
78          
79      ================================================================================================
80      Returns a random, uniformly distributed `Real64` between `0` (inclusive) and `1` (exclusive).
81      
82      @returns a random `Real64`
83      ================================================================================================
84      @default
85      @post(@return >= 0 & @return < 1)
86      method real64():Real64 {
87          return (int64().toUInt64 >> 11) / (1 << 53)
88      }
89  
90  }