1
/// Returns true iff the given permutation is a bijective mapping within the 0..max range.
2
///
3
/// This check requires O(max) time and space, so it should only be used for testing purposes.
4
5721
pub fn is_valid_permutation<P>(permutation: P, max: usize) -> bool
5
5721
where
6
5721
    P: Fn(usize) -> usize,
7
{
8
5721
    let mut visited = vec![false; max];
9

            
10
1662822
    for i in 0..max {
11
        // Out of bounds
12
1662822
        if permutation(i) >= max {
13
100
            return false;
14
1662722
        }
15

            
16
1662722
        if visited[permutation(i)] {
17
100
            return false;
18
1662622
        }
19
1662622
        visited[permutation(i)] = true;
20
    }
21

            
22
5521
    true
23
5721
}
24

            
25
#[cfg(test)]
26
mod tests {
27
    use rand::seq::SliceRandom;
28

            
29
    use crate::is_valid_permutation;
30
    use crate::random_test;
31

            
32
    #[test]
33
    #[cfg_attr(miri, ignore)] // Test is too slow under miri
34
1
    fn test_random_is_valid_permutation() {
35
100
        random_test(100, |rng| {
36
            // Generate a valid permutation.
37
100
            let valid_permutation: Vec<usize> = {
38
100
                let mut order: Vec<usize> = (0..100).collect();
39
100
                order.shuffle(rng);
40
100
                order
41
            };
42

            
43
30000
            assert!(is_valid_permutation(|i| valid_permutation[i], valid_permutation.len()));
44

            
45
            // Generate an invalid permutation (duplicate entries).
46
100
            let invalid_permutation = [0, 1, 2, 3, 4, 5, 6, 7, 8, 8];
47
100
            assert!(!is_valid_permutation(
48
2900
                |i| invalid_permutation[i],
49
100
                invalid_permutation.len()
50
            ));
51

            
52
            // Generate an invalid permutation (missing entries).
53
100
            let invalid_permutation = [0, 1, 3, 4, 5, 6, 7, 8];
54
100
            assert!(!is_valid_permutation(
55
2200
                |i| invalid_permutation[i],
56
100
                invalid_permutation.len()
57
            ));
58
100
        });
59
1
    }
60
}