concision_math/traits/
num.rs1use ndarray::{Array, Dimension};
6use num::complex::Complex;
7use num::{Float, Num, Signed, Zero};
8
9pub trait ComplexNum<T = f64> {
10 type Real: Sized;
11}
12pub trait AsComplex<T> {
14 type Complex: ComplexNum<T>;
15
16 fn as_complex(&self, real: bool) -> Self::Complex;
17
18 fn as_re(&self) -> Self::Complex {
19 self.as_complex(true)
20 }
21
22 fn as_im(&self) -> Self::Complex {
23 self.as_complex(false)
24 }
25}
26pub trait IntoComplex<T> {
28 type Complex: ComplexNum<T>;
29
30 fn into_complex(self, real: bool) -> Self::Complex
31 where
32 Self: Sized;
33
34 fn into_re(self) -> Self::Complex
35 where
36 Self: Sized,
37 {
38 self.into_complex(true)
39 }
40
41 fn into_im(self) -> Self::Complex
42 where
43 Self: Sized,
44 {
45 self.into_complex(false)
46 }
47}
48
49pub trait Conjugate {
50 type Output;
51
52 fn conj(&self) -> Self::Output;
53}
54
55pub trait FloorDiv<Rhs = Self> {
56 type Output;
57
58 fn floor_div(self, rhs: Rhs) -> Self::Output;
59}
60
61pub trait RoundTo {
62 fn round_to(&self, places: usize) -> Self;
63}
64
65impl<T> ComplexNum<T> for Complex<T>
69where
70 T: Num,
71{
72 type Real = T;
73}
74
75impl<T> ComplexNum<T> for T
76where
77 T: Num,
78{
79 type Real = T;
80}
81
82impl<T> AsComplex<T> for T
83where
84 T: Clone + Num,
85{
86 type Complex = Complex<T>;
87
88 fn as_complex(&self, real: bool) -> Complex<T> {
89 match real {
90 true => Complex::new(self.clone(), Self::zero()),
91 false => Complex::new(Self::zero(), self.clone()),
92 }
93 }
94}
95
96impl<T> IntoComplex<T> for T
97where
98 T: Num,
99{
100 type Complex = Complex<T>;
101
102 fn into_complex(self, real: bool) -> Self::Complex
103 where
104 Self: Sized,
105 {
106 match real {
107 true => Complex::new(self, T::zero()),
108 false => Complex::new(T::zero(), self),
109 }
110 }
111}
112
113impl<T> FloorDiv for T
114where
115 T: Copy + Num,
116{
117 type Output = T;
118
119 fn floor_div(self, rhs: Self) -> Self::Output {
120 crate::floor_div(self, rhs)
121 }
122}
123
124impl<T> RoundTo for T
125where
126 T: Float,
127{
128 fn round_to(&self, places: usize) -> Self {
129 crate::round_to(*self, places)
130 }
131}
132
133macro_rules! impl_conj {
138 ($($t:ident<$res:ident>),*) => {
139 $(
140 impl_conj!(@impl $t<$res>);
141 )*
142 };
143 (@impl $t:ident<$res:ident>) => {
144 impl Conjugate for $t {
145 type Output = $res<$t>;
146
147 fn conj(&self) -> Self::Output {
148 Complex { re: *self, im: -$t::zero() }
149 }
150 }
151 };
152}
153
154impl_conj!(f32<Complex>, f64<Complex>);
155
156impl<T> Conjugate for Complex<T>
157where
158 T: Clone + Signed,
159{
160 type Output = Complex<T>;
161
162 fn conj(&self) -> Self {
163 Complex::<T>::conj(self)
164 }
165}
166
167impl<T, D> Conjugate for Array<T, D>
168where
169 D: Dimension,
170 T: Clone + num::complex::ComplexFloat,
171{
172 type Output = Array<T, D>;
173 fn conj(&self) -> Self::Output {
174 self.mapv(|x| x.conj())
175 }
176}