random_generator.odin 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. package runtime
  2. import "base:intrinsics"
  3. @(require_results)
  4. random_generator_read_bytes :: proc(rg: Random_Generator, p: []byte) -> bool {
  5. if rg.procedure != nil {
  6. rg.procedure(rg.data, .Read, p)
  7. return true
  8. }
  9. return false
  10. }
  11. @(require_results)
  12. random_generator_read_ptr :: proc(rg: Random_Generator, p: rawptr, len: uint) -> bool {
  13. if rg.procedure != nil {
  14. rg.procedure(rg.data, .Read, ([^]byte)(p)[:len])
  15. return true
  16. }
  17. return false
  18. }
  19. @(require_results)
  20. random_generator_query_info :: proc(rg: Random_Generator) -> (info: Random_Generator_Query_Info) {
  21. if rg.procedure != nil {
  22. rg.procedure(rg.data, .Query_Info, ([^]byte)(&info)[:size_of(info)])
  23. }
  24. return
  25. }
  26. random_generator_reset_bytes :: proc(rg: Random_Generator, p: []byte) {
  27. if rg.procedure != nil {
  28. rg.procedure(rg.data, .Reset, p)
  29. }
  30. }
  31. random_generator_reset_u64 :: proc(rg: Random_Generator, p: u64) {
  32. if rg.procedure != nil {
  33. p := p
  34. rg.procedure(rg.data, .Reset, ([^]byte)(&p)[:size_of(p)])
  35. }
  36. }
  37. Default_Random_State :: struct {
  38. state: u64,
  39. inc: u64,
  40. }
  41. default_random_generator_proc :: proc(data: rawptr, mode: Random_Generator_Mode, p: []byte) {
  42. @(require_results)
  43. read_u64 :: proc "contextless" (r: ^Default_Random_State) -> u64 {
  44. old_state := r.state
  45. r.state = old_state * 6364136223846793005 + (r.inc|1)
  46. xor_shifted := (((old_state >> 59) + 5) ~ old_state) * 12605985483714917081
  47. rot := (old_state >> 59)
  48. return (xor_shifted >> rot) | (xor_shifted << ((-rot) & 63))
  49. }
  50. @(thread_local)
  51. global_rand_seed: Default_Random_State
  52. init :: proc "contextless" (r: ^Default_Random_State, seed: u64) {
  53. seed := seed
  54. if seed == 0 {
  55. seed = u64(intrinsics.read_cycle_counter())
  56. }
  57. r.state = 0
  58. r.inc = (seed << 1) | 1
  59. _ = read_u64(r)
  60. r.state += seed
  61. _ = read_u64(r)
  62. }
  63. r: ^Default_Random_State = ---
  64. if data == nil {
  65. r = &global_rand_seed
  66. } else {
  67. r = cast(^Default_Random_State)data
  68. }
  69. switch mode {
  70. case .Read:
  71. if r.state == 0 && r.inc == 0 {
  72. init(r, 0)
  73. }
  74. switch len(p) {
  75. case size_of(u64):
  76. // Fast path for a 64-bit destination.
  77. intrinsics.unaligned_store((^u64)(raw_data(p)), read_u64(r))
  78. case:
  79. // All other cases.
  80. pos := i8(0)
  81. val := u64(0)
  82. for &v in p {
  83. if pos == 0 {
  84. val = read_u64(r)
  85. pos = 8
  86. }
  87. v = byte(val)
  88. val >>= 8
  89. pos -= 1
  90. }
  91. }
  92. case .Reset:
  93. seed: u64
  94. mem_copy_non_overlapping(&seed, raw_data(p), min(size_of(seed), len(p)))
  95. init(r, seed)
  96. case .Query_Info:
  97. if len(p) != size_of(Random_Generator_Query_Info) {
  98. return
  99. }
  100. info := (^Random_Generator_Query_Info)(raw_data(p))
  101. info^ += {.Uniform, .Resettable}
  102. }
  103. }
  104. @(require_results)
  105. default_random_generator :: proc "contextless" (state: ^Default_Random_State = nil) -> Random_Generator {
  106. return {
  107. procedure = default_random_generator_proc,
  108. data = state,
  109. }
  110. }