binius_utils/
checked_arithmetics.rs1pub const fn checked_int_div(a: usize, b: usize) -> usize {
6 let result = a / b;
7 assert!(b * result == a);
8
9 result
10}
11
12#[inline]
15#[must_use]
16pub const fn strict_log_2(val: usize) -> Option<usize> {
17 if val == 0 {
18 return None;
19 }
20
21 let pow = val.trailing_zeros();
22 if val.wrapping_shr(pow) == 1 {
23 Some(pow as usize)
24 } else {
25 None
26 }
27}
28
29#[inline]
31#[must_use]
32pub const fn checked_log_2(val: usize) -> usize {
33 strict_log_2(val).expect("Value is not a power of 2")
34}
35
36#[must_use]
40pub const fn log2_ceil_usize(n: usize) -> usize {
41 min_bits(n.saturating_sub(1))
42}
43
44#[must_use]
48pub const fn min_bits(n: usize) -> usize {
49 (usize::BITS - n.leading_zeros()) as usize
50}
51
52#[must_use]
57#[inline]
58pub fn log2_strict_usize(n: usize) -> usize {
59 let res = n.trailing_zeros();
60 assert_eq!(n.wrapping_shr(res), 1, "Not a power of two: {n}");
61 res as usize
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 #[test]
69 fn test_checked_int_div_success() {
70 assert_eq!(checked_int_div(6, 1), 6);
71 assert_eq!(checked_int_div(6, 2), 3);
72 assert_eq!(checked_int_div(6, 6), 1);
73 }
74
75 #[test]
76 #[should_panic]
77 const fn test_checked_int_div_fail() {
78 _ = checked_int_div(5, 2);
79 }
80
81 #[test]
82 fn test_checked_log2_success() {
83 assert_eq!(checked_log_2(1), 0);
84 assert_eq!(checked_log_2(2), 1);
85 assert_eq!(checked_log_2(4), 2);
86 assert_eq!(checked_log_2(64), 6);
87 }
88
89 #[test]
90 #[should_panic]
91 const fn test_checked_log2_fail() {
92 _ = checked_log_2(6)
93 }
94}