generic_simd/shim/
token.rs

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