1
/// Returns true iff the given permutation is a bijective mapping within the 0..max range.
2
3260
pub fn is_valid_permutation<P>(permutation: P, max: usize) -> bool
3
3260
where
4
3260
    P: Fn(usize) -> usize,
5
{
6
3260
    let mut visited = vec![false; max];
7

            
8
444509
    for i in 0..max {
9
        // Out of bounds
10
444509
        if permutation(i) >= max {
11
100
            return false;
12
444409
        }
13

            
14
444409
        if visited[permutation(i)] {
15
100
            return false;
16
444309
        }
17
444309
        visited[permutation(i)] = true;
18
    }
19

            
20
3060
    true
21
3260
}
22

            
23
#[cfg(test)]
24
mod tests {
25

            
26
    use super::*;
27

            
28
    use crate::random_test;
29
    use rand::seq::SliceRandom;
30

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

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

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

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