qfall_math/rational/q/arithmetic/
add.rs1use super::super::Q;
12use crate::{
13 integer::Z,
14 macros::arithmetics::{
15 arithmetic_assign_between_types, arithmetic_assign_trait_borrowed_to_owned,
16 arithmetic_between_types, arithmetic_trait_borrowed_to_owned,
17 arithmetic_trait_mixed_borrowed_owned,
18 },
19};
20use flint_sys::fmpq::{fmpq_add, fmpq_add_fmpz, fmpq_add_si, fmpq_add_ui};
21use std::ops::{Add, AddAssign};
22
23impl AddAssign<&Q> for Q {
24 fn add_assign(&mut self, other: &Self) {
49 unsafe { fmpq_add(&mut self.value, &self.value, &other.value) };
50 }
51}
52impl AddAssign<&Z> for Q {
53 fn add_assign(&mut self, other: &Z) {
55 unsafe { fmpq_add_fmpz(&mut self.value, &self.value, &other.value) };
56 }
57}
58impl AddAssign<i64> for Q {
59 fn add_assign(&mut self, other: i64) {
61 unsafe { fmpq_add_si(&mut self.value, &self.value, other) };
62 }
63}
64impl AddAssign<u64> for Q {
65 fn add_assign(&mut self, other: u64) {
67 unsafe { fmpq_add_ui(&mut self.value, &self.value, other) };
68 }
69}
70impl AddAssign<f64> for Q {
71 fn add_assign(&mut self, other: f64) {
73 let other = Q::from(other);
74
75 unsafe { fmpq_add(&mut self.value, &self.value, &other.value) };
76 }
77}
78
79arithmetic_assign_trait_borrowed_to_owned!(AddAssign, add_assign, Q, Q);
80arithmetic_assign_trait_borrowed_to_owned!(AddAssign, add_assign, Q, Z);
81arithmetic_assign_between_types!(AddAssign, add_assign, Q, i64, i32 i16 i8);
82arithmetic_assign_between_types!(AddAssign, add_assign, Q, u64, u32 u16 u8);
83arithmetic_assign_between_types!(AddAssign, add_assign, Q, f64, f32);
84
85impl Add for &Q {
86 type Output = Q;
87
88 fn add(self, other: Self) -> Self::Output {
110 let mut out = Q::default();
111 unsafe {
112 fmpq_add(&mut out.value, &self.value, &other.value);
113 }
114 out
115 }
116}
117
118arithmetic_trait_borrowed_to_owned!(Add, add, Q, Q, Q);
119arithmetic_trait_mixed_borrowed_owned!(Add, add, Q, Q, Q);
120arithmetic_between_types!(Add, add, Q, Q, i64 i32 i16 i8 u64 u32 u16 u8 f32 f64);
121
122impl Add<&Z> for &Q {
123 type Output = Q;
124
125 fn add(self, other: &Z) -> Self::Output {
148 let mut out = Q::default();
149 unsafe {
150 fmpq_add_fmpz(&mut out.value, &self.value, &other.value);
151 }
152 out
153 }
154}
155
156arithmetic_trait_borrowed_to_owned!(Add, add, Q, Z, Q);
157arithmetic_trait_mixed_borrowed_owned!(Add, add, Q, Z, Q);
158
159#[cfg(test)]
160mod test_add_assign {
161 use crate::{integer::Z, rational::Q};
162
163 #[test]
165 fn correct_small() {
166 let mut a = Q::MINUS_ONE;
167 let b = Q::MINUS_ONE;
168 let c = Q::ONE;
169 let d = Q::from((1, 2));
170
171 a += &b;
172 assert_eq!(-2, a);
173 a += &c;
174 assert_eq!(-1, a);
175 a += &c;
176 assert_eq!(0, a);
177 a += &c;
178 assert_eq!(1, a);
179 a += &c;
180 assert_eq!(2, a);
181 a += 2 * b;
182 assert_eq!(0, a);
183 a += d;
184 assert_eq!(Q::from((1, 2)), a);
185 }
186
187 #[test]
189 fn correct_large() {
190 let mut a = Q::from(i64::MAX);
191 let b = Q::from(i64::MIN);
192 let c = Q::from(u64::MAX);
193
194 a += b;
195 assert_eq!(-1, a);
196 a += c;
197 assert_eq!(u64::MAX - 1, a);
198 }
199
200 #[test]
202 fn availability() {
203 let mut a = Q::from((1, 2));
204 let b = Q::from((4, 5));
205 let c = Z::ONE;
206
207 a += &b;
208 a += b;
209 a += &c;
210 a += c;
211 a += 0.5_f64;
212 a += 0.5_f32;
213 a += 1_u8;
214 a += 1_u16;
215 a += 1_u32;
216 a += 1_u64;
217 a += 1_i8;
218 a += 1_i16;
219 a += 1_i32;
220 a += 1_i64;
221 }
222}
223
224#[cfg(test)]
225mod test_add {
226 use super::Q;
227 use std::str::FromStr;
228
229 #[test]
231 fn add() {
232 let a: Q = Q::from(42);
233 let b: Q = Q::from((42, 2));
234 let c: Q = a + b;
235 assert_eq!(c, Q::from(63));
236 }
237
238 #[test]
240 fn add_borrow() {
241 let a: Q = Q::from(42);
242 let b: Q = Q::from((42, 2));
243 let c: Q = &a + &b;
244 assert_eq!(c, Q::from(63));
245 }
246
247 #[test]
249 fn add_first_borrowed() {
250 let a: Q = Q::from((42, 5));
251 let b: Q = Q::from((42, 10));
252 let c: Q = &a + b;
253 assert_eq!(c, Q::from((63, 5)));
254 }
255
256 #[test]
258 fn add_second_borrowed() {
259 let a: Q = Q::from(42);
260 let b: Q = Q::from((42, 2));
261 let c: Q = a + &b;
262 assert_eq!(c, Q::from(63));
263 }
264
265 #[test]
267 fn add_large() {
268 let a: Q = Q::from(i64::MAX);
269 let b: Q = Q::from(u64::MAX - 1);
270 let c: Q = Q::from((1, i32::MAX));
271 let d: Q = Q::from((1, u32::MAX));
272 let e: Q = &a + &a;
273 let f: Q = c + d;
274 assert_eq!(e, b);
275 assert_eq!(
276 f,
277 Q::from_str(&format!(
278 "{}/{}",
279 u64::from(u32::MAX) + u64::from((u32::MAX - 1) / 2),
280 u64::from(u32::MAX) * u64::from((u32::MAX - 1) / 2)
281 ))
282 .unwrap()
283 );
284 }
285}
286
287#[cfg(test)]
288mod test_add_between_q_and_z {
289 use crate::integer::Z;
290 use crate::rational::Q;
291
292 #[test]
294 fn add() {
295 let a: Q = Q::from((5, 7));
296 let b: Z = Z::from(4);
297 let c: Q = a + b;
298 assert_eq!(c, Q::from((33, 7)));
299 }
300
301 #[test]
303 fn add_borrow() {
304 let a: Q = Q::from((5, 7));
305 let b: Z = Z::from(4);
306 let c: Q = &a + &b;
307 assert_eq!(c, Q::from((33, 7)));
308 }
309
310 #[test]
312 fn add_first_borrowed() {
313 let a: Q = Q::from((5, 7));
314 let b: Z = Z::from(4);
315 let c: Q = &a + b;
316 assert_eq!(c, Q::from((33, 7)));
317 }
318
319 #[test]
321 fn add_second_borrowed() {
322 let a: Q = Q::from((5, 7));
323 let b: Z = Z::from(4);
324 let c: Q = a + &b;
325 assert_eq!(c, Q::from((33, 7)));
326 }
327
328 #[test]
330 fn add_large_numbers() {
331 let a: Q = Q::from((u64::MAX, 2));
332 let b: Q = Q::from((1, u64::MAX));
333 let c: Z = Z::from(u64::MAX);
334 let d: Q = a + &c;
335 let e: Q = b + c;
336 assert_eq!(d, Q::from(u64::MAX) + Q::from((u64::MAX, 2)));
337 assert_eq!(e, Q::from((1, u64::MAX)) + Q::from(u64::MAX));
338 }
339}
340
341#[cfg(test)]
342mod test_add_between_types {
343
344 use crate::rational::Q;
345
346 #[test]
348 #[allow(clippy::op_ref)]
349 fn add() {
350 let a: Q = Q::from(42);
351 let b: u64 = 1;
352 let c: u32 = 1;
353 let d: u16 = 1;
354 let e: u8 = 1;
355 let f: i64 = 1;
356 let g: i32 = 1;
357 let h: i16 = 1;
358 let i: i8 = 1;
359 let j: f32 = 0.3;
360 let k: f64 = 0.3;
361 let _: Q = &a + &b;
362 let _: Q = &a + &c;
363 let _: Q = &a + &d;
364 let _: Q = &a + &e;
365 let _: Q = &a + &f;
366 let _: Q = &a + &g;
367 let _: Q = &a + &h;
368 let _: Q = &a + &i;
369 let _: Q = &a + &j;
370 let _: Q = &a + &k;
371
372 let _: Q = &b + &a;
373 let _: Q = &c + &a;
374 let _: Q = &d + &a;
375 let _: Q = &e + &a;
376 let _: Q = &f + &a;
377 let _: Q = &g + &a;
378 let _: Q = &h + &a;
379 let _: Q = &i + &a;
380 let _: Q = &j + &a;
381 let _: Q = &k + &a;
382
383 let _: Q = &a + b;
384 let _: Q = &a + c;
385 let _: Q = &a + d;
386 let _: Q = &a + e;
387 let _: Q = &a + f;
388 let _: Q = &a + g;
389 let _: Q = &a + h;
390 let _: Q = &a + i;
391 let _: Q = &a + j;
392 let _: Q = &a + k;
393
394 let _: Q = &b + Q::from(42);
395 let _: Q = &c + Q::from(42);
396 let _: Q = &d + Q::from(42);
397 let _: Q = &e + Q::from(42);
398 let _: Q = &f + Q::from(42);
399 let _: Q = &g + Q::from(42);
400 let _: Q = &h + Q::from(42);
401 let _: Q = &i + Q::from(42);
402 let _: Q = &j + Q::from(42);
403 let _: Q = &k + Q::from(42);
404
405 let _: Q = Q::from(42) + &b;
406 let _: Q = Q::from(42) + &c;
407 let _: Q = Q::from(42) + &d;
408 let _: Q = Q::from(42) + &e;
409 let _: Q = Q::from(42) + &f;
410 let _: Q = Q::from(42) + &g;
411 let _: Q = Q::from(42) + &h;
412 let _: Q = Q::from(42) + &i;
413 let _: Q = Q::from(42) + &j;
414 let _: Q = Q::from(42) + &k;
415
416 let _: Q = b + &a;
417 let _: Q = c + &a;
418 let _: Q = d + &a;
419 let _: Q = e + &a;
420 let _: Q = f + &a;
421 let _: Q = g + &a;
422 let _: Q = h + &a;
423 let _: Q = i + &a;
424 let _: Q = j + &a;
425 let _: Q = k + &a;
426
427 let _: Q = Q::from(42) + b;
428 let _: Q = Q::from(42) + c;
429 let _: Q = Q::from(42) + d;
430 let _: Q = Q::from(42) + e;
431 let _: Q = Q::from(42) + f;
432 let _: Q = Q::from(42) + g;
433 let _: Q = Q::from(42) + h;
434 let _: Q = Q::from(42) + i;
435 let _: Q = Q::from(42) + j;
436 let _: Q = Q::from(42) + k;
437
438 let _: Q = b + Q::from(42);
439 let _: Q = c + Q::from(42);
440 let _: Q = d + Q::from(42);
441 let _: Q = e + Q::from(42);
442 let _: Q = f + Q::from(42);
443 let _: Q = g + Q::from(42);
444 let _: Q = h + Q::from(42);
445 let _: Q = i + Q::from(42);
446 let _: Q = j + Q::from(42);
447 let _: Q = k + Q::from(42);
448 }
449}