0

Here's what I tried

use ndarray::{arr2, s};
let mut a = arr2(&[[1, 2, 3],
                   [4, 5, 6]]);
let b = arr2(&[[2, 3, 3],
               [5, 6, 6]]);

a.slice_mut(s![.., ..2]).assign(&a.slice_mut(s![.., 1..]));

which obviously fails because of the borrowing rules (playround link):

error[E0499]: cannot borrow `a` as mutable more than once at a time
  --> src/main.rs:13:38
   |
13 |     a.slice_mut(s![.., ..2]).assign(&a.slice_mut(s![.., 1..]));
   |     -                        ------  ^ second mutable borrow occurs here
   |     |                        |
   |     |                        first borrow later used by call
   |     first mutable borrow occurs here

Here a is what I have and b is what I'm trying to get.

In numpy it is as easy as a[:, :2] = a[:, 1:].

PS Maybe there's a simple solution in nalgebra crate?

Jmb
  • 18,893
  • 2
  • 28
  • 55
Antony Hatchkins
  • 31,947
  • 10
  • 111
  • 111
  • Why don't you write a for loop? – Boiethios Aug 30 '19 at 09:06
  • @FrenchBoiethios just one for loop wont solve all the aliasing problems that might arise (eg left-to-right vs right-to-left copying). Also I'd expect the library do that for me, or at least help me with that. Otherwise I'd resort to plain C. – Antony Hatchkins Aug 30 '19 at 19:33

2 Answers2

0

In master branch of ndarray there's a special macro for that, more convenient than split_at_mut() in that it supports arbitrary slices - but it panics when the slices overlap:

use ndarray::multislice;
use ndarray::prelude::*;
let mut arr: Array1<_> = (0..4).collect();
let (mut a, mut b) = multislice!(arr, mut [..;2], mut [1..;2]);
a.assign(&b);

gives [1,1,3,3]

They even solve a Diophantine equation to check it. It happens at runtime as opposed to compile-time split_at_mut.

Antony Hatchkins
  • 31,947
  • 10
  • 111
  • 111
-2

Ok, got it

use ndarray::{arr2, s,Array};

let mut a = arr2(&[[1, 2, 3],
                   [4, 5, 6]]);
unsafe{
    let b = a.as_mut_ptr();
    let c = Vec::<i32>::from_raw_parts(b, 6, 6);
    let mut d = Array::from_shape_vec((2, 3), c).unwrap();
    a.slice_mut(s![.., ..2]).assign(&d.slice_mut(s![.., 1..]));
    std::mem::forget(d);
}
println!("{:?}",a);
Optimistic Peach
  • 3,862
  • 2
  • 18
  • 29
Antony Hatchkins
  • 31,947
  • 10
  • 111
  • 111
  • Note that there is no guaranty that this code will work: the order in which `assign` moves elements is not defined, so a future version of Rust or `ndarray` could break your code. – Jmb Aug 30 '19 at 06:39
  • 1
    It also wouldn't work if you wanted to move data to the right instead of moving them to the left… – Jmb Aug 30 '19 at 06:40
  • This program leads to undefined behavior. – E_net4 Aug 30 '19 at 07:33
  • @Jmb yes, it needs some logic similar to memmove implementation: reverse the slice if the moving to the left – Antony Hatchkins Aug 30 '19 at 19:20