aboutsummaryrefslogtreecommitdiff
path: root/core/math
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2024-07-11 17:01:34 +0100
committergingerBill <bill@gingerbill.org>2024-07-11 17:01:34 +0100
commit59d87d1f05b4339bf692bc2ef262a7259213020b (patch)
treeba11e1064583287b95ddc833722122a3982e9435 /core/math
parent6b3453cc64f59e290da49f5284c8582aa39f7e36 (diff)
Add `gen := context.random_generator` parameters to `rand` calls
Diffstat (limited to 'core/math')
-rw-r--r--core/math/rand/distributions.odin120
-rw-r--r--core/math/rand/exp.odin8
-rw-r--r--core/math/rand/normal.odin10
-rw-r--r--core/math/rand/rand.odin90
4 files changed, 114 insertions, 114 deletions
diff --git a/core/math/rand/distributions.odin b/core/math/rand/distributions.odin
index a10ea3238..755e6f86f 100644
--- a/core/math/rand/distributions.odin
+++ b/core/math/rand/distributions.odin
@@ -8,12 +8,12 @@ float32_uniform :: float32_range
// Triangular Distribution
// See: http://wikipedia.org/wiki/Triangular_distribution
@(require_results)
-float64_triangular :: proc(lo, hi: f64, mode: Maybe(f64)) -> f64 {
+float64_triangular :: proc(lo, hi: f64, mode: Maybe(f64), gen := context.random_generator) -> f64 {
if hi-lo == 0 {
return lo
}
lo, hi := lo, hi
- u := float64()
+ u := float64(gen)
c := f64(0.5) if mode == nil else clamp((mode.?-lo) / (hi-lo), 0, 1)
if u > c {
u = 1-u
@@ -26,12 +26,12 @@ float64_triangular :: proc(lo, hi: f64, mode: Maybe(f64)) -> f64 {
// Triangular Distribution
// See: http://wikipedia.org/wiki/Triangular_distribution
@(require_results)
-float32_triangular :: proc(lo, hi: f32, mode: Maybe(f32)) -> f32 {
+float32_triangular :: proc(lo, hi: f32, mode: Maybe(f32), gen := context.random_generator) -> f32 {
if hi-lo == 0 {
return lo
}
lo, hi := lo, hi
- u := float32()
+ u := float32(gen)
c := f32(0.5) if mode == nil else clamp((mode.?-lo) / (hi-lo), 0, 1)
if u > c {
u = 1-u
@@ -44,25 +44,25 @@ float32_triangular :: proc(lo, hi: f32, mode: Maybe(f32)) -> f32 {
// Normal/Gaussian Distribution
@(require_results)
-float64_normal :: proc(mean, stddev: f64) -> f64 {
- return norm_float64() * stddev + mean
+float64_normal :: proc(mean, stddev: f64, gen := context.random_generator) -> f64 {
+ return norm_float64(gen) * stddev + mean
}
// Normal/Gaussian Distribution
@(require_results)
-float32_normal :: proc(mean, stddev: f32) -> f32 {
- return f32(float64_normal(f64(mean), f64(stddev)))
+float32_normal :: proc(mean, stddev: f32, gen := context.random_generator) -> f32 {
+ return f32(float64_normal(f64(mean), f64(stddev), gen))
}
// Log Normal Distribution
@(require_results)
-float64_log_normal :: proc(mean, stddev: f64) -> f64 {
- return math.exp(float64_normal(mean, stddev))
+float64_log_normal :: proc(mean, stddev: f64, gen := context.random_generator) -> f64 {
+ return math.exp(float64_normal(mean, stddev, gen))
}
// Log Normal Distribution
@(require_results)
-float32_log_normal :: proc(mean, stddev: f32) -> f32 {
- return f32(float64_log_normal(f64(mean), f64(stddev)))
+float32_log_normal :: proc(mean, stddev: f32, gen := context.random_generator) -> f32 {
+ return f32(float64_log_normal(f64(mean), f64(stddev), gen))
}
@@ -72,8 +72,8 @@ float32_log_normal :: proc(mean, stddev: f32) -> f32 {
// 0 to positive infinity if lambda > 0
// negative infinity to 0 if lambda <= 0
@(require_results)
-float64_exponential :: proc(lambda: f64) -> f64 {
- return - math.ln(1 - float64()) / lambda
+float64_exponential :: proc(lambda: f64, gen := context.random_generator) -> f64 {
+ return - math.ln(1 - float64(gen)) / lambda
}
// Exponential Distribution
// `lambda` is 1.0/(desired mean). It should be non-zero.
@@ -81,8 +81,8 @@ float64_exponential :: proc(lambda: f64) -> f64 {
// 0 to positive infinity if lambda > 0
// negative infinity to 0 if lambda <= 0
@(require_results)
-float32_exponential :: proc(lambda: f32) -> f32 {
- return f32(float64_exponential(f64(lambda)))
+float32_exponential :: proc(lambda: f32, gen := context.random_generator) -> f32 {
+ return f32(float64_exponential(f64(lambda), gen))
}
@@ -96,7 +96,7 @@ float32_exponential :: proc(lambda: f32) -> f32 {
//
// mean is alpha*beta, variance is math.pow(alpha*beta, 2)
@(require_results)
-float64_gamma :: proc(alpha, beta: f64) -> f64 {
+float64_gamma :: proc(alpha, beta: f64, gen := context.random_generator) -> f64 {
if alpha <= 0 || beta <= 0 {
panic(#procedure + ": alpha and beta must be > 0.0")
}
@@ -112,11 +112,11 @@ float64_gamma :: proc(alpha, beta: f64) -> f64 {
bbb := alpha - LOG4
ccc := alpha + ainv
for {
- u1 := float64()
+ u1 := float64(gen)
if !(1e-7 < u1 && u1 < 0.9999999) {
continue
}
- u2 := 1 - float64()
+ u2 := 1 - float64(gen)
v := math.ln(u1 / (1 - u1)) / ainv
x := alpha * math.exp(v)
z := u1 * u1 * u2
@@ -127,12 +127,12 @@ float64_gamma :: proc(alpha, beta: f64) -> f64 {
}
case alpha == 1:
// float64_exponential(1/beta)
- return -math.ln(1 - float64()) * beta
+ return -math.ln(1 - float64(gen)) * beta
case:
// ALGORITHM GS of Statistical Computing - Kennedy & Gentle
x: f64
for {
- u := float64()
+ u := float64(gen)
b := (math.e + alpha) / math.e
p := b * u
if p <= 1 {
@@ -140,7 +140,7 @@ float64_gamma :: proc(alpha, beta: f64) -> f64 {
} else {
x = -math.ln((b - p) / alpha)
}
- u1 := float64()
+ u1 := float64(gen)
if p > 1 {
if u1 <= math.pow(x, alpha-1) {
break
@@ -162,8 +162,8 @@ float64_gamma :: proc(alpha, beta: f64) -> f64 {
//
// mean is alpha*beta, variance is math.pow(alpha*beta, 2)
@(require_results)
-float32_gamma :: proc(alpha, beta: f32) -> f32 {
- return f32(float64_gamma(f64(alpha), f64(beta)))
+float32_gamma :: proc(alpha, beta: f32, gen := context.random_generator) -> f32 {
+ return f32(float64_gamma(f64(alpha), f64(beta), gen))
}
@@ -173,14 +173,14 @@ float32_gamma :: proc(alpha, beta: f32) -> f32 {
//
// Return values range between 0 and 1
@(require_results)
-float64_beta :: proc(alpha, beta: f64) -> f64 {
+float64_beta :: proc(alpha, beta: f64, gen := context.random_generator) -> f64 {
if alpha <= 0 || beta <= 0 {
panic(#procedure + ": alpha and beta must be > 0.0")
}
// Knuth Vol 2 Ed 3 pg 134 "the beta distribution"
- y := float64_gamma(alpha, 1.0)
+ y := float64_gamma(alpha, 1.0, gen)
if y != 0 {
- return y / (y + float64_gamma(beta, 1.0))
+ return y / (y + float64_gamma(beta, 1.0, gen))
}
return 0
}
@@ -190,35 +190,35 @@ float64_beta :: proc(alpha, beta: f64) -> f64 {
//
// Return values range between 0 and 1
@(require_results)
-float32_beta :: proc(alpha, beta: f32) -> f32 {
- return f32(float64_beta(f64(alpha), f64(beta)))
+float32_beta :: proc(alpha, beta: f32, gen := context.random_generator) -> f32 {
+ return f32(float64_beta(f64(alpha), f64(beta), gen))
}
// Pareto distribution, `alpha` is the shape parameter.
// https://wikipedia.org/wiki/Pareto_distribution
@(require_results)
-float64_pareto :: proc(alpha: f64) -> f64 {
- return math.pow(1 - float64(), -1.0 / alpha)
+float64_pareto :: proc(alpha: f64, gen := context.random_generator) -> f64 {
+ return math.pow(1 - float64(gen), -1.0 / alpha)
}
// Pareto distribution, `alpha` is the shape parameter.
// https://wikipedia.org/wiki/Pareto_distribution
@(require_results)
-float32_pareto :: proc(alpha, beta: f32) -> f32 {
- return f32(float64_pareto(f64(alpha)))
+float32_pareto :: proc(alpha, beta: f32, gen := context.random_generator) -> f32 {
+ return f32(float64_pareto(f64(alpha), gen))
}
// Weibull distribution, `alpha` is the scale parameter, `beta` is the shape parameter.
@(require_results)
-float64_weibull :: proc(alpha, beta: f64) -> f64 {
- u := 1 - float64()
+float64_weibull :: proc(alpha, beta: f64, gen := context.random_generator) -> f64 {
+ u := 1 - float64(gen)
return alpha * math.pow(-math.ln(u), 1.0/beta)
}
// Weibull distribution, `alpha` is the scale parameter, `beta` is the shape parameter.
@(require_results)
-float32_weibull :: proc(alpha, beta: f32) -> f32 {
- return f32(float64_weibull(f64(alpha), f64(beta)))
+float32_weibull :: proc(alpha, beta: f32, gen := context.random_generator) -> f32 {
+ return f32(float64_weibull(f64(alpha), f64(beta), gen))
}
@@ -227,23 +227,23 @@ float32_weibull :: proc(alpha, beta: f32) -> f32 {
// `kappa` is the concentration parameter which must be >= 0
// When `kappa` is zero, the Distribution is a uniform Distribution over the range 0 to 2pi
@(require_results)
-float64_von_mises :: proc(mean_angle, kappa: f64) -> f64 {
+float64_von_mises :: proc(mean_angle, kappa: f64, gen := context.random_generator) -> f64 {
// Fisher, N.I., "Statistical Analysis of Circular Data", Cambridge University Press, 1993.
mu := mean_angle
if kappa <= 1e-6 {
- return math.TAU * float64()
+ return math.TAU * float64(gen)
}
s := 0.5 / kappa
t := s + math.sqrt(1 + s*s)
z: f64
for {
- u1 := float64()
+ u1 := float64(gen)
z = math.cos(math.TAU * 0.5 * u1)
d := z / (t + z)
- u2 := float64()
+ u2 := float64(gen)
if u2 < 1 - d*d || u2 <= (1-d)*math.exp(d) {
break
}
@@ -251,7 +251,7 @@ float64_von_mises :: proc(mean_angle, kappa: f64) -> f64 {
q := 1.0 / t
f := (q + z) / (1 + q*z)
- u3 := float64()
+ u3 := float64(gen)
if u3 > 0.5 {
return math.mod(mu + math.acos(f), math.TAU)
} else {
@@ -263,57 +263,57 @@ float64_von_mises :: proc(mean_angle, kappa: f64) -> f64 {
// `kappa` is the concentration parameter which must be >= 0
// When `kappa` is zero, the Distribution is a uniform Distribution over the range 0 to 2pi
@(require_results)
-float32_von_mises :: proc(mean_angle, kappa: f32) -> f32 {
- return f32(float64_von_mises(f64(mean_angle), f64(kappa)))
+float32_von_mises :: proc(mean_angle, kappa: f32, gen := context.random_generator) -> f32 {
+ return f32(float64_von_mises(f64(mean_angle), f64(kappa), gen))
}
// Cauchy-Lorentz Distribution
// `x_0` is the location, `gamma` is the scale where `gamma` > 0
@(require_results)
-float64_cauchy_lorentz :: proc(x_0, gamma: f64) -> f64 {
+float64_cauchy_lorentz :: proc(x_0, gamma: f64, gen := context.random_generator) -> f64 {
assert(gamma > 0)
// Calculated from the inverse CDF
- return math.tan(math.PI * (float64() - 0.5))*gamma + x_0
+ return math.tan(math.PI * (float64(gen) - 0.5))*gamma + x_0
}
// Cauchy-Lorentz Distribution
// `x_0` is the location, `gamma` is the scale where `gamma` > 0
@(require_results)
-float32_cauchy_lorentz :: proc(x_0, gamma: f32) -> f32 {
- return f32(float64_cauchy_lorentz(f64(x_0), f64(gamma)))
+float32_cauchy_lorentz :: proc(x_0, gamma: f32, gen := context.random_generator) -> f32 {
+ return f32(float64_cauchy_lorentz(f64(x_0), f64(gamma), gen))
}
// Log Cauchy-Lorentz Distribution
// `x_0` is the location, `gamma` is the scale where `gamma` > 0
@(require_results)
-float64_log_cauchy_lorentz :: proc(x_0, gamma: f64) -> f64 {
+float64_log_cauchy_lorentz :: proc(x_0, gamma: f64, gen := context.random_generator) -> f64 {
assert(gamma > 0)
- return math.exp(math.tan(math.PI * (float64() - 0.5))*gamma + x_0)
+ return math.exp(math.tan(math.PI * (float64(gen) - 0.5))*gamma + x_0)
}
// Log Cauchy-Lorentz Distribution
// `x_0` is the location, `gamma` is the scale where `gamma` > 0
@(require_results)
-float32_log_cauchy_lorentz :: proc(x_0, gamma: f32) -> f32 {
- return f32(float64_log_cauchy_lorentz(f64(x_0), f64(gamma)))
+float32_log_cauchy_lorentz :: proc(x_0, gamma: f32, gen := context.random_generator) -> f32 {
+ return f32(float64_log_cauchy_lorentz(f64(x_0), f64(gamma), gen))
}
// Laplace Distribution
// `b` is the scale where `b` > 0
@(require_results)
-float64_laplace :: proc(mean, b: f64) -> f64 {
+float64_laplace :: proc(mean, b: f64, gen := context.random_generator) -> f64 {
assert(b > 0)
- p := float64()-0.5
+ p := float64(gen)-0.5
return -math.sign(p)*math.ln(1 - 2*abs(p))*b + mean
}
// Laplace Distribution
// `b` is the scale where `b` > 0
@(require_results)
-float32_laplace :: proc(mean, b: f32) -> f32 {
- return f32(float64_laplace(f64(mean), f64(b)))
+float32_laplace :: proc(mean, b: f32, gen := context.random_generator) -> f32 {
+ return f32(float64_laplace(f64(mean), f64(b), gen))
}
@@ -321,18 +321,18 @@ float32_laplace :: proc(mean, b: f32) -> f32 {
// `eta` is the shape, `b` is the scale
// Both `eta` and `b` must be > 0
@(require_results)
-float64_gompertz :: proc(eta, b: f64) -> f64 {
+float64_gompertz :: proc(eta, b: f64, gen := context.random_generator) -> f64 {
if eta <= 0 || b <= 0 {
panic(#procedure + ": eta and b must be > 0.0")
}
- p := float64()
+ p := float64(gen)
return math.ln(1 - math.ln(1 - p)/eta)/b
}
// Gompertz Distribution
// `eta` is the shape, `b` is the scale
// Both `eta` and `b` must be > 0
@(require_results)
-float32_gompertz :: proc(eta, b: f32) -> f32 {
- return f32(float64_gompertz(f64(eta), f64(b)))
+float32_gompertz :: proc(eta, b: f32, gen := context.random_generator) -> f32 {
+ return f32(float64_gompertz(f64(eta), f64(b), gen))
}
diff --git a/core/math/rand/exp.odin b/core/math/rand/exp.odin
index f30f11f50..4ceb750da 100644
--- a/core/math/rand/exp.odin
+++ b/core/math/rand/exp.odin
@@ -16,7 +16,7 @@ import "core:math"
// https://www.jstatsoft.org/article/view/v005i08 [web page]
//
@(require_results)
-exp_float64 :: proc() -> f64 {
+exp_float64 :: proc(gen := context.random_generator) -> f64 {
re :: 7.69711747013104972
@(static, rodata)
@@ -199,16 +199,16 @@ exp_float64 :: proc() -> f64 {
}
for {
- j := uint32()
+ j := uint32(gen)
i := j & 0xFF
x := f64(j) * f64(we[i])
if j < ke[i] {
return x
}
if i == 0 {
- return re - math.ln(float64())
+ return re - math.ln(float64(gen))
}
- if fe[i]+f32(float64())*(fe[i-1]-fe[i]) < f32(math.exp(-x)) {
+ if fe[i]+f32(float64(gen))*(fe[i-1]-fe[i]) < f32(math.exp(-x)) {
return x
}
}
diff --git a/core/math/rand/normal.odin b/core/math/rand/normal.odin
index eefa013df..bc566344c 100644
--- a/core/math/rand/normal.odin
+++ b/core/math/rand/normal.odin
@@ -18,7 +18,7 @@ import "core:math"
// https://www.jstatsoft.org/article/view/v005i08 [web page]
//
@(require_results)
-norm_float64 :: proc() -> f64 {
+norm_float64 :: proc(gen := context.random_generator) -> f64 {
rn :: 3.442619855899
@(static, rodata)
@@ -116,7 +116,7 @@ norm_float64 :: proc() -> f64 {
}
for {
- j := i32(uint32())
+ j := i32(uint32(gen))
i := j & 0x7f
x := f64(j) * f64(wn[i])
if u32(abs(j)) < kn[i] {
@@ -126,15 +126,15 @@ norm_float64 :: proc() -> f64 {
if i == 0 {
for {
- x = -math.ln(float64()) * (1.0/ rn)
- y := -math.ln(float64())
+ x = -math.ln(float64(gen)) * (1.0/ rn)
+ y := -math.ln(float64(gen))
if y+y >= x*x {
break
}
}
return j > 0 ? rn + x : -rn - x
}
- if fn[i]+f32(float64())*(fn[i-1]-fn[i]) < f32(math.exp(-0.5*x*x)) {
+ if fn[i]+f32(float64(gen))*(fn[i-1]-fn[i]) < f32(math.exp(-0.5*x*x)) {
return x
}
}
diff --git a/core/math/rand/rand.odin b/core/math/rand/rand.odin
index 2b7b55096..10d254427 100644
--- a/core/math/rand/rand.odin
+++ b/core/math/rand/rand.odin
@@ -62,15 +62,15 @@ Possible Output:
10
*/
-reset :: proc(seed: u64) {
- runtime.random_generator_reset_u64(context.random_generator, seed)
+reset :: proc(seed: u64, gen := context.random_generator) {
+ runtime.random_generator_reset_u64(gen, seed)
}
@(private)
-_random_u64 :: proc() -> (res: u64) {
- ok := runtime.random_generator_read_ptr(context.random_generator, &res, size_of(res))
- assert(ok, "uninitialized context.random_generator")
+_random_u64 :: proc(gen := context.random_generator) -> (res: u64) {
+ ok := runtime.random_generator_read_ptr(gen, &res, size_of(res))
+ assert(ok, "uninitialized gen/context.random_generator")
return
}
@@ -95,7 +95,7 @@ Possible Output:
*/
@(require_results)
-uint32 :: proc() -> (val: u32) { return u32(_random_u64()) }
+uint32 :: proc(gen := context.random_generator) -> (val: u32) { return u32(_random_u64(gen)) }
/*
Generates a random 64 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
@@ -118,7 +118,7 @@ Possible Output:
*/
@(require_results)
-uint64 :: proc() -> (val: u64) { return _random_u64() }
+uint64 :: proc(gen := context.random_generator) -> (val: u64) { return _random_u64(gen) }
/*
Generates a random 128 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
@@ -141,9 +141,9 @@ Possible Output:
*/
@(require_results)
-uint128 :: proc() -> (val: u128) {
- a := u128(_random_u64())
- b := u128(_random_u64())
+uint128 :: proc(gen := context.random_generator) -> (val: u128) {
+ a := u128(_random_u64(gen))
+ b := u128(_random_u64(gen))
return (a<<64) | b
}
@@ -168,7 +168,7 @@ Possible Output:
389
*/
-@(require_results) int31 :: proc() -> (val: i32) { return i32(uint32() << 1 >> 1) }
+@(require_results) int31 :: proc(gen := context.random_generator) -> (val: i32) { return i32(uint32(gen) << 1 >> 1) }
/*
Generates a random 63 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
@@ -191,7 +191,7 @@ Possible Output:
389
*/
-@(require_results) int63 :: proc() -> (val: i64) { return i64(uint64() << 1 >> 1) }
+@(require_results) int63 :: proc(gen := context.random_generator) -> (val: i64) { return i64(uint64(gen) << 1 >> 1) }
/*
Generates a random 127 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
@@ -214,7 +214,7 @@ Possible Output:
389
*/
-@(require_results) int127 :: proc() -> (val: i128) { return i128(uint128() << 1 >> 1) }
+@(require_results) int127 :: proc(gen := context.random_generator) -> (val: i128) { return i128(uint128(gen) << 1 >> 1) }
/*
Generates a random 31 bit value in the range `[0, n)` using the provided random number generator. If no generator is provided the global random number generator will be used.
@@ -242,17 +242,17 @@ Possible Output:
*/
@(require_results)
-int31_max :: proc(n: i32) -> (val: i32) {
+int31_max :: proc(n: i32, gen := context.random_generator) -> (val: i32) {
if n <= 0 {
panic("Invalid argument to int31_max")
}
if n&(n-1) == 0 {
- return int31() & (n-1)
+ return int31(gen) & (n-1)
}
max := i32((1<<31) - 1 - (1<<31)%u32(n))
- v := int31()
+ v := int31(gen)
for v > max {
- v = int31()
+ v = int31(gen)
}
return v % n
}
@@ -283,17 +283,17 @@ Possible Output:
*/
@(require_results)
-int63_max :: proc(n: i64) -> (val: i64) {
+int63_max :: proc(n: i64, gen := context.random_generator) -> (val: i64) {
if n <= 0 {
panic("Invalid argument to int63_max")
}
if n&(n-1) == 0 {
- return int63() & (n-1)
+ return int63(gen) & (n-1)
}
max := i64((1<<63) - 1 - (1<<63)%u64(n))
- v := int63()
+ v := int63(gen)
for v > max {
- v = int63()
+ v = int63(gen)
}
return v % n
}
@@ -324,17 +324,17 @@ Possible Output:
*/
@(require_results)
-int127_max :: proc(n: i128) -> (val: i128) {
+int127_max :: proc(n: i128, gen := context.random_generator) -> (val: i128) {
if n <= 0 {
panic("Invalid argument to int127_max")
}
if n&(n-1) == 0 {
- return int127() & (n-1)
+ return int127(gen) & (n-1)
}
max := i128((1<<127) - 1 - (1<<127)%u128(n))
- v := int127()
+ v := int127(gen)
for v > max {
- v = int127()
+ v = int127(gen)
}
return v % n
}
@@ -365,14 +365,14 @@ Possible Output:
*/
@(require_results)
-int_max :: proc(n: int) -> (val: int) {
+int_max :: proc(n: int, gen := context.random_generator) -> (val: int) {
if n <= 0 {
panic("Invalid argument to int_max")
}
when size_of(int) == 4 {
- return int(int31_max(i32(n)))
+ return int(int31_max(i32(n), gen))
} else {
- return int(int63_max(i64(n)))
+ return int(int63_max(i64(n), gen))
}
}
@@ -396,7 +396,7 @@ Possible Output:
0.511
*/
-@(require_results) float64 :: proc() -> (val: f64) { return f64(int63_max(1<<53)) / (1 << 53) }
+@(require_results) float64 :: proc(gen := context.random_generator) -> (val: f64) { return f64(int63_max(1<<53, gen)) / (1 << 53) }
/*
Generates a random single floating point value in the range `[0, 1)` using the provided random number generator. If no generator is provided the global random number generator will be used.
@@ -418,7 +418,7 @@ Possible Output:
0.511
*/
-@(require_results) float32 :: proc() -> (val: f32) { return f32(int31_max(1<<24)) / (1 << 24) }
+@(require_results) float32 :: proc(gen := context.random_generator) -> (val: f32) { return f32(int31_max(1<<24, gen)) / (1 << 24) }
/*
Generates a random double floating point value in the range `[low, high)` using the provided random number generator. If no generator is provided the global random number generator will be used.
@@ -446,9 +446,9 @@ Possible Output:
673.130
*/
-@(require_results) float64_range :: proc(low, high: f64) -> (val: f64) {
+@(require_results) float64_range :: proc(low, high: f64, gen := context.random_generator) -> (val: f64) {
assert(low <= high, "low must be lower than or equal to high")
- val = (high-low)*float64() + low
+ val = (high-low)*float64(gen) + low
if val >= high {
val = max(low, high * (1 - math.F64_EPSILON))
}
@@ -481,9 +481,9 @@ Possible Output:
673.130
*/
-@(require_results) float32_range :: proc(low, high: f32) -> (val: f32) {
+@(require_results) float32_range :: proc(low, high: f32, gen := context.random_generator) -> (val: f32) {
assert(low <= high, "low must be lower than or equal to high")
- val = (high-low)*float32() + low
+ val = (high-low)*float32(gen) + low
if val >= high {
val = max(low, high * (1 - math.F32_EPSILON))
}
@@ -518,12 +518,12 @@ Possible Output:
*/
@(require_results)
-read :: proc(p: []byte) -> (n: int) {
+read :: proc(p: []byte, gen := context.random_generator) -> (n: int) {
pos := i8(0)
val := i64(0)
for n = 0; n < len(p); n += 1 {
if pos == 0 {
- val = int63()
+ val = int63(gen)
pos = 7
}
p[n] = byte(val)
@@ -566,10 +566,10 @@ Possible Output:
*/
@(require_results)
-perm :: proc(n: int, allocator := context.allocator) -> (res: []int, err: mem.Allocator_Error) #optional_allocator_error {
+perm :: proc(n: int, allocator := context.allocator, gen := context.random_generator) -> (res: []int, err: mem.Allocator_Error) #optional_allocator_error {
m := make([]int, n, allocator) or_return
for i := 0; i < n; i += 1 {
- j := int_max(i+1)
+ j := int_max(i+1, gen)
m[i] = m[j]
m[j] = i
}
@@ -599,14 +599,14 @@ Possible Output:
[2, 4, 3, 1]
*/
-shuffle :: proc(array: $T/[]$E) {
+shuffle :: proc(array: $T/[]$E, gen := context.random_generator) {
n := i64(len(array))
if n < 2 {
return
}
for i := i64(n - 1); i > 0; i -= 1 {
- j := int63_max(i + 1)
+ j := int63_max(i + 1, gen)
array[i], array[j] = array[j], array[i]
}
}
@@ -641,17 +641,17 @@ Possible Output:
*/
@(require_results)
-choice :: proc(array: $T/[]$E) -> (res: E) {
+choice :: proc(array: $T/[]$E, gen := context.random_generator) -> (res: E) {
n := i64(len(array))
if n < 1 {
return E{}
}
- return array[int63_max(n)]
+ return array[int63_max(n, gen)]
}
@(require_results)
-choice_enum :: proc($T: typeid) -> T
+choice_enum :: proc($T: typeid, gen := context.random_generator) -> T
where
intrinsics.type_is_enum(T),
size_of(T) <= 8,
@@ -659,11 +659,11 @@ choice_enum :: proc($T: typeid) -> T
{
when intrinsics.type_is_unsigned(intrinsics.type_core_type(T)) &&
u64(max(T)) > u64(max(i64)) {
- i := uint64() % u64(len(T))
+ i := uint64(gen) % u64(len(T))
i += u64(min(T))
return T(i)
} else {
- i := int63_max(i64(len(T)))
+ i := int63_max(i64(len(T)), gen)
i += i64(min(T))
return T(i)
}