Home > Net >  Transmute nested const generic array (Rust)
Transmute nested const generic array (Rust)

Time:07-25

I want to do

pub fn col_vec<T:Sized, const DIM0: usize>(mat: [T; DIM0]) -> [[T; 1]; DIM0] {
    unsafe { std::mem::transmute(mat) }
}

which is obviously safe to do. Rust rejects it as

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
  --> vf\src\shape_arr.rs:22:14
   |
22 |     unsafe { std::mem::transmute(mat) }
   |              ^^^^^^^^^^^^^^^^^^^
   |
   = note: source type: `[T; DIM0]` (this type does not have a fixed size)
   = note: target type: `[[T; 1]; DIM0]` (this type does not have a fixed size)

Is there some way around this?

CodePudding user response:

pub fn col_vec<T, const DIM0: usize>(mat: [T; DIM0]) -> [[T; 1]; DIM0] {
    mat.map(|x| [x])
}

The above code does the same thing using safe operations. While array::map() does sometimes result in code generation, in this case, the compiler appears capable of optimizing it down to just a copy of the entire array (and, presumably, nothing at all within some larger algorithm). I would recommend using this option.


Another option which is closer to transmute() is:

pub fn col_vec<T: bytemuck::Pod, const DIM0: usize>(mat: [T; DIM0]) -> [[T; 1]; DIM0] {
    bytemuck::cast(mat)
}

This version uses bytemuck, a library for performing byte-reinterpreting conversions between arbitrary types as long as it is safe to do so (which the T: bytemuck::Pod bound ensures). This is very flexible and can do any kind of matrix reshaping, but it has the disadvantage that the element type must meet the Pod constraint (it must not contain any pointers or padding, for example). This requirement is because, for individual conversions, bytemuck only checks that the input and output have the same length, so it can be used to do things like turning [u32; 4] into [u16; 8] or similar reshaping at the byte level.

  • Related