ref: 79f9ac7bc6aa7d3bd82568d022ca3c4ead841873
parent: 7b59bf042653209380b3a722184be80d7e9d81f9
author: Ori Bernstein <[email protected]>
date: Mon Dec 16 18:43:05 EST 2013
Add ranged random generation
--- a/libstd/rand.myr
+++ b/libstd/rand.myr
@@ -48,9 +48,9 @@
pkg std =
type rng
- /* no mkrng() yet because we don't have anything to automatically
- seed it with yet */
const mksrng : (seed : uint32 -> rng#)
+ generic rand : (rng : rng#, lo : @a::(tcnum,tctest,tcint), hi : @a::(tcnum,tctest,tcint) -> @a::(tcnum,tctest,tcint))
+ generic randN : (rng : rng# -> @a::(tcnum,tctest,tcint))
const rand32 : (rng : rng# -> uint32)
;;
@@ -59,6 +59,7 @@
i : uint32
;;
+/* allocates and initializes a random number generator */
const mksrng = {seed
var rng
@@ -67,6 +68,7 @@
-> rng
}
+/* initializes a random number generator from the seed `seed`. */
const init = {rng, seed
var i
@@ -77,7 +79,50 @@
rng.i = i
}
+/*
+ Generates a random integer from `rng` in the range [lo, hi],
+ returning the value. The range [lo, hi) must be positive,
+ nonempty, and the difference between hi and lo must be
+ less then 2^(type_bits - 1)
+*/
+generic rand = {rng, lo, hi -> @a::(tcint,tcnum,tctest)
+ var span, div
+ var maxrand
+ var val
+ span = hi - lo
+ maxrand = (1 << (8*sizeof(@a)-1)) - 1
+
+ assert(hi - lo > 0, "rand.myr: range for random values must be >= 1")
+ assert(span < maxrand, "rand.myr: span of ranges is too large")
+ div = maxrand/(span+1)
+ val = (randN(rng) & maxrand) / div
+
+ while val >= span
+ val = randN(rng) / div
+ ;;
+ -> val + lo
+}
+
+/*
+ Generates a random integer of any size from the
+ random number generator `rng`.
+*/
+generic randN = {rng -> @a::(tcint,tcnum,tctest)
+ var i, val
+
+ val = 0
+ for i = 0; i < sizeof(@a)/4; i++
+ val <<= 8*sizeof(@a)
+ val |= rand32(rng) castto(@a::(tcint,tcnum,tctest))
+ ;;
+ -> val
+}
+
+/*
+ generates a 32 bit unsigned random number
+ from the random number generator `rng`.
+*/
const rand32 = {rng
var x
@@ -94,6 +139,7 @@
}
+/* updates random number generator state when we tick over. */
const next = {rng
var k
var y
--- a/libstd/test.myr
+++ b/libstd/test.myr
@@ -108,8 +108,8 @@
var i
r = std.mksrng(10)
- for i = 0; i < 10; i++
- std.put("r[%i] = %l\n", i, std.rand32(r) castto(int64))
+ for i = 0; i < 300; i++
+ std.put("r[%i] = %l\n", i, std.rand(r, 5, 10) castto(int64))
;;
std.put("\n");
}
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -1567,7 +1567,7 @@
} else if ((t->type >= Tybyte && t->type <= Tyulong) || t->type == Tychar) {
uval = n->lit.intval;
if (uval < uvranges[t->type][0] || uval > uvranges[t->type][1])
- fatal(n->line, "Literal value %llu out of range for type \"%s\"", tystr(t));
+ fatal(n->line, "Literal value %llu out of range for type \"%s\"", uval, tystr(t));
}
}