fixed_bigint/fixeduint/
ilog_impl.rs1use super::{FixedUInt, MachineWord};
18use crate::const_numtraits::{ConstIlog, ConstPrimInt, ConstZero};
19use crate::machineword::ConstMachineWord;
20
21c0nst::c0nst! {
22 impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> c0nst ConstIlog for FixedUInt<T, N> {
23 fn ilog2(self) -> u32 {
24 match self.checked_ilog2() {
25 Some(v) => v,
26 None => panic!("ilog2: argument is zero"),
27 }
28 }
29
30 fn ilog10(self) -> u32 {
31 match self.checked_ilog10() {
32 Some(v) => v,
33 None => panic!("ilog10: argument is zero"),
34 }
35 }
36
37 fn ilog(self, base: Self) -> u32 {
38 match self.checked_ilog(base) {
39 Some(v) => v,
40 None => panic!("ilog: argument is zero or base is less than 2"),
41 }
42 }
43
44 fn checked_ilog2(self) -> Option<u32> {
45 if self.is_zero() {
46 return None;
47 }
48 let leading = ConstPrimInt::leading_zeros(self);
50 Some(Self::BIT_SIZE as u32 - 1 - leading)
51 }
52
53 fn checked_ilog10(self) -> Option<u32> {
54 if self.is_zero() {
55 return None;
56 }
57 let ten: Self = core::convert::From::from(10u8);
59 let mut n = self;
60 let mut count = 0u32;
61 while n >= ten {
62 n /= ten;
63 count += 1;
64 }
65 Some(count)
66 }
67
68 fn checked_ilog(self, base: Self) -> Option<u32> {
69 if self.is_zero() {
70 return None;
71 }
72 let two: Self = core::convert::From::from(2u8);
73 if base < two {
74 return None;
75 }
76 let mut n = self;
78 let mut count = 0u32;
79 while n >= base {
80 n /= base;
81 count += 1;
82 }
83 Some(count)
84 }
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
93 fn test_ilog2() {
94 type U16 = FixedUInt<u8, 2>;
95
96 assert_eq!(ConstIlog::ilog2(U16::from(1u8)), 0);
97 assert_eq!(ConstIlog::ilog2(U16::from(2u8)), 1);
98 assert_eq!(ConstIlog::ilog2(U16::from(3u8)), 1);
99 assert_eq!(ConstIlog::ilog2(U16::from(4u8)), 2);
100 assert_eq!(ConstIlog::ilog2(U16::from(7u8)), 2);
101 assert_eq!(ConstIlog::ilog2(U16::from(8u8)), 3);
102 assert_eq!(ConstIlog::ilog2(U16::from(255u8)), 7);
103 assert_eq!(ConstIlog::ilog2(U16::from(256u16)), 8);
104 assert_eq!(ConstIlog::ilog2(U16::from(32768u16)), 15);
105 }
106
107 #[test]
108 fn test_ilog10() {
109 type U16 = FixedUInt<u8, 2>;
110
111 assert_eq!(ConstIlog::ilog10(U16::from(1u8)), 0);
112 assert_eq!(ConstIlog::ilog10(U16::from(9u8)), 0);
113 assert_eq!(ConstIlog::ilog10(U16::from(10u8)), 1);
114 assert_eq!(ConstIlog::ilog10(U16::from(99u8)), 1);
115 assert_eq!(ConstIlog::ilog10(U16::from(100u8)), 2);
116 assert_eq!(ConstIlog::ilog10(U16::from(999u16)), 2);
117 assert_eq!(ConstIlog::ilog10(U16::from(1000u16)), 3);
118 assert_eq!(ConstIlog::ilog10(U16::from(9999u16)), 3);
119 assert_eq!(ConstIlog::ilog10(U16::from(10000u16)), 4);
120 }
121
122 #[test]
123 fn test_ilog() {
124 type U16 = FixedUInt<u8, 2>;
125
126 assert_eq!(ConstIlog::ilog(U16::from(8u8), U16::from(2u8)), 3);
128 assert_eq!(ConstIlog::ilog(U16::from(9u8), U16::from(2u8)), 3);
129
130 assert_eq!(ConstIlog::ilog(U16::from(1u8), U16::from(3u8)), 0);
132 assert_eq!(ConstIlog::ilog(U16::from(3u8), U16::from(3u8)), 1);
133 assert_eq!(ConstIlog::ilog(U16::from(8u8), U16::from(3u8)), 1);
134 assert_eq!(ConstIlog::ilog(U16::from(9u8), U16::from(3u8)), 2);
135 assert_eq!(ConstIlog::ilog(U16::from(27u8), U16::from(3u8)), 3);
136
137 assert_eq!(ConstIlog::ilog(U16::from(255u8), U16::from(16u8)), 1);
139 assert_eq!(ConstIlog::ilog(U16::from(256u16), U16::from(16u8)), 2);
140 }
141
142 #[test]
143 fn test_checked_ilog2() {
144 type U16 = FixedUInt<u8, 2>;
145
146 assert_eq!(ConstIlog::checked_ilog2(U16::from(0u8)), None);
147 assert_eq!(ConstIlog::checked_ilog2(U16::from(1u8)), Some(0));
148 assert_eq!(ConstIlog::checked_ilog2(U16::from(8u8)), Some(3));
149 }
150
151 #[test]
152 fn test_checked_ilog10() {
153 type U16 = FixedUInt<u8, 2>;
154
155 assert_eq!(ConstIlog::checked_ilog10(U16::from(0u8)), None);
156 assert_eq!(ConstIlog::checked_ilog10(U16::from(1u8)), Some(0));
157 assert_eq!(ConstIlog::checked_ilog10(U16::from(100u8)), Some(2));
158 }
159
160 #[test]
161 fn test_checked_ilog() {
162 type U16 = FixedUInt<u8, 2>;
163
164 assert_eq!(
166 ConstIlog::checked_ilog(U16::from(0u8), U16::from(2u8)),
167 None
168 );
169 assert_eq!(
171 ConstIlog::checked_ilog(U16::from(10u8), U16::from(0u8)),
172 None
173 );
174 assert_eq!(
175 ConstIlog::checked_ilog(U16::from(10u8), U16::from(1u8)),
176 None
177 );
178 assert_eq!(
180 ConstIlog::checked_ilog(U16::from(8u8), U16::from(2u8)),
181 Some(3)
182 );
183 }
184
185 c0nst::c0nst! {
186 pub c0nst fn const_ilog2<T: [c0nst] ConstMachineWord + MachineWord, const N: usize>(
187 v: FixedUInt<T, N>,
188 ) -> u32 {
189 ConstIlog::ilog2(v)
190 }
191
192 pub c0nst fn const_ilog10<T: [c0nst] ConstMachineWord + MachineWord, const N: usize>(
193 v: FixedUInt<T, N>,
194 ) -> u32 {
195 ConstIlog::ilog10(v)
196 }
197 }
198
199 #[test]
200 fn test_const_ilog() {
201 type U16 = FixedUInt<u8, 2>;
202
203 assert_eq!(const_ilog2(U16::from(8u8)), 3);
204 assert_eq!(const_ilog10(U16::from(100u8)), 2);
205
206 #[cfg(feature = "nightly")]
207 {
208 const EIGHT: U16 = FixedUInt { array: [8, 0] };
209 const HUNDRED: U16 = FixedUInt { array: [100, 0] };
210 const LOG2_RESULT: u32 = const_ilog2(EIGHT);
211 const LOG10_RESULT: u32 = const_ilog10(HUNDRED);
212 assert_eq!(LOG2_RESULT, 3);
213 assert_eq!(LOG10_RESULT, 2);
214 }
215 }
216}