feat: add WELL512-based Random module with seed, float, and int methods
Implement a new `random` module for the Wren language runtime, providing a `Random` class backed by the WELL512a PRNG algorithm. The module supports three seeding strategies (time-based, single numeric seed, and 16-element sequence), generates uniform floats in [0,1) and integers in the full uint32 range, and includes convenience methods for bounded ranges. The implementation adds the C foreign functions `randomAllocate`, `randomSeed0`, `randomSeed1`, `randomSeed16`, `randomFloat`, and `randomInt0`, registers them in the module registry, and includes the Wren wrapper class with constructors accepting no arguments, a number, or a sequence. The commit also adds 12 test scripts covering float/int generation, seeding reproducibility, and error handling for invalid seed types.
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
import "random" for Random
|
||||
|
||||
var random = Random.new(12345)
|
||||
|
||||
var below = 0
|
||||
for (i in 1..1000) {
|
||||
var n = random.float()
|
||||
if (n < 0.5) below = below + 1
|
||||
}
|
||||
|
||||
// Should be roughly evenly distributed.
|
||||
System.print(below > 450) // expect: true
|
||||
System.print(below < 550) // expect: true
|
||||
@@ -0,0 +1,10 @@
|
||||
import "random" for Random
|
||||
|
||||
var random = Random.new(12345)
|
||||
|
||||
var below = 0
|
||||
for (i in 1..100) {
|
||||
var n = random.float(5)
|
||||
if (n < 0) System.print("too low")
|
||||
if (n >= 5) System.print("too high")
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import "random" for Random
|
||||
|
||||
var random = Random.new(12345)
|
||||
|
||||
var below = 0
|
||||
for (i in 1..100) {
|
||||
var n = random.float(2, 5)
|
||||
if (n < 2) System.print("too low")
|
||||
if (n >= 5) System.print("too high")
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import "random" for Random
|
||||
|
||||
var random = Random.new(12345)
|
||||
|
||||
var below = 0
|
||||
for (i in 1..1000) {
|
||||
var n = random.int()
|
||||
if (n < 2147483648) below = below + 1
|
||||
}
|
||||
|
||||
// Should be roughly evenly distributed.
|
||||
System.print(below > 450) // expect: true
|
||||
System.print(below < 550) // expect: true
|
||||
@@ -0,0 +1,14 @@
|
||||
import "random" for Random
|
||||
|
||||
var random = Random.new(12345)
|
||||
|
||||
var counts = [0, 0, 0, 0, 0]
|
||||
for (i in 1..10000) {
|
||||
var n = random.int(5)
|
||||
counts[n] = counts[n] + 1
|
||||
}
|
||||
|
||||
for (count in counts) {
|
||||
if (count < 1900) System.print("too few")
|
||||
if (count > 2100) System.print("too many")
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import "random" for Random
|
||||
|
||||
var random = Random.new(12345)
|
||||
|
||||
var counts = [0, 0, 0, 0, 0, 0, 0, 0]
|
||||
for (i in 1..10000) {
|
||||
var n = random.int(3, 8)
|
||||
counts[n] = counts[n] + 1
|
||||
}
|
||||
|
||||
for (i in 0..2) {
|
||||
if (counts[i] != 0) System.print("too low value")
|
||||
}
|
||||
|
||||
for (i in 3..7) {
|
||||
if (counts[i] < 1900) System.print("too few")
|
||||
if (counts[i] > 2100) System.print("too many")
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import "random" for Random
|
||||
|
||||
var random = Random.new()
|
||||
|
||||
var correct = 0
|
||||
for (i in 1..100) {
|
||||
var n = random.float()
|
||||
if (n >= 0) correct = correct + 1
|
||||
if (n < 1) correct = correct + 1
|
||||
}
|
||||
|
||||
System.print(correct) // expect: 200
|
||||
@@ -0,0 +1,3 @@
|
||||
import "random" for Random
|
||||
|
||||
Random.new([]) // expect runtime error: Sequence cannot be empty.
|
||||
@@ -0,0 +1,12 @@
|
||||
import "random" for Random
|
||||
|
||||
var random1 = Random.new(123)
|
||||
var random2 = Random.new(123)
|
||||
|
||||
var correct = 0
|
||||
for (i in 1..100) {
|
||||
// Should produce the same values.
|
||||
if (random1.float() == random2.float()) correct = correct + 1
|
||||
}
|
||||
|
||||
System.print(correct) // expect: 100
|
||||
@@ -0,0 +1,12 @@
|
||||
import "random" for Random
|
||||
|
||||
var random1 = Random.new([1, 2, 3])
|
||||
var random2 = Random.new([1, 2, 3])
|
||||
|
||||
var correct = 0
|
||||
for (i in 1..100) {
|
||||
// Should produce the same values.
|
||||
if (random1.float() == random2.float()) correct = correct + 1
|
||||
}
|
||||
|
||||
System.print(correct) // expect: 100
|
||||
@@ -0,0 +1,3 @@
|
||||
import "random" for Random
|
||||
|
||||
Random.new(false) // expect runtime error: Seed must be a number or a sequence of numbers.
|
||||
@@ -0,0 +1,3 @@
|
||||
import "random" for Random
|
||||
|
||||
Random.new(["wrong type"]) // expect runtime error: Sequence elements must all be numbers.
|
||||
Reference in New Issue
Block a user