rand.odin 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. package rand
  2. import "core:intrinsics"
  3. Rand :: struct {
  4. state: u64,
  5. inc: u64,
  6. is_system: bool,
  7. }
  8. @(private)
  9. global_rand := create(u64(intrinsics.read_cycle_counter()))
  10. set_global_seed :: proc(seed: u64) {
  11. init(&global_rand, seed)
  12. }
  13. create :: proc(seed: u64) -> Rand {
  14. r: Rand
  15. init(&r, seed)
  16. return r
  17. }
  18. init :: proc(r: ^Rand, seed: u64) {
  19. r.state = 0
  20. r.inc = (seed << 1) | 1
  21. _random(r)
  22. r.state += seed
  23. _random(r)
  24. }
  25. init_as_system :: proc(r: ^Rand) {
  26. if !#defined(_system_random) {
  27. panic(#procedure + " is not supported on this platform yet")
  28. }
  29. r.state = 0
  30. r.inc = 0
  31. r.is_system = true
  32. }
  33. @(private)
  34. _random :: proc(r: ^Rand) -> u32 {
  35. r := r
  36. if r == nil {
  37. // NOTE(bill, 2020-09-07): Do this so that people can
  38. // enforce the global random state if necessary with `nil`
  39. r = &global_rand
  40. }
  41. when #defined(_system_random) {
  42. if r.is_system {
  43. return _system_random()
  44. }
  45. }
  46. old_state := r.state
  47. r.state = old_state * 6364136223846793005 + (r.inc|1)
  48. xor_shifted := u32(((old_state>>18) ~ old_state) >> 27)
  49. rot := u32(old_state >> 59)
  50. return (xor_shifted >> rot) | (xor_shifted << ((-rot) & 31))
  51. }
  52. uint32 :: proc(r: ^Rand = nil) -> u32 { return _random(r) }
  53. uint64 :: proc(r: ^Rand = nil) -> u64 {
  54. a := u64(_random(r))
  55. b := u64(_random(r))
  56. return (a<<32) | b
  57. }
  58. uint128 :: proc(r: ^Rand = nil) -> u128 {
  59. a := u128(_random(r))
  60. b := u128(_random(r))
  61. c := u128(_random(r))
  62. d := u128(_random(r))
  63. return (a<<96) | (b<<64) | (c<<32) | d
  64. }
  65. int31 :: proc(r: ^Rand = nil) -> i32 { return i32(uint32(r) << 1 >> 1) }
  66. int63 :: proc(r: ^Rand = nil) -> i64 { return i64(uint64(r) << 1 >> 1) }
  67. int127 :: proc(r: ^Rand = nil) -> i128 { return i128(uint128(r) << 1 >> 1) }
  68. int31_max :: proc(n: i32, r: ^Rand = nil) -> i32 {
  69. if n <= 0 {
  70. panic("Invalid argument to int31_max")
  71. }
  72. if n&(n-1) == 0 {
  73. return int31(r) & (n-1)
  74. }
  75. max := i32((1<<31) - 1 - (1<<31)%u32(n))
  76. v := int31(r)
  77. for v > max {
  78. v = int31(r)
  79. }
  80. return v % n
  81. }
  82. int63_max :: proc(n: i64, r: ^Rand = nil) -> i64 {
  83. if n <= 0 {
  84. panic("Invalid argument to int63_max")
  85. }
  86. if n&(n-1) == 0 {
  87. return int63(r) & (n-1)
  88. }
  89. max := i64((1<<63) - 1 - (1<<63)%u64(n))
  90. v := int63(r)
  91. for v > max {
  92. v = int63(r)
  93. }
  94. return v % n
  95. }
  96. int127_max :: proc(n: i128, r: ^Rand = nil) -> i128 {
  97. if n <= 0 {
  98. panic("Invalid argument to int127_max")
  99. }
  100. if n&(n-1) == 0 {
  101. return int127(r) & (n-1)
  102. }
  103. max := i128((1<<127) - 1 - (1<<127)%u128(n))
  104. v := int127(r)
  105. for v > max {
  106. v = int127(r)
  107. }
  108. return v % n
  109. }
  110. int_max :: proc(n: int, r: ^Rand = nil) -> int {
  111. if n <= 0 {
  112. panic("Invalid argument to int_max")
  113. }
  114. when size_of(int) == 4 {
  115. return int(int31_max(i32(n), r))
  116. } else {
  117. return int(int63_max(i64(n), r))
  118. }
  119. }
  120. // Uniform random distribution [0, 1)
  121. float64 :: proc(r: ^Rand = nil) -> f64 { return f64(int63_max(1<<53, r)) / (1 << 53) }
  122. // Uniform random distribution [0, 1)
  123. float32 :: proc(r: ^Rand = nil) -> f32 { return f32(float64(r)) }
  124. float64_range :: proc(lo, hi: f64, r: ^Rand = nil) -> f64 { return (hi-lo)*float64(r) + lo }
  125. float32_range :: proc(lo, hi: f32, r: ^Rand = nil) -> f32 { return (hi-lo)*float32(r) + lo }
  126. read :: proc(p: []byte, r: ^Rand = nil) -> (n: int) {
  127. pos := i8(0)
  128. val := i64(0)
  129. for n = 0; n < len(p); n += 1 {
  130. if pos == 0 {
  131. val = int63(r)
  132. pos = 7
  133. }
  134. p[n] = byte(val)
  135. val >>= 8
  136. pos -= 1
  137. }
  138. return
  139. }
  140. // perm returns a slice of n ints in a pseudo-random permutation of integers in the range [0, n)
  141. perm :: proc(n: int, r: ^Rand = nil, allocator := context.allocator) -> []int {
  142. m := make([]int, n, allocator)
  143. for i := 0; i < n; i += 1 {
  144. j := int_max(i+1, r)
  145. m[i] = m[j]
  146. m[j] = i
  147. }
  148. return m
  149. }
  150. shuffle :: proc(array: $T/[]$E, r: ^Rand = nil) {
  151. n := i64(len(array))
  152. if n < 2 {
  153. return
  154. }
  155. for i := i64(0); i < n; i += 1 {
  156. j := int63_max(n, r)
  157. array[i], array[j] = array[j], array[i]
  158. }
  159. }