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