strided_view/
auxiliary.rs

1//! Auxiliary routines ported from StridedViews.jl/src/auxiliary.jl
2
3/// Compute the relative order of strides.
4///
5/// Returns a vector where `result[i]` is the rank of `strides[i]` among all non-zero strides.
6/// Zero strides have order 1.
7///
8/// # Julia equivalent
9/// ```julia
10/// function indexorder(strides::NTuple{N,Int}) where {N}
11///     return ntuple(Val(N)) do i
12///         si = abs(strides[i])
13///         si == 0 && return 1
14///         k = 1
15///         for s in strides
16///             if s != 0 && abs(s) < si
17///                 k += 1
18///             end
19///         end
20///         return k
21///     end
22/// end
23/// ```
24pub fn index_order(strides: &[isize]) -> Vec<usize> {
25    let n = strides.len();
26    let mut result = vec![1usize; n];
27
28    for i in 0..n {
29        let si = strides[i].unsigned_abs();
30        if si == 0 {
31            result[i] = 1;
32            continue;
33        }
34        let mut k = 1usize;
35        for &s in strides {
36            if s != 0 && s.unsigned_abs() < si {
37                k += 1;
38            }
39        }
40        result[i] = k;
41    }
42
43    result
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49
50    #[test]
51    fn test_index_order() {
52        // strides [4, 1, 2]: order is [3, 1, 2] (4 is largest, 1 is smallest, 2 is middle)
53        let order = index_order(&[4, 1, 2]);
54        assert_eq!(order, vec![3, 1, 2]);
55    }
56
57    #[test]
58    fn test_index_order_with_zero() {
59        // Zero strides have order 1
60        let order = index_order(&[4, 0, 2]);
61        assert_eq!(order, vec![2, 1, 1]);
62    }
63
64    #[test]
65    fn test_index_order_negative_strides() {
66        let order = index_order(&[-4, 1, -2]);
67        assert_eq!(order, vec![3, 1, 2]);
68    }
69
70    #[test]
71    fn test_index_order_tied_strides() {
72        let order = index_order(&[2, 2, 1]);
73        assert_eq!(order, vec![2, 2, 1]);
74    }
75
76    #[test]
77    fn test_index_order_all_same() {
78        let order = index_order(&[3, 3, 3]);
79        assert_eq!(order, vec![1, 1, 1]);
80    }
81}