1import mt19937 2import math 3import rand.util 4 5const ( 6 range_limit = 40 7 value_count = 1000 8 seeds = [[u32(0xcafebabe), u32(0xdeadbeef)], [u32(0xc0de), u32(0xfeed)]] 9) 10 11const ( 12 sample_size = 1000 13 stats_epsilon = 0.05 14 inv_sqrt_12 = 1.0 / math.sqrt(12) 15) 16 17fn mt19937_basic_test() { 18 mut rng := mt19937.MT19937RNG{} 19 rng.seed([u32(0xdeadbeef)]) 20 target := [956529277, 3842322136, 3319553134, 1843186657, 2704993644, 595827513, 938518626, 21 1676224337, 3221315650, 1819026461] 22 for i := 0; i < 10; i++ { 23 assert target[i] == rng.u32() 24 } 25} 26 27fn gen_randoms(seed_data []u32, bound int) []u64 { 28 bound_u64 := u64(bound) 29 mut randoms := []u64{len:(20)} 30 mut rnd := mt19937.MT19937RNG{} 31 rnd.seed(seed_data) 32 for i in 0 .. 20 { 33 randoms[i] = rnd.u64n(bound_u64) 34 } 35 return randoms 36} 37 38fn test_mt19937_reproducibility() { 39 seed_data := util.time_seed_array(2) 40 randoms1 := gen_randoms(seed_data, 1000) 41 randoms2 := gen_randoms(seed_data, 1000) 42 assert randoms1.len == randoms2.len 43 len := randoms1.len 44 for i in 0 .. len { 45 assert randoms1[i] == randoms2[i] 46 } 47} 48 49// TODO: use the `in` syntax and remove this function 50// after generics has been completely implemented 51fn found(value u64, arr []u64) bool { 52 for item in arr { 53 if value == item { 54 return true 55 } 56 } 57 return false 58} 59 60fn test_mt19937_variability() { 61 // If this test fails and if it is certainly not the implementation 62 // at fault, try changing the seed values. Repeated values are 63 // improbable but not impossible. 64 for seed in seeds { 65 mut rng := mt19937.MT19937RNG{} 66 rng.seed(seed) 67 mut values := []u64{cap: value_count} 68 for i in 0 .. value_count { 69 value := rng.u64() 70 assert !found(value, values) 71 assert values.len == i 72 values << value 73 } 74 } 75} 76 77fn check_uniformity_u64(mut rng mt19937.MT19937RNG, range u64) { 78 range_f64 := f64(range) 79 expected_mean := range_f64 / 2.0 80 mut variance := 0.0 81 for _ in 0 .. sample_size { 82 diff := f64(rng.u64n(range)) - expected_mean 83 variance += diff * diff 84 } 85 variance /= sample_size - 1 86 sigma := math.sqrt(variance) 87 expected_sigma := range_f64 * inv_sqrt_12 88 error := (sigma - expected_sigma) / expected_sigma 89 assert math.abs(error) < stats_epsilon 90} 91 92fn test_mt19937_uniformity_u64() { 93 ranges := [14019545, 80240, 130] 94 for seed in seeds { 95 mut rng := mt19937.MT19937RNG{} 96 rng.seed(seed) 97 for range in ranges { 98 check_uniformity_u64(mut rng, u64(range)) 99 } 100 } 101} 102 103fn check_uniformity_f64(mut rng mt19937.MT19937RNG) { 104 expected_mean := 0.5 105 mut variance := 0.0 106 for _ in 0 .. sample_size { 107 diff := rng.f64() - expected_mean 108 variance += diff * diff 109 } 110 variance /= sample_size - 1 111 sigma := math.sqrt(variance) 112 expected_sigma := inv_sqrt_12 113 error := (sigma - expected_sigma) / expected_sigma 114 assert math.abs(error) < stats_epsilon 115} 116 117fn test_mt19937_uniformity_f64() { 118 // The f64 version 119 for seed in seeds { 120 mut rng := mt19937.MT19937RNG{} 121 rng.seed(seed) 122 check_uniformity_f64(mut rng) 123 } 124} 125 126fn test_mt19937_u32n() { 127 max := u32(16384) 128 for seed in seeds { 129 mut rng := mt19937.MT19937RNG{} 130 rng.seed(seed) 131 for _ in 0 .. range_limit { 132 value := rng.u32n(max) 133 assert value >= 0 134 assert value < max 135 } 136 } 137} 138 139fn test_mt19937_u64n() { 140 max := u64(379091181005) 141 for seed in seeds { 142 mut rng := mt19937.MT19937RNG{} 143 rng.seed(seed) 144 for _ in 0 .. range_limit { 145 value := rng.u64n(max) 146 assert value >= 0 147 assert value < max 148 } 149 } 150} 151 152fn test_mt19937_u32_in_range() { 153 max := u32(484468466) 154 min := u32(316846) 155 for seed in seeds { 156 mut rng := mt19937.MT19937RNG{} 157 rng.seed(seed) 158 for _ in 0 .. range_limit { 159 value := rng.u32_in_range(min, max) 160 assert value >= min 161 assert value < max 162 } 163 } 164} 165 166fn test_mt19937_u64_in_range() { 167 max := u64(216468454685163) 168 min := u64(6848646868) 169 for seed in seeds { 170 mut rng := mt19937.MT19937RNG{} 171 rng.seed(seed) 172 for _ in 0 .. range_limit { 173 value := rng.u64_in_range(min, max) 174 assert value >= min 175 assert value < max 176 } 177 } 178} 179 180fn test_mt19937_int31() { 181 max_u31 := 0x7FFFFFFF 182 sign_mask := 0x80000000 183 for seed in seeds { 184 mut rng := mt19937.MT19937RNG{} 185 rng.seed(seed) 186 for _ in 0 .. range_limit { 187 value := rng.int31() 188 assert value >= 0 189 assert value <= max_u31 190 // This statement ensures that the sign bit is zero 191 assert (value & sign_mask) == 0 192 } 193 } 194} 195 196fn test_mt19937_int63() { 197 max_u63 := i64(0x7FFFFFFFFFFFFFFF) 198 sign_mask := i64(0x8000000000000000) 199 for seed in seeds { 200 mut rng := mt19937.MT19937RNG{} 201 rng.seed(seed) 202 for _ in 0 .. range_limit { 203 value := rng.int63() 204 assert value >= 0 205 assert value <= max_u63 206 assert (value & sign_mask) == 0 207 } 208 } 209} 210 211fn test_mt19937_intn() { 212 max := 2525642 213 for seed in seeds { 214 mut rng := mt19937.MT19937RNG{} 215 rng.seed(seed) 216 for _ in 0 .. range_limit { 217 value := rng.intn(max) 218 assert value >= 0 219 assert value < max 220 } 221 } 222} 223 224fn test_mt19937_i64n() { 225 max := i64(3246727724653636) 226 for seed in seeds { 227 mut rng := mt19937.MT19937RNG{} 228 rng.seed(seed) 229 for _ in 0 .. range_limit { 230 value := rng.i64n(max) 231 assert value >= 0 232 assert value < max 233 } 234 } 235} 236 237fn test_mt19937_int_in_range() { 238 min := -4252 239 max := 1034 240 for seed in seeds { 241 mut rng := mt19937.MT19937RNG{} 242 rng.seed(seed) 243 for _ in 0 .. range_limit { 244 value := rng.int_in_range(min, max) 245 assert value >= min 246 assert value < max 247 } 248 } 249} 250 251fn test_mt19937_i64_in_range() { 252 min := i64(-24095) 253 max := i64(324058) 254 for seed in seeds { 255 mut rng := mt19937.MT19937RNG{} 256 rng.seed(seed) 257 for _ in 0 .. range_limit { 258 value := rng.i64_in_range(min, max) 259 assert value >= min 260 assert value < max 261 } 262 } 263} 264 265fn test_mt19937_f32() { 266 for seed in seeds { 267 mut rng := mt19937.MT19937RNG{} 268 rng.seed(seed) 269 for _ in 0 .. range_limit { 270 value := rng.f32() 271 assert value >= 0.0 272 assert value < 1.0 273 } 274 } 275} 276 277fn test_mt19937_f64() { 278 for seed in seeds { 279 mut rng := mt19937.MT19937RNG{} 280 rng.seed(seed) 281 for _ in 0 .. range_limit { 282 value := rng.f64() 283 assert value >= 0.0 284 assert value < 1.0 285 } 286 } 287} 288 289fn test_mt19937_f32n() { 290 max := f32(357.0) 291 for seed in seeds { 292 mut rng := mt19937.MT19937RNG{} 293 rng.seed(seed) 294 for _ in 0 .. range_limit { 295 value := rng.f32n(max) 296 assert value >= 0.0 297 assert value < max 298 } 299 } 300} 301 302fn test_mt19937_f64n() { 303 max := 1.52e6 304 for seed in seeds { 305 mut rng := mt19937.MT19937RNG{} 306 rng.seed(seed) 307 for _ in 0 .. range_limit { 308 value := rng.f64n(max) 309 assert value >= 0.0 310 assert value < max 311 } 312 } 313} 314 315fn test_mt19937_f32_in_range() { 316 min := f32(-24.0) 317 max := f32(125.0) 318 for seed in seeds { 319 mut rng := mt19937.MT19937RNG{} 320 rng.seed(seed) 321 for _ in 0 .. range_limit { 322 value := rng.f32_in_range(min, max) 323 assert value >= min 324 assert value < max 325 } 326 } 327} 328 329fn test_mt19937_f64_in_range() { 330 min := -548.7 331 max := 5015.2 332 for seed in seeds { 333 mut rng := mt19937.MT19937RNG{} 334 rng.seed(seed) 335 for _ in 0 .. range_limit { 336 value := rng.f64_in_range(min, max) 337 assert value >= min 338 assert value < max 339 } 340 } 341} 342