1pub mod frac_part {
19 use core::num::NonZero;
20
21 #[inline]
24 pub const fn u8(val: NonZero<u8>) -> i32 {
25 let val = val.get();
26 if val > 25 {
27 -1
28 } else if val > 2 {
29 -2
30 } else {
31 -3
32 }
33 }
34
35 #[inline]
38 pub const fn u16(val: NonZero<u16>) -> i32 {
39 let val = val.get();
40 if val > 6553 {
41 -1
42 } else if val > 655 {
43 -2
44 } else if val > 65 {
45 -3
46 } else if val > 6 {
47 -4
48 } else {
49 -5
50 }
51 }
52
53 pub const fn u32(val: NonZero<u32>) -> i32 {
56 const MAX: u32 = u32::MAX;
57 let mut val = val.get();
58 if val <= MAX / 100_000_000 {
59 val *= 100_000_000;
60 if val > MAX / 10 {
63 -9
64 } else {
65 debug_assert!(val > MAX / 100);
66 -10
67 }
68 } else {
69 greater_equal_m8_u32(val)
70 }
71 }
72
73 pub const fn u64(val: NonZero<u64>) -> i32 {
76 const MAX: u64 = u64::MAX;
77 let mut val = val.get();
78 let mut log = 0;
79 if val <= MAX / 10_000_000_000_000_000 {
80 val *= 10_000_000_000_000_000;
83 log += -16;
84 } else {
85 if val <= MAX / 100_000_000 {
86 val *= 100_000_000;
87 log += -8;
88 }
89 if val <= MAX / 10_000 {
90 val *= 10_000;
91 log += -4;
92 }
93 }
94 log + if val > MAX / 10 {
95 -1
96 } else if val > MAX / 100 {
97 -2
98 } else if val > MAX / 1000 {
99 -3
100 } else {
101 debug_assert!(val > MAX / 10_000);
102 -4
103 }
104 }
105
106 pub const fn u128(val: NonZero<u128>) -> i32 {
109 const MAX: u128 = u128::MAX;
110 let mut val = val.get();
111 let mut log = 0;
112 if val <= MAX / 100_000_000_000_000_000_000_000_000_000_000 {
113 val *= 100_000_000_000_000_000_000_000_000_000_000;
114 return -32 + greater_equal_m8_u32((val >> 96) as u32);
119 }
120 if val <= MAX / 10_000_000_000_000_000 {
121 val *= 10_000_000_000_000_000;
122 log += -16;
123 }
124 if val <= MAX / 100_000_000 {
125 val *= 100_000_000;
126 log += -8;
127 }
128 if log == -24 {
129 return -24 + greater_equal_m8_u64((val >> 64) as u64);
134 }
135 if val <= MAX / 10_000 {
137 val *= 10_000;
138 log += -4;
139 }
140 log + if val > MAX / 10 {
141 -1
142 } else if val > MAX / 100 {
143 -2
144 } else if val > MAX / 1000 {
145 -3
146 } else {
147 debug_assert!(val > MAX / 10_000);
148 -4
149 }
150 }
151
152 const fn greater_equal_m8_u32(mut val: u32) -> i32 {
155 const MAX: u32 = u32::MAX;
156 debug_assert!(val > MAX / 100_000_000);
157 let mut log = 0;
158 if val <= MAX / 10_000 {
159 val *= 10_000;
160 log += -4;
161 }
162 log + if val > MAX / 10 {
163 -1
164 } else if val > MAX / 100 {
165 -2
166 } else if val > MAX / 1000 {
167 -3
168 } else {
169 debug_assert!(val > MAX / 10_000);
170 -4
171 }
172 }
173
174 const fn greater_equal_m8_u64(mut val: u64) -> i32 {
177 const MAX: u64 = u64::MAX;
178 debug_assert!(val > MAX / 100_000_000);
179 let mut log = 0;
180 if val <= MAX / 10_000 {
181 val *= 10_000;
182 log += -4;
183 }
184 log + if val > MAX / 10 {
185 -1
186 } else if val > MAX / 100 {
187 -2
188 } else if val > MAX / 1000 {
189 -3
190 } else {
191 debug_assert!(val > MAX / 10_000);
192 -4
193 }
194 }
195}
196
197#[cfg(test)]
199mod tests {
200 use crate::log;
201 use crate::log::Base;
202 use crate::log10;
203 use core::num::NonZero;
204
205 const DEC: Base = match Base::new(10) {
206 Some(s) => s,
207 None => unreachable!(),
208 };
209
210 macro_rules! check_loop {
211 ($T:ident) => {
212 for i in 0..=$T::MAX.ilog10() as i32 {
213 let p = (10 as $T).pow(i as u32);
214 let nz = NonZero::<$T>::new(p).unwrap();
215 if i > 0 {
216 let nz_m1 = NonZero::<$T>::new(p - 1).unwrap();
217 assert_eq!((p - 1).ilog10() as i32, i - 1);
218 assert_eq!(log::int_part::$T(nz_m1, DEC), i - 1);
219 }
220 assert_eq!(p.ilog10() as i32, i);
221 assert_eq!(log::int_part::$T(nz, DEC), i);
222 let nz_p1 = NonZero::<$T>::new(p + 1).unwrap();
223 assert_eq!((p + 1).ilog10() as i32, i);
224 assert_eq!(log::int_part::$T(nz_p1, DEC), i);
225 }
226
227 for i in 0..-log10::frac_part::$T(NonZero::<$T>::new(1).unwrap()) {
228 let p = <$T>::MAX / (10 as $T).pow(i as u32);
229 let nz = NonZero::<$T>::new(p).unwrap();
230 if p > 1 {
231 let nz_m1 = NonZero::<$T>::new(p - 1).unwrap();
232 assert_eq!(log10::frac_part::$T(nz_m1), -1 - i);
233 assert_eq!(log::frac_part::$T(nz_m1, DEC), -1 - i);
234 }
235 assert_eq!(log10::frac_part::$T(nz), -1 - i);
236 assert_eq!(log::frac_part::$T(nz, DEC), -1 - i);
237 if i > 0 {
238 let nz_p1 = NonZero::<$T>::new(p + 1).unwrap();
239 assert_eq!(log10::frac_part::$T(nz_p1), -i);
240 assert_eq!(log::frac_part::$T(nz_p1, DEC), -i);
241 }
242 }
243 };
244 }
245
246 #[test]
247 fn log10_u8() {
248 let one = NonZero::<u8>::new(1).unwrap();
249
250 assert_eq!(1u8.ilog10(), 0);
251 assert_eq!(log::int_part::u8(one, DEC), 0);
252 assert_eq!(u8::MAX.ilog10(), 2);
253 assert_eq!(log::int_part::u8(NonZero::<u8>::MAX, DEC), 2);
254 assert_eq!(log10::frac_part::u8(one), -3);
255 assert_eq!(log::frac_part::u8(one, DEC), -3);
256 assert_eq!(log10::frac_part::u8(NonZero::<u8>::MAX), -1);
257 assert_eq!(log::frac_part::u8(NonZero::<u8>::MAX, DEC), -1);
258
259 check_loop! { u8 }
260 }
261
262 #[test]
263 fn log10_u16() {
264 let one = NonZero::<u16>::new(1).unwrap();
265
266 assert_eq!(1u16.ilog10(), 0);
267 assert_eq!(log::int_part::u16(one, DEC), 0);
268 assert_eq!(u16::MAX.ilog10(), 4);
269 assert_eq!(log::int_part::u16(NonZero::<u16>::MAX, DEC), 4);
270 assert_eq!(log10::frac_part::u16(one), -5);
271 assert_eq!(log::frac_part::u16(one, DEC), -5);
272 assert_eq!(log10::frac_part::u16(NonZero::<u16>::MAX), -1);
273 assert_eq!(log::frac_part::u16(NonZero::<u16>::MAX, DEC), -1);
274
275 check_loop! { u16 }
276 }
277
278 #[test]
279 fn log10_u32() {
280 let one = NonZero::<u32>::new(1).unwrap();
281
282 assert_eq!(1u32.ilog10(), 0);
283 assert_eq!(log::int_part::u32(NonZero::<u32>::new(1).unwrap(), DEC), 0);
284 assert_eq!(u32::MAX.ilog10(), 9);
285 assert_eq!(log::int_part::u32(NonZero::<u32>::MAX, DEC), 9);
286 assert_eq!(log10::frac_part::u32(one), -10);
287 assert_eq!(log::frac_part::u32(one, DEC), -10);
288 assert_eq!(log10::frac_part::u32(NonZero::<u32>::MAX), -1);
289 assert_eq!(log::frac_part::u32(NonZero::<u32>::MAX, DEC), -1);
290
291 check_loop! { u32 }
292 }
293
294 #[test]
295 fn log10_u64() {
296 let one = NonZero::<u64>::new(1).unwrap();
297
298 assert_eq!(1u64.ilog10(), 0);
299 assert_eq!(log::int_part::u64(one, DEC), 0);
300 assert_eq!(u64::MAX.ilog10(), 19);
301 assert_eq!(log::int_part::u64(NonZero::<u64>::MAX, DEC), 19);
302 assert_eq!(log10::frac_part::u64(one), -20);
303 assert_eq!(log::frac_part::u64(one, DEC), -20);
304 assert_eq!(log10::frac_part::u64(NonZero::<u64>::MAX), -1);
305 assert_eq!(log::frac_part::u64(NonZero::<u64>::MAX, DEC), -1);
306
307 check_loop! { u64 }
308 }
309
310 #[test]
311 fn log10_u128() {
312 let one = NonZero::<u128>::new(1).unwrap();
313
314 assert_eq!(1u128.ilog10(), 0);
315 assert_eq!(log::int_part::u128(one, DEC), 0);
316 assert_eq!(u128::MAX.ilog10(), 38);
317 assert_eq!(log::int_part::u128(NonZero::<u128>::MAX, DEC), 38);
318 assert_eq!(log10::frac_part::u128(one), -39);
319 assert_eq!(log::frac_part::u128(one, DEC), -39);
320 assert_eq!(log10::frac_part::u128(NonZero::<u128>::MAX), -1);
321 assert_eq!(log::frac_part::u128(NonZero::<u128>::MAX, DEC), -1);
322
323 check_loop! { u128 }
324 }
325}