Skip to content

Commit

Permalink
Random: add functions bits32, bits64, nativebits
Browse files Browse the repository at this point in the history
  • Loading branch information
xavierleroy committed Jul 20, 2021
1 parent f203a5d commit 46df597
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 0 deletions.
19 changes: 19 additions & 0 deletions stdlib/random.ml
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,22 @@ module State = struct

let bool s = (bits s land 1 = 0)

let bits32 s =
let b1 = Int32.(shift_right_logical (of_int (bits s)) 14) in (* 16 bits *)
let b2 = Int32.(shift_right_logical (of_int (bits s)) 14) in (* 16 bits *)
Int32.(logor b1 (shift_left b2 16))

let bits64 s =
let b1 = Int64.(shift_right_logical (of_int (bits s)) 9) in (* 21 bits *)
let b2 = Int64.(shift_right_logical (of_int (bits s)) 9) in (* 21 bits *)
let b3 = Int64.(shift_right_logical (of_int (bits s)) 8) in (* 22 bits *)
Int64.(logor b1 (logor (shift_left b2 21) (shift_left b3 42)))

let nativebits =
if Nativeint.size = 32
then fun s -> Nativeint.of_int32 (bits32 s)
else fun s -> Int64.to_nativeint (bits64 s)

end

(* This is the state you get with [init 27182818] and then applying
Expand Down Expand Up @@ -204,6 +220,9 @@ let nativeint bound = State.nativeint default bound
let int64 bound = State.int64 default bound
let float scale = State.float default scale
let bool () = State.bool default
let bits32 () = State.bits32 default
let bits64 () = State.bits64 default
let nativebits () = State.nativebits default

let full_init seed = State.full_init default seed
let init seed = State.full_init default [| seed |]
Expand Down
18 changes: 18 additions & 0 deletions stdlib/random.mli
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,21 @@ val float : float -> float
val bool : unit -> bool
(** [Random.bool ()] returns [true] or [false] with probability 0.5 each. *)

val bits32 : unit -> Int32.t
(** [Random.bits32 ()] returns 32 random bits as an integer between
{!Int32.min_int} and {!Int32.max_int}.
@since 4.14.0 *)

val bits64 : unit -> Int64.t
(** [Random.bits64 ()] returns 64 random bits as an integer between
{!Int64.min_int} and {!Int64.max_int}.
@since 4.14.0 *)

val nativebits : unit -> Nativeint.t
(** [Random.nativebits ()] returns 32 or 64 random bits (depending on
the bit width of the platform) as an integer between
{!Nativeint.min_int} and {!Nativeint.max_int}.
@since 4.14.0 *)

(** {1 Advanced functions} *)

Expand Down Expand Up @@ -106,6 +121,9 @@ module State : sig
val int64 : t -> Int64.t -> Int64.t
val float : t -> float -> float
val bool : t -> bool
val bits32 : t -> Int32.t
val bits64 : t -> Int64.t
val nativebits : t -> Nativeint.t
(** These functions are the same as the basic functions, except that they
use (and update) the given PRNG state instead of the default one.
*)
Expand Down
10 changes: 10 additions & 0 deletions testsuite/tests/lib-random/chi2.ml
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,23 @@ let _ =
(fun () -> int_of_float (Random.float 1.0 *. 256.0));
test "Random.float 1.0 (next 8 bits)"
(fun () -> int_of_float (Random.float 1.0 *. 65536.0));
test "Random.bits32 (bits 0-7)"
(fun () -> Int32.to_int (Random.bits32()));
test "Random.bits32 (bits 20-27)"
(fun () -> Int32.(to_int (shift_right (Random.bits32()) 20)));
test "Random.int32 2^30 (bits 0-7)"
(fun () -> Int32.to_int (Random.int32 0x40000000l));
test "Random.int32 2^30 (bits 20-27)"
(fun () -> Int32.(to_int (shift_right (Random.int32 0x40000000l) 20)));
test "Random.int32 (256 * p) / p"
(let p = 7048673l in
fun () -> Int32.(to_int (div (Random.int32 (mul 256l p)) p)));
test "Random.bits64 (bits 0-7)"
(fun () -> Int64.to_int (Random.bits64()));
test "Random.bits64 (bits 30-37)"
(fun () -> Int64.(to_int (shift_right (Random.bits64()) 30)));
test "Random.bits64 (bits 52-59)"
(fun () -> Int64.(to_int (shift_right (Random.bits64()) 52)));
test "Random.int64 2^60 (bits 0-7)"
(fun () -> Int64.to_int (Random.int64 0x1000000000000000L));
test "Random.int64 2^60 (bits 30-37)"
Expand Down

0 comments on commit 46df597

Please sign in to comment.