mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Update core:math/rand to use context.random_generator and remove rand.Rand
This commit is contained in:
@@ -29,6 +29,20 @@ random_generator_query_info :: proc(rg: Random_Generator) -> (info: Random_Gener
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
random_generator_reset_bytes :: proc(rg: Random_Generator, p: []byte) {
|
||||||
|
if rg.procedure != nil {
|
||||||
|
rg.procedure(rg.data, .Reset, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
random_generator_reset_u64 :: proc(rg: Random_Generator, p: u64) {
|
||||||
|
if rg.procedure != nil {
|
||||||
|
p := p
|
||||||
|
rg.procedure(rg.data, .Reset, ([^]byte)(&p)[:size_of(p)])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Default_Random_State :: struct {
|
Default_Random_State :: struct {
|
||||||
state: u64,
|
state: u64,
|
||||||
inc: u64,
|
inc: u64,
|
||||||
@@ -93,9 +107,9 @@ default_random_generator_proc :: proc(data: rawptr, mode: Random_Generator_Mode,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default_random_generator :: proc "contextless" () -> Random_Generator {
|
default_random_generator :: proc "contextless" (state: ^Default_Random_State = nil) -> Random_Generator {
|
||||||
return {
|
return {
|
||||||
procedure = default_random_generator_proc,
|
procedure = default_random_generator_proc,
|
||||||
data = nil,
|
data = state,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,12 +8,12 @@ float32_uniform :: float32_range
|
|||||||
// Triangular Distribution
|
// Triangular Distribution
|
||||||
// See: http://wikipedia.org/wiki/Triangular_distribution
|
// See: http://wikipedia.org/wiki/Triangular_distribution
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float64_triangular :: proc(lo, hi: f64, mode: Maybe(f64), r: ^Rand = nil) -> f64 {
|
float64_triangular :: proc(lo, hi: f64, mode: Maybe(f64)) -> f64 {
|
||||||
if hi-lo == 0 {
|
if hi-lo == 0 {
|
||||||
return lo
|
return lo
|
||||||
}
|
}
|
||||||
lo, hi := lo, hi
|
lo, hi := lo, hi
|
||||||
u := float64(r)
|
u := float64()
|
||||||
c := f64(0.5) if mode == nil else clamp((mode.?-lo) / (hi-lo), 0, 1)
|
c := f64(0.5) if mode == nil else clamp((mode.?-lo) / (hi-lo), 0, 1)
|
||||||
if u > c {
|
if u > c {
|
||||||
u = 1-u
|
u = 1-u
|
||||||
@@ -26,12 +26,12 @@ float64_triangular :: proc(lo, hi: f64, mode: Maybe(f64), r: ^Rand = nil) -> f64
|
|||||||
// Triangular Distribution
|
// Triangular Distribution
|
||||||
// See: http://wikipedia.org/wiki/Triangular_distribution
|
// See: http://wikipedia.org/wiki/Triangular_distribution
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float32_triangular :: proc(lo, hi: f32, mode: Maybe(f32), r: ^Rand = nil) -> f32 {
|
float32_triangular :: proc(lo, hi: f32, mode: Maybe(f32)) -> f32 {
|
||||||
if hi-lo == 0 {
|
if hi-lo == 0 {
|
||||||
return lo
|
return lo
|
||||||
}
|
}
|
||||||
lo, hi := lo, hi
|
lo, hi := lo, hi
|
||||||
u := float32(r)
|
u := float32()
|
||||||
c := f32(0.5) if mode == nil else clamp((mode.?-lo) / (hi-lo), 0, 1)
|
c := f32(0.5) if mode == nil else clamp((mode.?-lo) / (hi-lo), 0, 1)
|
||||||
if u > c {
|
if u > c {
|
||||||
u = 1-u
|
u = 1-u
|
||||||
@@ -44,25 +44,25 @@ float32_triangular :: proc(lo, hi: f32, mode: Maybe(f32), r: ^Rand = nil) -> f32
|
|||||||
|
|
||||||
// Normal/Gaussian Distribution
|
// Normal/Gaussian Distribution
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float64_normal :: proc(mean, stddev: f64, r: ^Rand = nil) -> f64 {
|
float64_normal :: proc(mean, stddev: f64) -> f64 {
|
||||||
return norm_float64(r) * stddev + mean
|
return norm_float64() * stddev + mean
|
||||||
}
|
}
|
||||||
// Normal/Gaussian Distribution
|
// Normal/Gaussian Distribution
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float32_normal :: proc(mean, stddev: f32, r: ^Rand = nil) -> f32 {
|
float32_normal :: proc(mean, stddev: f32) -> f32 {
|
||||||
return f32(float64_normal(f64(mean), f64(stddev), r))
|
return f32(float64_normal(f64(mean), f64(stddev)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Log Normal Distribution
|
// Log Normal Distribution
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float64_log_normal :: proc(mean, stddev: f64, r: ^Rand = nil) -> f64 {
|
float64_log_normal :: proc(mean, stddev: f64) -> f64 {
|
||||||
return math.exp(float64_normal(mean, stddev, r))
|
return math.exp(float64_normal(mean, stddev))
|
||||||
}
|
}
|
||||||
// Log Normal Distribution
|
// Log Normal Distribution
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float32_log_normal :: proc(mean, stddev: f32, r: ^Rand = nil) -> f32 {
|
float32_log_normal :: proc(mean, stddev: f32) -> f32 {
|
||||||
return f32(float64_log_normal(f64(mean), f64(stddev), r))
|
return f32(float64_log_normal(f64(mean), f64(stddev)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -72,8 +72,8 @@ float32_log_normal :: proc(mean, stddev: f32, r: ^Rand = nil) -> f32 {
|
|||||||
// 0 to positive infinity if lambda > 0
|
// 0 to positive infinity if lambda > 0
|
||||||
// negative infinity to 0 if lambda <= 0
|
// negative infinity to 0 if lambda <= 0
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float64_exponential :: proc(lambda: f64, r: ^Rand = nil) -> f64 {
|
float64_exponential :: proc(lambda: f64) -> f64 {
|
||||||
return - math.ln(1 - float64(r)) / lambda
|
return - math.ln(1 - float64()) / lambda
|
||||||
}
|
}
|
||||||
// Exponential Distribution
|
// Exponential Distribution
|
||||||
// `lambda` is 1.0/(desired mean). It should be non-zero.
|
// `lambda` is 1.0/(desired mean). It should be non-zero.
|
||||||
@@ -81,8 +81,8 @@ float64_exponential :: proc(lambda: f64, r: ^Rand = nil) -> f64 {
|
|||||||
// 0 to positive infinity if lambda > 0
|
// 0 to positive infinity if lambda > 0
|
||||||
// negative infinity to 0 if lambda <= 0
|
// negative infinity to 0 if lambda <= 0
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float32_exponential :: proc(lambda: f32, r: ^Rand = nil) -> f32 {
|
float32_exponential :: proc(lambda: f32) -> f32 {
|
||||||
return f32(float64_exponential(f64(lambda), r))
|
return f32(float64_exponential(f64(lambda)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ float32_exponential :: proc(lambda: f32, r: ^Rand = nil) -> f32 {
|
|||||||
//
|
//
|
||||||
// mean is alpha*beta, variance is math.pow(alpha*beta, 2)
|
// mean is alpha*beta, variance is math.pow(alpha*beta, 2)
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float64_gamma :: proc(alpha, beta: f64, r: ^Rand = nil) -> f64 {
|
float64_gamma :: proc(alpha, beta: f64) -> f64 {
|
||||||
if alpha <= 0 || beta <= 0 {
|
if alpha <= 0 || beta <= 0 {
|
||||||
panic(#procedure + ": alpha and beta must be > 0.0")
|
panic(#procedure + ": alpha and beta must be > 0.0")
|
||||||
}
|
}
|
||||||
@@ -112,11 +112,11 @@ float64_gamma :: proc(alpha, beta: f64, r: ^Rand = nil) -> f64 {
|
|||||||
bbb := alpha - LOG4
|
bbb := alpha - LOG4
|
||||||
ccc := alpha + ainv
|
ccc := alpha + ainv
|
||||||
for {
|
for {
|
||||||
u1 := float64(r)
|
u1 := float64()
|
||||||
if !(1e-7 < u1 && u1 < 0.9999999) {
|
if !(1e-7 < u1 && u1 < 0.9999999) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
u2 := 1 - float64(r)
|
u2 := 1 - float64()
|
||||||
v := math.ln(u1 / (1 - u1)) / ainv
|
v := math.ln(u1 / (1 - u1)) / ainv
|
||||||
x := alpha * math.exp(v)
|
x := alpha * math.exp(v)
|
||||||
z := u1 * u1 * u2
|
z := u1 * u1 * u2
|
||||||
@@ -127,12 +127,12 @@ float64_gamma :: proc(alpha, beta: f64, r: ^Rand = nil) -> f64 {
|
|||||||
}
|
}
|
||||||
case alpha == 1:
|
case alpha == 1:
|
||||||
// float64_exponential(1/beta)
|
// float64_exponential(1/beta)
|
||||||
return -math.ln(1 - float64(r)) * beta
|
return -math.ln(1 - float64()) * beta
|
||||||
case:
|
case:
|
||||||
// ALGORITHM GS of Statistical Computing - Kennedy & Gentle
|
// ALGORITHM GS of Statistical Computing - Kennedy & Gentle
|
||||||
x: f64
|
x: f64
|
||||||
for {
|
for {
|
||||||
u := float64(r)
|
u := float64()
|
||||||
b := (math.e + alpha) / math.e
|
b := (math.e + alpha) / math.e
|
||||||
p := b * u
|
p := b * u
|
||||||
if p <= 1 {
|
if p <= 1 {
|
||||||
@@ -140,7 +140,7 @@ float64_gamma :: proc(alpha, beta: f64, r: ^Rand = nil) -> f64 {
|
|||||||
} else {
|
} else {
|
||||||
x = -math.ln((b - p) / alpha)
|
x = -math.ln((b - p) / alpha)
|
||||||
}
|
}
|
||||||
u1 := float64(r)
|
u1 := float64()
|
||||||
if p > 1 {
|
if p > 1 {
|
||||||
if u1 <= math.pow(x, alpha-1) {
|
if u1 <= math.pow(x, alpha-1) {
|
||||||
break
|
break
|
||||||
@@ -162,8 +162,8 @@ float64_gamma :: proc(alpha, beta: f64, r: ^Rand = nil) -> f64 {
|
|||||||
//
|
//
|
||||||
// mean is alpha*beta, variance is math.pow(alpha*beta, 2)
|
// mean is alpha*beta, variance is math.pow(alpha*beta, 2)
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float32_gamma :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 {
|
float32_gamma :: proc(alpha, beta: f32) -> f32 {
|
||||||
return f32(float64_gamma(f64(alpha), f64(beta), r))
|
return f32(float64_gamma(f64(alpha), f64(beta)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -173,14 +173,14 @@ float32_gamma :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 {
|
|||||||
//
|
//
|
||||||
// Return values range between 0 and 1
|
// Return values range between 0 and 1
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float64_beta :: proc(alpha, beta: f64, r: ^Rand = nil) -> f64 {
|
float64_beta :: proc(alpha, beta: f64) -> f64 {
|
||||||
if alpha <= 0 || beta <= 0 {
|
if alpha <= 0 || beta <= 0 {
|
||||||
panic(#procedure + ": alpha and beta must be > 0.0")
|
panic(#procedure + ": alpha and beta must be > 0.0")
|
||||||
}
|
}
|
||||||
// Knuth Vol 2 Ed 3 pg 134 "the beta distribution"
|
// Knuth Vol 2 Ed 3 pg 134 "the beta distribution"
|
||||||
y := float64_gamma(alpha, 1.0, r)
|
y := float64_gamma(alpha, 1.0)
|
||||||
if y != 0 {
|
if y != 0 {
|
||||||
return y / (y + float64_gamma(beta, 1.0, r))
|
return y / (y + float64_gamma(beta, 1.0))
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@@ -190,35 +190,35 @@ float64_beta :: proc(alpha, beta: f64, r: ^Rand = nil) -> f64 {
|
|||||||
//
|
//
|
||||||
// Return values range between 0 and 1
|
// Return values range between 0 and 1
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float32_beta :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 {
|
float32_beta :: proc(alpha, beta: f32) -> f32 {
|
||||||
return f32(float64_beta(f64(alpha), f64(beta), r))
|
return f32(float64_beta(f64(alpha), f64(beta)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Pareto distribution, `alpha` is the shape parameter.
|
// Pareto distribution, `alpha` is the shape parameter.
|
||||||
// https://wikipedia.org/wiki/Pareto_distribution
|
// https://wikipedia.org/wiki/Pareto_distribution
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float64_pareto :: proc(alpha: f64, r: ^Rand = nil) -> f64 {
|
float64_pareto :: proc(alpha: f64) -> f64 {
|
||||||
return math.pow(1 - float64(r), -1.0 / alpha)
|
return math.pow(1 - float64(), -1.0 / alpha)
|
||||||
}
|
}
|
||||||
// Pareto distribution, `alpha` is the shape parameter.
|
// Pareto distribution, `alpha` is the shape parameter.
|
||||||
// https://wikipedia.org/wiki/Pareto_distribution
|
// https://wikipedia.org/wiki/Pareto_distribution
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float32_pareto :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 {
|
float32_pareto :: proc(alpha, beta: f32) -> f32 {
|
||||||
return f32(float64_pareto(f64(alpha), r))
|
return f32(float64_pareto(f64(alpha)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Weibull distribution, `alpha` is the scale parameter, `beta` is the shape parameter.
|
// Weibull distribution, `alpha` is the scale parameter, `beta` is the shape parameter.
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float64_weibull :: proc(alpha, beta: f64, r: ^Rand = nil) -> f64 {
|
float64_weibull :: proc(alpha, beta: f64) -> f64 {
|
||||||
u := 1 - float64(r)
|
u := 1 - float64()
|
||||||
return alpha * math.pow(-math.ln(u), 1.0/beta)
|
return alpha * math.pow(-math.ln(u), 1.0/beta)
|
||||||
}
|
}
|
||||||
// Weibull distribution, `alpha` is the scale parameter, `beta` is the shape parameter.
|
// Weibull distribution, `alpha` is the scale parameter, `beta` is the shape parameter.
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float32_weibull :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 {
|
float32_weibull :: proc(alpha, beta: f32) -> f32 {
|
||||||
return f32(float64_weibull(f64(alpha), f64(beta), r))
|
return f32(float64_weibull(f64(alpha), f64(beta)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -227,23 +227,23 @@ float32_weibull :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 {
|
|||||||
// `kappa` is the concentration parameter which must be >= 0
|
// `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
|
// When `kappa` is zero, the Distribution is a uniform Distribution over the range 0 to 2pi
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float64_von_mises :: proc(mean_angle, kappa: f64, r: ^Rand = nil) -> f64 {
|
float64_von_mises :: proc(mean_angle, kappa: f64) -> f64 {
|
||||||
// Fisher, N.I., "Statistical Analysis of Circular Data", Cambridge University Press, 1993.
|
// Fisher, N.I., "Statistical Analysis of Circular Data", Cambridge University Press, 1993.
|
||||||
|
|
||||||
mu := mean_angle
|
mu := mean_angle
|
||||||
if kappa <= 1e-6 {
|
if kappa <= 1e-6 {
|
||||||
return math.TAU * float64(r)
|
return math.TAU * float64()
|
||||||
}
|
}
|
||||||
|
|
||||||
s := 0.5 / kappa
|
s := 0.5 / kappa
|
||||||
t := s + math.sqrt(1 + s*s)
|
t := s + math.sqrt(1 + s*s)
|
||||||
z: f64
|
z: f64
|
||||||
for {
|
for {
|
||||||
u1 := float64(r)
|
u1 := float64()
|
||||||
z = math.cos(math.TAU * 0.5 * u1)
|
z = math.cos(math.TAU * 0.5 * u1)
|
||||||
|
|
||||||
d := z / (t + z)
|
d := z / (t + z)
|
||||||
u2 := float64(r)
|
u2 := float64()
|
||||||
if u2 < 1 - d*d || u2 <= (1-d)*math.exp(d) {
|
if u2 < 1 - d*d || u2 <= (1-d)*math.exp(d) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -251,7 +251,7 @@ float64_von_mises :: proc(mean_angle, kappa: f64, r: ^Rand = nil) -> f64 {
|
|||||||
|
|
||||||
q := 1.0 / t
|
q := 1.0 / t
|
||||||
f := (q + z) / (1 + q*z)
|
f := (q + z) / (1 + q*z)
|
||||||
u3 := float64(r)
|
u3 := float64()
|
||||||
if u3 > 0.5 {
|
if u3 > 0.5 {
|
||||||
return math.mod(mu + math.acos(f), math.TAU)
|
return math.mod(mu + math.acos(f), math.TAU)
|
||||||
} else {
|
} else {
|
||||||
@@ -263,57 +263,57 @@ float64_von_mises :: proc(mean_angle, kappa: f64, r: ^Rand = nil) -> f64 {
|
|||||||
// `kappa` is the concentration parameter which must be >= 0
|
// `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
|
// When `kappa` is zero, the Distribution is a uniform Distribution over the range 0 to 2pi
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float32_von_mises :: proc(mean_angle, kappa: f32, r: ^Rand = nil) -> f32 {
|
float32_von_mises :: proc(mean_angle, kappa: f32) -> f32 {
|
||||||
return f32(float64_von_mises(f64(mean_angle), f64(kappa), r))
|
return f32(float64_von_mises(f64(mean_angle), f64(kappa)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Cauchy-Lorentz Distribution
|
// Cauchy-Lorentz Distribution
|
||||||
// `x_0` is the location, `gamma` is the scale where `gamma` > 0
|
// `x_0` is the location, `gamma` is the scale where `gamma` > 0
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float64_cauchy_lorentz :: proc(x_0, gamma: f64, r: ^Rand = nil) -> f64 {
|
float64_cauchy_lorentz :: proc(x_0, gamma: f64) -> f64 {
|
||||||
assert(gamma > 0)
|
assert(gamma > 0)
|
||||||
|
|
||||||
// Calculated from the inverse CDF
|
// Calculated from the inverse CDF
|
||||||
|
|
||||||
return math.tan(math.PI * (float64(r) - 0.5))*gamma + x_0
|
return math.tan(math.PI * (float64() - 0.5))*gamma + x_0
|
||||||
}
|
}
|
||||||
// Cauchy-Lorentz Distribution
|
// Cauchy-Lorentz Distribution
|
||||||
// `x_0` is the location, `gamma` is the scale where `gamma` > 0
|
// `x_0` is the location, `gamma` is the scale where `gamma` > 0
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float32_cauchy_lorentz :: proc(x_0, gamma: f32, r: ^Rand = nil) -> f32 {
|
float32_cauchy_lorentz :: proc(x_0, gamma: f32) -> f32 {
|
||||||
return f32(float64_cauchy_lorentz(f64(x_0), f64(gamma), r))
|
return f32(float64_cauchy_lorentz(f64(x_0), f64(gamma)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Log Cauchy-Lorentz Distribution
|
// Log Cauchy-Lorentz Distribution
|
||||||
// `x_0` is the location, `gamma` is the scale where `gamma` > 0
|
// `x_0` is the location, `gamma` is the scale where `gamma` > 0
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float64_log_cauchy_lorentz :: proc(x_0, gamma: f64, r: ^Rand = nil) -> f64 {
|
float64_log_cauchy_lorentz :: proc(x_0, gamma: f64) -> f64 {
|
||||||
assert(gamma > 0)
|
assert(gamma > 0)
|
||||||
return math.exp(math.tan(math.PI * (float64(r) - 0.5))*gamma + x_0)
|
return math.exp(math.tan(math.PI * (float64() - 0.5))*gamma + x_0)
|
||||||
}
|
}
|
||||||
// Log Cauchy-Lorentz Distribution
|
// Log Cauchy-Lorentz Distribution
|
||||||
// `x_0` is the location, `gamma` is the scale where `gamma` > 0
|
// `x_0` is the location, `gamma` is the scale where `gamma` > 0
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float32_log_cauchy_lorentz :: proc(x_0, gamma: f32, r: ^Rand = nil) -> f32 {
|
float32_log_cauchy_lorentz :: proc(x_0, gamma: f32) -> f32 {
|
||||||
return f32(float64_log_cauchy_lorentz(f64(x_0), f64(gamma), r))
|
return f32(float64_log_cauchy_lorentz(f64(x_0), f64(gamma)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Laplace Distribution
|
// Laplace Distribution
|
||||||
// `b` is the scale where `b` > 0
|
// `b` is the scale where `b` > 0
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float64_laplace :: proc(mean, b: f64, r: ^Rand = nil) -> f64 {
|
float64_laplace :: proc(mean, b: f64) -> f64 {
|
||||||
assert(b > 0)
|
assert(b > 0)
|
||||||
p := float64(r)-0.5
|
p := float64()-0.5
|
||||||
return -math.sign(p)*math.ln(1 - 2*abs(p))*b + mean
|
return -math.sign(p)*math.ln(1 - 2*abs(p))*b + mean
|
||||||
}
|
}
|
||||||
// Laplace Distribution
|
// Laplace Distribution
|
||||||
// `b` is the scale where `b` > 0
|
// `b` is the scale where `b` > 0
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float32_laplace :: proc(mean, b: f32, r: ^Rand = nil) -> f32 {
|
float32_laplace :: proc(mean, b: f32) -> f32 {
|
||||||
return f32(float64_laplace(f64(mean), f64(b), r))
|
return f32(float64_laplace(f64(mean), f64(b)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -321,18 +321,18 @@ float32_laplace :: proc(mean, b: f32, r: ^Rand = nil) -> f32 {
|
|||||||
// `eta` is the shape, `b` is the scale
|
// `eta` is the shape, `b` is the scale
|
||||||
// Both `eta` and `b` must be > 0
|
// Both `eta` and `b` must be > 0
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float64_gompertz :: proc(eta, b: f64, r: ^Rand = nil) -> f64 {
|
float64_gompertz :: proc(eta, b: f64) -> f64 {
|
||||||
if eta <= 0 || b <= 0 {
|
if eta <= 0 || b <= 0 {
|
||||||
panic(#procedure + ": eta and b must be > 0.0")
|
panic(#procedure + ": eta and b must be > 0.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
p := float64(r)
|
p := float64()
|
||||||
return math.ln(1 - math.ln(1 - p)/eta)/b
|
return math.ln(1 - math.ln(1 - p)/eta)/b
|
||||||
}
|
}
|
||||||
// Gompertz Distribution
|
// Gompertz Distribution
|
||||||
// `eta` is the shape, `b` is the scale
|
// `eta` is the shape, `b` is the scale
|
||||||
// Both `eta` and `b` must be > 0
|
// Both `eta` and `b` must be > 0
|
||||||
@(require_results)
|
@(require_results)
|
||||||
float32_gompertz :: proc(eta, b: f32, r: ^Rand = nil) -> f32 {
|
float32_gompertz :: proc(eta, b: f32) -> f32 {
|
||||||
return f32(float64_gompertz(f64(eta), f64(b), r))
|
return f32(float64_gompertz(f64(eta), f64(b)))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import "core:math"
|
|||||||
// https://www.jstatsoft.org/article/view/v005i08 [web page]
|
// https://www.jstatsoft.org/article/view/v005i08 [web page]
|
||||||
//
|
//
|
||||||
@(require_results)
|
@(require_results)
|
||||||
exp_float64 :: proc(r: ^Rand = nil) -> f64 {
|
exp_float64 :: proc() -> f64 {
|
||||||
re :: 7.69711747013104972
|
re :: 7.69711747013104972
|
||||||
|
|
||||||
@(static, rodata)
|
@(static, rodata)
|
||||||
@@ -199,16 +199,16 @@ exp_float64 :: proc(r: ^Rand = nil) -> f64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
j := uint32(r)
|
j := uint32()
|
||||||
i := j & 0xFF
|
i := j & 0xFF
|
||||||
x := f64(j) * f64(we[i])
|
x := f64(j) * f64(we[i])
|
||||||
if j < ke[i] {
|
if j < ke[i] {
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
return re - math.ln(float64(r))
|
return re - math.ln(float64())
|
||||||
}
|
}
|
||||||
if fe[i]+f32(float64(r))*(fe[i-1]-fe[i]) < f32(math.exp(-x)) {
|
if fe[i]+f32(float64())*(fe[i-1]-fe[i]) < f32(math.exp(-x)) {
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import "core:math"
|
|||||||
// https://www.jstatsoft.org/article/view/v005i08 [web page]
|
// https://www.jstatsoft.org/article/view/v005i08 [web page]
|
||||||
//
|
//
|
||||||
@(require_results)
|
@(require_results)
|
||||||
norm_float64 :: proc(r: ^Rand = nil) -> f64 {
|
norm_float64 :: proc() -> f64 {
|
||||||
rn :: 3.442619855899
|
rn :: 3.442619855899
|
||||||
|
|
||||||
@(static, rodata)
|
@(static, rodata)
|
||||||
@@ -116,7 +116,7 @@ norm_float64 :: proc(r: ^Rand = nil) -> f64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
j := i32(uint32(r))
|
j := i32(uint32())
|
||||||
i := j & 0x7f
|
i := j & 0x7f
|
||||||
x := f64(j) * f64(wn[i])
|
x := f64(j) * f64(wn[i])
|
||||||
if u32(abs(j)) < kn[i] {
|
if u32(abs(j)) < kn[i] {
|
||||||
@@ -126,15 +126,15 @@ norm_float64 :: proc(r: ^Rand = nil) -> f64 {
|
|||||||
|
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
for {
|
for {
|
||||||
x = -math.ln(float64(r)) * (1.0/ rn)
|
x = -math.ln(float64()) * (1.0/ rn)
|
||||||
y := -math.ln(float64(r))
|
y := -math.ln(float64())
|
||||||
if y+y >= x*x {
|
if y+y >= x*x {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return j > 0 ? rn + x : -rn - x
|
return j > 0 ? rn + x : -rn - x
|
||||||
}
|
}
|
||||||
if fn[i]+f32(float64(r))*(fn[i-1]-fn[i]) < f32(math.exp(-0.5*x*x)) {
|
if fn[i]+f32(float64())*(fn[i-1]-fn[i]) < f32(math.exp(-0.5*x*x)) {
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+62
-289
@@ -10,52 +10,18 @@ import "core:crypto"
|
|||||||
import "core:math"
|
import "core:math"
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
|
|
||||||
Rand :: struct {
|
Default_Random_State :: runtime.Default_Random_State
|
||||||
state: u64,
|
default_random_generator :: runtime.default_random_generator
|
||||||
inc: u64,
|
|
||||||
is_system: bool,
|
create :: proc(seed: u64) -> (state: Default_Random_State) {
|
||||||
|
seed := seed
|
||||||
|
runtime.default_random_generator(&state)
|
||||||
|
runtime.default_random_generator_proc(&state, .Reset, ([^]byte)(&seed)[:size_of(seed)])
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
to_random_generator :: proc(r: ^Rand) -> runtime.Random_Generator {
|
|
||||||
return {
|
|
||||||
procedure = proc(data: rawptr, mode: runtime.Random_Generator_Mode, p: []byte) {
|
|
||||||
r := (^Rand)(data)
|
|
||||||
switch mode {
|
|
||||||
case .Read:
|
|
||||||
_ = read(p, r)
|
|
||||||
|
|
||||||
case .Reset:
|
|
||||||
if r.is_system {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
seed: u64
|
|
||||||
runtime.mem_copy_non_overlapping(&seed, raw_data(p), min(size_of(seed), len(p)))
|
|
||||||
init(r, seed)
|
|
||||||
|
|
||||||
|
|
||||||
case .Query_Info:
|
|
||||||
if len(p) != size_of(runtime.Random_Generator_Query_Info) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
info := (^runtime.Random_Generator_Query_Info)(raw_data(p))
|
|
||||||
info^ += {.Uniform}
|
|
||||||
if r.is_system {
|
|
||||||
info^ += {.External_Entropy}
|
|
||||||
} else {
|
|
||||||
info^ += {.Resettable}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data = r,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@(private)
|
|
||||||
global_rand := create(u64(intrinsics.read_cycle_counter()))
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Sets the seed used by the global random number generator.
|
Reset the seed used by the context.random_generator.
|
||||||
|
|
||||||
Inputs:
|
Inputs:
|
||||||
- seed: The seed value
|
- seed: The seed value
|
||||||
@@ -72,143 +38,46 @@ Example:
|
|||||||
Possible Output:
|
Possible Output:
|
||||||
|
|
||||||
10
|
10
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
@(deprecated="Prefer `rand.reset`")
|
||||||
set_global_seed :: proc(seed: u64) {
|
set_global_seed :: proc(seed: u64) {
|
||||||
init(&global_rand, seed)
|
runtime.random_generator_reset_u64(context.random_generator, seed)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Creates a new random number generator.
|
Reset the seed used by the context.random_generator.
|
||||||
|
|
||||||
Inputs:
|
Inputs:
|
||||||
- seed: The seed value to create the random number generator with
|
- seed: The seed value
|
||||||
|
|
||||||
Returns:
|
|
||||||
- res: The created random number generator
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
import "core:math/rand"
|
import "core:math/rand"
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
|
|
||||||
create_example :: proc() {
|
set_global_seed_example :: proc() {
|
||||||
my_rand := rand.create(1)
|
rand.set_global_seed(1)
|
||||||
fmt.println(rand.uint64(&my_rand))
|
fmt.println(rand.uint64())
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
Possible Output:
|
||||||
|
|
||||||
10
|
10
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
reset :: proc(seed: u64) {
|
||||||
create :: proc(seed: u64) -> (res: Rand) {
|
runtime.random_generator_reset_u64(context.random_generator, seed)
|
||||||
r: Rand
|
|
||||||
init(&r, seed)
|
|
||||||
return r
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Initialises a random number generator.
|
|
||||||
|
|
||||||
Inputs:
|
|
||||||
- r: The random number generator to initialise
|
|
||||||
- seed: The seed value to initialise this random number generator
|
|
||||||
|
|
||||||
Example:
|
|
||||||
import "core:math/rand"
|
|
||||||
import "core:fmt"
|
|
||||||
|
|
||||||
init_example :: proc() {
|
|
||||||
my_rand: rand.Rand
|
|
||||||
rand.init(&my_rand, 1)
|
|
||||||
fmt.println(rand.uint64(&my_rand))
|
|
||||||
}
|
|
||||||
|
|
||||||
Possible Output:
|
|
||||||
|
|
||||||
10
|
|
||||||
|
|
||||||
*/
|
|
||||||
init :: proc(r: ^Rand, seed: u64) {
|
|
||||||
r.state = 0
|
|
||||||
r.inc = (seed << 1) | 1
|
|
||||||
_random_u64(r)
|
|
||||||
r.state += seed
|
|
||||||
_random_u64(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Initialises a random number generator to use the system random number generator.
|
|
||||||
The system random number generator is platform specific, and not supported
|
|
||||||
on all targets.
|
|
||||||
|
|
||||||
Inputs:
|
|
||||||
- r: The random number generator to use the system random number generator
|
|
||||||
|
|
||||||
WARNING: Panics if the system random number generator is not supported.
|
|
||||||
Support can be determined via the `core:crypto.HAS_RAND_BYTES` constant.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
import "core:crypto"
|
|
||||||
import "core:math/rand"
|
|
||||||
import "core:fmt"
|
|
||||||
|
|
||||||
init_as_system_example :: proc() {
|
|
||||||
my_rand: rand.Rand
|
|
||||||
switch crypto.HAS_RAND_BYTES {
|
|
||||||
case true:
|
|
||||||
rand.init_as_system(&my_rand)
|
|
||||||
fmt.println(rand.uint64(&my_rand))
|
|
||||||
case false:
|
|
||||||
fmt.println("system random not supported!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Possible Output:
|
|
||||||
|
|
||||||
10
|
|
||||||
|
|
||||||
*/
|
|
||||||
init_as_system :: proc(r: ^Rand) {
|
|
||||||
if !crypto.HAS_RAND_BYTES {
|
|
||||||
panic(#procedure + " is not supported on this platform yet")
|
|
||||||
}
|
|
||||||
r.state = 0
|
|
||||||
r.inc = 0
|
|
||||||
r.is_system = true
|
|
||||||
}
|
|
||||||
|
|
||||||
@(private)
|
@(private)
|
||||||
_random_u64 :: proc(r: ^Rand) -> u64 {
|
_random_u64 :: proc() -> (res: u64) {
|
||||||
r := r
|
ok := runtime.random_generator_read_ptr(context.random_generator, &res, size_of(res))
|
||||||
switch {
|
assert(ok, "uninitialized context.random_generator")
|
||||||
case r == nil:
|
return
|
||||||
if res: u64; runtime.random_generator_read_ptr(context.random_generator, &res, size_of(res)) {
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
r = &global_rand
|
|
||||||
case r.is_system:
|
|
||||||
value: u64
|
|
||||||
crypto.rand_bytes((cast([^]u8)&value)[:size_of(u64)])
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
old_state := r.state
|
|
||||||
r.state = old_state * 6364136223846793005 + (r.inc|1)
|
|
||||||
xor_shifted := (((old_state >> 59) + 5) ~ old_state) * 12605985483714917081
|
|
||||||
rot := (old_state >> 59)
|
|
||||||
return (xor_shifted >> rot) | (xor_shifted << ((-rot) & 63))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Generates a random 32 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
|
Generates a random 32 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
|
||||||
|
|
||||||
Inputs:
|
|
||||||
- r: The random number generator to use, or nil for the global generator
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- val: A random unsigned 32 bit value
|
- val: A random unsigned 32 bit value
|
||||||
|
|
||||||
@@ -217,11 +86,7 @@ Example:
|
|||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
|
|
||||||
uint32_example :: proc() {
|
uint32_example :: proc() {
|
||||||
// Using the global random number generator
|
|
||||||
fmt.println(rand.uint32())
|
fmt.println(rand.uint32())
|
||||||
// Using local random number generator
|
|
||||||
my_rand := rand.create(1)
|
|
||||||
fmt.println(rand.uint32(&my_rand))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
Possible Output:
|
||||||
@@ -231,14 +96,11 @@ Possible Output:
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
uint32 :: proc(r: ^Rand = nil) -> (val: u32) { return u32(_random_u64(r)) }
|
uint32 :: proc() -> (val: u32) { return u32(_random_u64()) }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
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.
|
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.
|
||||||
|
|
||||||
Inputs:
|
|
||||||
- r: The random number generator to use, or nil for the global generator
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- val: A random unsigned 64 bit value
|
- val: A random unsigned 64 bit value
|
||||||
|
|
||||||
@@ -247,11 +109,7 @@ Example:
|
|||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
|
|
||||||
uint64_example :: proc() {
|
uint64_example :: proc() {
|
||||||
// Using the global random number generator
|
|
||||||
fmt.println(rand.uint64())
|
fmt.println(rand.uint64())
|
||||||
// Using local random number generator
|
|
||||||
my_rand := rand.create(1)
|
|
||||||
fmt.println(rand.uint64(&my_rand))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
Possible Output:
|
||||||
@@ -261,14 +119,11 @@ Possible Output:
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
uint64 :: proc(r: ^Rand = nil) -> (val: u64) { return _random_u64(r) }
|
uint64 :: proc() -> (val: u64) { return _random_u64() }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
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.
|
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.
|
||||||
|
|
||||||
Inputs:
|
|
||||||
- r: The random number generator to use, or nil for the global generator
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- val: A random unsigned 128 bit value
|
- val: A random unsigned 128 bit value
|
||||||
|
|
||||||
@@ -277,11 +132,7 @@ Example:
|
|||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
|
|
||||||
uint128_example :: proc() {
|
uint128_example :: proc() {
|
||||||
// Using the global random number generator
|
|
||||||
fmt.println(rand.uint128())
|
fmt.println(rand.uint128())
|
||||||
// Using local random number generator
|
|
||||||
my_rand := rand.create(1)
|
|
||||||
fmt.println(rand.uint128(&my_rand))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
Possible Output:
|
||||||
@@ -291,9 +142,9 @@ Possible Output:
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
uint128 :: proc(r: ^Rand = nil) -> (val: u128) {
|
uint128 :: proc() -> (val: u128) {
|
||||||
a := u128(_random_u64(r))
|
a := u128(_random_u64())
|
||||||
b := u128(_random_u64(r))
|
b := u128(_random_u64())
|
||||||
return (a<<64) | b
|
return (a<<64) | b
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,9 +152,6 @@ uint128 :: proc(r: ^Rand = nil) -> (val: u128) {
|
|||||||
Generates a random 31 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
|
Generates a random 31 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
|
||||||
The sign bit will always be set to 0, thus all generated numbers will be positive.
|
The sign bit will always be set to 0, thus all generated numbers will be positive.
|
||||||
|
|
||||||
Inputs:
|
|
||||||
- r: The random number generator to use, or nil for the global generator
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- val: A random 31 bit value
|
- val: A random 31 bit value
|
||||||
|
|
||||||
@@ -312,11 +160,7 @@ Example:
|
|||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
|
|
||||||
int31_example :: proc() {
|
int31_example :: proc() {
|
||||||
// Using the global random number generator
|
|
||||||
fmt.println(rand.int31())
|
fmt.println(rand.int31())
|
||||||
// Using local random number generator
|
|
||||||
my_rand := rand.create(1)
|
|
||||||
fmt.println(rand.int31(&my_rand))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
Possible Output:
|
||||||
@@ -325,15 +169,12 @@ Possible Output:
|
|||||||
389
|
389
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results) int31 :: proc(r: ^Rand = nil) -> (val: i32) { return i32(uint32(r) << 1 >> 1) }
|
@(require_results) int31 :: proc() -> (val: i32) { return i32(uint32() << 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.
|
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.
|
||||||
The sign bit will always be set to 0, thus all generated numbers will be positive.
|
The sign bit will always be set to 0, thus all generated numbers will be positive.
|
||||||
|
|
||||||
Inputs:
|
|
||||||
- r: The random number generator to use, or nil for the global generator
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- val: A random 63 bit value
|
- val: A random 63 bit value
|
||||||
|
|
||||||
@@ -342,11 +183,7 @@ Example:
|
|||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
|
|
||||||
int63_example :: proc() {
|
int63_example :: proc() {
|
||||||
// Using the global random number generator
|
|
||||||
fmt.println(rand.int63())
|
fmt.println(rand.int63())
|
||||||
// Using local random number generator
|
|
||||||
my_rand := rand.create(1)
|
|
||||||
fmt.println(rand.int63(&my_rand))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
Possible Output:
|
||||||
@@ -355,15 +192,12 @@ Possible Output:
|
|||||||
389
|
389
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results) int63 :: proc(r: ^Rand = nil) -> (val: i64) { return i64(uint64(r) << 1 >> 1) }
|
@(require_results) int63 :: proc() -> (val: i64) { return i64(uint64() << 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.
|
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.
|
||||||
The sign bit will always be set to 0, thus all generated numbers will be positive.
|
The sign bit will always be set to 0, thus all generated numbers will be positive.
|
||||||
|
|
||||||
Inputs:
|
|
||||||
- r: The random number generator to use, or nil for the global generator
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- val: A random 127 bit value
|
- val: A random 127 bit value
|
||||||
|
|
||||||
@@ -372,11 +206,7 @@ Example:
|
|||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
|
|
||||||
int127_example :: proc() {
|
int127_example :: proc() {
|
||||||
// Using the global random number generator
|
|
||||||
fmt.println(rand.int127())
|
fmt.println(rand.int127())
|
||||||
// Using local random number generator
|
|
||||||
my_rand := rand.create(1)
|
|
||||||
fmt.println(rand.int127(&my_rand))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
Possible Output:
|
||||||
@@ -385,14 +215,13 @@ Possible Output:
|
|||||||
389
|
389
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results) int127 :: proc(r: ^Rand = nil) -> (val: i128) { return i128(uint128(r) << 1 >> 1) }
|
@(require_results) int127 :: proc() -> (val: i128) { return i128(uint128() << 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.
|
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.
|
||||||
|
|
||||||
Inputs:
|
Inputs:
|
||||||
- n: The upper bound of the generated number, this value is exclusive
|
- n: The upper bound of the generated number, this value is exclusive
|
||||||
- r: The random number generator to use, or nil for the global generator
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- val: A random 31 bit value in the range `[0, n)`
|
- val: A random 31 bit value in the range `[0, n)`
|
||||||
@@ -404,11 +233,7 @@ Example:
|
|||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
|
|
||||||
int31_max_example :: proc() {
|
int31_max_example :: proc() {
|
||||||
// Using the global random number generator
|
|
||||||
fmt.println(rand.int31_max(16))
|
fmt.println(rand.int31_max(16))
|
||||||
// Using local random number generator
|
|
||||||
my_rand := rand.create(1)
|
|
||||||
fmt.println(rand.int31_max(1024, &my_rand))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
Possible Output:
|
||||||
@@ -418,17 +243,17 @@ Possible Output:
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
int31_max :: proc(n: i32, r: ^Rand = nil) -> (val: i32) {
|
int31_max :: proc(n: i32) -> (val: i32) {
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
panic("Invalid argument to int31_max")
|
panic("Invalid argument to int31_max")
|
||||||
}
|
}
|
||||||
if n&(n-1) == 0 {
|
if n&(n-1) == 0 {
|
||||||
return int31(r) & (n-1)
|
return int31() & (n-1)
|
||||||
}
|
}
|
||||||
max := i32((1<<31) - 1 - (1<<31)%u32(n))
|
max := i32((1<<31) - 1 - (1<<31)%u32(n))
|
||||||
v := int31(r)
|
v := int31()
|
||||||
for v > max {
|
for v > max {
|
||||||
v = int31(r)
|
v = int31()
|
||||||
}
|
}
|
||||||
return v % n
|
return v % n
|
||||||
}
|
}
|
||||||
@@ -438,7 +263,6 @@ Generates a random 63 bit value in the range `[0, n)` using the provided random
|
|||||||
|
|
||||||
Inputs:
|
Inputs:
|
||||||
- n: The upper bound of the generated number, this value is exclusive
|
- n: The upper bound of the generated number, this value is exclusive
|
||||||
- r: The random number generator to use, or nil for the global generator
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- val: A random 63 bit value in the range `[0, n)`
|
- val: A random 63 bit value in the range `[0, n)`
|
||||||
@@ -450,11 +274,7 @@ Example:
|
|||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
|
|
||||||
int63_max_example :: proc() {
|
int63_max_example :: proc() {
|
||||||
// Using the global random number generator
|
|
||||||
fmt.println(rand.int63_max(16))
|
fmt.println(rand.int63_max(16))
|
||||||
// Using local random number generator
|
|
||||||
my_rand := rand.create(1)
|
|
||||||
fmt.println(rand.int63_max(1024, &my_rand))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
Possible Output:
|
||||||
@@ -464,17 +284,17 @@ Possible Output:
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
int63_max :: proc(n: i64, r: ^Rand = nil) -> (val: i64) {
|
int63_max :: proc(n: i64) -> (val: i64) {
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
panic("Invalid argument to int63_max")
|
panic("Invalid argument to int63_max")
|
||||||
}
|
}
|
||||||
if n&(n-1) == 0 {
|
if n&(n-1) == 0 {
|
||||||
return int63(r) & (n-1)
|
return int63() & (n-1)
|
||||||
}
|
}
|
||||||
max := i64((1<<63) - 1 - (1<<63)%u64(n))
|
max := i64((1<<63) - 1 - (1<<63)%u64(n))
|
||||||
v := int63(r)
|
v := int63()
|
||||||
for v > max {
|
for v > max {
|
||||||
v = int63(r)
|
v = int63()
|
||||||
}
|
}
|
||||||
return v % n
|
return v % n
|
||||||
}
|
}
|
||||||
@@ -484,7 +304,6 @@ Generates a random 127 bit value in the range `[0, n)` using the provided random
|
|||||||
|
|
||||||
Inputs:
|
Inputs:
|
||||||
- n: The upper bound of the generated number, this value is exclusive
|
- n: The upper bound of the generated number, this value is exclusive
|
||||||
- r: The random number generator to use, or nil for the global generator
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- val: A random 127 bit value in the range `[0, n)`
|
- val: A random 127 bit value in the range `[0, n)`
|
||||||
@@ -496,11 +315,7 @@ Example:
|
|||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
|
|
||||||
int127_max_example :: proc() {
|
int127_max_example :: proc() {
|
||||||
// Using the global random number generator
|
|
||||||
fmt.println(rand.int127_max(16))
|
fmt.println(rand.int127_max(16))
|
||||||
// Using local random number generator
|
|
||||||
my_rand := rand.create(1)
|
|
||||||
fmt.println(rand.int127_max(1024, &my_rand))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
Possible Output:
|
||||||
@@ -510,17 +325,17 @@ Possible Output:
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
int127_max :: proc(n: i128, r: ^Rand = nil) -> (val: i128) {
|
int127_max :: proc(n: i128) -> (val: i128) {
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
panic("Invalid argument to int127_max")
|
panic("Invalid argument to int127_max")
|
||||||
}
|
}
|
||||||
if n&(n-1) == 0 {
|
if n&(n-1) == 0 {
|
||||||
return int127(r) & (n-1)
|
return int127() & (n-1)
|
||||||
}
|
}
|
||||||
max := i128((1<<127) - 1 - (1<<127)%u128(n))
|
max := i128((1<<127) - 1 - (1<<127)%u128(n))
|
||||||
v := int127(r)
|
v := int127()
|
||||||
for v > max {
|
for v > max {
|
||||||
v = int127(r)
|
v = int127()
|
||||||
}
|
}
|
||||||
return v % n
|
return v % n
|
||||||
}
|
}
|
||||||
@@ -530,7 +345,6 @@ Generates a random integer value in the range `[0, n)` using the provided random
|
|||||||
|
|
||||||
Inputs:
|
Inputs:
|
||||||
- n: The upper bound of the generated number, this value is exclusive
|
- n: The upper bound of the generated number, this value is exclusive
|
||||||
- r: The random number generator to use, or nil for the global generator
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- val: A random integer value in the range `[0, n)`
|
- val: A random integer value in the range `[0, n)`
|
||||||
@@ -542,11 +356,7 @@ Example:
|
|||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
|
|
||||||
int_max_example :: proc() {
|
int_max_example :: proc() {
|
||||||
// Using the global random number generator
|
|
||||||
fmt.println(rand.int_max(16))
|
fmt.println(rand.int_max(16))
|
||||||
// Using local random number generator
|
|
||||||
my_rand := rand.create(1)
|
|
||||||
fmt.println(rand.int_max(1024, &my_rand))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
Possible Output:
|
||||||
@@ -556,23 +366,20 @@ Possible Output:
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
int_max :: proc(n: int, r: ^Rand = nil) -> (val: int) {
|
int_max :: proc(n: int) -> (val: int) {
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
panic("Invalid argument to int_max")
|
panic("Invalid argument to int_max")
|
||||||
}
|
}
|
||||||
when size_of(int) == 4 {
|
when size_of(int) == 4 {
|
||||||
return int(int31_max(i32(n), r))
|
return int(int31_max(i32(n)))
|
||||||
} else {
|
} else {
|
||||||
return int(int63_max(i64(n), r))
|
return int(int63_max(i64(n)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Generates a random double 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.
|
Generates a random double 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.
|
||||||
|
|
||||||
Inputs:
|
|
||||||
- r: The random number generator to use, or nil for the global generator
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- val: A random double floating point value in the range `[0, 1)`
|
- val: A random double floating point value in the range `[0, 1)`
|
||||||
|
|
||||||
@@ -581,11 +388,7 @@ Example:
|
|||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
|
|
||||||
float64_example :: proc() {
|
float64_example :: proc() {
|
||||||
// Using the global random number generator
|
|
||||||
fmt.println(rand.float64())
|
fmt.println(rand.float64())
|
||||||
// Using local random number generator
|
|
||||||
my_rand := rand.create(1)
|
|
||||||
fmt.println(rand.float64(&my_rand))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
Possible Output:
|
||||||
@@ -594,14 +397,11 @@ Possible Output:
|
|||||||
0.511
|
0.511
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results) float64 :: proc(r: ^Rand = nil) -> (val: f64) { return f64(int63_max(1<<53, r)) / (1 << 53) }
|
@(require_results) float64 :: proc() -> (val: f64) { return f64(int63_max(1<<53)) / (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.
|
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.
|
||||||
|
|
||||||
Inputs:
|
|
||||||
- r: The random number generator to use, or nil for the global generator
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- val: A random single floating point value in the range `[0, 1)`
|
- val: A random single floating point value in the range `[0, 1)`
|
||||||
|
|
||||||
@@ -610,11 +410,7 @@ Example:
|
|||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
|
|
||||||
float32_example :: proc() {
|
float32_example :: proc() {
|
||||||
// Using the global random number generator
|
|
||||||
fmt.println(rand.float32())
|
fmt.println(rand.float32())
|
||||||
// Using local random number generator
|
|
||||||
my_rand := rand.create(1)
|
|
||||||
fmt.println(rand.float32(&my_rand))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
Possible Output:
|
||||||
@@ -623,7 +419,7 @@ Possible Output:
|
|||||||
0.511
|
0.511
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results) float32 :: proc(r: ^Rand = nil) -> (val: f32) { return f32(int31_max(1<<24, r)) / (1 << 24) }
|
@(require_results) float32 :: proc() -> (val: f32) { return f32(int31_max(1<<24)) / (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.
|
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.
|
||||||
@@ -633,7 +429,6 @@ WARNING: Panics if `high < low`
|
|||||||
Inputs:
|
Inputs:
|
||||||
- low: The lower bounds of the value, this value is inclusive
|
- low: The lower bounds of the value, this value is inclusive
|
||||||
- high: The upper bounds of the value, this value is exclusive
|
- high: The upper bounds of the value, this value is exclusive
|
||||||
- r: The random number generator to use, or nil for the global generator
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- val: A random double floating point value in the range [low, high)
|
- val: A random double floating point value in the range [low, high)
|
||||||
@@ -643,11 +438,7 @@ Example:
|
|||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
|
|
||||||
float64_range_example :: proc() {
|
float64_range_example :: proc() {
|
||||||
// Using the global random number generator
|
|
||||||
fmt.println(rand.float64_range(-10, 300))
|
fmt.println(rand.float64_range(-10, 300))
|
||||||
// Using local random number generator
|
|
||||||
my_rand := rand.create(1)
|
|
||||||
fmt.println(rand.float64_range(600, 900, &my_rand))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
Possible Output:
|
||||||
@@ -656,9 +447,9 @@ Possible Output:
|
|||||||
673.130
|
673.130
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results) float64_range :: proc(low, high: f64, r: ^Rand = nil) -> (val: f64) {
|
@(require_results) float64_range :: proc(low, high: f64) -> (val: f64) {
|
||||||
assert(low <= high, "low must be lower than or equal to high")
|
assert(low <= high, "low must be lower than or equal to high")
|
||||||
val = (high-low)*float64(r) + low
|
val = (high-low)*float64() + low
|
||||||
if val >= high {
|
if val >= high {
|
||||||
val = max(low, high * (1 - math.F64_EPSILON))
|
val = max(low, high * (1 - math.F64_EPSILON))
|
||||||
}
|
}
|
||||||
@@ -671,7 +462,6 @@ Generates a random single floating point value in the range `[low, high)` using
|
|||||||
Inputs:
|
Inputs:
|
||||||
- low: The lower bounds of the value, this value is inclusive
|
- low: The lower bounds of the value, this value is inclusive
|
||||||
- high: The upper bounds of the value, this value is exclusive
|
- high: The upper bounds of the value, this value is exclusive
|
||||||
- r: The random number generator to use, or nil for the global generator
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- val: A random single floating point value in the range [low, high)
|
- val: A random single floating point value in the range [low, high)
|
||||||
@@ -683,11 +473,7 @@ Example:
|
|||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
|
|
||||||
float32_range_example :: proc() {
|
float32_range_example :: proc() {
|
||||||
// Using the global random number generator
|
|
||||||
fmt.println(rand.float32_range(-10, 300))
|
fmt.println(rand.float32_range(-10, 300))
|
||||||
// Using local random number generator
|
|
||||||
my_rand := rand.create(1)
|
|
||||||
fmt.println(rand.float32_range(600, 900, &my_rand))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
Possible Output:
|
||||||
@@ -696,9 +482,9 @@ Possible Output:
|
|||||||
673.130
|
673.130
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results) float32_range :: proc(low, high: f32, r: ^Rand = nil) -> (val: f32) {
|
@(require_results) float32_range :: proc(low, high: f32) -> (val: f32) {
|
||||||
assert(low <= high, "low must be lower than or equal to high")
|
assert(low <= high, "low must be lower than or equal to high")
|
||||||
val = (high-low)*float32(r) + low
|
val = (high-low)*float32() + low
|
||||||
if val >= high {
|
if val >= high {
|
||||||
val = max(low, high * (1 - math.F32_EPSILON))
|
val = max(low, high * (1 - math.F32_EPSILON))
|
||||||
}
|
}
|
||||||
@@ -711,7 +497,6 @@ Due to floating point precision there is no guarantee if the upper and lower bou
|
|||||||
|
|
||||||
Inputs:
|
Inputs:
|
||||||
- p: The byte slice to fill
|
- p: The byte slice to fill
|
||||||
- r: The random number generator to use, or nil for the global generator
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- n: The number of bytes generated
|
- n: The number of bytes generated
|
||||||
@@ -721,7 +506,6 @@ Example:
|
|||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
|
|
||||||
read_example :: proc() {
|
read_example :: proc() {
|
||||||
// Using the global random number generator
|
|
||||||
data: [8]byte
|
data: [8]byte
|
||||||
n := rand.read(data[:])
|
n := rand.read(data[:])
|
||||||
fmt.println(n)
|
fmt.println(n)
|
||||||
@@ -735,12 +519,12 @@ Possible Output:
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
read :: proc(p: []byte, r: ^Rand = nil) -> (n: int) {
|
read :: proc(p: []byte) -> (n: int) {
|
||||||
pos := i8(0)
|
pos := i8(0)
|
||||||
val := i64(0)
|
val := i64(0)
|
||||||
for n = 0; n < len(p); n += 1 {
|
for n = 0; n < len(p); n += 1 {
|
||||||
if pos == 0 {
|
if pos == 0 {
|
||||||
val = int63(r)
|
val = int63()
|
||||||
pos = 7
|
pos = 7
|
||||||
}
|
}
|
||||||
p[n] = byte(val)
|
p[n] = byte(val)
|
||||||
@@ -757,7 +541,6 @@ Creates a slice of `int` filled with random values using the provided random num
|
|||||||
|
|
||||||
Inputs:
|
Inputs:
|
||||||
- n: The size of the created slice
|
- n: The size of the created slice
|
||||||
- r: The random number generator to use, or nil for the global generator
|
|
||||||
- allocator: (default: context.allocator)
|
- allocator: (default: context.allocator)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -770,16 +553,10 @@ Example:
|
|||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
|
|
||||||
perm_example :: proc() -> (err: mem.Allocator_Error) {
|
perm_example :: proc() -> (err: mem.Allocator_Error) {
|
||||||
// Using the global random number generator and using the context allocator
|
|
||||||
data := rand.perm(4) or_return
|
data := rand.perm(4) or_return
|
||||||
fmt.println(data)
|
fmt.println(data)
|
||||||
defer delete(data, context.allocator)
|
defer delete(data, context.allocator)
|
||||||
|
|
||||||
// Using local random number generator and temp allocator
|
|
||||||
my_rand := rand.create(1)
|
|
||||||
data_tmp := rand.perm(4, &my_rand, context.temp_allocator) or_return
|
|
||||||
fmt.println(data_tmp)
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -790,10 +567,10 @@ Possible Output:
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
perm :: proc(n: int, r: ^Rand = nil, allocator := context.allocator) -> (res: []int, err: mem.Allocator_Error) #optional_allocator_error {
|
perm :: proc(n: int, allocator := context.allocator) -> (res: []int, err: mem.Allocator_Error) #optional_allocator_error {
|
||||||
m := make([]int, n, allocator) or_return
|
m := make([]int, n, allocator) or_return
|
||||||
for i := 0; i < n; i += 1 {
|
for i := 0; i < n; i += 1 {
|
||||||
j := int_max(i+1, r)
|
j := int_max(i+1)
|
||||||
m[i] = m[j]
|
m[i] = m[j]
|
||||||
m[j] = i
|
m[j] = i
|
||||||
}
|
}
|
||||||
@@ -805,14 +582,12 @@ Randomizes the ordering of elements for the provided slice. If no generator is p
|
|||||||
|
|
||||||
Inputs:
|
Inputs:
|
||||||
- array: The slice to randomize
|
- array: The slice to randomize
|
||||||
- r: The random number generator to use, or nil for the global generator
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
import "core:math/rand"
|
import "core:math/rand"
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
|
|
||||||
shuffle_example :: proc() {
|
shuffle_example :: proc() {
|
||||||
// Using the global random number generator
|
|
||||||
data: [4]int = { 1, 2, 3, 4 }
|
data: [4]int = { 1, 2, 3, 4 }
|
||||||
fmt.println(data) // the contents are in order
|
fmt.println(data) // the contents are in order
|
||||||
rand.shuffle(data[:])
|
rand.shuffle(data[:])
|
||||||
@@ -825,14 +600,14 @@ Possible Output:
|
|||||||
[2, 4, 3, 1]
|
[2, 4, 3, 1]
|
||||||
|
|
||||||
*/
|
*/
|
||||||
shuffle :: proc(array: $T/[]$E, r: ^Rand = nil) {
|
shuffle :: proc(array: $T/[]$E) {
|
||||||
n := i64(len(array))
|
n := i64(len(array))
|
||||||
if n < 2 {
|
if n < 2 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := i64(n - 1); i > 0; i -= 1 {
|
for i := i64(n - 1); i > 0; i -= 1 {
|
||||||
j := int63_max(i + 1, r)
|
j := int63_max(i + 1)
|
||||||
array[i], array[j] = array[j], array[i]
|
array[i], array[j] = array[j], array[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -842,7 +617,6 @@ Returns a random element from the provided slice. If no generator is provided th
|
|||||||
|
|
||||||
Inputs:
|
Inputs:
|
||||||
- array: The slice to choose an element from
|
- array: The slice to choose an element from
|
||||||
- r: The random number generator to use, or nil for the global generator
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- res: A random element from `array`
|
- res: A random element from `array`
|
||||||
@@ -852,7 +626,6 @@ Example:
|
|||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
|
|
||||||
choice_example :: proc() {
|
choice_example :: proc() {
|
||||||
// Using the global random number generator
|
|
||||||
data: [4]int = { 1, 2, 3, 4 }
|
data: [4]int = { 1, 2, 3, 4 }
|
||||||
fmt.println(rand.choice(data[:]))
|
fmt.println(rand.choice(data[:]))
|
||||||
fmt.println(rand.choice(data[:]))
|
fmt.println(rand.choice(data[:]))
|
||||||
@@ -869,17 +642,17 @@ Possible Output:
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
choice :: proc(array: $T/[]$E, r: ^Rand = nil) -> (res: E) {
|
choice :: proc(array: $T/[]$E) -> (res: E) {
|
||||||
n := i64(len(array))
|
n := i64(len(array))
|
||||||
if n < 1 {
|
if n < 1 {
|
||||||
return E{}
|
return E{}
|
||||||
}
|
}
|
||||||
return array[int63_max(n, r)]
|
return array[int63_max(n)]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
choice_enum :: proc($T: typeid, r: ^Rand = nil) -> T
|
choice_enum :: proc($T: typeid) -> T
|
||||||
where
|
where
|
||||||
intrinsics.type_is_enum(T),
|
intrinsics.type_is_enum(T),
|
||||||
size_of(T) <= 8,
|
size_of(T) <= 8,
|
||||||
@@ -887,11 +660,11 @@ choice_enum :: proc($T: typeid, r: ^Rand = nil) -> T
|
|||||||
{
|
{
|
||||||
when intrinsics.type_is_unsigned(intrinsics.type_core_type(T)) &&
|
when intrinsics.type_is_unsigned(intrinsics.type_core_type(T)) &&
|
||||||
u64(max(T)) > u64(max(i64)) {
|
u64(max(T)) > u64(max(i64)) {
|
||||||
i := uint64(r) % u64(len(T))
|
i := uint64() % u64(len(T))
|
||||||
i += u64(min(T))
|
i += u64(min(T))
|
||||||
return T(i)
|
return T(i)
|
||||||
} else {
|
} else {
|
||||||
i := int63_max(i64(len(T)), r)
|
i := int63_max(i64(len(T)))
|
||||||
i += i64(min(T))
|
i += i64(min(T))
|
||||||
return T(i)
|
return T(i)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,8 +54,9 @@ test_xxhash_zero_streamed_random_updates :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
// XXH3_128_update
|
// XXH3_128_update
|
||||||
random_seed := rand.create(t.seed)
|
random_seed := rand.create(t.seed)
|
||||||
|
context.random_generator = rand.default_random_generator(&random_seed)
|
||||||
for len(b) > 0 {
|
for len(b) > 0 {
|
||||||
update_size := min(len(b), rand.int_max(8192, &random_seed))
|
update_size := min(len(b), rand.int_max(8192))
|
||||||
if update_size > 4096 {
|
if update_size > 4096 {
|
||||||
update_size %= 73
|
update_size %= 73
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ test_sort_with_indices :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
for test_size in test_sizes {
|
for test_size in test_sizes {
|
||||||
r := rand.create(t.seed)
|
r := rand.create(t.seed)
|
||||||
|
context.random_generator = rand.default_random_generator(&r)
|
||||||
|
|
||||||
vals := make([]u64, test_size)
|
vals := make([]u64, test_size)
|
||||||
r_idx := make([]int, test_size) // Reverse index
|
r_idx := make([]int, test_size) // Reverse index
|
||||||
@@ -21,7 +22,7 @@ test_sort_with_indices :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
// Set up test values
|
// Set up test values
|
||||||
for _, i in vals {
|
for _, i in vals {
|
||||||
vals[i] = rand.uint64(&r)
|
vals[i] = rand.uint64()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort
|
// Sort
|
||||||
@@ -29,7 +30,7 @@ test_sort_with_indices :: proc(t: ^testing.T) {
|
|||||||
defer delete(f_idx)
|
defer delete(f_idx)
|
||||||
|
|
||||||
// Verify sorted test values
|
// Verify sorted test values
|
||||||
rand.init(&r, t.seed)
|
rand.reset(t.seed)
|
||||||
|
|
||||||
for v, i in f_idx {
|
for v, i in f_idx {
|
||||||
r_idx[v] = i
|
r_idx[v] = i
|
||||||
@@ -45,7 +46,7 @@ test_sort_with_indices :: proc(t: ^testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
idx_pass := vals[r_idx[i]] == rand.uint64(&r)
|
idx_pass := vals[r_idx[i]] == rand.uint64()
|
||||||
testing.expect(t, idx_pass, "Expected index to have been sorted")
|
testing.expect(t, idx_pass, "Expected index to have been sorted")
|
||||||
if !idx_pass {
|
if !idx_pass {
|
||||||
break
|
break
|
||||||
@@ -62,6 +63,7 @@ test_sort_by_indices :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
for test_size in test_sizes {
|
for test_size in test_sizes {
|
||||||
r := rand.create(t.seed)
|
r := rand.create(t.seed)
|
||||||
|
context.random_generator = rand.default_random_generator(&r)
|
||||||
|
|
||||||
vals := make([]u64, test_size)
|
vals := make([]u64, test_size)
|
||||||
r_idx := make([]int, test_size) // Reverse index
|
r_idx := make([]int, test_size) // Reverse index
|
||||||
@@ -72,7 +74,7 @@ test_sort_by_indices :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
// Set up test values
|
// Set up test values
|
||||||
for _, i in vals {
|
for _, i in vals {
|
||||||
vals[i] = rand.uint64(&r)
|
vals[i] = rand.uint64()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort
|
// Sort
|
||||||
@@ -80,7 +82,7 @@ test_sort_by_indices :: proc(t: ^testing.T) {
|
|||||||
defer delete(f_idx)
|
defer delete(f_idx)
|
||||||
|
|
||||||
// Verify sorted test values
|
// Verify sorted test values
|
||||||
rand.init(&r, t.seed)
|
rand.reset(t.seed)
|
||||||
|
|
||||||
{
|
{
|
||||||
indices := make([]int, test_size)
|
indices := make([]int, test_size)
|
||||||
|
|||||||
@@ -17,9 +17,10 @@ map_insert_random_key_value :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
unique_keys := 0
|
unique_keys := 0
|
||||||
r := rand.create(t.seed + seed_incr)
|
r := rand.create(t.seed + seed_incr)
|
||||||
|
context.random_generator = rand.default_random_generator(&r)
|
||||||
for _ in 0..<entries {
|
for _ in 0..<entries {
|
||||||
k := rand.int63(&r)
|
k := rand.int63()
|
||||||
v := rand.int63(&r)
|
v := rand.int63()
|
||||||
|
|
||||||
if k not_in m {
|
if k not_in m {
|
||||||
unique_keys += 1
|
unique_keys += 1
|
||||||
@@ -37,11 +38,12 @@ map_insert_random_key_value :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
// Reset randomizer and verify
|
// Reset randomizer and verify
|
||||||
r = rand.create(t.seed + seed_incr)
|
r = rand.create(t.seed + seed_incr)
|
||||||
|
context.random_generator = rand.default_random_generator(&r)
|
||||||
|
|
||||||
num_fails := 0
|
num_fails := 0
|
||||||
for _ in 0..<entries {
|
for _ in 0..<entries {
|
||||||
k := rand.int63(&r)
|
k := rand.int63()
|
||||||
v := rand.int63(&r)
|
v := rand.int63()
|
||||||
|
|
||||||
cond := m[k] == v
|
cond := m[k] == v
|
||||||
if !cond {
|
if !cond {
|
||||||
@@ -67,9 +69,11 @@ map_update_random_key_value :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
unique_keys := 0
|
unique_keys := 0
|
||||||
r := rand.create(t.seed + seed_incr)
|
r := rand.create(t.seed + seed_incr)
|
||||||
|
context.random_generator = rand.default_random_generator(&r)
|
||||||
|
|
||||||
for _ in 0..<entries {
|
for _ in 0..<entries {
|
||||||
k := rand.int63(&r)
|
k := rand.int63()
|
||||||
v := rand.int63(&r)
|
v := rand.int63()
|
||||||
|
|
||||||
if k not_in m {
|
if k not_in m {
|
||||||
unique_keys += 1
|
unique_keys += 1
|
||||||
@@ -89,20 +93,23 @@ map_update_random_key_value :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
// Reset randomizer and update half the entries
|
// Reset randomizer and update half the entries
|
||||||
r = rand.create(t.seed + seed_incr)
|
r = rand.create(t.seed + seed_incr)
|
||||||
|
context.random_generator = rand.default_random_generator(&r)
|
||||||
|
|
||||||
for _ in 0..<half_entries {
|
for _ in 0..<half_entries {
|
||||||
k := rand.int63(&r)
|
k := rand.int63()
|
||||||
v := rand.int63(&r)
|
v := rand.int63()
|
||||||
|
|
||||||
m[k] = v + 42
|
m[k] = v + 42
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset randomizer and verify
|
// Reset randomizer and verify
|
||||||
r = rand.create(t.seed + seed_incr)
|
r = rand.create(t.seed + seed_incr)
|
||||||
|
context.random_generator = rand.default_random_generator(&r)
|
||||||
|
|
||||||
num_fails := 0
|
num_fails := 0
|
||||||
for i in 0..<entries {
|
for i in 0..<entries {
|
||||||
k := rand.int63(&r)
|
k := rand.int63()
|
||||||
v := rand.int63(&r)
|
v := rand.int63()
|
||||||
|
|
||||||
diff := i64(42) if i < half_entries else i64(0)
|
diff := i64(42) if i < half_entries else i64(0)
|
||||||
cond := m[k] == (v + diff)
|
cond := m[k] == (v + diff)
|
||||||
@@ -129,9 +136,11 @@ map_delete_random_key_value :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
unique_keys := 0
|
unique_keys := 0
|
||||||
r := rand.create(t.seed + seed_incr)
|
r := rand.create(t.seed + seed_incr)
|
||||||
|
context.random_generator = rand.default_random_generator(&r)
|
||||||
|
|
||||||
for _ in 0..<entries {
|
for _ in 0..<entries {
|
||||||
k := rand.int63(&r)
|
k := rand.int63()
|
||||||
v := rand.int63(&r)
|
v := rand.int63()
|
||||||
|
|
||||||
if k not_in m {
|
if k not_in m {
|
||||||
unique_keys += 1
|
unique_keys += 1
|
||||||
@@ -151,20 +160,23 @@ map_delete_random_key_value :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
// Reset randomizer and delete half the entries
|
// Reset randomizer and delete half the entries
|
||||||
r = rand.create(t.seed + seed_incr)
|
r = rand.create(t.seed + seed_incr)
|
||||||
|
context.random_generator = rand.default_random_generator(&r)
|
||||||
|
|
||||||
for _ in 0..<half_entries {
|
for _ in 0..<half_entries {
|
||||||
k := rand.int63(&r)
|
k := rand.int63()
|
||||||
_ = rand.int63(&r)
|
_ = rand.int63()
|
||||||
|
|
||||||
delete_key(&m, k)
|
delete_key(&m, k)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset randomizer and verify
|
// Reset randomizer and verify
|
||||||
r = rand.create(t.seed + seed_incr)
|
r = rand.create(t.seed + seed_incr)
|
||||||
|
context.random_generator = rand.default_random_generator(&r)
|
||||||
|
|
||||||
num_fails := 0
|
num_fails := 0
|
||||||
for i in 0..<entries {
|
for i in 0..<entries {
|
||||||
k := rand.int63(&r)
|
k := rand.int63()
|
||||||
v := rand.int63(&r)
|
v := rand.int63()
|
||||||
|
|
||||||
if i < half_entries {
|
if i < half_entries {
|
||||||
if k in m {
|
if k in m {
|
||||||
@@ -207,8 +219,10 @@ set_insert_random_key_value :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
unique_keys := 0
|
unique_keys := 0
|
||||||
r := rand.create(t.seed + seed_incr)
|
r := rand.create(t.seed + seed_incr)
|
||||||
|
context.random_generator = rand.default_random_generator(&r)
|
||||||
|
|
||||||
for _ in 0..<entries {
|
for _ in 0..<entries {
|
||||||
k := rand.int63(&r)
|
k := rand.int63()
|
||||||
if k not_in m {
|
if k not_in m {
|
||||||
unique_keys += 1
|
unique_keys += 1
|
||||||
}
|
}
|
||||||
@@ -225,10 +239,11 @@ set_insert_random_key_value :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
// Reset randomizer and verify
|
// Reset randomizer and verify
|
||||||
r = rand.create(t.seed + seed_incr)
|
r = rand.create(t.seed + seed_incr)
|
||||||
|
context.random_generator = rand.default_random_generator(&r)
|
||||||
|
|
||||||
num_fails := 0
|
num_fails := 0
|
||||||
for _ in 0..<entries {
|
for _ in 0..<entries {
|
||||||
k := rand.int63(&r)
|
k := rand.int63()
|
||||||
|
|
||||||
cond := k in m
|
cond := k in m
|
||||||
if !cond {
|
if !cond {
|
||||||
@@ -254,8 +269,10 @@ set_delete_random_key_value :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
unique_keys := 0
|
unique_keys := 0
|
||||||
r := rand.create(t.seed + seed_incr)
|
r := rand.create(t.seed + seed_incr)
|
||||||
|
context.random_generator = rand.default_random_generator(&r)
|
||||||
|
|
||||||
for _ in 0..<entries {
|
for _ in 0..<entries {
|
||||||
k := rand.int63(&r)
|
k := rand.int63()
|
||||||
|
|
||||||
if k not_in m {
|
if k not_in m {
|
||||||
unique_keys += 1
|
unique_keys += 1
|
||||||
@@ -275,17 +292,20 @@ set_delete_random_key_value :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
// Reset randomizer and delete half the entries
|
// Reset randomizer and delete half the entries
|
||||||
r = rand.create(t.seed + seed_incr)
|
r = rand.create(t.seed + seed_incr)
|
||||||
|
context.random_generator = rand.default_random_generator(&r)
|
||||||
|
|
||||||
for _ in 0..<half_entries {
|
for _ in 0..<half_entries {
|
||||||
k := rand.int63(&r)
|
k := rand.int63()
|
||||||
delete_key(&m, k)
|
delete_key(&m, k)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset randomizer and verify
|
// Reset randomizer and verify
|
||||||
r = rand.create(t.seed + seed_incr)
|
r = rand.create(t.seed + seed_incr)
|
||||||
|
context.random_generator = rand.default_random_generator(&r)
|
||||||
|
|
||||||
num_fails := 0
|
num_fails := 0
|
||||||
for i in 0..<entries {
|
for i in 0..<entries {
|
||||||
k := rand.int63(&r)
|
k := rand.int63()
|
||||||
|
|
||||||
if i < half_entries {
|
if i < half_entries {
|
||||||
if k in m {
|
if k in m {
|
||||||
|
|||||||
Reference in New Issue
Block a user