1extern crate rand;
18extern crate num;
19
20use rand::{Rng};
21use std::ops::Add;
22use rand::distributions::range::SampleRange;
23use std::fmt::Display;
24
25use num::traits::{One};
26
27#[allow(dead_code)]
31pub fn random_range<T>(low: T, high: T) -> T
32 where T: PartialOrd + Add<Output=T> + SampleRange + Display + One
33{
34
35 if low > high {
36 panic!("Low({}) is higher than high({}).", low, high);
37 }
38
39 let mut rng = rand::thread_rng();
40 let higher = high + T::one();
41 rng.gen_range::<T>(low, higher)
42}
43
44
45#[cfg(test)]
46mod tests {
47
48 use super::random_range;
49 use std::collections::HashMap;
50 use std::cmp::{max, min};
51
52 #[test]
53 #[should_panic(expected = "Low(10) is higher than high(5).")]
54 fn random_range_bad_arguments() {
55 random_range(10, 5);
56 }
57
58 #[test]
59 fn random_range_equal_arguments() {
60 for _ in 1..1000 {
61 assert_eq!(random_range(10, 10), 10);
62 }
63 }
64
65 #[test]
66 fn random_range_arguments() {
77 let low = 1;
78 let high = 1_000;
79 let each_number_times = 10_000;
80 let rand_numbers_count = (high-low+1) * each_number_times;
81 let mut results: HashMap<i32, i32> = HashMap::new();
82
83 for _ in 1..rand_numbers_count {
84 let r = random_range(low, high);
85 let counter = results.entry(r).or_insert(1);
86 *counter += 1;
87 }
88
89 let mut sum: i64 = 0;
91 let mut max_count = 0;
92 let mut min_count = rand_numbers_count * 10;
93 for (k ,v) in &results {
94 sum = sum + (*v as i64) * (*k as i64);
95 min_count = min(min_count, *v);
96 max_count = max(max_count, *v);
97 }
98 assert_eq!(results.len(), (high-low+1) as usize);
99 let average = sum as f32 / rand_numbers_count as f32;
100 let expected_average = (high + low) as f32 / 2.0;
101
102 assert!( expected_average <= average * 1.001);
103 assert!( expected_average >= average * 0.999);
104
105 assert!( (min_count as f32) > each_number_times as f32 * 0.95);
106 assert!( (min_count as f32) < each_number_times as f32 * 1.05);
107 }
108
109}