1use nd::{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 Squared::sqrd(self),
17 SquareRoot::sqrt(self)
18);
19
20macro_rules! unary_impl {
25 ($name:ident::$method:ident<[$($T:ty),* $(,)?]>) => {
26 unary_impl!(@loop $name::$method<[$($T),*]>);
27 };
28 ($($name:ident::$method:ident<$T:ty$(, Output = $O:ty)?>),* $(,)?) => {
29 $(unary_impl!(@impl $name::$method<$T$(, Output = $O>)?);)*
30 };
31 ($($name:ident::$method:ident<$T:ty, Output = $O:ty>),* $(,)?) => {
32 $(unary_impl!(@impl $name::$method<$T, Output = $O>);)*
33 };
34 (@loop $name:ident::$method:ident<[$($T:ty),* $(,)?]>) => {
35 $(unary_impl!(@impl $name::$method<$T>);)*
36 };
37 (@impl $name:ident::$method:ident<$T:ty>) => {
38 unary_impl!(@impl $name::$method<$T, Output = $T>);
39 };
40 (@impl $name:ident::$method:ident<$T:ty, Output = $O:ty>) => {
41 impl $name for $T {
42 type Output = $O;
43
44 fn $method(self) -> Self::Output {
45 <$T>::$method(self)
46 }
47 }
48 };
49}
50
51macro_rules! unary_impls {
52 ($($name:ident::$method:ident<[$($T:ty),* $(,)?]>),* $(,)?) => {
53 $(unary_impl!(@loop $name::$method<[$($T),*]>);)*
54 };
55}
56
57unary_impls!(
58 Abs::abs<[f32, f64]>,
59 Cosh::cosh<[f32, f64, Complex<f32>, Complex<f64>]>,
60 Cos::cos<[f32, f64, Complex<f32>, Complex<f64>]>,
61 Exp::exp<[f32, f64, Complex<f32>, Complex<f64>]>,
62 Sinh::sinh<[f32, f64, Complex<f32>, Complex<f64>]>,
63 Sine::sin<[f32, f64, Complex<f32>, Complex<f64>]>,
64 SquareRoot::sqrt<[f32, f64]>
65);
66
67impl<A, S, D> Abs for ArrayBase<S, D>
68where
69 A: Clone + Signed,
70 D: Dimension,
71 S: Data<Elem = A>,
72{
73 type Output = Array<A, D>;
74
75 fn abs(self) -> Self::Output {
76 self.mapv(|x| x.abs())
77 }
78}
79
80impl<'a, A, S, D> Abs for &'a ArrayBase<S, D>
81where
82 A: Clone + Signed,
83 D: Dimension,
84 S: Data<Elem = A>,
85{
86 type Output = Array<A, D>;
87
88 fn abs(self) -> Self::Output {
89 self.mapv(|x| x.abs())
90 }
91}
92
93impl<A> Squared for A
94where
95 A: Clone + core::ops::Mul<Output = A>,
96{
97 type Output = A;
98
99 fn sqrd(self) -> Self::Output {
100 self.clone() * self
101 }
102}
103
104impl<A> SquareRoot for Complex<A>
105where
106 Complex<A>: ComplexFloat<Real = A>,
107{
108 type Output = Self;
109
110 fn sqrt(self) -> Self::Output {
111 ComplexFloat::sqrt(self)
112 }
113}
114
115impl<A, B, S, D> SquareRoot for ArrayBase<S, D>
116where
117 A: Clone + SquareRoot<Output = B>,
118 D: Dimension,
119 S: Data<Elem = A>,
120{
121 type Output = Array<B, D>;
122
123 fn sqrt(self) -> Self::Output {
124 self.mapv(|x| x.sqrt())
125 }
126}
127
128impl<A, B, S, D> Exp for ArrayBase<S, D>
129where
130 A: Clone + Exp<Output = B>,
131 D: Dimension,
132 S: Data<Elem = A>,
133{
134 type Output = Array<B, D>;
135
136 fn exp(self) -> Self::Output {
137 self.mapv(|x| x.exp())
138 }
139}
140
141impl<'a, A, S, D> Exp for &'a ArrayBase<S, D>
142where
143 A: Clone + ComplexFloat,
144 D: Dimension,
145 S: Data<Elem = A>,
146{
147 type Output = Array<A, D>;
148
149 fn exp(self) -> Self::Output {
150 self.mapv(|x| x.exp())
151 }
152}