summaryrefslogtreecommitdiffstats
path: root/vendor/crypto-bigint/src/limb
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:47:55 +0000
commit2aadc03ef15cb5ca5cc2af8a7c08e070742f0ac4 (patch)
tree033cc839730fda84ff08db877037977be94e5e3a /vendor/crypto-bigint/src/limb
parentInitial commit. (diff)
downloadcargo-2aadc03ef15cb5ca5cc2af8a7c08e070742f0ac4.tar.xz
cargo-2aadc03ef15cb5ca5cc2af8a7c08e070742f0ac4.zip
Adding upstream version 0.70.1+ds1.upstream/0.70.1+ds1upstream
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.rs18
-rw-r--r--vendor/crypto-bigint/src/limb/cmp.rs200
-rw-r--r--vendor/crypto-bigint/src/limb/encoding.rs64
-rw-r--r--vendor/crypto-bigint/src/limb/from.rs74
-rw-r--r--vendor/crypto-bigint/src/limb/mul.rs195
-rw-r--r--vendor/crypto-bigint/src/limb/neg.rs20
-rw-r--r--vendor/crypto-bigint/src/limb/rand.rs38
-rw-r--r--vendor/crypto-bigint/src/limb/shl.rs74
-rw-r--r--vendor/crypto-bigint/src/limb/shr.rs74
-rw-r--r--vendor/crypto-bigint/src/limb/sub.rs182
15 files changed, 1197 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 0000000..0ef793b
--- /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::BITS) 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 0000000..3f0bfba
--- /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 0000000..26676d5
--- /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 0000000..cafac18
--- /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 0000000..a507822
--- /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 0000000..02a74de
--- /dev/null
+++ b/vendor/crypto-bigint/src/limb/bits.rs
@@ -0,0 +1,18 @@
+use super::Limb;
+
+impl Limb {
+ /// Calculate the number of bits needed to represent this number.
+ pub const fn bits(self) -> usize {
+ Limb::BITS - (self.0.leading_zeros() as usize)
+ }
+
+ /// Calculate the number of leading zeros in the binary representation of this number.
+ pub const fn leading_zeros(self) -> usize {
+ self.0.leading_zeros() as usize
+ }
+
+ /// Calculate the number of trailing zeros in the binary representation of this number.
+ pub const fn trailing_zeros(self) -> usize {
+ self.0.trailing_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 0000000..4cdec5b
--- /dev/null
+++ b/vendor/crypto-bigint/src/limb/cmp.rs
@@ -0,0 +1,200 @@
+//! Limb comparisons
+
+use super::HI_BIT;
+use crate::{CtChoice, Limb};
+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
+ }
+
+ /// Return `b` if `c` is truthy, otherwise return `a`.
+ #[inline]
+ pub(crate) const fn ct_select(a: Self, b: Self, c: CtChoice) -> Self {
+ Self(c.select(a.0, b.0))
+ }
+
+ /// Returns the truthy value if `self != 0` and the falsy value otherwise.
+ #[inline]
+ pub(crate) const fn ct_is_nonzero(&self) -> CtChoice {
+ let inner = self.0;
+ CtChoice::from_lsb((inner | inner.wrapping_neg()) >> HI_BIT)
+ }
+
+ /// Returns the truthy value if `lhs == rhs` and the falsy value otherwise.
+ #[inline]
+ pub(crate) const fn ct_eq(lhs: Self, rhs: Self) -> CtChoice {
+ let x = lhs.0;
+ let y = rhs.0;
+
+ // x ^ y == 0 if and only if x == y
+ Self(x ^ y).ct_is_nonzero().not()
+ }
+
+ /// Returns the truthy value if `lhs < rhs` and the falsy value otherwise.
+ #[inline]
+ pub(crate) const fn ct_lt(lhs: Self, rhs: Self) -> CtChoice {
+ let x = lhs.0;
+ let y = rhs.0;
+ let bit = (((!x) & y) | (((!x) | y) & (x.wrapping_sub(y)))) >> (Limb::BITS - 1);
+ CtChoice::from_lsb(bit)
+ }
+
+ /// Returns the truthy value if `lhs <= rhs` and the falsy value otherwise.
+ #[inline]
+ pub(crate) const fn ct_le(lhs: Self, rhs: Self) -> CtChoice {
+ let x = lhs.0;
+ let y = rhs.0;
+ let bit = (((!x) | y) & ((x ^ y) | !(y.wrapping_sub(x)))) >> (Limb::BITS - 1);
+ CtChoice::from_lsb(bit)
+ }
+}
+
+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 0000000..ab28a6a
--- /dev/null
+++ b/vendor/crypto-bigint/src/limb/encoding.rs
@@ -0,0 +1,64 @@
+//! Limb encoding
+
+use super::{Limb, Word};
+use crate::Encoding;
+
+impl Encoding for Limb {
+ #[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 0000000..aa64992
--- /dev/null
+++ b/vendor/crypto-bigint/src/limb/from.rs
@@ -0,0 +1,74 @@
+//! `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")]
+ 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")]
+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 0000000..7f8b084
--- /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::BITS) 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::BITS) 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, 257, 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/neg.rs b/vendor/crypto-bigint/src/limb/neg.rs
new file mode 100644
index 0000000..b658bb9
--- /dev/null
+++ b/vendor/crypto-bigint/src/limb/neg.rs
@@ -0,0 +1,20 @@
+//! Limb negation
+
+use crate::{Limb, Wrapping};
+use core::ops::Neg;
+
+impl Neg for Wrapping<Limb> {
+ type Output = Self;
+
+ fn neg(self) -> Self::Output {
+ Self(self.0.wrapping_neg())
+ }
+}
+
+impl Limb {
+ /// Perform wrapping negation.
+ #[inline(always)]
+ pub const fn wrapping_neg(self) -> Self {
+ Limb(self.0.wrapping_neg())
+ }
+}
diff --git a/vendor/crypto-bigint/src/limb/rand.rs b/vendor/crypto-bigint/src/limb/rand.rs
new file mode 100644
index 0000000..4347168
--- /dev/null
+++ b/vendor/crypto-bigint/src/limb/rand.rs
@@ -0,0 +1,38 @@
+//! Random number generator support
+
+use super::Limb;
+use crate::{Encoding, NonZero, Random, RandomMod};
+use rand_core::CryptoRngCore;
+use subtle::ConstantTimeLess;
+
+impl Random for Limb {
+ #[cfg(target_pointer_width = "32")]
+ fn random(rng: &mut impl CryptoRngCore) -> Self {
+ Self(rng.next_u32())
+ }
+
+ #[cfg(target_pointer_width = "64")]
+ fn random(rng: &mut impl CryptoRngCore) -> Self {
+ Self(rng.next_u64())
+ }
+}
+
+impl RandomMod for Limb {
+ fn random_mod(rng: &mut impl CryptoRngCore, modulus: &NonZero<Self>) -> Self {
+ let mut bytes = <Self as Encoding>::Repr::default();
+
+ let n_bits = modulus.bits();
+ let n_bytes = (n_bits + 7) / 8;
+ let mask = 0xff >> (8 * n_bytes - n_bits);
+
+ loop {
+ rng.fill_bytes(&mut bytes[..n_bytes]);
+ bytes[n_bytes - 1] &= mask;
+
+ 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 0000000..88e37f0
--- /dev/null
+++ b/vendor/crypto-bigint/src/limb/shl.rs
@@ -0,0 +1,74 @@
+//! Limb left bitshift
+
+use crate::{Limb, Word};
+use core::ops::{Shl, ShlAssign};
+
+impl Limb {
+ /// Computes `self << rhs`.
+ /// Panics if `rhs` overflows `Limb::BITS`.
+ #[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 0000000..7c422e0
--- /dev/null
+++ b/vendor/crypto-bigint/src/limb/shr.rs
@@ -0,0 +1,74 @@
+//! Limb right bitshift
+
+use crate::{Limb, Word};
+use core::ops::{Shr, ShrAssign};
+
+impl Limb {
+ /// Computes `self >> rhs`.
+ /// Panics if `rhs` overflows `Limb::BITS`.
+ #[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 0000000..0fc7a4a
--- /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::BITS - 1)) as WideWord;
+ let ret = a.wrapping_sub(b + borrow);
+ (Limb(ret as Word), Limb((ret >> Self::BITS) 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()));
+ }
+}