ospf_rust_math/algebra/operator/algorithmic/
pow.rs

1use std::ops::Div;
2
3use paste::paste;
4
5use crate::algebra::concept::{FloatingNumber, RealNumber, SemiArithmetic};
6use crate::algebra::operator::Reciprocal;
7use crate::algebra::ordinary::pow::*;
8
9pub trait Pow: Sized {
10    type Output;
11
12    fn pow(self, index: i64) -> Self::Output;
13
14    fn square(self) -> Self::Output {
15        self.pow(2)
16    }
17
18    fn cubic(self) -> Self::Output {
19        self.pow(3)
20    }
21}
22
23pub fn pow<Lhs: Pow>(lhs: Lhs, index: i64) -> Lhs::Output {
24    lhs.pow(index)
25}
26
27pub fn square<Lhs: Pow>(lhs: Lhs) -> Lhs::Output {
28    lhs.square()
29}
30
31pub fn cubic<Lhs: Pow>(lhs: Lhs) -> Lhs::Output {
32    lhs.cubic()
33}
34
35pub trait PowF<Index: FloatingNumber = Self>: Sized
36where
37    for<'a> &'a Index: Reciprocal<Output = Index>,
38{
39    type Output: FloatingNumber;
40
41    fn powf(self, index: &Index) -> Option<Self::Output>;
42
43    fn sqrt(self) -> Option<Self::Output> {
44        self.powf(&Index::TWO.reciprocal().unwrap())
45    }
46
47    fn cbrt(self) -> Option<Self::Output> {
48        self.powf(&Index::THREE.reciprocal().unwrap())
49    }
50}
51
52pub fn powf<Lhs: PowF<Rhs>, Rhs: FloatingNumber>(lhs: Lhs, rhs: &Rhs) -> Option<Lhs::Output>
53where
54    for<'a> &'a Rhs: Reciprocal<Output = Rhs>,
55{
56    lhs.powf(rhs)
57}
58
59pub fn sqrt<Lhs: PowF<Rhs>, Rhs: FloatingNumber>(lhs: Lhs) -> Option<Lhs::Output>
60where
61    for<'a> &'a Rhs: Reciprocal<Output = Rhs>,
62{
63    lhs.sqrt()
64}
65
66pub fn cbrt<Lhs: PowF<Rhs>, Rhs: FloatingNumber>(lhs: Lhs) -> Option<Lhs::Output>
67where
68    for<'a> &'a Rhs: Reciprocal<Output = Rhs>,
69{
70    lhs.cbrt()
71}
72
73pub trait Exp {
74    type Output;
75
76    fn exp(self) -> Self::Output;
77}
78
79pub fn exp<Lhs: Exp>(lhs: Lhs) -> Lhs::Output {
80    lhs.exp()
81}
82
83macro_rules! int_pow_template {
84    ($($type:ident)*) => ($(
85        impl Pow for $type {
86            type Output = $type;
87
88            paste! {
89                fn pow(self, index: i64) -> $type {
90                    if index >= 0 {
91                        [<pow_times_semi_group_ $type>](&self, index as u64)
92                    } else {
93                        (*$type::ZERO).clone()
94                    }
95                }
96            }
97        }
98
99        impl PowF<f64> for $type {
100            type Output = f64;
101
102            fn powf(self, index: &f64) -> Option<f64> {
103                Some((self as f64).powf(*index))
104            }
105
106            fn sqrt(self) -> Option<f64> {
107                Some((self as f64).sqrt())
108            }
109
110            fn cbrt(self) -> Option<f64> {
111                Some((self as f64).cbrt())
112            }
113        }
114
115        impl Exp for $type {
116            type Output = f64;
117
118            fn exp(self) -> f64 {
119                (self as f64).exp()
120            }
121        }
122    )*)
123}
124int_pow_template! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
125
126macro_rules! floating_pow_template {
127    ($($type:ident)*) => ($(
128        impl Pow for $type {
129            type Output = $type;
130
131            paste! {
132                fn pow(self, index: i64) -> $type {
133                    [<pow_times_group_ $type>](&self, index)
134                }
135            }
136        }
137
138        impl PowF for $type {
139            type Output = $type;
140
141            fn powf(self, index: &Self) -> Option<$type> {
142                Some(<$type>::powf(self, *index))
143            }
144
145            fn sqrt(self) -> Option<$type> {
146                Some(<$type>::sqrt(self))
147            }
148
149            fn cbrt(self) -> Option<$type> {
150                Some(<$type>::cbrt(self))
151            }
152        }
153
154        impl Exp for $type {
155            type Output = $type;
156
157            fn exp(self) -> $type {
158                <$type>::exp(self)
159            }
160        }
161    )*)
162}
163floating_pow_template! { f32 f64 }