concision_core/traits/
num.rs

1/*
2   Appellation: math <traits>
3   Contrib: FL03 <jo3mccain@icloud.com>
4*/
5use nd::{Array, Dimension};
6use num::complex::Complex;
7use num::{Float, Num, Signed, Zero};
8
9pub trait AsComplex {
10    type Real;
11
12    fn as_complex(&self, real: bool) -> Complex<Self::Real>;
13
14    fn as_re(&self) -> Complex<Self::Real> {
15        self.as_complex(true)
16    }
17
18    fn as_im(&self) -> Complex<Self::Real> {
19        self.as_complex(false)
20    }
21}
22
23pub trait IntoComplex: AsComplex {
24    fn into_complex(self, real: bool) -> Complex<Self::Real>
25    where
26        Self: Sized,
27    {
28        self.as_complex(real)
29    }
30
31    fn into_re(self) -> Complex<Self::Real>
32    where
33        Self: Sized,
34    {
35        self.as_complex(true)
36    }
37}
38
39pub trait Conjugate {
40    type Output;
41
42    fn conj(&self) -> Self::Output;
43}
44
45pub trait FloorDiv<Rhs = Self> {
46    type Output;
47
48    fn floor_div(self, rhs: Rhs) -> Self::Output;
49}
50
51pub trait RoundTo {
52    fn round_to(&self, places: usize) -> Self;
53}
54
55/*
56 ********* Implementations *********
57*/
58impl<T> AsComplex for T
59where
60    T: Copy + Num,
61{
62    type Real = T;
63
64    fn as_complex(&self, real: bool) -> Complex<Self> {
65        match real {
66            true => Complex::new(*self, Self::zero()),
67            false => Complex::new(Self::zero(), *self),
68        }
69    }
70}
71
72impl<T> IntoComplex for T where T: AsComplex {}
73
74macro_rules! impl_conj {
75    ($($t:ident<$res:ident>),*) => {
76        $(
77            impl_conj!(@impl $t<$res>);
78        )*
79    };
80    (@impl $t:ident<$res:ident>) => {
81        impl Conjugate for $t {
82            type Output = $res<$t>;
83
84            fn conj(&self) -> Self::Output {
85                Complex { re: *self, im: -$t::zero() }
86            }
87        }
88    };
89}
90
91impl_conj!(f32<Complex>, f64<Complex>);
92
93impl<T> Conjugate for Complex<T>
94where
95    T: Clone + Signed,
96{
97    type Output = Complex<T>;
98
99    fn conj(&self) -> Self {
100        Complex::<T>::conj(self)
101    }
102}
103
104impl<T, D> Conjugate for Array<T, D>
105where
106    D: Dimension,
107    T: Clone + num::complex::ComplexFloat,
108{
109    type Output = Array<T, D>;
110    fn conj(&self) -> Self::Output {
111        self.mapv(|x| x.conj())
112    }
113}
114
115impl<T> FloorDiv for T
116where
117    T: Copy + Num,
118{
119    type Output = T;
120
121    fn floor_div(self, rhs: Self) -> Self::Output {
122        crate::floor_div(self, rhs)
123    }
124}
125
126// impl<A, B, C> Pow<B> for A where A: num::traits::Pow<B, Output = C> {
127//     type Output = C;
128
129//     fn pow(self, rhs: B) -> Self::Output {
130//         num::traits::Pow::pow(self, rhs)
131//     }
132// }
133
134// impl<D, A, B, C> Pow<i32> for Array<A, D> where A: Clone + num::traits::Pow<B, Output = C>, D: Dimension  {
135//     type Output = Array<C, D>;
136
137//     fn pow(self, rhs: B) -> Self::Output {
138//         self.mapv(|x| x.pow(rhs))
139//     }
140// }
141
142impl<T> RoundTo for T
143where
144    T: Float,
145{
146    fn round_to(&self, places: usize) -> Self {
147        crate::round_to(*self, places)
148    }
149}