relp_num/rational/big/ops/
add_sub.rs1use std::ops::{Add, AddAssign, Sub, SubAssign};
2
3use crate::{Negateable, NonZero, Sign};
4use crate::rational::big::Big;
5use crate::rational::big::ops::building_blocks::{add_assign_fraction_non_zero, SignChange, sub_assign_fraction_non_zero};
6
7impl<const S: usize> Big<S> {
8 unsafe fn sub_assign_update_sign(&mut self, rhs: &Self) {
14 unsafe {
17 debug_assert!(self.numerator.is_well_formed());
18 debug_assert!(self.denominator.is_well_formed());
19 debug_assert!(rhs.numerator.is_well_formed());
20 debug_assert!(rhs.denominator.is_well_formed());
21 }
22 debug_assert!(self.numerator.is_not_zero());
23 debug_assert!(self.denominator.is_not_zero());
24 debug_assert!(rhs.numerator.is_not_zero());
25 debug_assert!(rhs.denominator.is_not_zero());
26
27 let sign_change = unsafe {
33 sub_assign_fraction_non_zero(
34 self.numerator.inner_mut(),
35 self.denominator.inner_mut(),
36 &rhs.numerator,
37 &rhs.denominator,
38 )
39 };
40 match sign_change {
41 SignChange::None => {}
42 SignChange::Flip => self.sign.negate(),
43 SignChange::Zero => self.sign = Sign::Zero,
44 }
45 }
46}
47
48impl<const S: usize> Add for Big<S> {
49 type Output = Self;
50
51 #[inline]
52 fn add(mut self, rhs: Big<S>) -> Self::Output {
53 match (self.sign, rhs.sign) {
54 (Sign::Positive, Sign::Positive) | (Sign::Negative, Sign::Negative) => {
55 unsafe {
57 add_assign_fraction_non_zero(
59 self.numerator.inner_mut(),
60 self.denominator.inner_mut(),
61 &rhs.numerator,
62 &rhs.denominator,
63 )
64 }
65 self
66 },
67 (Sign::Positive, Sign::Negative) | (Sign::Negative, Sign::Positive) => {
68 unsafe {
70 self.sub_assign_update_sign(&rhs);
72 }
73 self
74 },
75 (_, Sign::Zero) => self,
76 (Sign::Zero, _) => rhs,
77 }
78 }
79}
80
81impl<const S: usize> Add<Big<S>> for &Big<S> {
82 type Output = Big<S>;
83
84 #[inline]
85 fn add(self, rhs: Big<S>) -> Self::Output {
86 Add::add(rhs, self)
87 }
88}
89
90impl<const S: usize> Add<&Big<S>> for Big<S> {
91 type Output = Self;
92
93 #[inline]
94 fn add(mut self, rhs: &Big<S>) -> Self::Output {
95 self += rhs;
96 self
97 }
98}
99
100impl<const S: usize> Add for &Big<S> {
101 type Output = Big<S>;
102
103 #[inline]
104 fn add(self, rhs: Self) -> Self::Output {
105 let x = self.clone();
107 x + rhs
108 }
109}
110
111impl<const S: usize> AddAssign for Big<S> {
112 #[inline]
113 fn add_assign(&mut self, rhs: Big<S>) {
114 AddAssign::add_assign(self, &rhs);
116 }
117}
118
119impl<const S: usize> AddAssign<&Big<S>> for Big<S> {
120 #[inline]
121 fn add_assign(&mut self, rhs: &Big<S>) {
122 match (self.sign, rhs.sign) {
123 (Sign::Positive, Sign::Positive) | (Sign::Negative, Sign::Negative) => {
124 unsafe {
125 add_assign_fraction_non_zero(
127 self.numerator.inner_mut(),
128 self.denominator.inner_mut(),
129 &rhs.numerator,
130 &rhs.denominator,
131 )
132 }
133 },
134 (Sign::Positive, Sign::Negative) | (Sign::Negative, Sign::Positive) => {
135 unsafe {
136 self.sub_assign_update_sign(rhs);
138 }
139 },
140 (_, Sign::Zero) => {},
141 (Sign::Zero, _) => *self = rhs.clone(),
142 }
143 }
144}
145
146impl<const S: usize> Sub for Big<S> {
147 type Output = Self;
148
149 #[inline]
150 fn sub(mut self, mut rhs: Big<S>) -> Self::Output {
151 match (self.sign, rhs.sign) {
152 (Sign::Positive, Sign::Positive) | (Sign::Negative, Sign::Negative) => {
153 unsafe {
154 self.sub_assign_update_sign(&rhs);
156 }
157 self
158 },
159 (Sign::Positive, Sign::Negative) | (Sign::Negative, Sign::Positive) => {
160 unsafe {
161 add_assign_fraction_non_zero(
163 self.numerator.inner_mut(),
164 self.denominator.inner_mut(),
165 &rhs.numerator,
166 &rhs.denominator,
167 );
168 }
169 self
170 },
171 (_, Sign::Zero) => self,
172 (Sign::Zero, _) => {
173 rhs.sign = !rhs.sign;
174 rhs
175 },
176 }
177 }
178}
179
180impl<const S: usize> Sub<&Big<S>> for Big<S> {
181 type Output = Self;
182
183 #[inline]
184 fn sub(mut self, rhs: &Big<S>) -> Self::Output {
185 SubAssign::sub_assign(&mut self, rhs);
186 self
187 }
188}
189
190impl<const S: usize> Sub<Big<S>> for &Big<S> {
191 type Output = Big<S>;
192
193 #[inline]
194 fn sub(self, rhs: Big<S>) -> Self::Output {
195 -Sub::sub(rhs, self)
196 }
197}
198
199impl<const S: usize> Sub for &Big<S> {
200 type Output = Big<S>;
201
202 #[inline]
203 fn sub(self, rhs: Self) -> Self::Output {
204 Sub::sub(self.clone(), rhs)
206 }
207}
208
209impl<const S: usize> SubAssign<Big<S>> for Big<S> {
210 #[inline]
212 fn sub_assign(&mut self, rhs: Big<S>) {
213 SubAssign::sub_assign(self, &rhs);
214 }
215}
216
217impl<const S: usize> SubAssign<&Big<S>> for Big<S> {
218 #[inline]
219 fn sub_assign(&mut self, rhs: &Big<S>) {
220 match (self.sign, rhs.sign) {
221 (Sign::Positive, Sign::Positive) | (Sign::Negative, Sign::Negative) => {
222 unsafe {
223 self.sub_assign_update_sign(rhs);
225 }
226 },
227 (Sign::Positive, Sign::Negative) | (Sign::Negative, Sign::Positive) => unsafe {
228 add_assign_fraction_non_zero(
229 self.numerator.inner_mut(),
230 self.denominator.inner_mut(),
231 &rhs.numerator,
232 &rhs.denominator,
233 );
234 },
235 (_, Sign::Zero) => {},
236 (Sign::Zero, _) => {
237 *self = Self {
238 sign: !rhs.sign,
239 numerator: rhs.numerator.clone(),
240 denominator: rhs.denominator.clone(),
241 };
242 },
243 }
244 }
245}
246
247#[cfg(test)]
248mod test {
249 use crate::RB;
250
251 #[test]
252 fn test_add() {
253 let mut x = RB!(3, 4);
254 x += RB!(-5, 6);
255 assert_eq!(x, RB!(3 * 6 - 5 * 4, 4 * 6));
256
257 let mut x = RB!(3, 4);
258 x += RB!(5, 6);
259 assert_eq!(x, RB!(3 * 6 + 5 * 4, 4 * 6));
260
261 let mut x = RB!(0);
262 x += &RB!(-5, 6);
263 assert_eq!(x, RB!(-5, 6));
264
265 let mut x = RB!(-5, 6);
266 x += RB!(0);
267 assert_eq!(x, RB!(-5, 6));
268 }
269
270 #[test]
271 fn test_sub() {
272 let mut x = RB!(3, 4);
273 x -= RB!(-5, 6);
274 assert_eq!(x, RB!(3 * 6 + 5 * 4, 4 * 6));
275
276 let mut x = RB!(3, 4);
277 x -= RB!(5, 6);
278 assert_eq!(x, RB!(3 * 6 - 5 * 4, 4 * 6));
279
280 let mut x = RB!(0);
281 x -= RB!(-5, 6);
282 assert_eq!(x, RB!(5, 6));
283
284 let mut x = RB!(-5, 6);
285 x -= &RB!(0);
286 assert_eq!(x, RB!(-5, 6));
287 }
288}