ospf_rust_math/algebra/operator/algorithmic/
log.rs1use crate::algebra::*;
2
3pub trait Log<Base: FloatingNumber = Self>: Sized {
4 type Output;
5
6 fn log(self, base: &Base) -> Option<Self::Output>;
7
8 fn lg2(self) -> Option<Self::Output> {
9 self.log(Base::TWO)
10 }
11
12 fn lg(self) -> Option<Self::Output> {
13 self.log(Base::TEN)
14 }
15
16 fn ln(self) -> Option<Self::Output> {
17 self.log(Base::E)
18 }
19}
20
21pub fn log<Lhs: Log<Rhs>, Rhs: FloatingNumber>(lhs: Lhs, rhs: &Rhs) -> Option<Lhs::Output> {
22 lhs.log(&rhs)
23}
24
25pub fn lg2<Lhs: Log<Rhs>, Rhs: FloatingNumber>(lhs: Lhs) -> Option<Lhs::Output> {
26 lhs.lg2()
27}
28
29pub fn lg<Lhs: Log<Rhs>, Rhs: FloatingNumber>(lhs: Lhs) -> Option<Lhs::Output> {
30 lhs.lg()
31}
32
33pub fn ln<Lhs: Log<Rhs>, Rhs: FloatingNumber>(lhs: Lhs) -> Option<Lhs::Output> {
34 lhs.ln()
35}
36
37macro_rules! int_log_template {
38 ($($type:ident)*) => ($(
39 impl Log<f64> for $type {
40 type Output = f64;
41
42 fn log(self, base: &f64) -> Option<f64> {
43 Some((self as f64).log(*base))
44 }
45 }
46
47
48 impl Log<f64> for &$type {
49 type Output = f64;
50
51 fn log(self, base: &f64) -> Option<f64> {
52 Some((*self as f64).log(*base))
53 }
54 }
55 )*)
56}
57int_log_template! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
58
59macro_rules! floating_log_template {
60 ($($type:ident)*) => ($(
61 impl Log for $type {
62 type Output = $type;
63
64 fn log(self, base: &Self) -> Option<$type> {
65 Some(self.log(*base))
66 }
67 }
68
69 impl Log<$type> for &$type {
70 type Output = $type;
71
72 fn log(self, base: &$type) -> Option<$type> {
73 Some((*self).log(*base))
74 }
75 }
76 )*);
77}
78floating_log_template! { f32 f64 }
79
80#[cfg(test)]
81mod tests {
82 use std::fmt::Debug;
83
84 use crate::algebra::concept::{Integer, FloatingNumber};
85
86 use super::*;
87
88 fn test_int<T: Integer + Log<f64, Output = f64> + Debug>()
89 where
90 for<'a> &'a T: Log<f64, Output = f64>
91 {
92
93 }
94
95 fn test_flt<T: FloatingNumber + Log<T, Output = T> + Debug>()
96 where
97 for<'a> &'a T: Log<T, Output = T>
98 {
99 assert_eq!(&T::TWO.lg2().unwrap(), T::ONE);
100 }
101
102 #[test]
103 fn test() {
104 test_int::<u8>();
105 test_int::<u16>();
106 test_int::<u32>();
107 test_int::<u64>();
108 test_int::<u128>();
109 test_int::<i8>();
110 test_int::<i16>();
111 test_int::<i32>();
112 test_int::<i64>();
113 test_int::<i128>();
114 test_flt::<f32>();
115 test_flt::<f64>();
116 }
117}