concision_utils/ops/
unary.rs

1/*
2    Appellation: unary <traits>
3    Contrib: @FL03
4*/
5use ndarray::{Array, ArrayBase, Data, Dimension};
6use num::complex::{Complex, ComplexFloat};
7use num::traits::Signed;
8
9unary! {
10    Abs::abs(self),
11    Cos::cos(self),
12    Cosh::cosh(self),
13    Exp::exp(self),
14    Sine::sin(self),
15    Sinh::sinh(self),
16    Tan::tan(self),
17    Tanh::tanh(self),
18    Squared::pow2(self),
19    Cubed::pow3(self),
20    SquareRoot::sqrt(self)
21}
22
23unary! {
24    Conjugate::conj(&self),
25}
26
27/*
28 ********* Implementations *********
29*/
30
31macro_rules! unary_impl {
32    ($($name:ident<$T:ty$(, Output = $O:ty)?>::$method:ident),* $(,)?) => {
33        $(unary_impl!(@impl $name::$method<$T$(, Output = $O>)?);)*
34    };
35    ($($name:ident::<$T:ty, Output = $O:ty>::$method:ident),* $(,)?) => {
36        $(unary_impl!(@impl $name::$method<$T, Output = $O>);)*
37    };
38    ($($name:ident::<[$($T:ty),*]>::$method:ident),* $(,)?) => {
39        $(unary_impl!(@loop $name::$method<[$($T),*]>);)*
40    };
41    (@loop $name:ident::<[$($T:ty),* $(,)?]>::$method:ident) => {
42        $(unary_impl!(@impl $name::<$T>::$method);)*
43    };
44    (@impl $name:ident::<$T:ty>::$method:ident) => {
45        unary_impl!(@impl $name::<$T, Output = $T>::$method);
46    };
47    (@impl $name:ident::<$T:ty, Output = $O:ty>::$method:ident) => {
48        impl $name for $T {
49            type Output = $O;
50
51            fn $method(self) -> Self::Output {
52                <$T>::$method(self)
53            }
54        }
55    };
56}
57
58macro_rules! unary_impls {
59    ($($name:ident::<[$($T:ty),* $(,)?]>::$method:ident),* $(,)?) => {
60        $(unary_impl!(@loop $name::<[$($T),*]>::$method);)*
61    };
62}
63
64unary_impls! {
65    Abs::<[f32, f64]>::abs,
66    Cos::<[f32, f64, Complex<f32>, Complex<f64>]>::cos,
67    Cosh::<[f32, f64, Complex<f32>, Complex<f64>]>::cosh,
68    Exp::<[f32, f64, Complex<f32>, Complex<f64>]>::exp,
69    Sinh::<[f32, f64, Complex<f32>, Complex<f64>]>::sinh,
70    Sine::<[f32, f64, Complex<f32>, Complex<f64>]>::sin,
71    Tan::<[f32, f64, Complex<f32>, Complex<f64>]>::tan,
72    Tanh::<[f32, f64, Complex<f32>, Complex<f64>]>::tanh,
73    SquareRoot::<[f32, f64]>::sqrt
74}
75
76/*
77 ************* macro implementations *************
78*/
79
80macro_rules! impl_conj {
81    ($($t:ident<$res:ident>),*) => {
82        $(
83            impl_conj!(@impl $t<$res>);
84        )*
85    };
86    (@impl $t:ident<$res:ident>) => {
87        impl Conjugate for $t {
88            type Output = $res<$t>;
89
90            fn conj(&self) -> Self::Output {
91                Complex { re: *self, im: num_traits::Zero::zero() }
92            }
93        }
94    };
95}
96
97impl_conj!(f32<Complex>, f64<Complex>);
98
99impl<T> Conjugate for Complex<T>
100where
101    T: Clone + Signed,
102{
103    type Output = Complex<T>;
104
105    fn conj(&self) -> Self {
106        Complex::<T>::conj(self)
107    }
108}
109
110impl<T, D> Conjugate for Array<T, D>
111where
112    D: Dimension,
113    T: Clone + num::complex::ComplexFloat,
114{
115    type Output = Array<T, D>;
116    fn conj(&self) -> Self::Output {
117        self.mapv(|x| x.conj())
118    }
119}
120
121impl<A, S, D> Abs for ArrayBase<S, D>
122where
123    A: Clone + Signed,
124    D: Dimension,
125    S: Data<Elem = A>,
126{
127    type Output = Array<A, D>;
128
129    fn abs(self) -> Self::Output {
130        self.mapv(|x| x.abs())
131    }
132}
133
134impl<A, S, D> Abs for &ArrayBase<S, D>
135where
136    A: Clone + Signed,
137    D: Dimension,
138    S: Data<Elem = A>,
139{
140    type Output = Array<A, D>;
141
142    fn abs(self) -> Self::Output {
143        self.mapv(|x| x.abs())
144    }
145}
146
147impl<A> Squared for A
148where
149    A: Clone + core::ops::Mul<Output = A>,
150{
151    type Output = A;
152
153    fn pow2(self) -> Self::Output {
154        self.clone() * self
155    }
156}
157
158impl<A> SquareRoot for Complex<A>
159where
160    Complex<A>: ComplexFloat<Real = A>,
161{
162    type Output = Self;
163
164    fn sqrt(self) -> Self::Output {
165        ComplexFloat::sqrt(self)
166    }
167}
168
169impl<A, B, S, D> SquareRoot for ArrayBase<S, D>
170where
171    A: Clone + SquareRoot<Output = B>,
172    D: Dimension,
173    S: Data<Elem = A>,
174{
175    type Output = Array<B, D>;
176
177    fn sqrt(self) -> Self::Output {
178        self.mapv(|x| x.sqrt())
179    }
180}
181
182impl<A, B, S, D> Exp for ArrayBase<S, D>
183where
184    A: Clone + Exp<Output = B>,
185    D: Dimension,
186    S: Data<Elem = A>,
187{
188    type Output = Array<B, D>;
189
190    fn exp(self) -> Self::Output {
191        self.mapv(|x| x.exp())
192    }
193}
194
195impl<A, S, D> Exp for &ArrayBase<S, D>
196where
197    A: Clone + ComplexFloat,
198    D: Dimension,
199    S: Data<Elem = A>,
200{
201    type Output = Array<A, D>;
202
203    fn exp(self) -> Self::Output {
204        self.mapv(|x| x.exp())
205    }
206}