shithub: mc

Download patch

ref: 19dceaeb821c3288d0b593bb9ab495906b8bbaa4
parent: 7bdc67c54c5947c4f5c2f31a44a67e1c5409eb2f
author: Ori Bernstein <[email protected]>
date: Mon Dec 16 20:52:16 EST 2013

Fix the random number de-biasing.

--- a/libstd/rand.myr
+++ b/libstd/rand.myr
@@ -80,33 +80,37 @@
 }
 
 /*
-   Generates a random integer from `rng` in the range [lo, hi],
+   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 span, lim
 	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
+	span = hi - lo
+	maxrand = (1 << (8*sizeof(@a))) - 1 /* max for signed value */
+	if maxrand < 0 /* signed */
+		maxrand = (1 << (8*sizeof(@a)-1)) - 1 /* max for signed value */
 	;;
-	-> val + lo
+
+	lim = (maxrand/span)*span
+	val = (randN(rng) & maxrand)
+	while val > lim 
+		put("Rejected!\n")
+		val = (randN(rng) & maxrand)
+	;;
+	-> val % span + lo
 }
 
 /*
    Generates a random integer of any size from the
-   random number generator `rng`.
+   random number generator `rng`. The returned value
+   may be negative, if the type is signed.
 */
 generic randN = {rng -> @a::(tcint,tcnum,tctest)
 	var i, val