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.