Browse Source

Update `core:math/rand` to use `context.random_generator` and remove `rand.Rand`

gingerBill 1 year ago
parent
commit
7ec17ecf98

+ 16 - 2
base/runtime/random_generator.odin

@@ -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,
 	}
 	}
 }
 }

+ 60 - 60
core/math/rand/distributions.odin

@@ -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 {
-	return norm_float64(r) * stddev + mean
+float64_normal :: proc(mean, stddev: f64) -> f64 {
+	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 {
-	return f32(float64_normal(f64(mean), f64(stddev), r))
+float32_normal :: proc(mean, stddev: f32) -> f32 {
+	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 {
-	return math.exp(float64_normal(mean, stddev, r))
+float64_log_normal :: proc(mean, stddev: f64) -> f64 {
+	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 {
-	return f32(float64_log_normal(f64(mean), f64(stddev), r))
+float32_log_normal :: proc(mean, stddev: f32) -> f32 {
+	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 {
-	return - math.ln(1 - float64(r)) / lambda
+float64_exponential :: proc(lambda: f64) -> f64 {
+	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 {
-	return f32(float64_exponential(f64(lambda), r))
+float32_exponential :: proc(lambda: f32) -> f32 {
+	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 {
-	return f32(float64_gamma(f64(alpha), f64(beta), r))
+float32_gamma :: proc(alpha, beta: f32) -> f32 {
+	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 {
-	return f32(float64_beta(f64(alpha), f64(beta), r))
+float32_beta :: proc(alpha, beta: f32) -> f32 {
+	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 {
-	return math.pow(1 - float64(r), -1.0 / alpha)
+float64_pareto :: proc(alpha: f64) -> f64 {
+	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 {
-	return f32(float64_pareto(f64(alpha), r))
+float32_pareto :: proc(alpha, beta: f32) -> f32 {
+	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 {
-	u := 1 - float64(r)
+float64_weibull :: proc(alpha, beta: f64) -> f64 {
+	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 {
-	return f32(float64_weibull(f64(alpha), f64(beta), r))
+float32_weibull :: proc(alpha, beta: f32) -> f32 {
+	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 {
-	return f32(float64_von_mises(f64(mean_angle), f64(kappa), r))
+float32_von_mises :: proc(mean_angle, kappa: f32) -> f32 {
+	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 {
-	return f32(float64_cauchy_lorentz(f64(x_0), f64(gamma), r))
+float32_cauchy_lorentz :: proc(x_0, gamma: f32) -> f32 {
+	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 {
-	return f32(float64_log_cauchy_lorentz(f64(x_0), f64(gamma), r))
+float32_log_cauchy_lorentz :: proc(x_0, gamma: f32) -> f32 {
+	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 {
-	return f32(float64_laplace(f64(mean), f64(b), r))
+float32_laplace :: proc(mean, b: f32) -> f32 {
+	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 {
-	return f32(float64_gompertz(f64(eta), f64(b), r))
+float32_gompertz :: proc(eta, b: f32) -> f32 {
+	return f32(float64_gompertz(f64(eta), f64(b)))
 }
 }

+ 4 - 4
core/math/rand/exp.odin

@@ -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
 		}
 		}
 	}
 	}

+ 5 - 5
core/math/rand/normal.odin

@@ -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)
-				y := -math.ln(float64(r))
+				x = -math.ln(float64()) * (1.0/ rn)
+				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
 		}
 		}
 	}
 	}

+ 61 - 288
core/math/rand/rand.odin

@@ -10,52 +10,18 @@ import "core:crypto"
 import "core:math"
 import "core:math"
 import "core:mem"
 import "core:mem"
 
 
-Rand :: struct {
-	state: u64,
-	inc:   u64,
-	is_system: bool,
-}
+Default_Random_State :: runtime.Default_Random_State
+default_random_generator :: runtime.default_random_generator
 
 
-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,
-	}
+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
 }
 }
 
 
-
-@(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
-
-Returns:
-- res: The created random number generator
-
-Example:
-	import "core:math/rand"
-	import "core:fmt"
-
-	create_example :: proc() {
-		my_rand := rand.create(1)
-		fmt.println(rand.uint64(&my_rand))
-	}
-
-Possible Output:
-
-	10
-
-*/
-@(require_results)
-create :: proc(seed: u64) -> (res: Rand) {
-	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
+- seed: The seed value
 
 
 Example:
 Example:
 	import "core:math/rand"
 	import "core:math/rand"
 	import "core:fmt"
 	import "core:fmt"
 
 
-	init_example :: proc() {
-		my_rand: rand.Rand
-		rand.init(&my_rand, 1)
-		fmt.println(rand.uint64(&my_rand))
+	set_global_seed_example :: proc() {
+		rand.set_global_seed(1)
+		fmt.println(rand.uint64())
 	}
 	}
 
 
 Possible Output:
 Possible Output:
 
 
 	10
 	10
-
 */
 */
-init :: proc(r: ^Rand, seed: u64) {
-	r.state = 0
-	r.inc = (seed << 1) | 1
-	_random_u64(r)
-	r.state += seed
-	_random_u64(r)
+reset :: proc(seed: u64) {
+	runtime.random_generator_reset_u64(context.random_generator, seed)
 }
 }
 
 
-/*
-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 {
-	r := r
-	switch {
-	case r == nil:
-		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))
+_random_u64 :: proc() -> (res: u64) {
+	ok := runtime.random_generator_read_ptr(context.random_generator, &res, size_of(res))
+	assert(ok, "uninitialized context.random_generator")
+	return
 }
 }
 
 
 /*
 /*
 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) {
-	a := u128(_random_u64(r))
-	b := u128(_random_u64(r))
+uint128 :: proc() -> (val: u128) {
+	a := u128(_random_u64())
+	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)
 	}
 	}

+ 2 - 1
tests/core/hash/test_core_hash.odin

@@ -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
 			}
 			}

+ 7 - 5
tests/core/slice/test_core_slice.odin

@@ -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)

+ 41 - 21
tests/internal/test_map.odin

@@ -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)
-			v := rand.int63(&r)
+			k := rand.int63()
+			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)
-			v := rand.int63(&r)
+			k := rand.int63()
+			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)
-			v := rand.int63(&r)
+			k := rand.int63()
+			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)
-			v := rand.int63(&r)
+			k := rand.int63()
+			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)
-			v := rand.int63(&r)
+			k := rand.int63()
+			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)
-			v := rand.int63(&r)
+			k := rand.int63()
+			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)
-			_  = rand.int63(&r)
+			k := rand.int63()
+			_  = 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)
-			v := rand.int63(&r)
+			k := rand.int63()
+			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 {