#[derive(Debug, Clone)]
pub enum Order {
RowMajor,
ColumnMajor,
}
pub fn address(order: &Order, shape: &[usize], index: &[usize]) -> usize {
match order {
Order::RowMajor => row_major_address(shape, index),
Order::ColumnMajor => col_major_address(shape, index),
}
}
fn row_major_address(shape: &[usize], index: &[usize]) -> usize {
let d = {
assert_eq!(shape.len(), index.len());
shape.len()
};
let mut res = index[0];
for i in 1..d {
res = res * shape[i] + index[i];
}
res
}
fn col_major_address(shape: &[usize], index: &[usize]) -> usize {
let d = {
assert_eq!(shape.len(), index.len());
shape.len()
};
let mut res = index[d - 1];
for i in (0..(d - 1)).rev() {
res = res * shape[i] + index[i];
}
res
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn row_major_test_2d() {
assert_eq!(row_major_address(&[2, 3], &[0, 0]), 0);
assert_eq!(row_major_address(&[2, 3], &[0, 1]), 1);
assert_eq!(row_major_address(&[2, 3], &[0, 2]), 2);
assert_eq!(row_major_address(&[2, 3], &[1, 0]), 3);
assert_eq!(row_major_address(&[2, 3], &[1, 1]), 4);
assert_eq!(row_major_address(&[2, 3], &[1, 2]), 5);
}
#[test]
fn col_major_test_2d() {
assert_eq!(col_major_address(&[2, 3], &[0, 0]), 0);
assert_eq!(col_major_address(&[2, 3], &[1, 0]), 1);
assert_eq!(col_major_address(&[2, 3], &[0, 1]), 2);
assert_eq!(col_major_address(&[2, 3], &[1, 1]), 3);
assert_eq!(col_major_address(&[2, 3], &[0, 2]), 4);
assert_eq!(col_major_address(&[2, 3], &[1, 2]), 5);
}
}