From d51ffc171183010ac3dab1f4cc771a8a139ea034 Mon Sep 17 00:00:00 2001 From: Isaac Holt Date: Fri, 23 Feb 2024 13:22:52 +0000 Subject: [PATCH 1/3] fix ilog behaves differently from std lib #39, bump version to 0.11.0 --- Cargo.toml | 2 +- README.md | 4 ++-- changes/v0.11.0 | 2 ++ src/bint/endian.rs | 4 ++-- src/bint/mod.rs | 22 ++++++++++++---------- src/buint/cast.rs | 2 +- src/buint/endian.rs | 6 +++--- src/buint/mod.rs | 39 ++++++++++++++------------------------- src/errors/macros.rs | 16 ++++++++++++++++ src/int/mod.rs | 8 ++++---- src/lib.rs | 2 +- 11 files changed, 58 insertions(+), 49 deletions(-) create mode 100644 changes/v0.11.0 diff --git a/Cargo.toml b/Cargo.toml index b9a9bbf..02cc1bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bnum" -version = "0.10.0" +version = "0.11.0" authors = ["isaac-holt "] edition = "2021" license = "MIT OR Apache-2.0" diff --git a/README.md b/README.md index 522f59d..8c6c6db 100644 --- a/README.md +++ b/README.md @@ -32,13 +32,13 @@ This crate uses Rust's const generics to allow creation of integers of arbitrary To install and use `bnum`, simply add the following line to your `Cargo.toml` file in the `[dependencies]` section: ```toml -bnum = "0.10.0" +bnum = "0.11.0" ``` Or, to enable various `bnum` features as well, add for example this line instead: ```toml -bnum = { version = "0.10.0", features = ["rand"] } # enables the "rand" feature +bnum = { version = "0.11.0", features = ["rand"] } # enables the "rand" feature ``` ## Example Usage diff --git a/changes/v0.11.0 b/changes/v0.11.0 new file mode 100644 index 0000000..9748c6b --- /dev/null +++ b/changes/v0.11.0 @@ -0,0 +1,2 @@ +- Make integer ilog methods panic for invalid inputs in release mode as well as debug mode. +- Match ilog panic message with that of Rust's primitives. \ No newline at end of file diff --git a/src/bint/endian.rs b/src/bint/endian.rs index a1807f2..27034bd 100644 --- a/src/bint/endian.rs +++ b/src/bint/endian.rs @@ -1,6 +1,6 @@ use crate::digit; use crate::doc; -use core::mem::MaybeUninit; +// use core::mem::MaybeUninit; macro_rules! endian { ($BUint: ident, $BInt: ident, $Digit: ident) => { @@ -131,7 +131,7 @@ macro_rules! endian { $Digit::MIN }; let mut out_digits = [sign_bits; N]; - let slice_ptr = slice.as_ptr(); + // let slice_ptr = slice.as_ptr(); let mut i = 0; let exact = len >> digit::$Digit::BYTE_SHIFT; while i < exact { diff --git a/src/bint/mod.rs b/src/bint/mod.rs index d784f48..e681875 100644 --- a/src/bint/mod.rs +++ b/src/bint/mod.rs @@ -4,11 +4,13 @@ macro_rules! ilog { #[must_use = doc::must_use_op!()] #[inline] pub const fn $method(self, $($base : $ty),*) -> ExpType { + $( + if $base.le(&<$ty>::ONE) { + panic!(errors::err_msg!(errors::invalid_log_base!())) + } + ), * if self.is_negative() { - #[cfg(debug_assertions)] - panic!(errors::err_msg!("attempt to calculate ilog of negative number")); - #[cfg(not(debug_assertions))] - 0 + panic!(errors::err_msg!(errors::non_positive_log_message!())) } else { self.bits.$method($($base.bits)?) } @@ -463,16 +465,16 @@ macro_rules! mod_impl { #[test] fn sum() { - let v = vec![&UTEST::ZERO, &UTEST::ONE, &UTEST::TWO, &UTEST::THREE, &UTEST::FOUR]; - assert_eq!(UTEST::TEN, v.iter().copied().sum()); - assert_eq!(UTEST::TEN, v.into_iter().sum()); + let v = vec![&ITEST::ZERO, &ITEST::ONE, &ITEST::TWO, &ITEST::THREE, &ITEST::FOUR]; + assert_eq!(ITEST::TEN, v.iter().copied().sum()); + assert_eq!(ITEST::TEN, v.into_iter().sum()); } #[test] fn product() { - let v = vec![&UTEST::ONE, &UTEST::TWO, &UTEST::THREE]; - assert_eq!(UTEST::SIX, v.iter().copied().sum()); - assert_eq!(UTEST::SIX, v.into_iter().sum()); + let v = vec![&ITEST::ONE, &ITEST::TWO, &ITEST::THREE]; + assert_eq!(ITEST::SIX, v.iter().copied().sum()); + assert_eq!(ITEST::SIX, v.into_iter().sum()); } } } diff --git a/src/buint/cast.rs b/src/buint/cast.rs index d9d7f47..0d303dd 100644 --- a/src/buint/cast.rs +++ b/src/buint/cast.rs @@ -124,7 +124,7 @@ macro_rules! as_buint { use crate::cast::CastFrom; use crate::doc; use crate::nightly::impl_const; -use core::mem::MaybeUninit; +// use core::mem::MaybeUninit; macro_rules! cast { ($BUint: ident, $BInt: ident, $Digit: ident) => { diff --git a/src/buint/endian.rs b/src/buint/endian.rs index 732ebff..e484b7f 100644 --- a/src/buint/endian.rs +++ b/src/buint/endian.rs @@ -1,6 +1,6 @@ use crate::digit; use crate::doc; -use core::mem::MaybeUninit; +// use core::mem::MaybeUninit; macro_rules! endian { ($BUint: ident, $BInt: ident, $Digit: ident) => { @@ -66,7 +66,7 @@ macro_rules! endian { pub const fn from_be_slice(slice: &[u8]) -> Option { let len = slice.len(); let mut out = Self::ZERO; - let slice_ptr = slice.as_ptr(); + // let slice_ptr = slice.as_ptr(); let mut i = 0; let exact = len >> digit::$Digit::BYTE_SHIFT; while i < exact { @@ -131,7 +131,7 @@ macro_rules! endian { pub const fn from_le_slice(slice: &[u8]) -> Option { let len = slice.len(); let mut out = Self::ZERO; - let slice_ptr = slice.as_ptr(); + // let slice_ptr = slice.as_ptr(); let mut i = 0; let exact = len >> digit::$Digit::BYTE_SHIFT; while i < exact { diff --git a/src/buint/mod.rs b/src/buint/mod.rs index 513d3c1..3d00417 100644 --- a/src/buint/mod.rs +++ b/src/buint/mod.rs @@ -1,10 +1,9 @@ -#[cfg(debug_assertions)] use crate::errors::{self, option_expect}; use crate::digit; use crate::doc; use crate::ExpType; -use core::mem::MaybeUninit; +// use core::mem::MaybeUninit; #[cfg(feature = "serde")] use ::{ @@ -296,42 +295,32 @@ macro_rules! mod_impl { #[must_use = doc::must_use_op!()] #[inline] pub const fn ilog2(self) -> ExpType { - #[cfg(debug_assertions)] - return option_expect!( + option_expect!( self.checked_ilog2(), - errors::err_msg!("attempt to calculate ilog2 of zero") - ); - #[cfg(not(debug_assertions))] - match self.checked_ilog2() { - Some(n) => n, - None => 0, - } + errors::err_msg!(errors::non_positive_log_message!()) + ) } #[doc = doc::ilog10!(U)] #[must_use = doc::must_use_op!()] #[inline] pub const fn ilog10(self) -> ExpType { - #[cfg(debug_assertions)] - return option_expect!(self.checked_ilog10(), errors::err_msg!("attempt to calculate ilog10 of zero")); - #[cfg(not(debug_assertions))] - match self.checked_ilog10() { - Some(n) => n, - None => 0, - } + option_expect!( + self.checked_ilog10(), + errors::err_msg!(errors::non_positive_log_message!()) + ) } #[doc = doc::ilog!(U)] #[must_use = doc::must_use_op!()] #[inline] pub const fn ilog(self, base: Self) -> ExpType { - #[cfg(debug_assertions)] - return option_expect!(self.checked_ilog(base), errors::err_msg!("attempt to calculate ilog of zero or ilog with base < 2")); - #[cfg(not(debug_assertions))] - match self.checked_ilog(base) { - Some(n) => n, - None => 0, + if base.le(&Self::ONE) { + panic!("{}", errors::err_msg!(errors::invalid_log_base!())); } + option_expect!( + self.checked_ilog(base), errors::err_msg!(errors::non_positive_log_message!()) + ) } #[doc = doc::abs_diff!(U)] @@ -384,7 +373,7 @@ macro_rules! mod_impl { let digit_shift = (rhs >> digit::$Digit::BIT_SHIFT) as usize; let bit_shift = rhs & digit::$Digit::BITS_MINUS_1; - let num_copies = N.saturating_sub(digit_shift); // TODO: use unchecked_ methods from primitives when these are stablised and constified + // let num_copies = N.saturating_sub(digit_shift); // TODO: use unchecked_ methods from primitives when these are stablised and constified if bit_shift != 0 { let carry_shift = digit::$Digit::BITS - bit_shift; diff --git a/src/errors/macros.rs b/src/errors/macros.rs index 3acbbb2..cbc20c7 100644 --- a/src/errors/macros.rs +++ b/src/errors/macros.rs @@ -38,6 +38,22 @@ macro_rules! rem_by_zero_message { pub(crate) use rem_by_zero_message; +macro_rules! non_positive_log_message { + () => { + "argument of integer logarithm must be positive" + } +} + +pub(crate) use non_positive_log_message; + +macro_rules! invalid_log_base { + () => { + "base of integer logarithm must be at least 2" + } +} + +pub(crate) use invalid_log_base; + macro_rules! rem_zero { () => { panic!(crate::errors::err_msg!(crate::errors::rem_by_zero_message!())) diff --git a/src/int/mod.rs b/src/int/mod.rs index 5855de9..7756d71 100644 --- a/src/int/mod.rs +++ b/src/int/mod.rs @@ -61,22 +61,22 @@ macro_rules! tests { } test_bignum! { function: <$int>::ilog(a: $int, base: $int), - skip: crate::test::debug_skip!(a <= 0 || base <= 1) + skip: a <= 0 || base <= 1 } test_bignum! { function: <$int>::ilog2(a: $int), - skip: crate::test::debug_skip!(a <= 0) + skip: a <= 0 } test_bignum! { function: <$int>::ilog10(a: $int), - skip: crate::test::debug_skip!(a <= 0) + skip: a <= 0 } test_bignum! { function: <$int>::checked_next_multiple_of(a: $int, b: $int) } test_bignum! { function: <$int>::next_multiple_of(a: $int, b: $int), - skip: crate::test::debug_skip!(a.checked_next_multiple_of(b).is_none()) + skip: crate::test::debug_skip!(a.checked_next_multiple_of(b).is_none()) || b == 0 } test_bignum! { function: <$int>::div_floor(a: $int, b: $int), diff --git a/src/lib.rs b/src/lib.rs index 3e48a9b..c55a525 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,7 +16,7 @@ wrapping_next_power_of_two, float_next_up_down, unchecked_math, - unchecked_shifts, + // unchecked_shifts, ) )] #![doc = include_str!("../README.md")] From 88235e6678dcaed6e8df0f984581b22a6fade109 Mon Sep 17 00:00:00 2001 From: Isaac Holt Date: Fri, 23 Feb 2024 13:45:15 +0000 Subject: [PATCH 2/3] enable unchecked_shifts feature when testing --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index c55a525..3e48a9b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,7 +16,7 @@ wrapping_next_power_of_two, float_next_up_down, unchecked_math, - // unchecked_shifts, + unchecked_shifts, ) )] #![doc = include_str!("../README.md")] From bc003649109bbe3fac12af55869b93b3a2e03242 Mon Sep 17 00:00:00 2001 From: Isaac Holt Date: Fri, 23 Feb 2024 13:50:00 +0000 Subject: [PATCH 3/3] update codecov.yml --- codecov.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/codecov.yml b/codecov.yml index 8249085..dce6387 100644 --- a/codecov.yml +++ b/codecov.yml @@ -2,7 +2,7 @@ coverage: status: project: default: - threshold: 1% # needed because due to property based testing, coverage isn't exactly the same each time + threshold: 2% # needed because due to property based testing, coverage isn't exactly the same each time patch: default: - threshold: 1% # needed because due to property based testing, coverage isn't exactly the same each time \ No newline at end of file + threshold: 2% # needed because due to property based testing, coverage isn't exactly the same each time \ No newline at end of file