concision_core/traits/
scalar.rs

1/*
2    Appellation: scalar <module>
3    Contrib: @FL03
4*/
5/// [Numerical] is a trait for all numerical types; implements a number of core operations
6pub trait Numerical
7where
8    Self: Clone
9        + Copy
10        + PartialEq
11        + PartialOrd
12        + Send
13        + Sync
14        + core::fmt::Debug
15        + core::ops::Add
16        + core::ops::AddAssign
17        + core::ops::Div
18        + core::ops::DivAssign
19        + core::ops::Mul
20        + core::ops::MulAssign
21        + core::ops::Rem
22        + core::ops::RemAssign
23        + core::ops::Sub
24        + core::ops::SubAssign,
25{
26    private!();
27}
28
29/// The [Scalar] trait extends the [Numerical] trait to include additional mathematical
30/// operations for the purpose of reducing the number of overall traits required to
31/// complete various machine-learning tasks.
32pub trait Scalar
33where
34    Self: Numerical
35        + Sized
36        + 'static
37        + core::fmt::Display
38        + core::iter::Product
39        + core::iter::Sum
40        + core::ops::Neg
41        + num_traits::One
42        + num_traits::Zero
43        + num_traits::Num
44        + num_traits::NumCast
45        + num_traits::NumAssign
46        + num_traits::NumAssignOps
47        + num_traits::NumAssignRef
48        + num_traits::NumOps
49        + num_traits::NumRef
50        + num_traits::FromPrimitive
51        + num_traits::ToPrimitive
52        + num_traits::Signed
53        + num_traits::Pow<Self, Output = Self>
54        + num_traits::Float
55        + num_traits::FloatConst,
56{
57    private!();
58
59    fn one() -> Self
60    where
61        Self: Sized,
62    {
63        num_traits::One::one()
64    }
65
66    fn zero() -> Self
67    where
68        Self: Sized,
69    {
70        num_traits::Zero::zero()
71    }
72}
73
74#[cfg(feature = "complex")]
75pub trait ScalarComplex
76where
77    Self::Complex<Self::Real>: num::complex::ComplexFloat,
78{
79    type Real: num_traits::real::Real;
80    type Complex<T>;
81
82    private!();
83    /// create a new complex number
84    fn new(real: Self::Real, imag: Self::Real) -> Self::Complex<Self::Real>;
85    /// returns a reference to the real part of the object
86    fn real(&self) -> Self::Real;
87    /// returns a reference to the imaginary part of the object
88    fn imag(&self) -> Self::Real;
89    /// returns the absolute value of the complex number
90    fn abs(&self) -> Self::Real {
91        use num_traits::real::Real;
92        self.real().hypot(self.imag())
93    }
94    /// compute the complex conjugate of the object
95    fn conj(&self) -> Self::Complex<Self::Real> {
96        use core::ops::Neg;
97        Self::new(self.real(), self.imag().neg())
98    }
99}
100
101#[cfg(feature = "complex")]
102impl<U> ScalarComplex for U
103where
104    U: num::complex::ComplexFloat,
105    U::Real: Scalar,
106{
107    type Real = U::Real;
108    type Complex<V> = num_complex::Complex<V>;
109
110    seal!();
111
112    fn new(real: Self::Real, imag: Self::Real) -> Self::Complex<Self::Real> {
113        num_complex::Complex::new(real, imag)
114    }
115
116    fn real(&self) -> Self::Real {
117        self.re()
118    }
119
120    fn imag(&self) -> Self::Real {
121        self.im()
122    }
123}
124
125macro_rules! impl_scalar {
126    (@impl $t:ty) => {
127        impl Numerical for $t {
128            seal!();
129        }
130    };
131    (@scalar $t:ty) => {
132        impl_scalar!(@impl $t);
133
134        impl Scalar for $t {
135            seal!();
136        }
137    };
138    ($($t:ty),* $(,)?) => {
139        $(
140            impl_scalar!(@impl $t);
141        )*
142    };
143    (#[scalar] $($t:ty),* $(,)?) => {
144        $(
145            impl_scalar!(@scalar $t);
146        )*
147    };
148}
149
150impl_scalar! {
151    u8,
152    u16,
153    u32,
154    u64,
155    u128,
156    usize,
157    i8,
158    i16,
159    i32,
160    i64,
161    i128,
162    isize
163}
164
165impl_scalar! {
166    #[scalar]
167    f32,
168    f64,
169}
170
171impl<A, S, D> Numerical for ndarray::ArrayBase<S, D>
172where
173    A: Numerical,
174    D: ndarray::Dimension,
175    S: ndarray::RawData<Elem = A> + ndarray::Data + ndarray::DataMut + ndarray::DataOwned,
176    ndarray::ArrayBase<S, D>: Numerical,
177{
178    seal!();
179}