ospf_rust_math/algebra/concept/
scalar.rs

1use num::complex::ComplexFloat;
2
3use super::{
4    Arithmetic, Bits, Bounded, Invariant, NumberField, PlusSemiGroup, Precision, Signed,
5    TimesGroup, Unsigned,
6};
7
8pub trait Scalar: Arithmetic + Bounded {}
9
10impl<T: Arithmetic + Bounded> Scalar for T {}
11
12pub enum RealNumberCategory {
13    Nan,
14    Infinite,
15    NegativeInfinite,
16    Zero,
17    Subnormal,
18    Normal,
19}
20
21pub trait RealNumber: Scalar + Precision + Invariant {
22    const TWO: &'static Self;
23    const THREE: &'static Self;
24    const FIVE: &'static Self;
25    const TEN: &'static Self;
26
27    const NAN: &'static Option<Self> = &None;
28    const INF: &'static Option<Self> = &None;
29    const NEG_INF: &'static Option<Self> = &None;
30
31    // todo: category
32
33    fn is_nan(&self) -> bool {
34        Self::NAN
35            .as_ref()
36            .is_some_and(|nan_value| self == nan_value)
37    }
38
39    fn is_inf(&self) -> bool {
40        Self::INF
41            .as_ref()
42            .is_some_and(|inf_value| self == inf_value)
43    }
44
45    fn is_neg_inf(&self) -> bool {
46        Self::NEG_INF
47            .as_ref()
48            .is_some_and(|inf_value| self == inf_value)
49    }
50
51    fn is_finite(&self) -> bool {
52        !self.is_inf() && !self.is_inf() && !self.is_neg_inf()
53    }
54}
55
56pub trait Integer: RealNumber + Bits + Ord + Eq {}
57
58impl<T: RealNumber + Bits + Ord + Eq> Integer for T {}
59
60pub trait IntegerNumber: Integer + NumberField + Signed {}
61
62impl<T: Integer + NumberField + Signed> IntegerNumber for T {}
63
64pub trait UIntegerNumber: Integer + PlusSemiGroup + TimesGroup + Unsigned {}
65
66impl<T: Integer + PlusSemiGroup + TimesGroup + Unsigned> UIntegerNumber for T {}
67
68pub trait RationalNumber<I: Integer>: RealNumber + NumberField + Ord + Eq {
69    fn num(&self) -> &I;
70    fn den(&self) -> &I;
71}
72
73pub trait FloatingNumber: RealNumber + NumberField + Signed {
74    const PI: &'static Self;
75    const E: &'static Self;
76
77    fn floor(&self) -> Self;
78    fn ceil(&self) -> Self;
79    fn round(&self) -> Self;
80    fn trunc(&self) -> Self;
81    fn fract(&self) -> Self;
82}
83
84pub trait NumericIntegerNumber<I: IntegerNumber>: Integer + Signed + Ord + Eq {}
85
86pub trait NumericUIntegerNumber<I: UIntegerNumber>: Integer + Unsigned + Ord + Eq {}
87
88macro_rules! int_real_number_template {
89    ($($type:ident)*) => ($(
90        impl RealNumber for $type {
91            const TWO: &'static Self = &2;
92            const THREE: &'static Self = &3;
93            const FIVE: &'static Self = &5;
94            const TEN: &'static Self = &10;
95        }
96    )*)
97}
98int_real_number_template! { i8 i16 i32 i64 i128 isize }
99
100macro_rules! uint_real_number_template {
101    ($($type:ident)*) => ($(
102        impl RealNumber for $type {
103            const TWO: &'static Self = &2;
104            const THREE: &'static Self = &3;
105            const FIVE: &'static Self = &5;
106            const TEN: &'static Self = &10;
107        }
108    )*)
109}
110uint_real_number_template! { u8 u16 u32 u64 u128 usize }
111
112macro_rules! floating_real_number_template {
113    ($($type:ident)*) => ($(
114        impl RealNumber for $type {
115            const TWO: &'static Self = &2.;
116            const THREE: &'static Self = &3.;
117            const FIVE: &'static Self = &5.;
118            const TEN: &'static Self = &10.;
119
120            const NAN: &'static Option<Self> = &Some(<$type>::NAN);
121            const INF: &'static Option<Self> = &Some(<$type>::INFINITY);
122            const NEG_INF: &'static Option<Self> = &Some(<$type>::NEG_INFINITY);
123
124            fn is_nan(&self) -> bool {
125                <$type>::is_nan(*self)
126            }
127
128            fn is_inf(&self) -> bool {
129                <$type>::is_infinite(*self) && <$type>::is_sign_positive(*self)
130            }
131
132            fn is_neg_inf(&self) -> bool {
133                <$type>::is_infinite(*self) && <$type>::is_sign_negative(*self)
134            }
135        }
136
137        impl FloatingNumber for $type {
138                const PI: &'static Self = &std::$type::consts::PI;
139                const E: &'static Self = &std::$type::consts::E;
140
141                fn floor(&self) -> Self {
142                    <$type>::floor(*self)
143                }
144
145                fn ceil(&self) -> Self {
146                    <$type>::ceil(*self)
147                }
148
149                fn round(&self) -> Self {
150                    <$type>::round(*self)
151                }
152
153                fn trunc(&self) -> Self {
154                    <$type>::trunc(*self)
155                }
156
157                fn fract(&self) -> Self {
158                    <$type>::fract(*self)
159                }
160            }
161    )*)
162}
163floating_real_number_template! { f32 f64 }