Probably easiest to use a crate like ndarray; those data structures support things like swapping dimensions or reversing the order along an axis, and you can do a rotation e.g. like this:
use ndarray::{array, s};
fn main() {
let mut a = array![
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]
];
let mut a90 = a.slice_mut(s![.., ..;-1]).reversed_axes();
dbg!(&a90);
// [[ 4, 8, 12, 16],
// [ 3, 7, 11, 15],
// [ 2, 6, 10, 14],
// [ 1, 5, 9, 13]]
a90[(0,0)] = 99;
a90[(0,1)] = 42;
dbg!(&a90);
// [[99, 42, 12, 16],
// [ 3, 7, 11, 15],
// [ 2, 6, 10, 14],
// [ 1, 5, 9, 13]]
dbg!(&a);
// [[ 1, 2, 3, 99],
// [ 5, 6, 7, 42],
// [ 9, 10, 11, 12],
// [13, 14, 15, 16]]
}
Rust Playground
Edit: That being said, creating the right kind of [[&mut i32; 4]; 4]
-type array isn't out of the question either. Especially with recently-ish stabilized API like <[T; N]>::each_mut
:
use std::array;
fn main() {
let mut a = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]
];
let a90: [[&mut i32; 4]; 4] = {
let mut iters = a.each_mut().map(|line| line.iter_mut().rev());
array::from_fn(|_| iters.each_mut().map(|iter| iter.next().unwrap()))
};
dbg!(&a90);
// [[ 4, 8, 12, 16],
// [ 3, 7, 11, 15],
// [ 2, 6, 10, 14],
// [ 1, 5, 9, 13]]
*a90[0][0] = 99;
*a90[0][1] = 42;
dbg!(&a90);
// [[99, 42, 12, 16],
// [ 3, 7, 11, 15],
// [ 2, 6, 10, 14],
// [ 1, 5, 9, 13]]
dbg!(&a);
// [[ 1, 2, 3, 99],
// [ 5, 6, 7, 42],
// [ 9, 10, 11, 12],
// [13, 14, 15, 16]]
}
Rust Playground
Note that both of these solutions do not allow for interleaved access, i.e. you cannot use a
until you're done with using a90
. If that isn't what you were looking for, feel free to clarify.