Extract original slice from SliceStorage and SliceStorageMut

224 Views Asked by At

I am working on some software where I am managing a buffer of floats in a Vec<T> where T is either an f32 or f64. I sometimes need to interpret this buffer, or sections of it, as a mathematical vector. To this end, I am taking advantage of MatrixSlice and friends in nalgebra.

I can create a DVectorSliceMut, for example, the following way

fn as_vector<'a>(slice: &'a mut [f64]) -> DVectorSliceMut<'a, f64> {
    DVectorSliceMut::from(slice)
}

However, sometimes I need to later extract the original slice from the DVectorSliceMut with the original lifetime 'a. Is there a way to do this?

The StorageMut trait has a as_mut_slice member function, but the lifetime of the returned slice is the lifetime of the reference to the Storage implementor, not the original slice. I am okay with a solution which consumes the DVectorSliceMut if necessary.

Update: Methods into_slice and into_slice_mut have been respectively added to the SliceStorage and SliceStorageMut traits as of nalgebra v0.28.0.

2

There are 2 best solutions below

0
On BEST ANSWER

Methods into_slice and into_slice_mut which return the original slice have been respectively added to the SliceStorage and SliceStorageMut traits as of nalgebra v0.28.0.

0
On

Given the current API of nalgebra (v0.27.1) there isn't much that you can do, except:

  • life with the shorter life-time of StorageMut::as_mut_slice
  • make a feature request for such a function at nalgebra (which seems you already did)
  • employ your own unsafe code to make StorageMut::ptr_mut into a &'a mut

You could go with the third option until nalgebra gets update and implement something like this in your own code:

use nalgebra::base::dimension::Dim;
use nalgebra::base::storage::Storage;
use nalgebra::base::storage::StorageMut;

fn into_slice<'a>(vec: DVectorSliceMut<'a, f64>) -> &'a mut [f64] {
    let mut inner = vec.data;
    // from nalgebra
    // https://docs.rs/nalgebra/0.27.1/src/nalgebra/base/matrix_slice.rs.html#190
    let (nrows, ncols) = inner.shape();
    if nrows.value() != 0 && ncols.value() != 0 {
        let sz = inner.linear_index(nrows.value() - 1, ncols.value() - 1);
        unsafe { core::slice::from_raw_parts_mut(inner.ptr_mut(), sz + 1) }
    } else {
        unsafe { core::slice::from_raw_parts_mut(inner.ptr_mut(), 0) }
    }
}