generic_simd/shim/
width.rs

1use crate::vector::{width, Vector};
2use core::marker::PhantomData;
3
4#[cfg(feature = "complex")]
5use crate::vector::Complex;
6
7/// Determines the doubled width of this vector.
8pub trait Double {
9    type Doubled: width::Width;
10}
11
12impl Double for width::W1 {
13    type Doubled = width::W2;
14}
15
16impl Double for width::W2 {
17    type Doubled = width::W4;
18}
19
20impl Double for width::W4 {
21    type Doubled = width::W8;
22}
23
24/// Shim that doubles the width of a vector.
25#[derive(Copy, Clone, Debug)]
26#[repr(transparent)]
27pub struct Shim2<Underlying, Scalar>([Underlying; 2], PhantomData<Scalar>);
28
29/// Shim that quadruples the width of a vector.
30pub type Shim4<Underlying, Scalar> = Shim2<Shim2<Underlying, Scalar>, Scalar>;
31
32/// Shim that octuples the width of a vector.
33pub type Shim8<Underlying, Scalar> = Shim4<Shim2<Underlying, Scalar>, Scalar>;
34
35unsafe impl<Underlying, Scalar> Vector for Shim2<Underlying, Scalar>
36where
37    Underlying: Vector<Scalar = Scalar>,
38    Underlying::Width: Double,
39    Scalar: Copy,
40{
41    type Scalar = Scalar;
42    type Token = <Underlying as Vector>::Token;
43    type Width = <Underlying::Width as Double>::Doubled;
44    type Underlying = [<Underlying as Vector>::Underlying; 2];
45
46    #[inline]
47    fn zeroed(token: Self::Token) -> Self {
48        Self([Underlying::zeroed(token); 2], PhantomData)
49    }
50
51    #[inline]
52    fn splat(token: Self::Token, from: Self::Scalar) -> Self {
53        Self([Underlying::splat(token, from); 2], PhantomData)
54    }
55}
56
57impl<Underlying, Scalar> AsRef<[Scalar]> for Shim2<Underlying, Scalar>
58where
59    Underlying: Vector<Scalar = Scalar>,
60    Underlying::Width: Double,
61    Scalar: Copy,
62{
63    #[inline]
64    fn as_ref(&self) -> &[Scalar] {
65        self.as_slice()
66    }
67}
68
69impl<Underlying, Scalar> AsMut<[Scalar]> for Shim2<Underlying, Scalar>
70where
71    Underlying: Vector<Scalar = Scalar>,
72    Underlying::Width: Double,
73    Scalar: Copy,
74{
75    #[inline]
76    fn as_mut(&mut self) -> &mut [Scalar] {
77        self.as_slice_mut()
78    }
79}
80
81impl<Underlying, Scalar> core::ops::Deref for Shim2<Underlying, Scalar>
82where
83    Underlying: Vector<Scalar = Scalar>,
84    Underlying::Width: Double,
85    Scalar: Copy,
86{
87    type Target = [Scalar];
88
89    #[inline]
90    fn deref(&self) -> &Self::Target {
91        self.as_slice()
92    }
93}
94
95impl<Underlying, Scalar> core::ops::DerefMut for Shim2<Underlying, Scalar>
96where
97    Underlying: Vector<Scalar = Scalar>,
98    Underlying::Width: Double,
99    Scalar: Copy,
100{
101    #[inline]
102    fn deref_mut(&mut self) -> &mut <Self as core::ops::Deref>::Target {
103        self.as_slice_mut()
104    }
105}
106
107macro_rules! implement {
108    {
109        @op $trait:ident :: $func:ident
110    } => {
111        impl<Underlying, Scalar> core::ops::$trait<Self> for Shim2<Underlying, Scalar>
112        where
113            Underlying: Copy + core::ops::$trait<Underlying, Output=Underlying>,
114        {
115            type Output = Self;
116
117            #[inline]
118            fn $func(self, rhs: Self) -> Self {
119                Self([self.0[0].$func(rhs.0[0]), self.0[1].$func(rhs.0[1])], PhantomData)
120            }
121        }
122
123        impl<Underlying, Scalar> core::ops::$trait<Scalar> for Shim2<Underlying, Scalar>
124        where
125            Underlying: Copy + core::ops::$trait<Scalar, Output=Underlying>,
126            Scalar: Copy,
127        {
128            type Output = Self;
129
130            #[inline]
131            fn $func(self, rhs: Scalar) -> Self {
132                Self([self.0[0].$func(rhs), self.0[1].$func(rhs)], PhantomData)
133            }
134        }
135    };
136
137    {
138        @op_assign $trait:ident :: $func:ident
139    } => {
140        impl<Underlying, Scalar> core::ops::$trait<Self> for Shim2<Underlying, Scalar>
141        where
142            Underlying: Copy + core::ops::$trait<Underlying>,
143            Scalar: Copy,
144        {
145            #[inline]
146            fn $func(&mut self, rhs: Self) {
147                self.0[0].$func(rhs.0[0]);
148                self.0[1].$func(rhs.0[1]);
149            }
150        }
151
152        impl<Underlying, Scalar> core::ops::$trait<Scalar> for Shim2<Underlying, Scalar>
153        where
154            Underlying: Copy + core::ops::$trait<Scalar>,
155            Scalar: Copy,
156        {
157            #[inline]
158            fn $func(&mut self, rhs: Scalar) {
159                self.0[0].$func(rhs);
160                self.0[1].$func(rhs);
161            }
162        }
163    };
164}
165
166implement! { @op Add::add }
167implement! { @op Sub::sub }
168implement! { @op Mul::mul }
169implement! { @op Div::div }
170implement! { @op_assign AddAssign::add_assign }
171implement! { @op_assign SubAssign::sub_assign }
172implement! { @op_assign MulAssign::mul_assign }
173implement! { @op_assign DivAssign::div_assign }
174
175impl<Underlying, Scalar> core::ops::Neg for Shim2<Underlying, Scalar>
176where
177    Underlying: Copy + core::ops::Neg<Output = Underlying>,
178{
179    type Output = Self;
180
181    #[inline]
182    fn neg(self) -> Self {
183        Self([-self.0[0], -self.0[1]], PhantomData)
184    }
185}
186
187impl<Underlying, Scalar> core::iter::Sum<Shim2<Underlying, Scalar>>
188    for Option<Shim2<Underlying, Scalar>>
189where
190    Shim2<Underlying, Scalar>: core::ops::AddAssign,
191    Underlying: Copy,
192{
193    #[inline]
194    fn sum<I>(mut iter: I) -> Self
195    where
196        I: Iterator<Item = Shim2<Underlying, Scalar>>,
197    {
198        if let Some(mut sum) = iter.next() {
199            for v in iter {
200                sum += v;
201            }
202            Some(sum)
203        } else {
204            None
205        }
206    }
207}
208
209impl<Underlying, Scalar> core::iter::Sum<Shim2<Underlying, Scalar>>
210    for <Shim2<Underlying, Scalar> as Vector>::Scalar
211where
212    Option<Shim2<Underlying, Scalar>>: core::iter::Sum<Shim2<Underlying, Scalar>>,
213    Underlying: Vector<Scalar = Scalar>,
214    Underlying::Width: Double,
215    Scalar: Copy + core::ops::Add<Self, Output = Self> + Default,
216{
217    #[inline]
218    fn sum<I>(iter: I) -> Self
219    where
220        I: Iterator<Item = Shim2<Underlying, Scalar>>,
221    {
222        let mut value = Self::default();
223        if let Some(sums) = iter.sum::<Option<Shim2<Underlying, Scalar>>>() {
224            for sum in sums.as_slice() {
225                value = value + *sum;
226            }
227        }
228        value
229    }
230}
231
232impl<Underlying, Scalar> core::iter::Product<Shim2<Underlying, Scalar>>
233    for Option<Shim2<Underlying, Scalar>>
234where
235    Shim2<Underlying, Scalar>: core::ops::MulAssign,
236    Underlying: Copy,
237{
238    #[inline]
239    fn product<I>(mut iter: I) -> Self
240    where
241        I: Iterator<Item = Shim2<Underlying, Scalar>>,
242    {
243        if let Some(mut sum) = iter.next() {
244            for v in iter {
245                sum *= v;
246            }
247            Some(sum)
248        } else {
249            None
250        }
251    }
252}
253
254impl<Underlying, Scalar> core::iter::Product<Shim2<Underlying, Scalar>>
255    for <Shim2<Underlying, Scalar> as Vector>::Scalar
256where
257    Option<Shim2<Underlying, Scalar>>: core::iter::Product<Shim2<Underlying, Scalar>>,
258    Underlying: Vector<Scalar = Scalar>,
259    Underlying::Width: Double,
260    Scalar: Copy + core::ops::Mul<Self, Output = Self> + Default,
261{
262    #[inline]
263    fn product<I>(iter: I) -> Self
264    where
265        I: Iterator<Item = Shim2<Underlying, Scalar>>,
266    {
267        let mut value = Self::default();
268        if let Some(products) = iter.product::<Option<Shim2<Underlying, Scalar>>>() {
269            for product in products.as_slice() {
270                value = value * *product;
271            }
272        }
273        value
274    }
275}
276
277#[cfg(feature = "complex")]
278impl<Underlying, Real> Complex for Shim2<Underlying, num_complex::Complex<Real>>
279where
280    Underlying: Vector<Scalar = num_complex::Complex<Real>> + Complex<RealScalar = Real>,
281    Underlying::Width: Double,
282    Real: Copy,
283{
284    type RealScalar = Real;
285
286    #[inline]
287    fn conj(self) -> Self {
288        Self([self.0[0].conj(), self.0[1].conj()], PhantomData)
289    }
290
291    #[inline]
292    fn mul_i(self) -> Self {
293        Self([self.0[0].mul_i(), self.0[1].mul_i()], PhantomData)
294    }
295
296    #[inline]
297    fn mul_neg_i(self) -> Self {
298        Self([self.0[0].mul_neg_i(), self.0[1].mul_neg_i()], PhantomData)
299    }
300}