summaryrefslogtreecommitdiffstats
path: root/vendor/crypto-bigint/src/uint/neg.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/crypto-bigint/src/uint/neg.rs')
-rw-r--r--vendor/crypto-bigint/src/uint/neg.rs51
1 files changed, 51 insertions, 0 deletions
diff --git a/vendor/crypto-bigint/src/uint/neg.rs b/vendor/crypto-bigint/src/uint/neg.rs
new file mode 100644
index 0000000..4881a27
--- /dev/null
+++ b/vendor/crypto-bigint/src/uint/neg.rs
@@ -0,0 +1,51 @@
+use core::ops::Neg;
+
+use crate::{CtChoice, Limb, Uint, WideWord, Word, Wrapping};
+
+impl<const LIMBS: usize> Neg for Wrapping<Uint<LIMBS>> {
+ type Output = Self;
+
+ fn neg(self) -> Self::Output {
+ Self(self.0.wrapping_neg())
+ }
+}
+
+impl<const LIMBS: usize> Uint<LIMBS> {
+ /// Negates based on `choice` by wrapping the integer.
+ pub(crate) const fn conditional_wrapping_neg(&self, choice: CtChoice) -> Uint<LIMBS> {
+ Uint::ct_select(self, &self.wrapping_neg(), choice)
+ }
+
+ /// Perform wrapping negation.
+ pub const fn wrapping_neg(&self) -> Self {
+ let mut ret = [Limb::ZERO; LIMBS];
+ let mut carry = 1;
+ let mut i = 0;
+ while i < LIMBS {
+ let r = (!self.limbs[i].0 as WideWord) + carry;
+ ret[i] = Limb(r as Word);
+ carry = r >> Limb::BITS;
+ i += 1;
+ }
+ Uint::new(ret)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::U256;
+
+ #[test]
+ fn wrapping_neg() {
+ assert_eq!(U256::ZERO.wrapping_neg(), U256::ZERO);
+ assert_eq!(U256::MAX.wrapping_neg(), U256::ONE);
+ assert_eq!(
+ U256::from_u64(13).wrapping_neg(),
+ U256::from_u64(13).not().saturating_add(&U256::ONE)
+ );
+ assert_eq!(
+ U256::from_u64(42).wrapping_neg(),
+ U256::from_u64(42).saturating_sub(&U256::ONE).not()
+ );
+ }
+}