1use crate::{ConstChoice, ConstCtOption, Int, Uint};
4
5impl<const LIMBS: usize> Int<LIMBS> {
6 pub const fn overflowing_neg(&self) -> (Self, ConstChoice) {
13 Self(self.0.bitxor(&Uint::MAX)).overflowing_add(&Int::ONE)
14 }
15
16 pub const fn wrapping_neg(&self) -> Self {
21 self.overflowing_neg().0
22 }
23
24 pub const fn wrapping_neg_if(&self, negate: ConstChoice) -> Int<LIMBS> {
29 Self(self.0.wrapping_neg_if(negate))
30 }
31
32 pub const fn checked_neg(&self) -> ConstCtOption<Self> {
37 let (value, overflow) = self.overflowing_neg();
38 ConstCtOption::new(value, overflow.not())
39 }
40}
41
42#[cfg(test)]
43mod tests {
44 use crate::{ConstChoice, I128};
45
46 #[test]
47 fn overflowing_neg() {
48 let min_plus_one = I128 {
49 0: I128::MIN.0.wrapping_add(&I128::ONE.0),
50 };
51
52 let (res, overflow) = I128::MIN.overflowing_neg();
53 assert_eq!(res, I128::MIN);
54 assert_eq!(overflow, ConstChoice::TRUE);
55
56 let (res, overflow) = I128::MINUS_ONE.overflowing_neg();
57 assert_eq!(res, I128::ONE);
58 assert_eq!(overflow, ConstChoice::FALSE);
59
60 let (res, overflow) = I128::ZERO.overflowing_neg();
61 assert_eq!(res, I128::ZERO);
62 assert_eq!(overflow, ConstChoice::FALSE);
63
64 let (res, overflow) = I128::ONE.overflowing_neg();
65 assert_eq!(res, I128::MINUS_ONE);
66 assert_eq!(overflow, ConstChoice::FALSE);
67
68 let (res, overflow) = I128::MAX.overflowing_neg();
69 assert_eq!(res, min_plus_one);
70 assert_eq!(overflow, ConstChoice::FALSE);
71 }
72
73 #[test]
74 fn wrapping_neg_if() {
75 let min_plus_one = I128 {
76 0: I128::MIN.0.wrapping_add(&I128::ONE.0),
77 };
78
79 let do_negate = ConstChoice::TRUE;
80 assert_eq!(I128::MIN.wrapping_neg_if(do_negate), I128::MIN);
81 assert_eq!(I128::MINUS_ONE.wrapping_neg_if(do_negate), I128::ONE);
82 assert_eq!(I128::ZERO.wrapping_neg_if(do_negate), I128::ZERO);
83 assert_eq!(I128::ONE.wrapping_neg_if(do_negate), I128::MINUS_ONE);
84 assert_eq!(I128::MAX.wrapping_neg_if(do_negate), min_plus_one);
85
86 let do_not_negate = ConstChoice::FALSE;
87 assert_eq!(I128::MIN.wrapping_neg_if(do_not_negate), I128::MIN);
88 assert_eq!(
89 I128::MINUS_ONE.wrapping_neg_if(do_not_negate),
90 I128::MINUS_ONE
91 );
92 assert_eq!(I128::ZERO.wrapping_neg_if(do_not_negate), I128::ZERO);
93 assert_eq!(I128::ONE.wrapping_neg_if(do_not_negate), I128::ONE);
94 assert_eq!(I128::MAX.wrapping_neg_if(do_not_negate), I128::MAX);
95 }
96
97 #[test]
98 fn checked_neg() {
99 assert_eq!(I128::MIN.checked_neg().is_none(), ConstChoice::TRUE);
100 assert_eq!(I128::MINUS_ONE.checked_neg().unwrap(), I128::ONE);
101 assert_eq!(I128::ZERO.checked_neg().unwrap(), I128::ZERO);
102 assert_eq!(I128::ONE.checked_neg().unwrap(), I128::MINUS_ONE);
103 assert_eq!(
104 I128::MAX.checked_neg().unwrap(),
105 I128::from_be_hex("80000000000000000000000000000001")
106 );
107
108 let negative = I128::from_be_hex("91113333555577779999BBBBDDDDFFFF");
109 let positive = I128::from_be_hex("6EEECCCCAAAA88886666444422220001");
110 assert_eq!(negative.checked_neg().unwrap(), positive);
111 assert_eq!(positive.checked_neg().unwrap(), negative);
112 assert_eq!(
113 positive.checked_neg().unwrap().checked_neg().unwrap(),
114 positive
115 );
116 }
117}