use "random"
class ref Randomness
"""
Source of randomness, providing methods for generatic uniformly distributed
values from a given closed interval: [min, max]
in order for the user to be able to generate every possible value for a given
primitive numeric type.
All primitive number method create numbers in range [min, max)
"""
let _random: Random
new ref create(seed1: U64 = 42, seed2: U64 = 0) =>
_random = Rand(seed1, seed2)
fun ref u8(min: U8 = U8.min_value(), max: U8 = U8.max_value()): U8 =>
"""
Generate a U8 in closed interval [min, max]
(default: [min_value, max_value]).
Behavior is undefined if `min` > `max`.
"""
if (min == U8.min_value()) and (max == U8.max_value()) then
_random.u8()
else
min + _random.int((max - min).u64() + 1).u8()
end
fun ref u16(min: U16 = U16.min_value(), max: U16 = U16.max_value()): U16 =>
"""
Generate a U16 in closed interval [min, max]
(default: [min_value, max_value]).
Behavior is undefined if `min` > `max`.
"""
if (min == U16.min_value()) and (max == U16.max_value()) then
_random.u16()
else
min + _random.int((max - min).u64() + 1).u16()
end
fun ref u32(min: U32 = U32.min_value(), max: U32 = U32.max_value()): U32 =>
"""
Generate a U32 in closed interval [min, max]
(default: [min_value, max_value]).
Behavior is undefined if `min` > `max`.
"""
if (min == U32.min_value()) and (max == U32.max_value()) then
_random.u32()
else
min + _random.int((max - min).u64() + 1).u32()
end
fun ref u64(min: U64 = U64.min_value(), max: U64 = U64.max_value()): U64 =>
"""
Generate a U64 in closed interval [min, max]
(default: [min_value, max_value]).
Behavior is undefined if `min` > `max`.
"""
if (min == U64.min_value()) and (max == U64.max_value()) then
_random.u64()
elseif min > U32.max_value().u64() then
(u32((min >> 32).u32(), (max >> 32).u32()).u64() << 32) or _random.u32().u64()
elseif max > U32.max_value().u64() then
let high = (u32((min >> 32).u32(), (max >> 32).u32()).u64() << 32).u64()
let low =
if high > 0 then
_random.u32().u64()
else
u32(min.u32(), U32.max_value()).u64()
end
high or low
else
// range within U32 range
u32(min.u32(), max.u32()).u64()
end
fun ref u128(
min: U128 = U128.min_value(),
max: U128 = U128.max_value())
: U128
=>
"""
Generate a U128 in closed interval [min, max]
(default: [min_value, max_value]).
Behavior is undefined if `min` > `max`.
"""
if (min == U128.min_value()) and (max == U128.max_value()) then
_random.u128()
elseif min > U64.max_value().u128() then
// both above U64 range - chose random low 64 bits
(u64((min >> 64).u64(), (max >> 64).u64()).u128() << 64) or u64().u128()
elseif max > U64.max_value().u128() then
// min below U64 max value
let high = (u64((min >> 64).u64(), (max >> 64).u64()).u128() << 64)
let low =
if high > 0 then
// number will be bigger than U64 max anyway, so chose a random lower u64
u64().u128()
else
// number <= U64 max, so chose lower u64 while considering requested range min
u64(min.u64(), U64.max_value()).u128()
end
high or low
else
// range within u64 range
u64(min.u64(), max.u64()).u128()
end
fun ref ulong(
min: ULong = ULong.min_value(),
max: ULong = ULong.max_value())
: ULong
=>
"""
Generate a ULong in closed interval [min, max]
(default: [min_value, max_value]).
Behavior is undefined if `min` > `max`.
"""
u64(min.u64(), max.u64()).ulong()
fun ref usize(
min: USize = USize.min_value(),
max: USize = USize.max_value())
: USize
=>
"""
Generate a USize in closed interval [min, max]
(default: [min_value, max_value]).
Behavior is undefined if `min` > `max`.
"""
u64(min.u64(), max.u64()).usize()
fun ref i8(min: I8 = I8.min_value(), max: I8 = I8.max_value()): I8 =>
"""
Generate a I8 in closed interval [min, max]
(default: [min_value, max_value]).
Behavior is undefined if `min` > `max`.
"""
min + u8(0, (max - min).u8()).i8()
fun ref i16(min: I16 = I16.min_value(), max: I16 = I16.max_value()): I16 =>
"""
Generate a I16 in closed interval [min, max]
(default: [min_value, max_value]).
Behavior is undefined if `min` > `max`.
"""
min + u16(0, (max - min).u16()).i16()
fun ref i32(min: I32 = I32.min_value(), max: I32 = I32.max_value()): I32 =>
"""
Generate a I32 in closed interval [min, max]
(default: [min_value, max_value]).
Behavior is undefined if `min` > `max`.
"""
min + u32(0, (max - min).u32()).i32()
fun ref i64(min: I64 = I64.min_value(), max: I64 = I64.max_value()): I64 =>
"""
Generate a I64 in closed interval [min, max]
(default: [min_value, max_value]).
Behavior is undefined if `min` > `max`.
"""
min + u64(0, (max - min).u64()).i64()
fun ref i128(
min: I128 = I128.min_value(),
max: I128 = I128.max_value())
: I128
=>
"""
Generate a I128 in closed interval [min, max]
(default: [min_value, max_value]).
Behavior is undefined if `min` > `max`.
"""
min + u128(0, (max - min).u128()).i128()
fun ref ilong(
min: ILong = ILong.min_value(),
max: ILong = ILong.max_value())
: ILong
=>
"""
Generate a ILong in closed interval [min, max]
(default: [min_value, max_value]).
Behavior is undefined if `min` > `max`.
"""
min + ulong(0, (max - min).ulong()).ilong()
fun ref isize(
min: ISize = ISize.min_value(),
max: ISize = ISize.max_value())
: ISize
=>
"""
Generate a ISize in closed interval [min, max]
(default: [min_value, max_value]).
Behavior is undefined if `min` > `max`.
"""
min + usize(0, (max - min).usize()).isize()
fun ref f32(min: F32 = 0.0, max: F32 = 1.0): F32 =>
"""
Generate a F32 in closed interval [min, max]
(default: [0.0, 1.0]).
"""
(_random.real().f32() * (max-min)) + min
fun ref f64(min: F64 = 0.0, max: F64 = 1.0): F64 =>
"""
Generate a F64 in closed interval [min, max]
(default: [0.0, 1.0]).
"""
(_random.real() * (max-min)) + min
fun ref bool(): Bool =>
"""
Generate a random Bool value.
"""
(_random.next() % 2) == 0
fun ref shuffle[T](array: Array[T] ref) =>
_random.shuffle[T](array)