ospf_rust_math/algebra/operator/algorithmic/
pow.rs1use 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 }