fixed_bigint/fixeduint/
checked_pow_impl.rs1use super::{FixedUInt, MachineWord};
18use crate::machineword::ConstMachineWord;
19use const_num_traits::Nct;
20use const_num_traits::{CheckedMul, CheckedPow, One};
21
22c0nst::c0nst! {
23 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> CheckedPow for FixedUInt<T, N, Nct> {
24 fn checked_pow(self, exp: u32) -> Option<Self> {
25 if exp == 0 {
26 return Some(Self::one());
27 }
28 let mut result = Self::one();
30 let mut base = self;
31 let mut e = exp;
32 while e > 0 {
33 if (e & 1) == 1 {
34 result = match CheckedMul::checked_mul(result, base) {
35 Some(v) => v,
36 None => return None,
37 };
38 }
39 e >>= 1;
40 if e > 0 {
41 base = match CheckedMul::checked_mul(base, base) {
42 Some(v) => v,
43 None => return None,
44 };
45 }
46 }
47 Some(result)
48 }
49 }
50
51 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> CheckedPow for &FixedUInt<T, N, Nct> {
52 fn checked_pow(self, exp: u32) -> Option<FixedUInt<T, N, Nct>> {
53 <FixedUInt<T, N, Nct> as CheckedPow>::checked_pow(*self, exp)
54 }
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61
62 #[test]
63 fn test_checked_pow() {
64 type U16 = FixedUInt<u8, 2>;
65
66 assert_eq!(
68 CheckedPow::checked_pow(U16::from(2u8), 0),
69 Some(U16::from(1u8))
70 );
71 assert_eq!(
72 CheckedPow::checked_pow(U16::from(2u8), 1),
73 Some(U16::from(2u8))
74 );
75 assert_eq!(
76 CheckedPow::checked_pow(U16::from(2u8), 2),
77 Some(U16::from(4u8))
78 );
79 assert_eq!(
80 CheckedPow::checked_pow(U16::from(2u8), 8),
81 Some(U16::from(256u16))
82 );
83 assert_eq!(
84 CheckedPow::checked_pow(U16::from(3u8), 3),
85 Some(U16::from(27u8))
86 );
87
88 assert_eq!(
90 CheckedPow::checked_pow(U16::from(0u8), 0),
91 Some(U16::from(1u8))
92 );
93 assert_eq!(
94 CheckedPow::checked_pow(U16::from(0u8), 5),
95 Some(U16::from(0u8))
96 );
97 assert_eq!(
98 CheckedPow::checked_pow(U16::from(1u8), 100),
99 Some(U16::from(1u8))
100 );
101
102 assert_eq!(CheckedPow::checked_pow(U16::from(2u8), 16), None); assert_eq!(CheckedPow::checked_pow(U16::from(256u16), 2), None); assert_eq!(
108 CheckedPow::checked_pow(U16::from(2u8), 15),
109 Some(U16::from(32768u16))
110 );
111 }
112
113 c0nst::c0nst! {
114 pub c0nst fn const_checked_pow<T: [c0nst] ConstMachineWord + MachineWord, const N: usize>(
115 base: FixedUInt<T, N, Nct>,
116 exp: u32,
117 ) -> Option<FixedUInt<T, N, Nct>> {
118 CheckedPow::checked_pow(base, exp)
119 }
120 }
121
122 #[test]
123 fn test_const_checked_pow() {
124 type U16 = FixedUInt<u8, 2>;
125
126 assert_eq!(
127 const_checked_pow(U16::from(2u8), 8),
128 Some(U16::from(256u16))
129 );
130
131 #[cfg(feature = "nightly")]
132 {
133 const BASE: U16 = FixedUInt::from_array([2, 0]);
134 const POW_RESULT: Option<U16> = const_checked_pow(BASE, 8);
135 assert_eq!(POW_RESULT, Some(FixedUInt::from_array([0, 1]))); }
137 }
138}