From 965f378fe84176da3ff2bd40b57fef88f687fbfb Mon Sep 17 00:00:00 2001 From: Malte Kliemann Date: Mon, 2 Dec 2024 14:40:21 +0100 Subject: [PATCH] Fix `log_ceil` and add extensive tests --- zrml/neo-swaps/src/utility.rs | 39 ++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/zrml/neo-swaps/src/utility.rs b/zrml/neo-swaps/src/utility.rs index 62103304b..c366c8d1f 100644 --- a/zrml/neo-swaps/src/utility.rs +++ b/zrml/neo-swaps/src/utility.rs @@ -16,8 +16,10 @@ // along with Zeitgeist. If not, see . use sp_runtime::SaturatedConversion; +use sp_runtime::traits::{One, Zero}; pub(crate) trait LogCeil { + /// Calculates the ceil of the log with base 2 of `self`. fn log_ceil(&self) -> Self; } @@ -25,10 +27,45 @@ impl LogCeil for u16 { fn log_ceil(&self) -> Self { let x = *self; - let bits_minus_one = u16::MAX.saturating_sub(1); + if x.is_zero() { + return One::one(); + } + + let bits_minus_one: u16 = u16::BITS.saturating_sub(1).saturated_into(); let leading_zeros: u16 = x.leading_zeros().saturated_into(); let floor_log2 = bits_minus_one.saturating_sub(leading_zeros); if x.is_power_of_two() { floor_log2 } else { floor_log2.saturating_add(1) } } } + +#[cfg(test)] +mod tests { + use super::*; + use test_case::test_case; + + #[test_case(0, 1)] + #[test_case(1, 0)] + #[test_case(2, 1)] + #[test_case(3, 2)] + #[test_case(4, 2)] + #[test_case(5, 3)] + #[test_case(6, 3)] + #[test_case(7, 3)] + #[test_case(8, 3)] + #[test_case(9, 4)] + #[test_case(15, 4)] + #[test_case(16, 4)] + #[test_case(17, 5)] + #[test_case(1023, 10)] + #[test_case(1024, 10)] + #[test_case(1025, 11)] + #[test_case(32767, 15)] + #[test_case(32768, 15)] + #[test_case(32769, 16)] + #[test_case(65535, 16)] + fn log_ceil_works(value: u16, expected: u16) { + let actual = value.log_ceil(); + assert_eq!(actual, expected); + } +}