1use 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
27macro_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
76macro_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}