crypto_bigint/limb/
sub.rs1use crate::{
4 Checked, CheckedSub, CtOption, Limb, Sub, SubAssign, SubMod, Wrapping, WrappingSub,
5 primitives::borrowing_sub,
6};
7
8impl Limb {
9 #[deprecated(since = "0.7.0", note = "please use `borrowing_sub` instead")]
11 #[must_use]
12 pub const fn sbb(self, rhs: Limb, borrow: Limb) -> (Limb, Limb) {
13 self.borrowing_sub(rhs, borrow)
14 }
15
16 #[inline(always)]
18 #[must_use]
19 pub const fn borrowing_sub(self, rhs: Limb, borrow: Limb) -> (Limb, Limb) {
20 let (res, borrow) = borrowing_sub(self.0, rhs.0, borrow.0);
21 (Limb(res), Limb(borrow))
22 }
23
24 #[inline]
26 #[must_use]
27 pub const fn saturating_sub(&self, rhs: Self) -> Self {
28 Limb(self.0.saturating_sub(rhs.0))
29 }
30
31 #[inline(always)]
34 #[must_use]
35 pub const fn wrapping_sub(&self, rhs: Self) -> Self {
36 Limb(self.0.wrapping_sub(rhs.0))
37 }
38}
39
40impl CheckedSub for Limb {
41 #[inline]
42 fn checked_sub(&self, rhs: &Self) -> CtOption<Self> {
43 let (result, underflow) = self.borrowing_sub(*rhs, Limb::ZERO);
44 CtOption::new(result, underflow.is_zero())
45 }
46}
47
48impl Sub for Limb {
49 type Output = Self;
50
51 #[inline]
52 fn sub(self, rhs: Self) -> Self {
53 self.checked_sub(&rhs)
54 .expect("attempted to subtract with underflow")
55 }
56}
57
58impl Sub<&Self> for Limb {
59 type Output = Self;
60
61 #[inline]
62 fn sub(self, rhs: &Self) -> Self {
63 self - *rhs
64 }
65}
66
67impl SubAssign for Limb {
68 #[inline]
69 fn sub_assign(&mut self, rhs: Self) {
70 *self = *self - rhs;
71 }
72}
73
74impl SubAssign<&Self> for Limb {
75 #[inline]
76 fn sub_assign(&mut self, rhs: &Self) {
77 *self = *self - *rhs;
78 }
79}
80
81impl SubAssign for Wrapping<Limb> {
82 #[inline]
83 fn sub_assign(&mut self, other: Self) {
84 *self = *self - other;
85 }
86}
87
88impl SubAssign<&Wrapping<Limb>> for Wrapping<Limb> {
89 #[inline]
90 fn sub_assign(&mut self, other: &Self) {
91 *self = *self - other;
92 }
93}
94
95impl SubAssign for Checked<Limb> {
96 #[inline]
97 fn sub_assign(&mut self, other: Self) {
98 *self = *self - other;
99 }
100}
101
102impl SubAssign<&Checked<Limb>> for Checked<Limb> {
103 #[inline]
104 fn sub_assign(&mut self, other: &Self) {
105 *self = *self - other;
106 }
107}
108
109impl WrappingSub for Limb {
110 #[inline]
111 fn wrapping_sub(&self, v: &Self) -> Self {
112 self.wrapping_sub(*v)
113 }
114}
115
116impl SubMod for Limb {
117 type Output = Self;
118
119 fn sub_mod(&self, rhs: &Self, p: &crate::NonZero<Self>) -> Self::Output {
120 let (res, borrow) = self.borrowing_sub(*rhs, Limb::ZERO);
121 Self::select(res, res.wrapping_add(p.get()), borrow.is_nonzero())
122 }
123}
124
125#[cfg(test)]
126mod tests {
127 use crate::{CheckedSub, Limb};
128
129 #[test]
130 fn borrowing_sub_no_borrow() {
131 let (res, borrow) = Limb::ONE.borrowing_sub(Limb::ONE, Limb::ZERO);
132 assert_eq!(res, Limb::ZERO);
133 assert_eq!(borrow, Limb::ZERO);
134 }
135
136 #[test]
137 fn borrowing_sub_with_borrow() {
138 let (res, borrow) = Limb::ZERO.borrowing_sub(Limb::ONE, Limb::ZERO);
139
140 assert_eq!(res, Limb::MAX);
141 assert_eq!(borrow, Limb::MAX);
142 }
143
144 #[test]
145 fn wrapping_sub_no_borrow() {
146 assert_eq!(Limb::ONE.wrapping_sub(Limb::ONE), Limb::ZERO);
147 }
148
149 #[test]
150 fn wrapping_sub_with_borrow() {
151 assert_eq!(Limb::ZERO.wrapping_sub(Limb::ONE), Limb::MAX);
152 }
153
154 #[test]
155 fn checked_sub_ok() {
156 let result = Limb::ONE.checked_sub(&Limb::ONE);
157 assert_eq!(result.unwrap(), Limb::ZERO);
158 }
159
160 #[test]
161 fn checked_sub_overflow() {
162 let result = Limb::ZERO.checked_sub(&Limb::ONE);
163 assert!(!bool::from(result.is_some()));
164 }
165}