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