rand.odin 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package rand
  2. Rand :: struct {
  3. state: u64,
  4. inc: u64,
  5. }
  6. @(private, static)
  7. _GLOBAL_SEED_DATA := 1234567890;
  8. @(private, static)
  9. global_rand := create(u64(uintptr(&_GLOBAL_SEED_DATA)));
  10. @(private, static)
  11. global_rand_ptr := &global_rand;
  12. set_global_seed :: proc(seed: u64) {
  13. init(global_rand_ptr, seed);
  14. }
  15. create :: proc(seed: u64) -> Rand {
  16. r: Rand;
  17. init(&r, seed);
  18. return r;
  19. }
  20. init :: proc(r: ^Rand, seed: u64) {
  21. r.state = 0;
  22. r.inc = (seed << 1) | 1;
  23. _random(r);
  24. r.state += seed;
  25. _random(r);
  26. }
  27. _random :: proc(r: ^Rand) -> u32 {
  28. old_state := r.state;
  29. r.state = old_state * 6364136223846793005 + (r.inc|1);
  30. xor_shifted := u32(((old_state>>18) ~ old_state) >> 27);
  31. rot := u32(old_state >> 59);
  32. return (xor_shifted >> rot) | (xor_shifted << ((-rot) & 31));
  33. }
  34. uint32 :: proc(r: ^Rand = global_rand_ptr) -> u32 { return _random(r); }
  35. uint64 :: proc(r: ^Rand = global_rand_ptr) -> u64 {
  36. a := u64(_random(r));
  37. b := u64(_random(r));
  38. return (a<<32) | b;
  39. }
  40. uint128 :: proc(r: ^Rand = global_rand_ptr) -> u128 {
  41. a := u128(_random(r));
  42. b := u128(_random(r));
  43. c := u128(_random(r));
  44. d := u128(_random(r));
  45. return (a<<96) | (b<<64) | (c<<32) | d;
  46. }
  47. int31 :: proc(r: ^Rand = global_rand_ptr) -> i32 { return i32(uint32(r) << 1 >> 1); }
  48. int63 :: proc(r: ^Rand = global_rand_ptr) -> i64 { return i64(uint64(r) << 1 >> 1); }
  49. int127 :: proc(r: ^Rand = global_rand_ptr) -> i128 { return i128(uint128(r) << 1 >> 1); }
  50. int31_max :: proc(n: i32, r: ^Rand = global_rand_ptr) -> i32 {
  51. if n <= 0 do panic("Invalid argument to int31_max");
  52. if n&(n-1) == 0 {
  53. return int31(r) & (n-1);
  54. }
  55. max := i32((1<<31) - 1 - (1<<31)&u32(n));
  56. v := int31(r);
  57. for v > max {
  58. v = int31(r);
  59. }
  60. return v % n;
  61. }
  62. int63_max :: proc(n: i64, r: ^Rand = global_rand_ptr) -> i64 {
  63. if n <= 0 do panic("Invalid argument to int63_max");
  64. if n&(n-1) == 0 {
  65. return int63(r) & (n-1);
  66. }
  67. max := i64((1<<63) - 1 - (1<<63)&u64(n));
  68. v := int63(r);
  69. for v > max {
  70. v = int63(r);
  71. }
  72. return v % n;
  73. }
  74. int127_max :: proc(n: i128, r: ^Rand = global_rand_ptr) -> i128 {
  75. if n <= 0 do panic("Invalid argument to int63_max");
  76. if n&(n-1) == 0 {
  77. return int127(r) & (n-1);
  78. }
  79. max := i128((1<<63) - 1 - (1<<63)&u128(n));
  80. v := int127(r);
  81. for v > max {
  82. v = int127(r);
  83. }
  84. return v % n;
  85. }
  86. int_max :: proc(n: int, r: ^Rand = global_rand_ptr) -> int {
  87. if n <= 0 do panic("Invalid argument to int_max");
  88. when size_of(int) == 4 {
  89. return int(int31_max(i32(n), r));
  90. } else {
  91. return int(int63_max(i64(n), r));
  92. }
  93. }
  94. float64 :: proc(r: ^Rand = global_rand_ptr) -> f64 { return f64(int63_max(1<<53, r)) / (1 << 53); }
  95. float32 :: proc(r: ^Rand = global_rand_ptr) -> f32 { return f32(float64(r)); }
  96. float64_range :: proc(lo, hi: f64, r: ^Rand = global_rand_ptr) -> f64 { return (hi-lo)*float64(r) + lo; }
  97. float32_range :: proc(lo, hi: f32, r: ^Rand = global_rand_ptr) -> f32 { return (hi-lo)*float32(r) + lo; }
  98. read :: proc(p: []byte, r: ^Rand = global_rand_ptr) -> (n: int) {
  99. pos := i8(0);
  100. val := i64(0);
  101. for n = 0; n < len(p); n += 1 {
  102. if pos == 0 {
  103. val = int63(r);
  104. pos = 7;
  105. }
  106. p[n] = byte(val);
  107. val >>= 8;
  108. pos -= 1;
  109. }
  110. return;
  111. }
  112. // perm returns a slice of n ints in a pseudo-random permutation of integers in the range [0, n)
  113. perm :: proc(n: int, r: ^Rand = global_rand_ptr) -> []int {
  114. m := make([]int, n);
  115. for i := 0; i < n; i += 1 {
  116. j := int_max(i+1);
  117. m[i] = m[j];
  118. m[j] = i;
  119. }
  120. return m;
  121. }
  122. shuffle :: proc(array: $T/[]$E, r: ^Rand = global_rand_ptr) {
  123. n := i64(len(array));
  124. if n < 2 do return;
  125. for i := i64(0); i < n; i += 1 {
  126. j := int63_max(n, r);
  127. array[i], array[j] = array[j], array[i];
  128. }
  129. }