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