concision_core/math/
traits.rs

1/*
2    Appellation: traits <module>
3    Contrib: FL03 <jo3mccain@icloud.com>
4*/
5use 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
20/*
21 ********* Implementations *********
22*/
23
24macro_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}