diff options
| author | gingerBill <bill@gingerbill.org> | 2018-01-17 19:09:22 +0000 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2018-01-17 19:09:22 +0000 |
| commit | b3734a5f771e46df1d8bde4a187fb8a4e93e6612 (patch) | |
| tree | dcff33f003c5caf01b89841d3e167d0871880d9a /core/math | |
| parent | 419ab6f00c5396c1296a78e931693ba38d7ea102 (diff) | |
Add math/rand.odin
Diffstat (limited to 'core/math')
| -rw-r--r-- | core/math/rand.odin | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/core/math/rand.odin b/core/math/rand.odin new file mode 100644 index 000000000..4862ad496 --- /dev/null +++ b/core/math/rand.odin @@ -0,0 +1,60 @@ +Rand :: struct { + state: u64, + inc: u64, +} + +init :: proc(r: ^Rand, seed: u64 = 8675309) { + r.state = 0; + r.inc = (seed << 1) | 1; + _random(r); + r.state += seed; + _random(r); +} + +_random :: proc(r: ^Rand) -> u32 { + old_state := r.state; + r.state = old_state * 6364136223846793005 + (r.inc|1); + xor_shifted := u32(((old_state>>18) ~ old_state) >> 27); + rot := u32(old_state >> 59); + return (xor_shifted >> rot) | (xor_shifted << ((-rot) & 31)); +} + +uint32 :: proc(r: ^Rand) -> u32 { return _random(r); } + +uint64 :: proc(r: ^Rand) -> u64 { + a := u64(_random(r)); + b := u64(_random(r)); + return (a<<32) | b; +} + +int31 :: proc(r: ^Rand) -> i32 { return i32(uint32(r) << 1 >> 1); } +int63 :: proc(r: ^Rand) -> i64 { return i64(uint64(r) << 1 >> 1); } + +int31_max :: proc(r: ^Rand, n: i32) -> i32 { + if n <= 0 do panic("Invalid argument to int31_max"); + if n&(n-1) == 0 { + return int31(r) & (n-1); + } + max := i32((1<<31) - 1 - (1<<31)&u32(n)); + v := int31(r); + for v > max { + v = int31(r); + } + return v % n; +} + +int63_max :: proc(r: ^Rand, n: i64) -> i64 { + if n <= 0 do panic("Invalid argument to int63_max"); + if n&(n-1) == 0 { + return int63(r) & (n-1); + } + max := i64((1<<63) - 1 - (1<<63)&u64(n)); + v := int63(r); + for v > max { + v = int63(r); + } + return v % n; +} + +float64 :: proc(r: ^Rand) -> f64 { return f64(int63_max(r, 1<<53)) / (1 << 53); } +float32 :: proc(r: ^Rand) -> f32 { return f32(float64(r)); } |