simd_aligned/
conversion.rs

1use crate::traits::Simd;
2
3#[inline]
4pub const fn simd_container_flat_slice<T>(data: &[T], length: usize) -> &[T::Element]
5where
6    T: Simd + Default + Clone,
7{
8    let ptr = data.as_ptr().cast::<T::Element>();
9
10    // This "should be safe(tm)" since:
11    //
12    // 1) a slice of `N x f32x8` elements are transformed into a slice of
13    // `attributes * f32` elements, where `attributes <=  N * 8`.
14    //
15    // 2) The lifetime of the returned value should automatically match the self borrow.
16
17    unsafe { std::slice::from_raw_parts(ptr, length) }
18}
19
20#[inline]
21pub fn simd_container_flat_slice_mut<T>(data: &mut [T], length: usize) -> &mut [T::Element]
22where
23    T: Simd + Default + Clone,
24{
25    let mut_ptr = data.as_mut_ptr().cast::<T::Element>();
26
27    // See comment above
28    unsafe { std::slice::from_raw_parts_mut(mut_ptr, length) }
29}
30
31/// Converts an slice of SIMD vectors into a flat slice of elements.
32///
33/// # Example
34/// ```rust
35/// use simd_aligned::{packed_as_flat, arch::f32x4};
36///
37/// let packed = [f32x4::splat(0_f32); 4];
38///
39/// let flat = packed_as_flat(&packed);
40///
41/// assert_eq!(flat.len(), 16);
42/// ```
43#[inline]
44pub const fn packed_as_flat<T>(data: &[T]) -> &[T::Element]
45where
46    T: Simd + Default + Clone,
47{
48    simd_container_flat_slice(data, data.len() * T::LANES)
49}
50
51/// Converts a mutable slice of SIMD vectors into a flat slice of elements.
52/// # Example
53/// ```rust
54/// use simd_aligned::{packed_as_flat_mut, arch::f32x4};
55///
56/// let mut packed = [f32x4::splat(0_f32); 4];
57///
58/// let flat = packed_as_flat_mut(&mut packed);
59///
60/// assert_eq!(flat.len(), 16);
61/// ```
62#[inline]
63pub fn packed_as_flat_mut<T>(data: &mut [T]) -> &mut [T::Element]
64where
65    T: Simd + Default + Clone,
66{
67    simd_container_flat_slice_mut(data, data.len() * T::LANES)
68}
69
70#[cfg(test)]
71mod test {
72    use super::{packed_as_flat, packed_as_flat_mut};
73    use crate::arch::f32x4;
74
75    #[test]
76    fn slice_flattening() {
77        let x_0 = [f32x4::splat(0.0); 0];
78        let x_1 = [f32x4::splat(0.0); 1];
79
80        let mut x_0_m = [f32x4::splat(0.0); 0];
81        let mut x_1_m = [f32x4::splat(0.0); 1];
82
83        let y_0 = packed_as_flat(&x_0);
84        let y_1 = packed_as_flat(&x_1);
85
86        let y_0_m = packed_as_flat_mut(&mut x_0_m);
87        let y_1_m = packed_as_flat_mut(&mut x_1_m);
88
89        assert_eq!(y_0.len(), 0);
90        assert_eq!(y_1.len(), 4);
91        assert_eq!(y_0_m.len(), 0);
92        assert_eq!(y_1_m.len(), 4);
93    }
94}