package hedgehog

  1. Overview
  2. Docs

Source file seed.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
(* Splittable pseudorandom number generator.

   Delegates to OCaml's built-in Random.State which uses a splittable LXM
   algorithm (added in OCaml 5.0).

   Random.State.t is mutable, so we copy before each operation to preserve
   the functional (immutable) API that generators expect. *)

type t = Random.State.t

let from x = Random.State.make [| Int64.to_int x |]
let random () = Random.State.make_self_init ()

let split seed =
  let copy = Random.State.copy seed in
  let derived = Random.State.split copy in
  (copy, derived)

let next_int64 seed =
  let copy = Random.State.copy seed in
  let v = Random.State.bits64 copy in
  (v, copy)

let next_int lo hi seed =
  let copy = Random.State.copy seed in
  if lo = hi then (lo, copy)
  else
    let range = hi - lo + 1 in
    if range <= 0 then
      (* Overflow: the full int range is requested. *)
      let v = Random.State.bits64 copy in
      (Int64.to_int v, copy)
    else
      let v = Random.State.full_int copy range in
      (lo + v, copy)

let next_int64_range lo hi seed =
  let copy = Random.State.copy seed in
  if lo = hi then (lo, copy)
  else
    let range = Int64.sub hi lo in
    if range < 0L then
      (* Unsigned overflow: full int64 range requested *)
      let v = Random.State.bits64 copy in
      (v, copy)
    else if range = Int64.max_int then
      (* int64 bound would overflow, use bits64 and mask *)
      let v = Int64.logand (Random.State.bits64 copy) Int64.max_int in
      (Int64.add lo v, copy)
    else
      let v = Random.State.int64 copy (Int64.succ range) in
      (Int64.add lo v, copy)

let next_float lo hi seed =
  let copy = Random.State.copy seed in
  let v = Random.State.float copy (hi -. lo) in
  (lo +. v, copy)