about summary refs log tree commit diff
path: root/src/fuzzer
diff options
context:
space:
mode:
authorJesse Ruderman <jruderman@gmail.com>2011-09-23 23:24:43 -0700
committerJesse Ruderman <jruderman@gmail.com>2011-09-23 23:24:43 -0700
commitfbe00fc23650f4e6f7d7c8093c8f9dbbdb61661a (patch)
tree17b23d6e2841f3b564fdc79a4772da1b84489c4f /src/fuzzer
parent3bac3378aeefad870404b3e4a3618c912600ce6a (diff)
downloadrust-fbe00fc23650f4e6f7d7c8093c8f9dbbdb61661a.tar.gz
rust-fbe00fc23650f4e6f7d7c8093c8f9dbbdb61661a.zip
Add rand_util.rs
Diffstat (limited to 'src/fuzzer')
-rw-r--r--src/fuzzer/rand_util.rs93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/fuzzer/rand_util.rs b/src/fuzzer/rand_util.rs
new file mode 100644
index 00000000000..ad6fc958e76
--- /dev/null
+++ b/src/fuzzer/rand_util.rs
@@ -0,0 +1,93 @@
+use std;
+import std::rand;
+import std::vec;
+
+// random uint less than n
+fn under(r : rand::rng, n : uint) -> uint { assert n != 0u; r.next() as uint % n }
+
+// random choice from a vec
+fn choice<T>(r : rand::rng, v : [T]) -> T { assert vec::len(v) != 0u; v[under(r, vec::len(v))] }
+
+// 1 in n chance of being true
+fn unlikely(r : rand::rng, n : uint) -> bool { under(r, n) == 0u }
+
+// shuffle a vec in place
+fn shuffle<@T>(r : rand::rng, &v : [mutable T]) {
+    let i = vec::len(v);
+    while i >= 2u {
+        // Loop invariant: elements with index >= i have been locked in place.
+        i -= 1u;
+        vec::swap(v, i, under(r, i + 1u)); // Lock element i in place.
+    }
+}
+
+// create a shuffled copy of a vec
+fn shuffled<@T>(r : rand::rng, v : [T]) -> [T] {
+    let w = vec::to_mut(v);
+    shuffle(r, w);
+    vec::from_mut(w) // Shouldn't this happen automatically?
+}
+
+// sample from a population without replacement
+//fn sample<T>(r : rand::rng, pop : [T], k : uint) -> [T] { fail }
+
+// Two ways to make a weighted choice.
+// * weighted_choice is O(number of choices) time
+// * weighted_vec is O(total weight) space
+type weighted<T> = { weight: uint, item: T };
+fn weighted_choice<@T>(r : rand::rng, v : [weighted<T>]) -> T {
+    assert vec::len(v) != 0u;
+    let total = 0u;
+    for {weight: weight, item: _} in v {
+        total += weight;
+    }
+    assert total >= 0u;
+    let chosen = under(r, total);
+    let so_far = 0u;
+    for {weight: weight, item: item} in v {
+        so_far += weight;
+        if so_far > chosen {
+            ret item;
+        }
+    }
+    std::util::unreachable();
+}
+
+fn weighted_vec<T>(v : [weighted<T>]) -> [T] {
+    let r = [];
+    for {weight: weight, item: item} in v {
+        let i = 0u;
+        while i < weight {
+            r += [item];
+            i += 1u;
+        }
+    }
+    r
+}
+
+fn main()
+{
+    let r = rand::mk_rng();
+
+    log_err under(r, 5u);
+    log_err choice(r, [10, 20, 30]);
+    log_err if unlikely(r, 5u) { "unlikely" } else { "likely" };
+
+    let a = [mutable 1, 2, 3];
+    shuffle(r, a);
+    log_err a;
+
+    let i = 0u;
+    let v = [
+        {weight:1u, item:"low"},
+        {weight:8u, item:"middle"},
+        {weight:1u, item:"high"}
+    ];
+    let w = weighted_vec(v);
+
+    while i < 1000u {
+        log_err "Immed: " + weighted_choice(r, v);
+        log_err "Fast: " + choice(r, w);
+        i += 1u;
+    }
+}