ospf_rust_math/algebra/ordinary/
pow.rs

1use std::ops::{Div, Mul};
2
3use paste::paste;
4
5use crate::algebra::concept::Arithmetic;
6
7pub(self) fn pow_pos_impl<T: Arithmetic>(value: &T, base: &T, index: u64) -> T
8where
9    for<'a> &'a T: Mul<Output = T>,
10{
11    if index == 0 {
12        T::ONE.clone()
13    } else {
14        pow_pos_impl(&(value * base), base, index - 1)
15    }
16}
17
18pub(self) fn pow_neg_impl<T: Arithmetic>(value: &T, base: &T, index: i64) -> T
19where
20    for<'a> &'a T: Div<Output = T>,
21{
22    if index == 0 {
23        T::ONE.clone()
24    } else {
25        pow_neg_impl(&(value / base), base, index + 1)
26    }
27}
28
29pub(crate) fn pow_times_semi_group<T: Arithmetic>(base: &T, index: u64) -> T
30where
31    for<'a> &'a T: Mul<Output = T>,
32{
33    if index >= 1 {
34        pow_pos_impl(T::ONE, base, index)
35    } else {
36        T::ONE.clone()
37    }
38}
39
40pub(crate) fn pow_times_group<T: Arithmetic>(base: &T, index: i64) -> T
41where
42    for<'a> &'a T: Mul<Output = T> + Div<Output = T>,
43{
44    if index >= 1 {
45        pow_pos_impl(T::ONE, base, index as u64)
46    } else if index <= -1 {
47        pow_neg_impl(T::ONE, base, index)
48    } else {
49        T::ONE.clone()
50    }
51}
52
53macro_rules! pow_pos_template {
54    ($($type:ident)*) => ($(
55        paste! {
56            pub(self) fn [<pow_pos_ $type>](value: &$type, base: &$type, index: u64) -> $type {
57                if index == 0 {
58                    (*$type::ONE).clone()
59                } else {
60                    [<pow_pos_ $type>](&(value * base), base, index - 1)
61                }
62            }
63        }
64    )*)
65}
66pow_pos_template! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize f32 f64 }
67
68macro_rules! pow_neg_template {
69    ($($type:ident)*) => ($(
70        paste! {
71            pub(self) fn [<pow_neg_ $type>](value: &$type, base: &$type, index: i64) -> $type {
72                if index == 0 {
73                    (*$type::ONE).clone()
74                } else {
75                    [<pow_neg_ $type>](&(value / base), base, index + 1)
76                }
77            }
78        }
79    )*)
80}
81pow_neg_template! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize f32 f64 }
82
83macro_rules! pow_times_semi_group_template {
84    ($($type:ident)*) => ($(
85        paste! {
86            pub(crate) fn [<pow_times_semi_group_ $type>](base: &$type, index: u64) -> $type {
87                if index >= 1 {
88                    [<pow_pos_ $type>]($type::ONE, base, index)
89                } else {
90                    (*$type::ONE).clone()
91                }
92            }
93        }
94    )*)
95}
96pow_times_semi_group_template! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize f32 f64 }
97
98macro_rules! pow_times_group_template {
99    ($($type:ident)*) => ($(
100        paste! {
101            pub(crate) fn [<pow_times_group_ $type>](base: &$type, index: i64) -> $type {
102                if index >= 1 {
103                    [<pow_pos_ $type>]($type::ONE, base, index as u64)
104                } else if index <= -1 {
105                    [<pow_neg_ $type>]($type::ONE, base, index)
106                } else {
107                    (*$type::ONE).clone()
108                }
109            }
110        }
111    )*)
112}
113pow_times_group_template! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize f32 f64 }