()
| 640 | |
| 641 | #[test] |
| 642 | fn test_prf_output_permutation() -> Result<()> { |
| 643 | let mut prf = Prf::new(None)?; |
| 644 | let mut helper = |n: u64| -> Result<()> { |
| 645 | let result_type = array_type(vec![n], UINT64); |
| 646 | let mut perm_statistics: HashMap<Vec<u64>, u64> = HashMap::new(); |
| 647 | let expected_count_per_perm = 100; |
| 648 | let n_factorial: u64 = (2..=n).product(); |
| 649 | let runs = expected_count_per_perm * n_factorial; |
| 650 | for input in 0..runs { |
| 651 | let result_value = prf.output_permutation(input, n)?; |
| 652 | let perm = result_value.to_flattened_array_u64(result_type.clone())?; |
| 653 | |
| 654 | let mut perm_sorted = perm.clone(); |
| 655 | perm_sorted.sort(); |
| 656 | let range_vec: Vec<u64> = (0..n).collect(); |
| 657 | assert_eq!(perm_sorted, range_vec); |
| 658 | |
| 659 | perm_statistics |
| 660 | .entry(perm) |
| 661 | .and_modify(|counter| *counter += 1) |
| 662 | .or_insert(0); |
| 663 | } |
| 664 | |
| 665 | // Check that all permutations occurred in the experiments |
| 666 | assert_eq!(perm_statistics.len() as u64, n_factorial); |
| 667 | |
| 668 | // Chi-square test with significance level 10^(-6) |
| 669 | // <https://www.itl.nist.gov/div898/handbook/eda/section3/eda35f.htm> |
| 670 | if n > 1 { |
| 671 | let counters: Vec<u64> = perm_statistics.values().map(|c| *c).collect(); |
| 672 | let chi2 = chi_statistics(&counters, expected_count_per_perm); |
| 673 | // Critical value is computed with n!-1 degrees of freedom |
| 674 | if n == 4 { |
| 675 | assert!(chi2 < 70.5496_f64); |
| 676 | } |
| 677 | if n == 5 { |
| 678 | assert!(chi2 < 207.1986_f64); |
| 679 | } |
| 680 | } |
| 681 | Ok(()) |
| 682 | }; |
| 683 | helper(1)?; |
| 684 | helper(4)?; |
| 685 | helper(5) |
| 686 | } |
| 687 | |
| 688 | #[test] |
| 689 | fn test_prf_output_permutation_correctness() -> Result<()> { |
nothing calls this directly
no test coverage detected