binius_utils/
checked_arithmetics.rs

1// Copyright 2024-2025 Irreducible Inc.
2// Copyright (c) 2024 The Plonky3 Authors
3
4/// Division implementation that fails in case when `a`` isn't divisible by `b`
5pub 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/// log2 implementation that fails when `val` is not a power of 2.
13pub const fn checked_log_2(val: usize) -> usize {
14	let result = val.ilog2();
15	assert!(2usize.pow(result) == val);
16
17	result as _
18}
19
20/// Computes `ceil(log_2(n))`.
21#[must_use]
22pub const fn log2_ceil_usize(n: usize) -> usize {
23	(usize::BITS - n.saturating_sub(1).leading_zeros()) as usize
24}
25
26/// Computes `log_2(n)`
27///
28/// # Panics
29/// Panics if `n` is not a power of two.
30#[must_use]
31#[inline]
32pub fn log2_strict_usize(n: usize) -> usize {
33	let res = n.trailing_zeros();
34	assert_eq!(n.wrapping_shr(res), 1, "Not a power of two: {n}");
35	res as usize
36}
37
38#[cfg(test)]
39mod tests {
40	use super::*;
41
42	#[test]
43	fn test_checked_int_div_success() {
44		assert_eq!(checked_int_div(6, 1), 6);
45		assert_eq!(checked_int_div(6, 2), 3);
46		assert_eq!(checked_int_div(6, 6), 1);
47	}
48
49	#[test]
50	#[should_panic]
51	const fn test_checked_int_div_fail() {
52		_ = checked_int_div(5, 2);
53	}
54
55	#[test]
56	fn test_checked_log2_success() {
57		assert_eq!(checked_log_2(1), 0);
58		assert_eq!(checked_log_2(2), 1);
59		assert_eq!(checked_log_2(4), 2);
60		assert_eq!(checked_log_2(64), 6);
61	}
62
63	#[test]
64	#[should_panic]
65	const fn test_checked_log2_fail() {
66		_ = checked_log_2(6)
67	}
68}