simd_aligned/
vec.rs

1use std::ops::{Deref, DerefMut, Index, IndexMut};
2
3use crate::traits::Simd;
4
5use super::{
6    conversion::{simd_container_flat_slice, simd_container_flat_slice_mut},
7    packed::PackedMxN,
8};
9
10/// A dynamic (heap allocated) vector aligned for fast and safe SIMD access that also provides a
11/// flat view on its data.
12///
13/// # Example
14///
15/// ```rust
16///
17/// // Create a vector of f64x__ elements that, in total, will hold space
18/// // for at least 4 f64 values. Internally this might be one f64x4, two f64x2,
19/// // or one f64x8 where the 2nd half is hidden, depending on the current architecture.
20/// use simd_aligned::{VecSimd, arch::f64x4};
21///
22/// let mut v = VecSimd::<f64x4>::with(0_f64, 4);
23///
24/// // Get a 'flat view' (&[f64]) into the SIMD vectors and fill it.
25/// v.flat_mut().clone_from_slice(&[0.0, 1.0, 2.0, 3.0]);
26/// ```
27
28#[derive(Clone, Debug)]
29pub struct VecSimd<T>
30where
31    T: Simd + Default + Clone,
32{
33    pub(crate) simd_rows: PackedMxN<T>,
34}
35
36impl<T> VecSimd<T>
37where
38    T: Simd + Default + Clone,
39{
40    /// Produce a [`VecSimd`] with the given element `t` as default and a flat size of `size`.
41    #[inline]
42    pub fn with(t: T::Element, size: usize) -> Self {
43        Self {
44            simd_rows: PackedMxN::with(T::splat(t), 1, size),
45        }
46    }
47
48    /// Get a flat view for this [`VecSimd`].
49    #[inline]
50    #[must_use]
51    pub fn flat(&self) -> &[T::Element] {
52        simd_container_flat_slice(&self.simd_rows.data[..], self.simd_rows.row_length)
53    }
54
55    /// Get a flat, mutable view for this [`VecSimd`].
56    #[inline]
57    pub fn flat_mut(&mut self) -> &mut [T::Element] {
58        simd_container_flat_slice_mut(&mut self.simd_rows.data[..], self.simd_rows.row_length)
59    }
60}
61
62impl<T> Index<usize> for VecSimd<T>
63where
64    T: Simd + Default + Clone,
65{
66    type Output = T;
67
68    #[inline]
69    fn index(&self, index: usize) -> &Self::Output {
70        &self.simd_rows.data[index]
71    }
72}
73
74impl<T> IndexMut<usize> for VecSimd<T>
75where
76    T: Simd + Default + Clone,
77{
78    #[inline]
79    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
80        &mut self.simd_rows.data[index]
81    }
82}
83
84impl<T> Deref for VecSimd<T>
85where
86    T: Simd + Default + Clone,
87{
88    type Target = [T];
89
90    fn deref(&self) -> &[T] {
91        &self.simd_rows.data[..]
92    }
93}
94
95impl<T> DerefMut for VecSimd<T>
96where
97    T: Simd + Default + Clone,
98{
99    fn deref_mut(&mut self) -> &mut [T] {
100        &mut self.simd_rows.data[..]
101    }
102}
103
104#[cfg(test)]
105mod test {
106    use super::VecSimd;
107    use crate::arch::f32x4;
108
109    #[test]
110    fn allocation_size() {
111        let v_1 = VecSimd::<f32x4>::with(0.0f32, 4);
112        let v_2 = VecSimd::<f32x4>::with(0.0f32, 5);
113
114        assert_eq!(v_1.simd_rows.data.len(), 1);
115        assert_eq!(v_2.simd_rows.data.len(), 2);
116    }
117
118    #[test]
119    fn flat() {
120        let mut v = VecSimd::<f32x4>::with(10.0f32, 16);
121        let r_m = v.flat_mut();
122
123        assert_eq!(r_m.len(), 16);
124
125        for x in r_m {
126            *x = 1.0
127        }
128
129        let mut sum = 0.0;
130        let r = v.flat();
131
132        assert_eq!(r.len(), 16);
133
134        for x in r {
135            sum += x;
136        }
137
138        assert!((sum - 16.0).abs() <= std::f32::EPSILON);
139    }
140
141    #[test]
142    fn deref() {
143        let v = VecSimd::<f32x4>::with(0.0f32, 16);
144        assert_eq!(&v[0], &v[0]);
145    }
146}