From 3cf8c9063bfeaf9d692f7890055f82c4aaa8edaf Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Wed, 2 Aug 2023 16:23:38 -0300 Subject: [PATCH 1/2] optimize add to avoid overflow check --- .../src/field/fields/montgomery_backed_prime_fields.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/math/src/field/fields/montgomery_backed_prime_fields.rs b/math/src/field/fields/montgomery_backed_prime_fields.rs index f3e49d956..ed99fe4d0 100644 --- a/math/src/field/fields/montgomery_backed_prime_fields.rs +++ b/math/src/field/fields/montgomery_backed_prime_fields.rs @@ -97,7 +97,7 @@ where /// Checks whether the most significant limb of the modulus is at /// most `0x7FFFFFFFFFFFFFFE`. This check is useful since special /// optimizations exist for this kind of moduli. - const fn moduli_has_one_spare_bit() -> bool { + const fn modulus_has_one_spare_bit() -> bool { M::MODULUS.limbs[0] < (1u64 << 63) - 1 } } @@ -111,21 +111,23 @@ where #[inline(always)] fn add(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType { let (sum, overflow) = UnsignedInteger::add(a, b); - if !overflow { + if Self::modulus_has_one_spare_bit() { if sum >= M::MODULUS { sum - M::MODULUS } else { sum } - } else { + } else if overflow || sum >= M::MODULUS { let (diff, _) = UnsignedInteger::sub(&sum, &M::MODULUS); diff + } else { + sum } } #[inline(always)] fn mul(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType { - if Self::moduli_has_one_spare_bit() { + if Self::modulus_has_one_spare_bit() { MontgomeryAlgorithms::cios_optimized_for_moduli_with_one_spare_bit( a, b, From b04d4c944185317cd9a62dd2708a4b18591a7e35 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Wed, 2 Aug 2023 18:26:21 -0300 Subject: [PATCH 2/2] ensure function is evaluated at compile time --- math/src/field/fields/montgomery_backed_prime_fields.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/math/src/field/fields/montgomery_backed_prime_fields.rs b/math/src/field/fields/montgomery_backed_prime_fields.rs index ed99fe4d0..7ae24a996 100644 --- a/math/src/field/fields/montgomery_backed_prime_fields.rs +++ b/math/src/field/fields/montgomery_backed_prime_fields.rs @@ -41,6 +41,7 @@ where &M::MODULUS, &Self::MU, ); + const MODULUS_HAS_ONE_SPARE_BIT: bool = Self::modulus_has_one_spare_bit(); /// Computes `- modulus^{-1} mod 2^{64}` /// This algorithm is given by Dussé and Kaliski Jr. in @@ -97,6 +98,7 @@ where /// Checks whether the most significant limb of the modulus is at /// most `0x7FFFFFFFFFFFFFFE`. This check is useful since special /// optimizations exist for this kind of moduli. + #[inline(always)] const fn modulus_has_one_spare_bit() -> bool { M::MODULUS.limbs[0] < (1u64 << 63) - 1 } @@ -111,7 +113,7 @@ where #[inline(always)] fn add(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType { let (sum, overflow) = UnsignedInteger::add(a, b); - if Self::modulus_has_one_spare_bit() { + if Self::MODULUS_HAS_ONE_SPARE_BIT { if sum >= M::MODULUS { sum - M::MODULUS } else { @@ -127,7 +129,7 @@ where #[inline(always)] fn mul(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType { - if Self::modulus_has_one_spare_bit() { + if Self::MODULUS_HAS_ONE_SPARE_BIT { MontgomeryAlgorithms::cios_optimized_for_moduli_with_one_spare_bit( a, b,