summaryrefslogtreecommitdiffstats
path: root/vendor/crypto-bigint/src/limb
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:41 +0000
commit10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 (patch)
treebdffd5d80c26cf4a7a518281a204be1ace85b4c1 /vendor/crypto-bigint/src/limb
parentReleasing progress-linux version 1.70.0+dfsg1-9~progress7.99u1. (diff)
downloadrustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.tar.xz
rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.zip
Merging upstream version 1.70.0+dfsg2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/crypto-bigint/src/limb')
-rw-r--r--vendor/crypto-bigint/src/limb/add.rs180
-rw-r--r--vendor/crypto-bigint/src/limb/bit_and.rs21
-rw-r--r--vendor/crypto-bigint/src/limb/bit_not.rs19
-rw-r--r--vendor/crypto-bigint/src/limb/bit_or.rs19
-rw-r--r--vendor/crypto-bigint/src/limb/bit_xor.rs19
-rw-r--r--vendor/crypto-bigint/src/limb/bits.rs8
-rw-r--r--vendor/crypto-bigint/src/limb/cmp.rs176
-rw-r--r--vendor/crypto-bigint/src/limb/encoding.rs67
-rw-r--r--vendor/crypto-bigint/src/limb/from.rs76
-rw-r--r--vendor/crypto-bigint/src/limb/mul.rs195
-rw-r--r--vendor/crypto-bigint/src/limb/rand.rs45
-rw-r--r--vendor/crypto-bigint/src/limb/shl.rs73
-rw-r--r--vendor/crypto-bigint/src/limb/shr.rs73
-rw-r--r--vendor/crypto-bigint/src/limb/sub.rs182
14 files changed, 1153 insertions, 0 deletions
diff --git a/vendor/crypto-bigint/src/limb/add.rs b/vendor/crypto-bigint/src/limb/add.rs
new file mode 100644
index 000000000..ddeda9e67
--- /dev/null
+++ b/vendor/crypto-bigint/src/limb/add.rs
@@ -0,0 +1,180 @@
+//! Limb addition
+
+use crate::{Checked, CheckedAdd, Limb, WideWord, Word, Wrapping, Zero};
+use core::ops::{Add, AddAssign};
+use subtle::CtOption;
+
+impl Limb {
+ /// Computes `self + rhs + carry`, returning the result along with the new carry.
+ #[inline(always)]
+ pub const fn adc(self, rhs: Limb, carry: Limb) -> (Limb, Limb) {
+ let a = self.0 as WideWord;
+ let b = rhs.0 as WideWord;
+ let carry = carry.0 as WideWord;
+ let ret = a + b + carry;
+ (Limb(ret as Word), Limb((ret >> Self::BIT_SIZE) as Word))
+ }
+
+ /// Perform saturating addition.
+ #[inline]
+ pub const fn saturating_add(&self, rhs: Self) -> Self {
+ Limb(self.0.saturating_add(rhs.0))
+ }
+
+ /// Perform wrapping addition, discarding overflow.
+ #[inline(always)]
+ pub const fn wrapping_add(&self, rhs: Self) -> Self {
+ Limb(self.0.wrapping_add(rhs.0))
+ }
+}
+
+impl CheckedAdd for Limb {
+ type Output = Self;
+
+ #[inline]
+ fn checked_add(&self, rhs: Self) -> CtOption<Self> {
+ let (result, carry) = self.adc(rhs, Limb::ZERO);
+ CtOption::new(result, carry.is_zero())
+ }
+}
+
+impl Add for Wrapping<Limb> {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Wrapping<Limb> {
+ Wrapping(self.0.wrapping_add(rhs.0))
+ }
+}
+
+impl Add<&Wrapping<Limb>> for Wrapping<Limb> {
+ type Output = Wrapping<Limb>;
+
+ fn add(self, rhs: &Wrapping<Limb>) -> Wrapping<Limb> {
+ Wrapping(self.0.wrapping_add(rhs.0))
+ }
+}
+
+impl Add<Wrapping<Limb>> for &Wrapping<Limb> {
+ type Output = Wrapping<Limb>;
+
+ fn add(self, rhs: Wrapping<Limb>) -> Wrapping<Limb> {
+ Wrapping(self.0.wrapping_add(rhs.0))
+ }
+}
+
+impl Add<&Wrapping<Limb>> for &Wrapping<Limb> {
+ type Output = Wrapping<Limb>;
+
+ fn add(self, rhs: &Wrapping<Limb>) -> Wrapping<Limb> {
+ Wrapping(self.0.wrapping_add(rhs.0))
+ }
+}
+
+impl AddAssign for Wrapping<Limb> {
+ fn add_assign(&mut self, other: Self) {
+ *self = *self + other;
+ }
+}
+
+impl AddAssign<&Wrapping<Limb>> for Wrapping<Limb> {
+ fn add_assign(&mut self, other: &Self) {
+ *self = *self + other;
+ }
+}
+
+impl Add for Checked<Limb> {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Checked<Limb> {
+ Checked(
+ self.0
+ .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_add(rhs))),
+ )
+ }
+}
+
+impl Add<&Checked<Limb>> for Checked<Limb> {
+ type Output = Checked<Limb>;
+
+ fn add(self, rhs: &Checked<Limb>) -> Checked<Limb> {
+ Checked(
+ self.0
+ .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_add(rhs))),
+ )
+ }
+}
+
+impl Add<Checked<Limb>> for &Checked<Limb> {
+ type Output = Checked<Limb>;
+
+ fn add(self, rhs: Checked<Limb>) -> Checked<Limb> {
+ Checked(
+ self.0
+ .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_add(rhs))),
+ )
+ }
+}
+
+impl Add<&Checked<Limb>> for &Checked<Limb> {
+ type Output = Checked<Limb>;
+
+ fn add(self, rhs: &Checked<Limb>) -> Checked<Limb> {
+ Checked(
+ self.0
+ .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_add(rhs))),
+ )
+ }
+}
+
+impl AddAssign for Checked<Limb> {
+ fn add_assign(&mut self, other: Self) {
+ *self = *self + other;
+ }
+}
+
+impl AddAssign<&Checked<Limb>> for Checked<Limb> {
+ fn add_assign(&mut self, other: &Self) {
+ *self = *self + other;
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::{CheckedAdd, Limb};
+
+ #[test]
+ fn adc_no_carry() {
+ let (res, carry) = Limb::ZERO.adc(Limb::ONE, Limb::ZERO);
+ assert_eq!(res, Limb::ONE);
+ assert_eq!(carry, Limb::ZERO);
+ }
+
+ #[test]
+ fn adc_with_carry() {
+ let (res, carry) = Limb::MAX.adc(Limb::ONE, Limb::ZERO);
+ assert_eq!(res, Limb::ZERO);
+ assert_eq!(carry, Limb::ONE);
+ }
+
+ #[test]
+ fn wrapping_add_no_carry() {
+ assert_eq!(Limb::ZERO.wrapping_add(Limb::ONE), Limb::ONE);
+ }
+
+ #[test]
+ fn wrapping_add_with_carry() {
+ assert_eq!(Limb::MAX.wrapping_add(Limb::ONE), Limb::ZERO);
+ }
+
+ #[test]
+ fn checked_add_ok() {
+ let result = Limb::ZERO.checked_add(Limb::ONE);
+ assert_eq!(result.unwrap(), Limb::ONE);
+ }
+
+ #[test]
+ fn checked_add_overflow() {
+ let result = Limb::MAX.checked_add(Limb::ONE);
+ assert!(!bool::from(result.is_some()));
+ }
+}
diff --git a/vendor/crypto-bigint/src/limb/bit_and.rs b/vendor/crypto-bigint/src/limb/bit_and.rs
new file mode 100644
index 000000000..3f0bfba0e
--- /dev/null
+++ b/vendor/crypto-bigint/src/limb/bit_and.rs
@@ -0,0 +1,21 @@
+//! Limb bit and operations.
+
+use super::Limb;
+use core::ops::BitAnd;
+
+impl Limb {
+ /// Calculates `a & b`.
+ #[inline(always)]
+ pub const fn bitand(self, rhs: Self) -> Self {
+ Limb(self.0 & rhs.0)
+ }
+}
+
+impl BitAnd for Limb {
+ type Output = Limb;
+
+ #[inline(always)]
+ fn bitand(self, rhs: Self) -> Self::Output {
+ self.bitand(rhs)
+ }
+}
diff --git a/vendor/crypto-bigint/src/limb/bit_not.rs b/vendor/crypto-bigint/src/limb/bit_not.rs
new file mode 100644
index 000000000..26676d598
--- /dev/null
+++ b/vendor/crypto-bigint/src/limb/bit_not.rs
@@ -0,0 +1,19 @@
+//! Limb bit not operations.
+
+use super::Limb;
+use core::ops::Not;
+
+impl Limb {
+ /// Calculates `!a`.
+ pub const fn not(self) -> Self {
+ Limb(!self.0)
+ }
+}
+
+impl Not for Limb {
+ type Output = Limb;
+
+ fn not(self) -> <Self as Not>::Output {
+ self.not()
+ }
+}
diff --git a/vendor/crypto-bigint/src/limb/bit_or.rs b/vendor/crypto-bigint/src/limb/bit_or.rs
new file mode 100644
index 000000000..cafac18da
--- /dev/null
+++ b/vendor/crypto-bigint/src/limb/bit_or.rs
@@ -0,0 +1,19 @@
+//! Limb bit or operations.
+
+use super::Limb;
+use core::ops::BitOr;
+
+impl Limb {
+ /// Calculates `a | b`.
+ pub const fn bitor(self, rhs: Self) -> Self {
+ Limb(self.0 | rhs.0)
+ }
+}
+
+impl BitOr for Limb {
+ type Output = Limb;
+
+ fn bitor(self, rhs: Self) -> Self::Output {
+ self.bitor(rhs)
+ }
+}
diff --git a/vendor/crypto-bigint/src/limb/bit_xor.rs b/vendor/crypto-bigint/src/limb/bit_xor.rs
new file mode 100644
index 000000000..a50782293
--- /dev/null
+++ b/vendor/crypto-bigint/src/limb/bit_xor.rs
@@ -0,0 +1,19 @@
+//! Limb bit xor operations.
+
+use super::Limb;
+use core::ops::BitXor;
+
+impl Limb {
+ /// Calculates `a ^ b`.
+ pub const fn bitxor(self, rhs: Self) -> Self {
+ Limb(self.0 ^ rhs.0)
+ }
+}
+
+impl BitXor for Limb {
+ type Output = Limb;
+
+ fn bitxor(self, rhs: Self) -> Self::Output {
+ self.bitxor(rhs)
+ }
+}
diff --git a/vendor/crypto-bigint/src/limb/bits.rs b/vendor/crypto-bigint/src/limb/bits.rs
new file mode 100644
index 000000000..c470ae9ab
--- /dev/null
+++ b/vendor/crypto-bigint/src/limb/bits.rs
@@ -0,0 +1,8 @@
+use super::Limb;
+
+impl Limb {
+ /// Calculate the number of bits needed to represent this number.
+ pub const fn bits(self) -> usize {
+ Limb::BIT_SIZE - (self.0.leading_zeros() as usize)
+ }
+}
diff --git a/vendor/crypto-bigint/src/limb/cmp.rs b/vendor/crypto-bigint/src/limb/cmp.rs
new file mode 100644
index 000000000..76cc4b07c
--- /dev/null
+++ b/vendor/crypto-bigint/src/limb/cmp.rs
@@ -0,0 +1,176 @@
+//! Limb comparisons
+
+use super::{Limb, SignedWord, WideSignedWord, Word, HI_BIT};
+use core::cmp::Ordering;
+use subtle::{Choice, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess};
+
+impl Limb {
+ /// Is this limb an odd number?
+ #[inline]
+ pub fn is_odd(&self) -> Choice {
+ Choice::from(self.0 as u8 & 1)
+ }
+
+ /// Perform a comparison of the inner value in variable-time.
+ ///
+ /// Note that the [`PartialOrd`] and [`Ord`] impls wrap constant-time
+ /// comparisons using the `subtle` crate.
+ pub fn cmp_vartime(&self, other: &Self) -> Ordering {
+ self.0.cmp(&other.0)
+ }
+
+ /// Performs an equality check in variable-time.
+ pub const fn eq_vartime(&self, other: &Self) -> bool {
+ self.0 == other.0
+ }
+
+ /// Returns all 1's if `a`!=0 or 0 if `a`==0.
+ ///
+ /// Const-friendly: we can't yet use `subtle` in `const fn` contexts.
+ #[inline]
+ pub(crate) const fn is_nonzero(self) -> Word {
+ let inner = self.0 as SignedWord;
+ ((inner | inner.saturating_neg()) >> HI_BIT) as Word
+ }
+
+ #[inline]
+ pub(crate) const fn ct_cmp(lhs: Self, rhs: Self) -> SignedWord {
+ let a = lhs.0 as WideSignedWord;
+ let b = rhs.0 as WideSignedWord;
+ let gt = ((b - a) >> Limb::BIT_SIZE) & 1;
+ let lt = ((a - b) >> Limb::BIT_SIZE) & 1 & !gt;
+ (gt as SignedWord) - (lt as SignedWord)
+ }
+}
+
+impl ConstantTimeEq for Limb {
+ #[inline]
+ fn ct_eq(&self, other: &Self) -> Choice {
+ self.0.ct_eq(&other.0)
+ }
+}
+
+impl ConstantTimeGreater for Limb {
+ #[inline]
+ fn ct_gt(&self, other: &Self) -> Choice {
+ self.0.ct_gt(&other.0)
+ }
+}
+
+impl ConstantTimeLess for Limb {
+ #[inline]
+ fn ct_lt(&self, other: &Self) -> Choice {
+ self.0.ct_lt(&other.0)
+ }
+}
+
+impl Eq for Limb {}
+
+impl Ord for Limb {
+ fn cmp(&self, other: &Self) -> Ordering {
+ let mut n = 0i8;
+ n -= self.ct_lt(other).unwrap_u8() as i8;
+ n += self.ct_gt(other).unwrap_u8() as i8;
+
+ match n {
+ -1 => Ordering::Less,
+ 1 => Ordering::Greater,
+ _ => {
+ debug_assert_eq!(n, 0);
+ debug_assert!(bool::from(self.ct_eq(other)));
+ Ordering::Equal
+ }
+ }
+ }
+}
+
+impl PartialOrd for Limb {
+ #[inline]
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl PartialEq for Limb {
+ #[inline]
+ fn eq(&self, other: &Self) -> bool {
+ self.ct_eq(other).into()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::{Limb, Zero};
+ use core::cmp::Ordering;
+ use subtle::{ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess};
+
+ #[test]
+ fn is_zero() {
+ assert!(bool::from(Limb::ZERO.is_zero()));
+ assert!(!bool::from(Limb::ONE.is_zero()));
+ assert!(!bool::from(Limb::MAX.is_zero()));
+ }
+
+ #[test]
+ fn is_odd() {
+ assert!(!bool::from(Limb::ZERO.is_odd()));
+ assert!(bool::from(Limb::ONE.is_odd()));
+ assert!(bool::from(Limb::MAX.is_odd()));
+ }
+
+ #[test]
+ fn ct_eq() {
+ let a = Limb::ZERO;
+ let b = Limb::MAX;
+
+ assert!(bool::from(a.ct_eq(&a)));
+ assert!(!bool::from(a.ct_eq(&b)));
+ assert!(!bool::from(b.ct_eq(&a)));
+ assert!(bool::from(b.ct_eq(&b)));
+ }
+
+ #[test]
+ fn ct_gt() {
+ let a = Limb::ZERO;
+ let b = Limb::ONE;
+ let c = Limb::MAX;
+
+ assert!(bool::from(b.ct_gt(&a)));
+ assert!(bool::from(c.ct_gt(&a)));
+ assert!(bool::from(c.ct_gt(&b)));
+
+ assert!(!bool::from(a.ct_gt(&a)));
+ assert!(!bool::from(b.ct_gt(&b)));
+ assert!(!bool::from(c.ct_gt(&c)));
+
+ assert!(!bool::from(a.ct_gt(&b)));
+ assert!(!bool::from(a.ct_gt(&c)));
+ assert!(!bool::from(b.ct_gt(&c)));
+ }
+
+ #[test]
+ fn ct_lt() {
+ let a = Limb::ZERO;
+ let b = Limb::ONE;
+ let c = Limb::MAX;
+
+ assert!(bool::from(a.ct_lt(&b)));
+ assert!(bool::from(a.ct_lt(&c)));
+ assert!(bool::from(b.ct_lt(&c)));
+
+ assert!(!bool::from(a.ct_lt(&a)));
+ assert!(!bool::from(b.ct_lt(&b)));
+ assert!(!bool::from(c.ct_lt(&c)));
+
+ assert!(!bool::from(b.ct_lt(&a)));
+ assert!(!bool::from(c.ct_lt(&a)));
+ assert!(!bool::from(c.ct_lt(&b)));
+ }
+
+ #[test]
+ fn cmp() {
+ assert_eq!(Limb::ZERO.cmp(&Limb::ONE), Ordering::Less);
+ assert_eq!(Limb::ONE.cmp(&Limb::ONE), Ordering::Equal);
+ assert_eq!(Limb::MAX.cmp(&Limb::ONE), Ordering::Greater);
+ }
+}
diff --git a/vendor/crypto-bigint/src/limb/encoding.rs b/vendor/crypto-bigint/src/limb/encoding.rs
new file mode 100644
index 000000000..39974b061
--- /dev/null
+++ b/vendor/crypto-bigint/src/limb/encoding.rs
@@ -0,0 +1,67 @@
+//! Limb encoding
+
+use super::{Limb, Word};
+use crate::Encoding;
+
+impl Encoding for Limb {
+ const BIT_SIZE: usize = Self::BIT_SIZE;
+ const BYTE_SIZE: usize = Self::BYTE_SIZE;
+
+ #[cfg(target_pointer_width = "32")]
+ type Repr = [u8; 4];
+ #[cfg(target_pointer_width = "64")]
+ type Repr = [u8; 8];
+
+ #[inline]
+ fn from_be_bytes(bytes: Self::Repr) -> Self {
+ Limb(Word::from_be_bytes(bytes))
+ }
+
+ #[inline]
+ fn from_le_bytes(bytes: Self::Repr) -> Self {
+ Limb(Word::from_le_bytes(bytes))
+ }
+
+ #[inline]
+ fn to_be_bytes(&self) -> Self::Repr {
+ self.0.to_be_bytes()
+ }
+
+ #[inline]
+ fn to_le_bytes(&self) -> Self::Repr {
+ self.0.to_le_bytes()
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use proptest::prelude::*;
+
+ prop_compose! {
+ fn limb()(inner in any::<Word>()) -> Limb {
+ Limb(inner)
+ }
+ }
+
+ proptest! {
+ #[test]
+ fn roundtrip(a in limb()) {
+ assert_eq!(a, Limb::from_be_bytes(a.to_be_bytes()));
+ assert_eq!(a, Limb::from_le_bytes(a.to_le_bytes()));
+ }
+ }
+
+ proptest! {
+ #[test]
+ fn reverse(a in limb()) {
+ let mut bytes = a.to_be_bytes();
+ bytes.reverse();
+ assert_eq!(a, Limb::from_le_bytes(bytes));
+
+ let mut bytes = a.to_le_bytes();
+ bytes.reverse();
+ assert_eq!(a, Limb::from_be_bytes(bytes));
+ }
+ }
+}
diff --git a/vendor/crypto-bigint/src/limb/from.rs b/vendor/crypto-bigint/src/limb/from.rs
new file mode 100644
index 000000000..fd2765bc9
--- /dev/null
+++ b/vendor/crypto-bigint/src/limb/from.rs
@@ -0,0 +1,76 @@
+//! `From`-like conversions for [`Limb`].
+
+use super::{Limb, WideWord, Word};
+
+impl Limb {
+ /// Create a [`Limb`] from a `u8` integer (const-friendly)
+ // TODO(tarcieri): replace with `const impl From<u8>` when stable
+ pub const fn from_u8(n: u8) -> Self {
+ Limb(n as Word)
+ }
+
+ /// Create a [`Limb`] from a `u16` integer (const-friendly)
+ // TODO(tarcieri): replace with `const impl From<u16>` when stable
+ pub const fn from_u16(n: u16) -> Self {
+ Limb(n as Word)
+ }
+
+ /// Create a [`Limb`] from a `u32` integer (const-friendly)
+ // TODO(tarcieri): replace with `const impl From<u32>` when stable
+ pub const fn from_u32(n: u32) -> Self {
+ #[allow(trivial_numeric_casts)]
+ Limb(n as Word)
+ }
+
+ /// Create a [`Limb`] from a `u64` integer (const-friendly)
+ // TODO(tarcieri): replace with `const impl From<u64>` when stable
+ #[cfg(target_pointer_width = "64")]
+ #[cfg_attr(docsrs, doc(cfg(target_pointer_width = "64")))]
+ pub const fn from_u64(n: u64) -> Self {
+ Limb(n)
+ }
+}
+
+impl From<u8> for Limb {
+ #[inline]
+ fn from(n: u8) -> Limb {
+ Limb(n.into())
+ }
+}
+
+impl From<u16> for Limb {
+ #[inline]
+ fn from(n: u16) -> Limb {
+ Limb(n.into())
+ }
+}
+
+impl From<u32> for Limb {
+ #[inline]
+ fn from(n: u32) -> Limb {
+ Limb(n.into())
+ }
+}
+
+#[cfg(target_pointer_width = "64")]
+#[cfg_attr(docsrs, doc(cfg(target_pointer_width = "64")))]
+impl From<u64> for Limb {
+ #[inline]
+ fn from(n: u64) -> Limb {
+ Limb(n)
+ }
+}
+
+impl From<Limb> for Word {
+ #[inline]
+ fn from(limb: Limb) -> Word {
+ limb.0
+ }
+}
+
+impl From<Limb> for WideWord {
+ #[inline]
+ fn from(limb: Limb) -> WideWord {
+ limb.0.into()
+ }
+}
diff --git a/vendor/crypto-bigint/src/limb/mul.rs b/vendor/crypto-bigint/src/limb/mul.rs
new file mode 100644
index 000000000..a342c6eae
--- /dev/null
+++ b/vendor/crypto-bigint/src/limb/mul.rs
@@ -0,0 +1,195 @@
+//! Limb multiplication
+
+use crate::{Checked, CheckedMul, Limb, WideWord, Word, Wrapping, Zero};
+use core::ops::{Mul, MulAssign};
+use subtle::CtOption;
+
+impl Limb {
+ /// Computes `self + (b * c) + carry`, returning the result along with the new carry.
+ #[inline(always)]
+ pub const fn mac(self, b: Limb, c: Limb, carry: Limb) -> (Limb, Limb) {
+ let a = self.0 as WideWord;
+ let b = b.0 as WideWord;
+ let c = c.0 as WideWord;
+ let carry = carry.0 as WideWord;
+ let ret = a + (b * c) + carry;
+ (Limb(ret as Word), Limb((ret >> Self::BIT_SIZE) as Word))
+ }
+
+ /// Perform saturating multiplication.
+ #[inline]
+ pub const fn saturating_mul(&self, rhs: Self) -> Self {
+ Limb(self.0.saturating_mul(rhs.0))
+ }
+
+ /// Perform wrapping multiplication, discarding overflow.
+ #[inline(always)]
+ pub const fn wrapping_mul(&self, rhs: Self) -> Self {
+ Limb(self.0.wrapping_mul(rhs.0))
+ }
+
+ /// Compute "wide" multiplication, with a product twice the size of the input.
+ pub(crate) const fn mul_wide(&self, rhs: Self) -> WideWord {
+ (self.0 as WideWord) * (rhs.0 as WideWord)
+ }
+}
+
+impl CheckedMul for Limb {
+ type Output = Self;
+
+ #[inline]
+ fn checked_mul(&self, rhs: Self) -> CtOption<Self> {
+ let result = self.mul_wide(rhs);
+ let overflow = Limb((result >> Self::BIT_SIZE) as Word);
+ CtOption::new(Limb(result as Word), overflow.is_zero())
+ }
+}
+
+impl Mul for Wrapping<Limb> {
+ type Output = Self;
+
+ fn mul(self, rhs: Self) -> Wrapping<Limb> {
+ Wrapping(self.0.wrapping_mul(rhs.0))
+ }
+}
+
+impl Mul<&Wrapping<Limb>> for Wrapping<Limb> {
+ type Output = Wrapping<Limb>;
+
+ fn mul(self, rhs: &Wrapping<Limb>) -> Wrapping<Limb> {
+ Wrapping(self.0.wrapping_mul(rhs.0))
+ }
+}
+
+impl Mul<Wrapping<Limb>> for &Wrapping<Limb> {
+ type Output = Wrapping<Limb>;
+
+ fn mul(self, rhs: Wrapping<Limb>) -> Wrapping<Limb> {
+ Wrapping(self.0.wrapping_mul(rhs.0))
+ }
+}
+
+impl Mul<&Wrapping<Limb>> for &Wrapping<Limb> {
+ type Output = Wrapping<Limb>;
+
+ fn mul(self, rhs: &Wrapping<Limb>) -> Wrapping<Limb> {
+ Wrapping(self.0.wrapping_mul(rhs.0))
+ }
+}
+
+impl MulAssign for Wrapping<Limb> {
+ fn mul_assign(&mut self, other: Self) {
+ *self = *self * other;
+ }
+}
+
+impl MulAssign<&Wrapping<Limb>> for Wrapping<Limb> {
+ fn mul_assign(&mut self, other: &Self) {
+ *self = *self * other;
+ }
+}
+
+impl Mul for Checked<Limb> {
+ type Output = Self;
+
+ fn mul(self, rhs: Self) -> Checked<Limb> {
+ Checked(
+ self.0
+ .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_mul(rhs))),
+ )
+ }
+}
+
+impl Mul<&Checked<Limb>> for Checked<Limb> {
+ type Output = Checked<Limb>;
+
+ fn mul(self, rhs: &Checked<Limb>) -> Checked<Limb> {
+ Checked(
+ self.0
+ .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_mul(rhs))),
+ )
+ }
+}
+
+impl Mul<Checked<Limb>> for &Checked<Limb> {
+ type Output = Checked<Limb>;
+
+ fn mul(self, rhs: Checked<Limb>) -> Checked<Limb> {
+ Checked(
+ self.0
+ .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_mul(rhs))),
+ )
+ }
+}
+
+impl Mul<&Checked<Limb>> for &Checked<Limb> {
+ type Output = Checked<Limb>;
+
+ fn mul(self, rhs: &Checked<Limb>) -> Checked<Limb> {
+ Checked(
+ self.0
+ .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_mul(rhs))),
+ )
+ }
+}
+
+impl MulAssign for Checked<Limb> {
+ fn mul_assign(&mut self, other: Self) {
+ *self = *self * other;
+ }
+}
+
+impl MulAssign<&Checked<Limb>> for Checked<Limb> {
+ fn mul_assign(&mut self, other: &Self) {
+ *self = *self * other;
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::{CheckedMul, Limb, WideWord};
+
+ #[test]
+ fn mul_wide_zero_and_one() {
+ assert_eq!(Limb::ZERO.mul_wide(Limb::ZERO), 0);
+ assert_eq!(Limb::ZERO.mul_wide(Limb::ONE), 0);
+ assert_eq!(Limb::ONE.mul_wide(Limb::ZERO), 0);
+ assert_eq!(Limb::ONE.mul_wide(Limb::ONE), 1);
+ }
+
+ #[test]
+ fn mul_wide() {
+ let primes: &[u32] = &[3, 5, 17, 256, 65537];
+
+ for &a_int in primes {
+ for &b_int in primes {
+ let actual = Limb::from_u32(a_int).mul_wide(Limb::from_u32(b_int));
+ let expected = a_int as WideWord * b_int as WideWord;
+ assert_eq!(actual, expected);
+ }
+ }
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "32")]
+ fn checked_mul_ok() {
+ let n = Limb::from_u16(0xffff);
+ assert_eq!(n.checked_mul(n).unwrap(), Limb::from_u32(0xfffe_0001));
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn checked_mul_ok() {
+ let n = Limb::from_u32(0xffff_ffff);
+ assert_eq!(
+ n.checked_mul(n).unwrap(),
+ Limb::from_u64(0xffff_fffe_0000_0001)
+ );
+ }
+
+ #[test]
+ fn checked_mul_overflow() {
+ let n = Limb::MAX;
+ assert!(bool::from(n.checked_mul(n).is_none()));
+ }
+}
diff --git a/vendor/crypto-bigint/src/limb/rand.rs b/vendor/crypto-bigint/src/limb/rand.rs
new file mode 100644
index 000000000..0bc8af31a
--- /dev/null
+++ b/vendor/crypto-bigint/src/limb/rand.rs
@@ -0,0 +1,45 @@
+//! Random number generator support
+
+use super::Limb;
+use crate::{Encoding, NonZero, Random, RandomMod};
+use rand_core::{CryptoRng, RngCore};
+use subtle::ConstantTimeLess;
+
+#[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))]
+impl Random for Limb {
+ #[cfg(target_pointer_width = "32")]
+ fn random(mut rng: impl CryptoRng + RngCore) -> Self {
+ Self(rng.next_u32())
+ }
+
+ #[cfg(target_pointer_width = "64")]
+ fn random(mut rng: impl CryptoRng + RngCore) -> Self {
+ Self(rng.next_u64())
+ }
+}
+
+#[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))]
+impl RandomMod for Limb {
+ fn random_mod(mut rng: impl CryptoRng + RngCore, modulus: &NonZero<Self>) -> Self {
+ let mut bytes = <Self as Encoding>::Repr::default();
+
+ // TODO(tarcieri): use `div_ceil` when available
+ // See: https://github.com/rust-lang/rust/issues/88581
+ let mut n_bytes = modulus.bits() / 8;
+
+ // Ensure the randomly generated value can always be larger than
+ // the modulus in order to ensure a uniform distribution
+ if n_bytes < Self::BYTE_SIZE {
+ n_bytes += 1;
+ }
+
+ loop {
+ rng.fill_bytes(&mut bytes[..n_bytes]);
+ let n = Limb::from_le_bytes(bytes);
+
+ if n.ct_lt(modulus).into() {
+ return n;
+ }
+ }
+ }
+}
diff --git a/vendor/crypto-bigint/src/limb/shl.rs b/vendor/crypto-bigint/src/limb/shl.rs
new file mode 100644
index 000000000..c0003ddbb
--- /dev/null
+++ b/vendor/crypto-bigint/src/limb/shl.rs
@@ -0,0 +1,73 @@
+//! Limb left bitshift
+
+use crate::{Limb, Word};
+use core::ops::{Shl, ShlAssign};
+
+impl Limb {
+ /// Computes `self << rhs`.
+ #[inline(always)]
+ pub const fn shl(self, rhs: Self) -> Self {
+ Limb(self.0 << rhs.0)
+ }
+}
+
+impl Shl for Limb {
+ type Output = Self;
+
+ #[inline(always)]
+ fn shl(self, rhs: Self) -> Self::Output {
+ self.shl(rhs)
+ }
+}
+
+impl Shl<usize> for Limb {
+ type Output = Self;
+
+ #[inline(always)]
+ fn shl(self, rhs: usize) -> Self::Output {
+ self.shl(Limb(rhs as Word))
+ }
+}
+
+impl ShlAssign for Limb {
+ #[inline(always)]
+ fn shl_assign(&mut self, other: Self) {
+ *self = self.shl(other);
+ }
+}
+
+impl ShlAssign<usize> for Limb {
+ #[inline(always)]
+ fn shl_assign(&mut self, other: usize) {
+ *self = self.shl(Limb(other as Word));
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::Limb;
+
+ #[test]
+ fn shl1() {
+ assert_eq!(Limb(1) << 1, Limb(2));
+ }
+
+ #[test]
+ fn shl2() {
+ assert_eq!(Limb(1) << 2, Limb(4));
+ }
+
+ #[test]
+ fn shl_assign1() {
+ let mut l = Limb(1);
+ l <<= 1;
+ assert_eq!(l, Limb(2));
+ }
+
+ #[test]
+ fn shl_assign2() {
+ let mut l = Limb(1);
+ l <<= 2;
+ assert_eq!(l, Limb(4));
+ }
+}
diff --git a/vendor/crypto-bigint/src/limb/shr.rs b/vendor/crypto-bigint/src/limb/shr.rs
new file mode 100644
index 000000000..29ee76353
--- /dev/null
+++ b/vendor/crypto-bigint/src/limb/shr.rs
@@ -0,0 +1,73 @@
+//! Limb right bitshift
+
+use crate::{Limb, Word};
+use core::ops::{Shr, ShrAssign};
+
+impl Limb {
+ /// Computes `self >> rhs`.
+ #[inline(always)]
+ pub const fn shr(self, rhs: Self) -> Self {
+ Limb(self.0 >> rhs.0)
+ }
+}
+
+impl Shr for Limb {
+ type Output = Self;
+
+ #[inline(always)]
+ fn shr(self, rhs: Self) -> Self::Output {
+ self.shr(rhs)
+ }
+}
+
+impl Shr<usize> for Limb {
+ type Output = Self;
+
+ #[inline(always)]
+ fn shr(self, rhs: usize) -> Self::Output {
+ self.shr(Limb(rhs as Word))
+ }
+}
+
+impl ShrAssign for Limb {
+ #[inline(always)]
+ fn shr_assign(&mut self, other: Self) {
+ *self = self.shr(other);
+ }
+}
+
+impl ShrAssign<usize> for Limb {
+ #[inline(always)]
+ fn shr_assign(&mut self, other: usize) {
+ *self = self.shr(Limb(other as Word));
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::Limb;
+
+ #[test]
+ fn shr1() {
+ assert_eq!(Limb(2) >> 1, Limb(1));
+ }
+
+ #[test]
+ fn shr2() {
+ assert_eq!(Limb(16) >> 2, Limb(4));
+ }
+
+ #[test]
+ fn shr_assign1() {
+ let mut l = Limb::ONE;
+ l >>= 1;
+ assert_eq!(l, Limb::ZERO);
+ }
+
+ #[test]
+ fn shr_assign2() {
+ let mut l = Limb(32);
+ l >>= 2;
+ assert_eq!(l, Limb(8));
+ }
+}
diff --git a/vendor/crypto-bigint/src/limb/sub.rs b/vendor/crypto-bigint/src/limb/sub.rs
new file mode 100644
index 000000000..1560a1b64
--- /dev/null
+++ b/vendor/crypto-bigint/src/limb/sub.rs
@@ -0,0 +1,182 @@
+//! Limb subtraction
+
+use crate::{Checked, CheckedSub, Limb, WideWord, Word, Wrapping, Zero};
+use core::ops::{Sub, SubAssign};
+use subtle::CtOption;
+
+impl Limb {
+ /// Computes `self - (rhs + borrow)`, returning the result along with the new borrow.
+ #[inline(always)]
+ pub const fn sbb(self, rhs: Limb, borrow: Limb) -> (Limb, Limb) {
+ let a = self.0 as WideWord;
+ let b = rhs.0 as WideWord;
+ let borrow = (borrow.0 >> (Self::BIT_SIZE - 1)) as WideWord;
+ let ret = a.wrapping_sub(b + borrow);
+ (Limb(ret as Word), Limb((ret >> Self::BIT_SIZE) as Word))
+ }
+
+ /// Perform saturating subtraction.
+ #[inline]
+ pub const fn saturating_sub(&self, rhs: Self) -> Self {
+ Limb(self.0.saturating_sub(rhs.0))
+ }
+
+ /// Perform wrapping subtraction, discarding underflow and wrapping around
+ /// the boundary of the type.
+ #[inline(always)]
+ pub const fn wrapping_sub(&self, rhs: Self) -> Self {
+ Limb(self.0.wrapping_sub(rhs.0))
+ }
+}
+
+impl CheckedSub for Limb {
+ type Output = Self;
+
+ #[inline]
+ fn checked_sub(&self, rhs: Self) -> CtOption<Self> {
+ let (result, underflow) = self.sbb(rhs, Limb::ZERO);
+ CtOption::new(result, underflow.is_zero())
+ }
+}
+
+impl Sub for Wrapping<Limb> {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Wrapping<Limb> {
+ Wrapping(self.0.wrapping_sub(rhs.0))
+ }
+}
+
+impl Sub<&Wrapping<Limb>> for Wrapping<Limb> {
+ type Output = Wrapping<Limb>;
+
+ fn sub(self, rhs: &Wrapping<Limb>) -> Wrapping<Limb> {
+ Wrapping(self.0.wrapping_sub(rhs.0))
+ }
+}
+
+impl Sub<Wrapping<Limb>> for &Wrapping<Limb> {
+ type Output = Wrapping<Limb>;
+
+ fn sub(self, rhs: Wrapping<Limb>) -> Wrapping<Limb> {
+ Wrapping(self.0.wrapping_sub(rhs.0))
+ }
+}
+
+impl Sub<&Wrapping<Limb>> for &Wrapping<Limb> {
+ type Output = Wrapping<Limb>;
+
+ fn sub(self, rhs: &Wrapping<Limb>) -> Wrapping<Limb> {
+ Wrapping(self.0.wrapping_sub(rhs.0))
+ }
+}
+
+impl SubAssign for Wrapping<Limb> {
+ fn sub_assign(&mut self, other: Self) {
+ *self = *self - other;
+ }
+}
+
+impl SubAssign<&Wrapping<Limb>> for Wrapping<Limb> {
+ fn sub_assign(&mut self, other: &Self) {
+ *self = *self - other;
+ }
+}
+
+impl Sub for Checked<Limb> {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Checked<Limb> {
+ Checked(
+ self.0
+ .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_sub(rhs))),
+ )
+ }
+}
+
+impl Sub<&Checked<Limb>> for Checked<Limb> {
+ type Output = Checked<Limb>;
+
+ fn sub(self, rhs: &Checked<Limb>) -> Checked<Limb> {
+ Checked(
+ self.0
+ .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_sub(rhs))),
+ )
+ }
+}
+
+impl Sub<Checked<Limb>> for &Checked<Limb> {
+ type Output = Checked<Limb>;
+
+ fn sub(self, rhs: Checked<Limb>) -> Checked<Limb> {
+ Checked(
+ self.0
+ .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_sub(rhs))),
+ )
+ }
+}
+
+impl Sub<&Checked<Limb>> for &Checked<Limb> {
+ type Output = Checked<Limb>;
+
+ fn sub(self, rhs: &Checked<Limb>) -> Checked<Limb> {
+ Checked(
+ self.0
+ .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_sub(rhs))),
+ )
+ }
+}
+
+impl SubAssign for Checked<Limb> {
+ fn sub_assign(&mut self, other: Self) {
+ *self = *self - other;
+ }
+}
+
+impl SubAssign<&Checked<Limb>> for Checked<Limb> {
+ fn sub_assign(&mut self, other: &Self) {
+ *self = *self - other;
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::{CheckedSub, Limb};
+
+ #[test]
+ fn sbb_no_borrow() {
+ let (res, borrow) = Limb::ONE.sbb(Limb::ONE, Limb::ZERO);
+ assert_eq!(res, Limb::ZERO);
+ assert_eq!(borrow, Limb::ZERO);
+ }
+
+ #[test]
+ fn sbb_with_borrow() {
+ let (res, borrow) = Limb::ZERO.sbb(Limb::ONE, Limb::ZERO);
+
+ assert_eq!(res, Limb::MAX);
+ assert_eq!(borrow, Limb::MAX);
+ }
+
+ #[test]
+ fn wrapping_sub_no_borrow() {
+ assert_eq!(Limb::ONE.wrapping_sub(Limb::ONE), Limb::ZERO);
+ }
+
+ #[test]
+ fn wrapping_sub_with_borrow() {
+ assert_eq!(Limb::ZERO.wrapping_sub(Limb::ONE), Limb::MAX);
+ }
+
+ #[test]
+ fn checked_sub_ok() {
+ let result = Limb::ONE.checked_sub(Limb::ONE);
+ assert_eq!(result.unwrap(), Limb::ZERO);
+ }
+
+ #[test]
+ fn checked_sub_overflow() {
+ let result = Limb::ZERO.checked_sub(Limb::ONE);
+ assert!(!bool::from(result.is_some()));
+ }
+}