shithub: mc

Download patch

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));
     }
 }