multidimensional-arrayrustrust-ndarray

What's alternative for roll() in rust Ndarray crate?


There is a roll function in Numpy. But ndarray docs don't mention anything similar.

I am trying to "roll" my array by an integer. For example

let ar = arr2(&[[1.,2.,3.], [7., 8., 9.]]);

calling numpy roll(ar, 1) would produce the desired result:

[[3.,1., 2.],
 [9., 7., 8.]]

Is there an alternative for ndarray in rust or a workaround?

Update: Found this old open thread, not sure if any more up to date solution has been implemented: https://github.com/rust-ndarray/ndarray/issues/281


Solution

  • Ndarray documentation provides an example: https://docs.rs/ndarray/latest/ndarray/struct.ArrayBase.html#method.uninit

    However, it did not give expected result. I ammended it slightly:

    /// Shifts 2D array by {int} to the right
    /// Creates a new Array2 (cloning)
    fn shift_right_by(by: usize, a: &Array2<f64>) -> Array2<f64> {
        // if shift_by is > than number of columns
        let x: isize = (by % a.len_of(Axis(1))) as isize;
    
        // if shift by 0 simply return the original
        if x == 0 {
            return a.clone();
        }
        // create an uninitialized array
        let mut b = Array2::uninit(a.dim());
    
        // x first columns in b are two last in a
        // rest of columns in b are the initial columns in a
        a.slice(s![.., -x..]).assign_to(b.slice_mut(s![.., ..x]));
        a.slice(s![.., ..-x]).assign_to(b.slice_mut(s![.., x..]));
    
        // Now we can promise that `b` is safe to use with all operations
        unsafe { b.assume_init() }
    }