From 7a0780a17b1382ffd4a050468775bcf7c58440de Mon Sep 17 00:00:00 2001 From: Erik Takke Date: Wed, 9 Oct 2024 15:18:03 +0200 Subject: [PATCH 01/19] Introduce basic Int struct --- src/int.rs | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 59 ++++++++++++++--------------- 2 files changed, 135 insertions(+), 31 deletions(-) create mode 100644 src/int.rs diff --git a/src/int.rs b/src/int.rs new file mode 100644 index 000000000..1f0453c9a --- /dev/null +++ b/src/int.rs @@ -0,0 +1,107 @@ +//! Stack-allocated big signed integers. + +use crate::{Limb, Uint}; + +#[derive(Copy, Clone, Hash)] +pub struct Int { + // TODO(erik): replace with Choice once I've figured how to const-construct those. + is_negative: bool, + magnitude: Uint, +} + +impl Int { + /// The value `0`. + pub const ZERO: Self = Self { + is_negative: false, + magnitude: Uint::ZERO, + }; + + /// The value `1`. + pub const ONE: Self = Self { + is_negative: false, + magnitude: Uint::ONE, + }; + + /// The value `-1`. + pub const MINUS_ONE: Self = Self { + is_negative: true, + magnitude: Uint::ONE, + }; + + /// Maximum value this [`Uint`] can express. + pub const MAX: Self = Self { + is_negative: false, + magnitude: Uint::MAX, + }; + + /// Smallest value this [`Uint`] can express. + // Note: keep in mind that when `LIMBS = 0`, the minimal value we can express is zero. + pub const MIN: Self = Self { + is_negative: LIMBS != 0, + magnitude: Uint::MAX, + }; + + /// The number of limbs used on this platform. + pub const LIMBS: usize = LIMBS; + + /// Const-friendly [`Int`] constructor. + pub const fn new(is_negative: bool, limbs: [Limb; LIMBS]) -> Self { + Self { + is_negative, + magnitude: Uint::new(limbs), + } + } +} + +#[cfg(test)] +#[allow(clippy::unwrap_used)] +mod tests { + use crate::{U128, Uint}; + use crate::int::Int; + + #[cfg(target_pointer_width = "64")] + type I128 = Int<2>; + + #[cfg(target_pointer_width = "32")] + type I128 = Int<4>; + + #[test] + fn zero() { + let n = I128::ZERO; + assert!(!n.is_negative); + assert_eq!(n.magnitude, U128::ZERO); + } + + #[test] + fn one() { + let n = I128::ONE; + assert!(!n.is_negative); + assert_eq!(n.magnitude, U128::ONE); + } + + #[test] + fn minus_one() { + let n = I128::MINUS_ONE; + assert!(n.is_negative); + assert_eq!(n.magnitude, U128::ONE); + } + + #[test] + fn min() { + let n = I128::MIN; + assert!(n.is_negative); + assert_eq!(n.magnitude, U128::MAX); + + // Deal with case that LIMBS = 0 + let n = Int::<0>::MIN; + assert!(!n.is_negative); + assert_eq!(n.magnitude, Uint::<0>::MAX); // dirty trick; MAX is zero, while ZERO panics. + } + + #[test] + fn max() { + let n = I128::MAX; + assert!(!n.is_negative); + assert_eq!(n.magnitude, U128::MAX); + } +} diff --git a/src/lib.rs b/src/lib.rs index cdfab0abb..6da3860a4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -155,22 +155,19 @@ #[macro_use] extern crate alloc; -#[macro_use] -mod macros; - -pub mod modular; +#[cfg(feature = "rand_core")] +pub use rand_core; +#[cfg(feature = "rlp")] +pub use rlp; +pub use subtle; +#[cfg(feature = "zeroize")] +pub use zeroize; #[cfg(feature = "hybrid-array")] -mod array; -mod checked; -mod const_choice; -mod limb; -mod non_zero; -mod odd; -mod primitives; -mod traits; -mod uint; -mod wrapping; +pub use { + crate::array::{ArrayDecoding, ArrayEncoding, ByteArray}, + hybrid_array::{self, typenum::consts}, +}; pub use crate::{ checked::Checked, @@ -179,34 +176,34 @@ pub use crate::{ non_zero::NonZero, odd::Odd, traits::*, - uint::div_limb::Reciprocal, uint::*, + uint::div_limb::Reciprocal, wrapping::Wrapping, }; -pub use subtle; - #[cfg(feature = "alloc")] pub use crate::uint::boxed::BoxedUint; -#[cfg(feature = "hybrid-array")] -pub use { - crate::array::{ArrayDecoding, ArrayEncoding, ByteArray}, - hybrid_array::{self, typenum::consts}, -}; - -#[cfg(feature = "rand_core")] -pub use rand_core; +#[macro_use] +mod macros; -#[cfg(feature = "rlp")] -pub use rlp; +pub mod modular; -#[cfg(feature = "zeroize")] -pub use zeroize; +#[cfg(feature = "hybrid-array")] +mod array; +mod checked; +mod const_choice; +mod int; +mod limb; +mod non_zero; +mod odd; +mod primitives; +mod traits; +mod uint; +mod wrapping; /// Import prelude for this crate: includes important traits. pub mod prelude { - pub use crate::traits::*; - #[cfg(feature = "hybrid-array")] pub use crate::array::{ArrayDecoding, ArrayEncoding}; + pub use crate::traits::*; } From 47a0fde3f011f632c6d1e38cf2827f1fb125de79 Mon Sep 17 00:00:00 2001 From: Erik Takke Date: Thu, 10 Oct 2024 10:43:27 +0200 Subject: [PATCH 02/19] Introduce (not fully correct) Int::checked_add --- src/int.rs | 44 ++++++++++--- src/int/add.rs | 165 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 201 insertions(+), 8 deletions(-) create mode 100644 src/int/add.rs diff --git a/src/int.rs b/src/int.rs index 1f0453c9a..c89a42592 100644 --- a/src/int.rs +++ b/src/int.rs @@ -1,8 +1,13 @@ //! Stack-allocated big signed integers. +use num_traits::Zero; +use subtle::Choice; + use crate::{Limb, Uint}; -#[derive(Copy, Clone, Hash)] +mod add; + +#[derive(Copy, Clone, Hash, Debug, PartialEq)] pub struct Int { // TODO(erik): replace with Choice once I've figured how to const-construct those. is_negative: bool, @@ -51,19 +56,42 @@ impl Int { magnitude: Uint::new(limbs), } } + + /// Const-friendly [`Int`] constructor, using a `Uint`. + pub const fn new_from_uint(is_negative: bool, magnitude: Uint) -> Self { + Self { + is_negative, + magnitude, + } + } + + /// Whether this [`Int`] is negative + pub fn is_negative(&self) -> Choice { + Choice::from(u8::from(self.is_negative)) + } + + /// Whether this [`Int`] is zero + pub fn is_zero(&self) -> Choice { + Choice::from(u8::from(self.magnitude.is_zero())) + } + + /// Whether this [`Int`] is non-negative, i.e. >= 0. + pub fn is_non_negative(&self) -> Choice { + !Choice::from(u8::from(self.is_negative)) + } } +#[cfg(target_pointer_width = "64")] +type I128 = Int<2>; + +#[cfg(target_pointer_width = "32")] +type I128 = Int<4>; + #[cfg(test)] #[allow(clippy::unwrap_used)] mod tests { use crate::{U128, Uint}; - use crate::int::Int; - - #[cfg(target_pointer_width = "64")] - type I128 = Int<2>; - - #[cfg(target_pointer_width = "32")] - type I128 = Int<4>; + use crate::int::{I128, Int}; #[test] fn zero() { diff --git a/src/int/add.rs b/src/int/add.rs new file mode 100644 index 000000000..b46b0d588 --- /dev/null +++ b/src/int/add.rs @@ -0,0 +1,165 @@ +//! [`Int`] addition operations. + +use core::ops::Add; + +use subtle::{Choice, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess, CtOption}; + +use crate::{CheckedAdd, CheckedSub, ConstantTimeSelect}; +use crate::int::Int; + +impl Add for Int { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self.add(&rhs) + } +} + +impl Add<&Int> for Int { + type Output = Self; + + fn add(self, rhs: &Self) -> Self { + self.checked_add(rhs) + .expect("attempted to add with overflow") + } +} + +impl CheckedAdd for Int { + fn checked_add(&self, rhs: &Self) -> CtOption { + // Based on the signs of lhs and rhs, we have to consider the following cases: + // case | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | + // -----|---|---|---|---|---|---|---|---|---| + // lhs | + | + | + | 0 | 0 | 0 | - | - | - | + // rhs | + | 0 | - | + | 0 | - | + | 0 | - | + // + // Whether to add or subtract the two halves, which is chosen as follows: + // case | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | + // -----|---|---|---|---|---|---|---|---|---| + // a/s | a | a | s | a | a | s | s | s | a | + // +/- | + | + | ? | + | + | ? | ? | - | - | + + // One of the two has the result we seek. + // Now it is a matter of computing which. + let magnitude_sum = self.magnitude.checked_add(&rhs.magnitude); + let magnitude_diff = self.magnitude.checked_sub(&rhs.magnitude); + + // Select the magnitude, based on whether lhs and rhs have the same sign. + let equal_sign = self.is_negative().ct_eq(&rhs.is_negative()); + // Note: we must include the case that either side is ZERO for selecting magnitude_sum + let use_sum = self.is_zero() | rhs.is_zero() | equal_sign; + let magnitude = CtOption::ct_select(&magnitude_diff, &magnitude_sum, use_sum); + + // Determine whether the result is negative, based on whether lhs or rhs has a greater magnitude. + let self_gt_rhs = self.magnitude.ct_gt(&rhs.magnitude); + let self_lt_rhs = self.magnitude.ct_lt(&rhs.magnitude); + let is_negative = (self.is_non_negative() | rhs.is_negative() | self_gt_rhs) + & (self.is_negative() | (rhs.is_negative() & self_lt_rhs)); + + magnitude.and_then(|magnitude| { + CtOption::new( + Self { + is_negative: is_negative.unwrap_u8() == 1, + magnitude, + }, + Choice::from(1), + ) + }) + } +} + +#[cfg(test)] +mod tests { + use crate::{CheckedAdd, U128}; + use crate::int::I128; + + #[test] + fn checked_add() { + let max_minus_one = U128::MAX.wrapping_sub(&U128::ONE); + let two = U128::from(2u32); + + // lhs = MIN + + let result = I128::MIN.checked_add(&I128::MIN); + assert!(bool::from(result.is_none())); + + let result = I128::MIN.checked_add(&I128::MINUS_ONE); + assert!(bool::from(result.is_none())); + + let result = I128::MIN.checked_add(&I128::ZERO); + assert_eq!(result.unwrap(), I128::MIN); + + let result = I128::MIN.checked_add(&I128::ONE); + assert_eq!(result.unwrap(), I128::new_from_uint(true, max_minus_one)); + + let result = I128::MIN.checked_add(&I128::MAX); + assert_eq!(result.unwrap(), I128::ZERO); + + // lhs = -1 + + let result = I128::MINUS_ONE.checked_add(&I128::MIN); + assert!(bool::from(result.is_none())); + + let result = I128::MINUS_ONE.checked_add(&I128::MINUS_ONE); + assert_eq!(result.unwrap(), I128::new_from_uint(true, two)); + + let result = I128::MINUS_ONE.checked_add(&I128::ZERO); + assert_eq!(result.unwrap(), I128::MINUS_ONE); + + let result = I128::MINUS_ONE.checked_add(&I128::ONE); + assert_eq!(result.unwrap(), I128::ZERO); + + let result = I128::MINUS_ONE.checked_add(&I128::MAX); + assert_eq!(result.unwrap(), I128::new_from_uint(false, max_minus_one)); + + // lhs = 0 + + let result = I128::ZERO.checked_add(&I128::MIN); + assert_eq!(result.unwrap(), I128::MIN); + + let result = I128::ZERO.checked_add(&I128::MINUS_ONE); + assert_eq!(result.unwrap(), I128::MINUS_ONE); + + let result = I128::ZERO.checked_add(&I128::ZERO); + assert_eq!(result.unwrap(), I128::ZERO); + + let result = I128::ZERO.checked_add(&I128::ONE); + assert_eq!(result.unwrap(), I128::ONE); + + let result = I128::ZERO.checked_add(&I128::MAX); + assert_eq!(result.unwrap(), I128::MAX); + + // lhs = 1 + + let result = I128::ONE.checked_add(&I128::MIN); + assert_eq!(result.unwrap(), I128::new_from_uint(true, max_minus_one)); + + let result = I128::ONE.checked_add(&I128::MINUS_ONE); + assert_eq!(result.unwrap(), I128::ZERO); + + let result = I128::ONE.checked_add(&I128::ZERO); + assert_eq!(result.unwrap(), I128::ONE); + + let result = I128::ONE.checked_add(&I128::ONE); + assert_eq!(result.unwrap(), I128::new_from_uint(false, two)); + + let result = I128::ONE.checked_add(&I128::MAX); + assert!(bool::from(result.is_none())); + + // lhs = MAX + + let result = I128::MAX.checked_add(&I128::MIN); + assert_eq!(result.unwrap(), I128::ZERO); + + let result = I128::MAX.checked_add(&I128::MINUS_ONE); + assert_eq!(result.unwrap(), I128::new_from_uint(false, max_minus_one)); + + let result = I128::MAX.checked_add(&I128::ZERO); + assert_eq!(result.unwrap(), I128::MAX); + + let result = I128::MAX.checked_add(&I128::ONE); + assert!(bool::from(result.is_none())); + + let result = I128::MAX.checked_add(&I128::MAX); + assert!(bool::from(result.is_none())); + } +} From 2aae18a664ac6ad3b4ac4bf04adf8fdb3683a8b2 Mon Sep 17 00:00:00 2001 From: Erik Takke Date: Thu, 10 Oct 2024 11:22:50 +0200 Subject: [PATCH 03/19] pass add checked tests --- src/int.rs | 15 ++++++++++++++- src/int/add.rs | 43 +++++++++++++++---------------------------- src/int/cmp.rs | 17 +++++++++++++++++ 3 files changed, 46 insertions(+), 29 deletions(-) create mode 100644 src/int/cmp.rs diff --git a/src/int.rs b/src/int.rs index c89a42592..17dcf6e26 100644 --- a/src/int.rs +++ b/src/int.rs @@ -1,11 +1,12 @@ //! Stack-allocated big signed integers. use num_traits::Zero; -use subtle::Choice; +use subtle::{Choice, ConditionallySelectable}; use crate::{Limb, Uint}; mod add; +mod cmp; #[derive(Copy, Clone, Hash, Debug, PartialEq)] pub struct Int { @@ -81,6 +82,18 @@ impl Int { } } +impl ConditionallySelectable for Int { + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + let magnitude = Uint::conditional_select(&a.magnitude, &b.magnitude, choice); + let is_negative = Choice::conditional_select(&a.is_negative(), &b.is_negative(), choice); + + Self { + is_negative: is_negative.unwrap_u8() == 1, + magnitude + } + } +} + #[cfg(target_pointer_width = "64")] type I128 = Int<2>; diff --git a/src/int/add.rs b/src/int/add.rs index b46b0d588..302d96331 100644 --- a/src/int/add.rs +++ b/src/int/add.rs @@ -26,34 +26,21 @@ impl Add<&Int> for Int { impl CheckedAdd for Int { fn checked_add(&self, rhs: &Self) -> CtOption { - // Based on the signs of lhs and rhs, we have to consider the following cases: - // case | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | - // -----|---|---|---|---|---|---|---|---|---| - // lhs | + | + | + | 0 | 0 | 0 | - | - | - | - // rhs | + | 0 | - | + | 0 | - | + | 0 | - | - // - // Whether to add or subtract the two halves, which is chosen as follows: - // case | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | - // -----|---|---|---|---|---|---|---|---|---| - // a/s | a | a | s | a | a | s | s | s | a | - // +/- | + | + | ? | + | + | ? | ? | - | - | - - // One of the two has the result we seek. - // Now it is a matter of computing which. - let magnitude_sum = self.magnitude.checked_add(&rhs.magnitude); - let magnitude_diff = self.magnitude.checked_sub(&rhs.magnitude); - - // Select the magnitude, based on whether lhs and rhs have the same sign. - let equal_sign = self.is_negative().ct_eq(&rhs.is_negative()); - // Note: we must include the case that either side is ZERO for selecting magnitude_sum - let use_sum = self.is_zero() | rhs.is_zero() | equal_sign; - let magnitude = CtOption::ct_select(&magnitude_diff, &magnitude_sum, use_sum); - - // Determine whether the result is negative, based on whether lhs or rhs has a greater magnitude. - let self_gt_rhs = self.magnitude.ct_gt(&rhs.magnitude); - let self_lt_rhs = self.magnitude.ct_lt(&rhs.magnitude); - let is_negative = (self.is_non_negative() | rhs.is_negative() | self_gt_rhs) - & (self.is_negative() | (rhs.is_negative() & self_lt_rhs)); + // Step 1. Select the element with the largest magnitude to be the lhs. + let (lhs, rhs) = Int::abs_max_min(self, rhs); + + // Step 2. Add/subtract the magnitudes of the two sides to/from each other + let magnitude_add = lhs.magnitude.checked_add(&rhs.magnitude); + let magnitude_sub = lhs.magnitude.checked_sub(&rhs.magnitude); + + // Step 3. Select magnitude_sub when the signs of the two elements are not the same. + let unequal_sign = !lhs.is_negative().ct_eq(&rhs.is_negative()); + let magnitude = CtOption::ct_select(&magnitude_add, &magnitude_sub, unequal_sign); + + // Step 4. Determine whether the result is negative. + // This is the case when `lhs` is negative and |lhs| =/= |rhs| + let is_negative = lhs.is_negative() + ^ (lhs.is_negative() & !rhs.is_negative() & lhs.magnitude.ct_eq(&rhs.magnitude)); magnitude.and_then(|magnitude| { CtOption::new( diff --git a/src/int/cmp.rs b/src/int/cmp.rs new file mode 100644 index 000000000..8ee22e3d7 --- /dev/null +++ b/src/int/cmp.rs @@ -0,0 +1,17 @@ +use subtle::{ConditionallySelectable, ConstantTimeLess}; + +use crate::int::Int; + +impl Int { + /// Given two [`Int`]s, return a tuple, containing in order: + /// - the one with the greatest absolute value, and + /// - the one with the smallest absolute value. + /// + /// When both elements have the same size, their order is maintained. + pub(crate) fn abs_max_min(&self, rhs: &Self) -> (Self, Self) { + let swap = self.magnitude.ct_lt(&rhs.magnitude); + let greatest = Int::conditional_select(self, rhs, swap); + let smallest = Int::conditional_select(rhs, self, swap); + (greatest, smallest) + } +} From 5595c2e6c5d16b46978f62d4b0fedbd9561ebe7b Mon Sep 17 00:00:00 2001 From: Erik Takke Date: Thu, 10 Oct 2024 11:33:05 +0200 Subject: [PATCH 04/19] minor add_checked improvements --- src/int/add.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/int/add.rs b/src/int/add.rs index 302d96331..0a17c142e 100644 --- a/src/int/add.rs +++ b/src/int/add.rs @@ -34,13 +34,14 @@ impl CheckedAdd for Int { let magnitude_sub = lhs.magnitude.checked_sub(&rhs.magnitude); // Step 3. Select magnitude_sub when the signs of the two elements are not the same. - let unequal_sign = !lhs.is_negative().ct_eq(&rhs.is_negative()); - let magnitude = CtOption::ct_select(&magnitude_add, &magnitude_sub, unequal_sign); - - // Step 4. Determine whether the result is negative. - // This is the case when `lhs` is negative and |lhs| =/= |rhs| - let is_negative = lhs.is_negative() - ^ (lhs.is_negative() & !rhs.is_negative() & lhs.magnitude.ct_eq(&rhs.magnitude)); + let different_signs = lhs.is_negative().ct_ne(&rhs.is_negative()); + let magnitude = CtOption::ct_select(&magnitude_add, &magnitude_sub, different_signs); + + // Step 4. Determine the sign of the result. + // This is always the same as the sign of the lhs (since it has the larger magnitude), + // except when the sum is zero. + let sum_is_zero = different_signs & lhs.magnitude.ct_eq(&rhs.magnitude); + let is_negative = lhs.is_negative() & !sum_is_zero; magnitude.and_then(|magnitude| { CtOption::new( From b6b73b652533c80a92dfe0da3857f5144b9a7eb4 Mon Sep 17 00:00:00 2001 From: Erik Takke Date: Thu, 10 Oct 2024 11:40:05 +0200 Subject: [PATCH 05/19] clean up --- src/int.rs | 15 ++------------- src/int/add.rs | 2 +- src/int/cmp.rs | 11 +++++++---- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/int.rs b/src/int.rs index 17dcf6e26..dbcf96a4b 100644 --- a/src/int.rs +++ b/src/int.rs @@ -1,6 +1,5 @@ //! Stack-allocated big signed integers. -use num_traits::Zero; use subtle::{Choice, ConditionallySelectable}; use crate::{Limb, Uint}; @@ -70,26 +69,16 @@ impl Int { pub fn is_negative(&self) -> Choice { Choice::from(u8::from(self.is_negative)) } - - /// Whether this [`Int`] is zero - pub fn is_zero(&self) -> Choice { - Choice::from(u8::from(self.magnitude.is_zero())) - } - - /// Whether this [`Int`] is non-negative, i.e. >= 0. - pub fn is_non_negative(&self) -> Choice { - !Choice::from(u8::from(self.is_negative)) - } } impl ConditionallySelectable for Int { fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { let magnitude = Uint::conditional_select(&a.magnitude, &b.magnitude, choice); let is_negative = Choice::conditional_select(&a.is_negative(), &b.is_negative(), choice); - + Self { is_negative: is_negative.unwrap_u8() == 1, - magnitude + magnitude, } } } diff --git a/src/int/add.rs b/src/int/add.rs index 0a17c142e..d30bf82ab 100644 --- a/src/int/add.rs +++ b/src/int/add.rs @@ -2,7 +2,7 @@ use core::ops::Add; -use subtle::{Choice, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess, CtOption}; +use subtle::{Choice, ConstantTimeEq, CtOption}; use crate::{CheckedAdd, CheckedSub, ConstantTimeSelect}; use crate::int::Int; diff --git a/src/int/cmp.rs b/src/int/cmp.rs index 8ee22e3d7..8783e0376 100644 --- a/src/int/cmp.rs +++ b/src/int/cmp.rs @@ -1,13 +1,16 @@ +//! [`Int`] comparisons. +//! +//! By default, these are all constant-time and use the `subtle` crate. + use subtle::{ConditionallySelectable, ConstantTimeLess}; use crate::int::Int; impl Int { - /// Given two [`Int`]s, return a tuple, containing in order: - /// - the one with the greatest absolute value, and - /// - the one with the smallest absolute value. + /// Given two [`Int`]s, return a tuple with the larger magnitude first. /// - /// When both elements have the same size, their order is maintained. + /// When both have the same magnitude, they are returned in the same order + /// as they were provided. pub(crate) fn abs_max_min(&self, rhs: &Self) -> (Self, Self) { let swap = self.magnitude.ct_lt(&rhs.magnitude); let greatest = Int::conditional_select(self, rhs, swap); From 26d1501fec177de8e7434e068e2d88d1217e2e08 Mon Sep 17 00:00:00 2001 From: Erik Takke Date: Thu, 10 Oct 2024 12:03:17 +0200 Subject: [PATCH 06/19] implement some add traits --- src/int.rs | 10 ++++-- src/int/add.rs | 93 +++++++++++++++++++++++++++++++++++--------------- 2 files changed, 74 insertions(+), 29 deletions(-) diff --git a/src/int.rs b/src/int.rs index dbcf96a4b..ed767dae1 100644 --- a/src/int.rs +++ b/src/int.rs @@ -83,6 +83,12 @@ impl ConditionallySelectable for Int { } } +impl Default for Int { + fn default() -> Self { + Self::ZERO + } +} + #[cfg(target_pointer_width = "64")] type I128 = Int<2>; @@ -92,8 +98,8 @@ type I128 = Int<4>; #[cfg(test)] #[allow(clippy::unwrap_used)] mod tests { - use crate::{U128, Uint}; - use crate::int::{I128, Int}; + use crate::int::{Int, I128}; + use crate::{Uint, U128}; #[test] fn zero() { diff --git a/src/int/add.rs b/src/int/add.rs index d30bf82ab..da7f7e796 100644 --- a/src/int/add.rs +++ b/src/int/add.rs @@ -1,12 +1,43 @@ //! [`Int`] addition operations. -use core::ops::Add; +use core::ops::{Add, AddAssign}; -use subtle::{Choice, ConstantTimeEq, CtOption}; +use subtle::{Choice, ConstantTimeEq, ConstantTimeLess, CtOption}; -use crate::{CheckedAdd, CheckedSub, ConstantTimeSelect}; +use crate::{Checked, CheckedAdd, CheckedSub, ConstantTimeSelect, Uint}; use crate::int::Int; +impl Int { + /// Add two [`Int`]s, checking for overflow. + /// + /// Assumes `self.magnitude >= rhs.magnitude`. + fn checked_adc(&self, rhs: &Self) -> CtOption { + // Step 1. Add/subtract the magnitudes of the two sides to/from each other + let magnitude_add = self.magnitude.checked_add(&rhs.magnitude); + let magnitude_sub = self.magnitude.checked_sub(&rhs.magnitude); + + // Step 2. Select magnitude_sub when the signs of the two elements are not the same. + let different_signs = self.is_negative().ct_ne(&rhs.is_negative()); + let magnitude = CtOption::ct_select(&magnitude_add, &magnitude_sub, different_signs); + + // Step 3. Determine the sign of the result. + // This is always the same as the sign of the self (since it assumed to have the + // larger magnitude), except when the sum is zero. + let sum_is_zero = different_signs & self.magnitude.ct_eq(&rhs.magnitude); + let is_negative = self.is_negative() & !sum_is_zero; + + magnitude.and_then(|magnitude| { + CtOption::new( + Self { + is_negative: is_negative.unwrap_u8() == 1, + magnitude, + }, + Choice::from(1), + ) + }) + } +} + impl Add for Int { type Output = Self; @@ -24,34 +55,42 @@ impl Add<&Int> for Int { } } -impl CheckedAdd for Int { - fn checked_add(&self, rhs: &Self) -> CtOption { - // Step 1. Select the element with the largest magnitude to be the lhs. - let (lhs, rhs) = Int::abs_max_min(self, rhs); +impl AddAssign for Int { + fn add_assign(&mut self, mut rhs: Self) { + // Order the elements, such that |lhs| >= |rhs| + let self_lt_other = self.magnitude.ct_lt(&rhs.magnitude); + Uint::ct_swap(&mut self.magnitude, &mut rhs.magnitude, self_lt_other); + + *self = self + .checked_adc(&rhs) + .expect("attempted to add with overflow"); + } +} - // Step 2. Add/subtract the magnitudes of the two sides to/from each other - let magnitude_add = lhs.magnitude.checked_add(&rhs.magnitude); - let magnitude_sub = lhs.magnitude.checked_sub(&rhs.magnitude); +impl AddAssign<&Int> for Int { + fn add_assign(&mut self, other: &Self) { + *self = *self + other; + } +} - // Step 3. Select magnitude_sub when the signs of the two elements are not the same. - let different_signs = lhs.is_negative().ct_ne(&rhs.is_negative()); - let magnitude = CtOption::ct_select(&magnitude_add, &magnitude_sub, different_signs); +impl AddAssign for Checked> { + fn add_assign(&mut self, other: Self) { + *self = *self + other; + } +} - // Step 4. Determine the sign of the result. - // This is always the same as the sign of the lhs (since it has the larger magnitude), - // except when the sum is zero. - let sum_is_zero = different_signs & lhs.magnitude.ct_eq(&rhs.magnitude); - let is_negative = lhs.is_negative() & !sum_is_zero; +impl AddAssign<&Checked>> for Checked> { + fn add_assign(&mut self, other: &Self) { + *self = *self + other; + } +} - magnitude.and_then(|magnitude| { - CtOption::new( - Self { - is_negative: is_negative.unwrap_u8() == 1, - magnitude, - }, - Choice::from(1), - ) - }) +impl CheckedAdd for Int { + /// Add two [`Int`]s, checking for overflow. + fn checked_add(&self, rhs: &Self) -> CtOption { + // Select the element with the largest magnitude to be the lhs. + let (lhs, rhs) = Int::abs_max_min(self, rhs); + lhs.checked_adc(&rhs) } } From 3efe42142d8d67496ff9a9f17ccc534b0aba0b4d Mon Sep 17 00:00:00 2001 From: Erik Takke Date: Thu, 10 Oct 2024 12:39:35 +0200 Subject: [PATCH 07/19] Refactor Int::add --- src/int/add.rs | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/src/int/add.rs b/src/int/add.rs index da7f7e796..2131af474 100644 --- a/src/int/add.rs +++ b/src/int/add.rs @@ -2,29 +2,30 @@ use core::ops::{Add, AddAssign}; -use subtle::{Choice, ConstantTimeEq, ConstantTimeLess, CtOption}; +use subtle::{Choice, ConstantTimeEq, CtOption}; -use crate::{Checked, CheckedAdd, CheckedSub, ConstantTimeSelect, Uint}; +use crate::{Checked, CheckedAdd, CheckedSub, ConstantTimeSelect}; use crate::int::Int; impl Int { /// Add two [`Int`]s, checking for overflow. - /// - /// Assumes `self.magnitude >= rhs.magnitude`. fn checked_adc(&self, rhs: &Self) -> CtOption { - // Step 1. Add/subtract the magnitudes of the two sides to/from each other - let magnitude_add = self.magnitude.checked_add(&rhs.magnitude); - let magnitude_sub = self.magnitude.checked_sub(&rhs.magnitude); + // Step 1. Select the element with the largest magnitude to be the lhs. + let (lhs, rhs) = Int::abs_max_min(self, rhs); + + // Step 2. Add/subtract the magnitudes of the two sides to/from each other + let magnitude_add = lhs.magnitude.checked_add(&rhs.magnitude); + let magnitude_sub = lhs.magnitude.checked_sub(&rhs.magnitude); - // Step 2. Select magnitude_sub when the signs of the two elements are not the same. - let different_signs = self.is_negative().ct_ne(&rhs.is_negative()); + // Step 3. Select magnitude_sub when the signs of the two elements are not the same. + let different_signs = lhs.is_negative().ct_ne(&rhs.is_negative()); let magnitude = CtOption::ct_select(&magnitude_add, &magnitude_sub, different_signs); - // Step 3. Determine the sign of the result. + // Step 4. Determine the sign of the result. // This is always the same as the sign of the self (since it assumed to have the // larger magnitude), except when the sum is zero. - let sum_is_zero = different_signs & self.magnitude.ct_eq(&rhs.magnitude); - let is_negative = self.is_negative() & !sum_is_zero; + let sum_is_zero = different_signs & lhs.magnitude.ct_eq(&rhs.magnitude); + let is_negative = lhs.is_negative() & !sum_is_zero; magnitude.and_then(|magnitude| { CtOption::new( @@ -56,14 +57,8 @@ impl Add<&Int> for Int { } impl AddAssign for Int { - fn add_assign(&mut self, mut rhs: Self) { - // Order the elements, such that |lhs| >= |rhs| - let self_lt_other = self.magnitude.ct_lt(&rhs.magnitude); - Uint::ct_swap(&mut self.magnitude, &mut rhs.magnitude, self_lt_other); - - *self = self - .checked_adc(&rhs) - .expect("attempted to add with overflow"); + fn add_assign(&mut self, other: Self) { + *self += &other; } } @@ -88,9 +83,7 @@ impl AddAssign<&Checked>> for Checked> impl CheckedAdd for Int { /// Add two [`Int`]s, checking for overflow. fn checked_add(&self, rhs: &Self) -> CtOption { - // Select the element with the largest magnitude to be the lhs. - let (lhs, rhs) = Int::abs_max_min(self, rhs); - lhs.checked_adc(&rhs) + self.checked_adc(rhs) } } From e38062a7ebc904b19b569ea9db07f6633681bb2c Mon Sep 17 00:00:00 2001 From: Erik Takke Date: Thu, 10 Oct 2024 12:39:55 +0200 Subject: [PATCH 08/19] Introduce Int::eq --- src/int/cmp.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/int/cmp.rs b/src/int/cmp.rs index 8783e0376..19cf5854a 100644 --- a/src/int/cmp.rs +++ b/src/int/cmp.rs @@ -2,9 +2,10 @@ //! //! By default, these are all constant-time and use the `subtle` crate. -use subtle::{ConditionallySelectable, ConstantTimeLess}; +use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeLess}; use crate::int::Int; +use crate::Uint; impl Int { /// Given two [`Int`]s, return a tuple with the larger magnitude first. @@ -17,4 +18,18 @@ impl Int { let smallest = Int::conditional_select(rhs, self, swap); (greatest, smallest) } + + #[inline] + /// TODO: make this a const function? + pub(crate) fn eq(lhs: &Self, rhs: &Self) -> Choice { + Choice::from(Uint::eq(&lhs.magnitude, &rhs.magnitude)) + & Choice::ct_eq(&lhs.is_negative(), &rhs.is_negative()) + } +} + +impl ConstantTimeEq for Int { + #[inline] + fn ct_eq(&self, other: &Self) -> Choice { + Int::eq(self, other) + } } From 43700d6fa3f37d9b7401b984cc020cb1105dd6ce Mon Sep 17 00:00:00 2001 From: Erik Takke Date: Thu, 10 Oct 2024 12:40:52 +0200 Subject: [PATCH 09/19] Introduce Int::neg --- src/int.rs | 23 ++++++++++++++++++++--- src/int/neg.rs | 21 +++++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 src/int/neg.rs diff --git a/src/int.rs b/src/int.rs index ed767dae1..59dc4a526 100644 --- a/src/int.rs +++ b/src/int.rs @@ -1,11 +1,14 @@ //! Stack-allocated big signed integers. -use subtle::{Choice, ConditionallySelectable}; +use num_traits::Zero; +use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; use crate::{Limb, Uint}; mod add; mod cmp; +mod neg; +mod sub; #[derive(Copy, Clone, Hash, Debug, PartialEq)] pub struct Int { @@ -69,6 +72,11 @@ impl Int { pub fn is_negative(&self) -> Choice { Choice::from(u8::from(self.is_negative)) } + + /// Whether this [`Int`] is zero + pub fn is_zero(&self) -> bool { + self.magnitude.is_zero() + } } impl ConditionallySelectable for Int { @@ -89,6 +97,16 @@ impl Default for Int { } } +impl Zero for Int { + fn zero() -> Self { + Self::ZERO + } + + fn is_zero(&self) -> bool { + self.ct_eq(&Self::ZERO).into() + } +} + #[cfg(target_pointer_width = "64")] type I128 = Int<2>; @@ -98,8 +116,7 @@ type I128 = Int<4>; #[cfg(test)] #[allow(clippy::unwrap_used)] mod tests { - use crate::int::{Int, I128}; - use crate::{Uint, U128}; + use crate::{U128, Uint, int::{I128, Int}}; #[test] fn zero() { diff --git a/src/int/neg.rs b/src/int/neg.rs new file mode 100644 index 000000000..68e0b30a1 --- /dev/null +++ b/src/int/neg.rs @@ -0,0 +1,21 @@ +//! [`Int`] negation operation. + +use crate::int::Int; +use crate::WrappingNeg; + +impl Int { + /// Perform wrapping negation. + pub fn wrapping_neg(&self) -> Self { + Self { + is_negative: !self.is_negative & !self.is_zero(), + magnitude: self.magnitude, + } + } +} + +impl WrappingNeg for Int { + #[inline] + fn wrapping_neg(&self) -> Self { + self.wrapping_neg() + } +} From 2d7257d751549ddedd025457e004e44ab9780289 Mon Sep 17 00:00:00 2001 From: Erik Takke Date: Thu, 10 Oct 2024 12:41:09 +0200 Subject: [PATCH 10/19] Impl Int::sub --- src/int/sub.rs | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 src/int/sub.rs diff --git a/src/int/sub.rs b/src/int/sub.rs new file mode 100644 index 000000000..00db7edd7 --- /dev/null +++ b/src/int/sub.rs @@ -0,0 +1,85 @@ +//! [`Int`] subtraction operations. + +use core::ops::{Sub, SubAssign}; + +use subtle::CtOption; + +use crate::{Checked, CheckedAdd, CheckedSub}; +use crate::int::Int; + +impl CheckedSub for Int { + fn checked_sub(&self, rhs: &Self) -> CtOption { + self.checked_add(&rhs.wrapping_neg()) + } +} + +impl Sub for Int { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self.sub(&rhs) + } +} + +impl Sub<&Int> for Int { + type Output = Self; + + fn sub(self, rhs: &Self) -> Self { + self.checked_sub(rhs) + .expect("attempted to subtract with underflow") + } +} + +impl SubAssign for Int { + fn sub_assign(&mut self, other: Self) { + *self -= &other + } +} + +impl SubAssign<&Int> for Int { + fn sub_assign(&mut self, other: &Self) { + *self = *self - other; + } +} + +impl SubAssign for Checked> { + fn sub_assign(&mut self, other: Self) { + *self = *self - other; + } +} + +impl SubAssign<&Checked>> for Checked> { + fn sub_assign(&mut self, other: &Self) { + *self = *self - other; + } +} + +#[cfg(test)] +mod tests { + use crate::CheckedSub; + use crate::int::I128; + + #[test] + fn checked_sub_ok() { + let result = I128::MIN.checked_sub(&I128::MIN); + assert_eq!(result.unwrap(), I128::ZERO); + + let result = I128::MINUS_ONE.checked_sub(&I128::MINUS_ONE); + assert_eq!(result.unwrap(), I128::ZERO); + + let result = I128::ZERO.checked_sub(&I128::ZERO); + assert_eq!(result.unwrap(), I128::ZERO); + + let result = I128::ONE.checked_sub(&I128::ONE); + assert_eq!(result.unwrap(), I128::ZERO); + + let result = I128::MAX.checked_sub(&I128::MAX); + assert_eq!(result.unwrap(), I128::ZERO); + } + + #[test] + fn checked_sub_overflow() { + let result = I128::ZERO.checked_sub(&I128::ONE); + assert!(!bool::from(result.is_some())); + } +} From f97d60caba01d7f5679b37009f9c0ed5061c858f Mon Sep 17 00:00:00 2001 From: Erik Takke Date: Thu, 10 Oct 2024 13:01:10 +0200 Subject: [PATCH 11/19] Impl Int::checked_mul --- src/int.rs | 1 + src/int/mul.rs | 15 +++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 src/int/mul.rs diff --git a/src/int.rs b/src/int.rs index 59dc4a526..55d69d712 100644 --- a/src/int.rs +++ b/src/int.rs @@ -7,6 +7,7 @@ use crate::{Limb, Uint}; mod add; mod cmp; +mod mul; mod neg; mod sub; diff --git a/src/int/mul.rs b/src/int/mul.rs new file mode 100644 index 000000000..54f0de403 --- /dev/null +++ b/src/int/mul.rs @@ -0,0 +1,15 @@ +//! [`Int`] multiplication operations. + +use subtle::{ConstantTimeEq, CtOption}; + +use crate::{CheckedMul, Uint, Zero}; +use crate::int::Int; + +impl CheckedMul> for Int { + #[inline] + fn checked_mul(&self, rhs: &Int) -> CtOption { + let (lo, hi) = self.magnitude.split_mul(&rhs.magnitude); + let is_negative = (self.is_negative() ^ rhs.is_negative()) & lo.ct_ne(&Uint::ZERO); + CtOption::new(Int::new_from_uint(is_negative.into(), lo), hi.is_zero()) + } +} From aa5a0852638959aae0606b2bc1f41c5ad058ffc7 Mon Sep 17 00:00:00 2001 From: Erik Takke Date: Thu, 10 Oct 2024 13:01:21 +0200 Subject: [PATCH 12/19] Impl Int::checked_div --- src/int.rs | 6 +++++- src/int/div.rs | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/int/div.rs diff --git a/src/int.rs b/src/int.rs index 55d69d712..4b18c20ad 100644 --- a/src/int.rs +++ b/src/int.rs @@ -7,6 +7,7 @@ use crate::{Limb, Uint}; mod add; mod cmp; +mod div; mod mul; mod neg; mod sub; @@ -117,7 +118,10 @@ type I128 = Int<4>; #[cfg(test)] #[allow(clippy::unwrap_used)] mod tests { - use crate::{U128, Uint, int::{I128, Int}}; + use crate::{ + int::{I128, Int}, + U128, Uint, + }; #[test] fn zero() { diff --git a/src/int/div.rs b/src/int/div.rs new file mode 100644 index 000000000..e5af85f0c --- /dev/null +++ b/src/int/div.rs @@ -0,0 +1,18 @@ +//! [`Int`] division operations. + +use subtle::{Choice, ConstantTimeEq, CtOption}; + +use crate::{CheckedDiv, Uint}; +use crate::int::Int; + +impl CheckedDiv for Int { + fn checked_div(&self, rhs: &Self) -> CtOption { + self.magnitude.checked_div(&rhs.magnitude) + .and_then(|magnitude| { + let res_is_zero = magnitude.ct_eq(&Uint::ZERO); + let is_negative = (self.is_negative() ^ rhs.is_negative()) & !res_is_zero; + CtOption::new(Int::new_from_uint(is_negative.into(), magnitude), Choice::from(1u8)) + } + ) + } +} From e85d199c963916425e357e7b8c4abafe4d390efa Mon Sep 17 00:00:00 2001 From: Erik Takke Date: Mon, 14 Oct 2024 18:01:20 +0200 Subject: [PATCH 13/19] Add `allow(dead_code)` tags --- src/int.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/int.rs b/src/int.rs index 4b18c20ad..bc0f4e3bb 100644 --- a/src/int.rs +++ b/src/int.rs @@ -110,9 +110,11 @@ impl Zero for Int { } #[cfg(target_pointer_width = "64")] +#[allow(dead_code)] type I128 = Int<2>; #[cfg(target_pointer_width = "32")] +#[allow(dead_code)] type I128 = Int<4>; #[cfg(test)] From 66ef85f39d8096c0c39f59e113ec8d9fd4f5e7ed Mon Sep 17 00:00:00 2001 From: Erik Takke Date: Mon, 14 Oct 2024 18:01:32 +0200 Subject: [PATCH 14/19] Update `add` annotations --- src/int/add.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/int/add.rs b/src/int/add.rs index 2131af474..3e891a01a 100644 --- a/src/int/add.rs +++ b/src/int/add.rs @@ -17,7 +17,8 @@ impl Int { let magnitude_add = lhs.magnitude.checked_add(&rhs.magnitude); let magnitude_sub = lhs.magnitude.checked_sub(&rhs.magnitude); - // Step 3. Select magnitude_sub when the signs of the two elements are not the same. + // Step 3. Select the correct magnitude. + // magnitude_sub is used when the signs of the two elements are not the same. let different_signs = lhs.is_negative().ct_ne(&rhs.is_negative()); let magnitude = CtOption::ct_select(&magnitude_add, &magnitude_sub, different_signs); From 12232b31f2406c2793077b0060cb586224d850a0 Mon Sep 17 00:00:00 2001 From: Erik Takke Date: Mon, 14 Oct 2024 18:03:15 +0200 Subject: [PATCH 15/19] Fix formatting --- src/int.rs | 4 ++-- src/int/add.rs | 4 ++-- src/int/div.rs | 13 ++++++++----- src/int/mul.rs | 2 +- src/int/sub.rs | 4 ++-- 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/int.rs b/src/int.rs index bc0f4e3bb..fdbcd6cc8 100644 --- a/src/int.rs +++ b/src/int.rs @@ -121,8 +121,8 @@ type I128 = Int<4>; #[allow(clippy::unwrap_used)] mod tests { use crate::{ - int::{I128, Int}, - U128, Uint, + int::{Int, I128}, + Uint, U128, }; #[test] diff --git a/src/int/add.rs b/src/int/add.rs index 3e891a01a..fac0fde4a 100644 --- a/src/int/add.rs +++ b/src/int/add.rs @@ -4,8 +4,8 @@ use core::ops::{Add, AddAssign}; use subtle::{Choice, ConstantTimeEq, CtOption}; -use crate::{Checked, CheckedAdd, CheckedSub, ConstantTimeSelect}; use crate::int::Int; +use crate::{Checked, CheckedAdd, CheckedSub, ConstantTimeSelect}; impl Int { /// Add two [`Int`]s, checking for overflow. @@ -90,8 +90,8 @@ impl CheckedAdd for Int { #[cfg(test)] mod tests { - use crate::{CheckedAdd, U128}; use crate::int::I128; + use crate::{CheckedAdd, U128}; #[test] fn checked_add() { diff --git a/src/int/div.rs b/src/int/div.rs index e5af85f0c..d876fb96a 100644 --- a/src/int/div.rs +++ b/src/int/div.rs @@ -2,17 +2,20 @@ use subtle::{Choice, ConstantTimeEq, CtOption}; -use crate::{CheckedDiv, Uint}; use crate::int::Int; +use crate::{CheckedDiv, Uint}; impl CheckedDiv for Int { fn checked_div(&self, rhs: &Self) -> CtOption { - self.magnitude.checked_div(&rhs.magnitude) + self.magnitude + .checked_div(&rhs.magnitude) .and_then(|magnitude| { let res_is_zero = magnitude.ct_eq(&Uint::ZERO); let is_negative = (self.is_negative() ^ rhs.is_negative()) & !res_is_zero; - CtOption::new(Int::new_from_uint(is_negative.into(), magnitude), Choice::from(1u8)) - } - ) + CtOption::new( + Int::new_from_uint(is_negative.into(), magnitude), + Choice::from(1u8), + ) + }) } } diff --git a/src/int/mul.rs b/src/int/mul.rs index 54f0de403..b63383441 100644 --- a/src/int/mul.rs +++ b/src/int/mul.rs @@ -2,8 +2,8 @@ use subtle::{ConstantTimeEq, CtOption}; -use crate::{CheckedMul, Uint, Zero}; use crate::int::Int; +use crate::{CheckedMul, Uint, Zero}; impl CheckedMul> for Int { #[inline] diff --git a/src/int/sub.rs b/src/int/sub.rs index 00db7edd7..bf7c7a5c6 100644 --- a/src/int/sub.rs +++ b/src/int/sub.rs @@ -4,8 +4,8 @@ use core::ops::{Sub, SubAssign}; use subtle::CtOption; -use crate::{Checked, CheckedAdd, CheckedSub}; use crate::int::Int; +use crate::{Checked, CheckedAdd, CheckedSub}; impl CheckedSub for Int { fn checked_sub(&self, rhs: &Self) -> CtOption { @@ -56,8 +56,8 @@ impl SubAssign<&Checked>> for Checked> #[cfg(test)] mod tests { - use crate::CheckedSub; use crate::int::I128; + use crate::CheckedSub; #[test] fn checked_sub_ok() { From 7e379c9bda69466ff19d6cb5a2b05fe7078e2695 Mon Sep 17 00:00:00 2001 From: Erik Takke Date: Mon, 14 Oct 2024 18:08:53 +0200 Subject: [PATCH 16/19] revert lib.rs --- .idea/.gitignore | 5 ++++ .idea/crypto-bigint.iml | 13 +++++++++ .idea/modules.xml | 8 ++++++ .idea/vcs.xml | 6 ++++ src/lib.rs | 62 ++++++++++++++++++++++------------------- 5 files changed, 65 insertions(+), 29 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/crypto-bigint.iml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 000000000..b58b603fe --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,5 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/crypto-bigint.iml b/.idea/crypto-bigint.iml new file mode 100644 index 000000000..7a99ccf7a --- /dev/null +++ b/.idea/crypto-bigint.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 000000000..6a97abca6 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 000000000..35eb1ddfb --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 6da3860a4..927d8e79e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -155,19 +155,23 @@ #[macro_use] extern crate alloc; -#[cfg(feature = "rand_core")] -pub use rand_core; -#[cfg(feature = "rlp")] -pub use rlp; -pub use subtle; -#[cfg(feature = "zeroize")] -pub use zeroize; +#[macro_use] +mod macros; + +pub mod modular; #[cfg(feature = "hybrid-array")] -pub use { - crate::array::{ArrayDecoding, ArrayEncoding, ByteArray}, - hybrid_array::{self, typenum::consts}, -}; +mod array; +mod checked; +mod const_choice; +mod int; +mod limb; +mod non_zero; +mod odd; +mod primitives; +mod traits; +mod uint; +mod wrapping; pub use crate::{ checked::Checked, @@ -176,34 +180,34 @@ pub use crate::{ non_zero::NonZero, odd::Odd, traits::*, - uint::*, uint::div_limb::Reciprocal, + uint::*, wrapping::Wrapping, }; +pub use subtle; + #[cfg(feature = "alloc")] pub use crate::uint::boxed::BoxedUint; -#[macro_use] -mod macros; +#[cfg(feature = "hybrid-array")] +pub use { + crate::array::{ArrayDecoding, ArrayEncoding, ByteArray}, + hybrid_array::{self, typenum::consts}, +}; -pub mod modular; +#[cfg(feature = "rand_core")] +pub use rand_core; -#[cfg(feature = "hybrid-array")] -mod array; -mod checked; -mod const_choice; -mod int; -mod limb; -mod non_zero; -mod odd; -mod primitives; -mod traits; -mod uint; -mod wrapping; +#[cfg(feature = "rlp")] +pub use rlp; + +#[cfg(feature = "zeroize")] +pub use zeroize; /// Import prelude for this crate: includes important traits. pub mod prelude { + pub use crate::traits::*; + #[cfg(feature = "hybrid-array")] pub use crate::array::{ArrayDecoding, ArrayEncoding}; - pub use crate::traits::*; -} +} \ No newline at end of file From 5b8c12f029e7f797c1e2e8caec33f13891105a17 Mon Sep 17 00:00:00 2001 From: Erik Takke Date: Mon, 14 Oct 2024 18:10:12 +0200 Subject: [PATCH 17/19] Remove `.idea` files --- .idea/.gitignore | 5 ----- .idea/crypto-bigint.iml | 13 ------------- .idea/modules.xml | 8 -------- .idea/vcs.xml | 6 ------ 4 files changed, 32 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/crypto-bigint.iml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index b58b603fe..000000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ diff --git a/.idea/crypto-bigint.iml b/.idea/crypto-bigint.iml deleted file mode 100644 index 7a99ccf7a..000000000 --- a/.idea/crypto-bigint.iml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 6a97abca6..000000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1ddfb..000000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From 7a8e45c4a465ca636fc0fb0335829405e5167b8f Mon Sep 17 00:00:00 2001 From: Erik Takke Date: Mon, 14 Oct 2024 18:10:45 +0200 Subject: [PATCH 18/19] revert lib.rs --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 927d8e79e..c9f94b8ae 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -210,4 +210,4 @@ pub mod prelude { #[cfg(feature = "hybrid-array")] pub use crate::array::{ArrayDecoding, ArrayEncoding}; -} \ No newline at end of file +} From 8f6802d16564677623cf2a827b0ccccc52a8c9ae Mon Sep 17 00:00:00 2001 From: Erik Takke Date: Mon, 14 Oct 2024 18:16:01 +0200 Subject: [PATCH 19/19] Update `checked_sub_overflow` tests. --- src/int/sub.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/int/sub.rs b/src/int/sub.rs index bf7c7a5c6..4e127f5f4 100644 --- a/src/int/sub.rs +++ b/src/int/sub.rs @@ -79,7 +79,10 @@ mod tests { #[test] fn checked_sub_overflow() { - let result = I128::ZERO.checked_sub(&I128::ONE); - assert!(!bool::from(result.is_some())); + let result = I128::MIN.checked_sub(&I128::ONE); + assert!(bool::from(result.is_none())); + + let result = I128::MAX.checked_sub(&I128::MINUS_ONE); + assert!(bool::from(result.is_none())); } }