qfall_math/rational/q/arithmetic/
div.rs1use super::super::Q;
12use crate::{
13 error::MathError,
14 integer::Z,
15 macros::arithmetics::{
16 arithmetic_assign_between_types, arithmetic_assign_trait_borrowed_to_owned,
17 arithmetic_between_types, arithmetic_trait_borrowed_to_owned,
18 arithmetic_trait_mixed_borrowed_owned,
19 },
20};
21use flint_sys::fmpq::{fmpq_div, fmpq_div_fmpz, fmpq_is_zero};
22use std::ops::{Div, DivAssign};
23
24impl DivAssign<&Q> for Q {
25 fn div_assign(&mut self, other: &Self) {
50 assert!(!other.is_zero(), "Tried to divide {self} by zero.");
51
52 unsafe { fmpq_div(&mut self.value, &self.value, &other.value) };
53 }
54}
55impl DivAssign<&Z> for Q {
56 fn div_assign(&mut self, other: &Z) {
58 assert!(!other.is_zero(), "Tried to divide {self} by zero.");
59
60 unsafe { fmpq_div_fmpz(&mut self.value, &self.value, &other.value) };
61 }
62}
63impl DivAssign<i64> for Q {
64 fn div_assign(&mut self, other: i64) {
66 assert!(other != 0, "Tried to divide {self} by zero.");
67
68 let other = Z::from(other);
69 unsafe { fmpq_div_fmpz(&mut self.value, &self.value, &other.value) };
70 }
71}
72impl DivAssign<u64> for Q {
73 fn div_assign(&mut self, other: u64) {
75 assert!(other != 0, "Tried to divide {self} by zero.");
76
77 let other = Z::from(other);
78 unsafe { fmpq_div_fmpz(&mut self.value, &self.value, &other.value) };
79 }
80}
81impl DivAssign<f64> for Q {
82 fn div_assign(&mut self, other: f64) {
84 assert!(other != 0.0, "Tried to divide {self} by zero.");
85 let other = Q::from(other);
86
87 unsafe { fmpq_div(&mut self.value, &self.value, &other.value) };
88 }
89}
90
91arithmetic_assign_trait_borrowed_to_owned!(DivAssign, div_assign, Q, Q);
92arithmetic_assign_trait_borrowed_to_owned!(DivAssign, div_assign, Q, Z);
93arithmetic_assign_between_types!(DivAssign, div_assign, Q, i64, i32 i16 i8);
94arithmetic_assign_between_types!(DivAssign, div_assign, Q, u64, u32 u16 u8);
95arithmetic_assign_between_types!(DivAssign, div_assign, Q, f64, f32);
96
97impl Div for &Q {
98 type Output = Q;
99 fn div(self, other: Self) -> Self::Output {
124 self.div_safe(other).unwrap()
125 }
126}
127
128arithmetic_trait_borrowed_to_owned!(Div, div, Q, Q, Q);
129arithmetic_trait_mixed_borrowed_owned!(Div, div, Q, Q, Q);
130arithmetic_between_types!(Div, div, Q, Q, i64 i32 i16 i8 u64 u32 u16 u8 f32 f64);
131
132impl Div<&Z> for &Q {
133 type Output = Q;
134
135 fn div(self, other: &Z) -> Self::Output {
158 assert!(!other.is_zero(), "Tried to divide {self} by zero.");
159
160 let mut out = Q::default();
161 unsafe {
162 fmpq_div_fmpz(&mut out.value, &self.value, &other.value);
163 }
164 out
165 }
166}
167
168arithmetic_trait_borrowed_to_owned!(Div, div, Q, Z, Q);
169arithmetic_trait_mixed_borrowed_owned!(Div, div, Q, Z, Q);
170
171impl Q {
172 pub fn div_safe(&self, divisor: &Q) -> Result<Q, MathError> {
194 if 0 != unsafe { fmpq_is_zero(&divisor.value) } {
195 return Err(MathError::DivisionByZeroError(format!(
196 "tried to divide Q with value {self} by Q with value {divisor}"
197 )));
198 }
199 let mut out = Q::default();
200 unsafe {
201 fmpq_div(&mut out.value, &self.value, &divisor.value);
202 }
203 Ok(out)
204 }
205}
206
207#[cfg(test)]
208mod test_div_assign {
209 use crate::{integer::Z, rational::Q};
210
211 #[test]
213 fn correct_small() {
214 let mut a = Q::from(2);
215 let b = Q::from((42, 2));
216
217 a /= b;
218
219 assert_eq!(a, Q::from((4, 42)));
220 }
221
222 #[test]
224 fn correct_large() {
225 let mut a = Q::from(u64::MAX - 1);
226 let b = Q::from(2);
227 let mut c = Q::from((1, i32::MAX));
228 let d = Q::from((1, u32::MAX));
229
230 a /= &b;
231 c /= d;
232
233 assert_eq!(a, Q::from(i64::MAX));
234 assert_eq!(c, Q::from((u32::MAX, (u32::MAX - 1) / 2)));
235 }
236
237 #[test]
239 fn availability() {
240 let mut a = Q::from((1, 2));
241 let b = Q::from((4, 5));
242 let c = Z::ONE;
243
244 a /= &b;
245 a /= b;
246 a /= &c;
247 a /= c;
248 a /= 0.5_f64;
249 a /= 0.5_f32;
250 a /= 1_u8;
251 a /= 1_u16;
252 a /= 1_u32;
253 a /= 1_u64;
254 a /= 1_i8;
255 a /= 1_i16;
256 a /= 1_i32;
257 a /= 1_i64;
258 }
259
260 #[test]
262 #[should_panic]
263 fn div_by_zero() {
264 let mut a = Q::from((2, 3));
265 let b = 0;
266
267 a /= b;
268 }
269}
270
271#[cfg(test)]
272mod test_div {
273 use super::Q;
274
275 #[test]
277 fn div() {
278 let a: Q = Q::from(2);
279 let b: Q = Q::from((42, 2));
280 let c: Q = a / b;
281 assert_eq!(c, Q::from((4, 42)));
282 }
283
284 #[test]
286 fn div_borrow() {
287 let a: Q = Q::from(2);
288 let b: Q = Q::from((42, 2));
289 let c: Q = &a / &b;
290 assert_eq!(c, Q::from((4, 42)));
291 }
292
293 #[test]
295 fn div_first_borrowed() {
296 let a: Q = Q::from(4);
297 let b: Q = Q::from((42, 10));
298 let c: Q = &a / b;
299 assert_eq!(c, Q::from((40, 42)));
300 }
301
302 #[test]
304 fn div_second_borrowed() {
305 let a: Q = Q::from(2);
306 let b: Q = Q::from((42, 2));
307 let c: Q = a / &b;
308 assert_eq!(c, Q::from((4, 42)));
309 }
310
311 #[test]
313 fn div_large() {
314 let a: Q = Q::from(u64::MAX - 1);
315 let b: Q = Q::from(2);
316 let c: Q = Q::from((1, i32::MAX));
317 let d: Q = Q::from((1, u32::MAX));
318
319 let e: Q = &a / &b;
320 let f: Q = c / d;
321
322 assert_eq!(e, Q::from(i64::MAX));
323 assert_eq!(f, Q::from((u32::MAX, (u32::MAX - 1) / 2)));
324 }
325
326 #[test]
328 #[should_panic]
329 fn div_by_zero() {
330 let a: Q = Q::from(2);
331 let b: Q = Q::ZERO;
332 let _c = a / b;
333 }
334
335 #[test]
337 fn div_by_zero_safe() {
338 let a: Q = Q::from(2);
339 let b: Q = Q::ZERO;
340 assert!(&a.div_safe(&b).is_err());
341 }
342}
343
344#[cfg(test)]
345mod test_div_between_q_and_z {
346 use crate::integer::Z;
347 use crate::rational::Q;
348
349 #[test]
351 fn div() {
352 let a: Q = Q::from((5, 7));
353 let b: Z = Z::from(4);
354 let c: Q = a / b;
355 assert_eq!(c, Q::from((5, 28)));
356 }
357
358 #[test]
360 fn div_borrow() {
361 let a: Q = Q::from((5, 7));
362 let b: Z = Z::from(4);
363 let c: Q = &a / &b;
364 assert_eq!(c, Q::from((5, 28)));
365 }
366
367 #[test]
369 fn div_first_borrowed() {
370 let a: Q = Q::from((5, 7));
371 let b: Z = Z::from(4);
372 let c: Q = &a / b;
373 assert_eq!(c, Q::from((5, 28)));
374 }
375
376 #[test]
378 fn div_second_borrowed() {
379 let a: Q = Q::from((5, 7));
380 let b: Z = Z::from(4);
381 let c: Q = a / &b;
382 assert_eq!(c, Q::from((5, 28)));
383 }
384
385 #[test]
387 fn div_large_numbers() {
388 let a: Q = Q::from((u64::MAX, 2));
389 let b: Q = Q::from((1, u64::MAX));
390 let c: Z = Z::from(u64::MAX);
391
392 let d: Q = a / &c;
393 let e: Q = b / c;
394
395 assert_eq!(d, Q::from((u64::MAX, 2)) / Q::from(u64::MAX));
396 assert_eq!(e, Q::from((1, u64::MAX)) / Q::from(u64::MAX));
397 }
398
399 #[test]
401 #[should_panic]
402 fn div_by_zero() {
403 let a: Q = Q::from((2, 3));
404 let b: Z = Z::ZERO;
405 let _c = a / b;
406 }
407}
408
409#[cfg(test)]
410mod test_div_between_types {
411 use crate::rational::Q;
412
413 #[test]
415 #[allow(clippy::op_ref)]
416 fn div() {
417 let a: Q = Q::from(42);
418 let b: u64 = 1;
419 let c: u32 = 1;
420 let d: u16 = 1;
421 let e: u8 = 1;
422 let f: i64 = 1;
423 let g: i32 = 1;
424 let h: i16 = 1;
425 let i: i8 = 1;
426 let j: f32 = 0.3;
427 let k: f64 = 0.3;
428
429 let _: Q = &a / &b;
430 let _: Q = &a / &c;
431 let _: Q = &a / &d;
432 let _: Q = &a / &e;
433 let _: Q = &a / &f;
434 let _: Q = &a / &g;
435 let _: Q = &a / &h;
436 let _: Q = &a / &i;
437 let _: Q = &a / &j;
438 let _: Q = &a / &k;
439
440 let _: Q = &b / &a;
441 let _: Q = &c / &a;
442 let _: Q = &d / &a;
443 let _: Q = &e / &a;
444 let _: Q = &f / &a;
445 let _: Q = &g / &a;
446 let _: Q = &h / &a;
447 let _: Q = &i / &a;
448 let _: Q = &j / &a;
449 let _: Q = &k / &a;
450
451 let _: Q = &a / b;
452 let _: Q = &a / c;
453 let _: Q = &a / d;
454 let _: Q = &a / e;
455 let _: Q = &a / f;
456 let _: Q = &a / g;
457 let _: Q = &a / h;
458 let _: Q = &a / i;
459 let _: Q = &a / j;
460 let _: Q = &a / k;
461
462 let _: Q = &b / Q::from(42);
463 let _: Q = &c / Q::from(42);
464 let _: Q = &d / Q::from(42);
465 let _: Q = &e / Q::from(42);
466 let _: Q = &f / Q::from(42);
467 let _: Q = &g / Q::from(42);
468 let _: Q = &h / Q::from(42);
469 let _: Q = &i / Q::from(42);
470 let _: Q = &j / Q::from(42);
471 let _: Q = &k / Q::from(42);
472
473 let _: Q = Q::from(42) / &b;
474 let _: Q = Q::from(42) / &c;
475 let _: Q = Q::from(42) / &d;
476 let _: Q = Q::from(42) / &e;
477 let _: Q = Q::from(42) / &f;
478 let _: Q = Q::from(42) / &g;
479 let _: Q = Q::from(42) / &h;
480 let _: Q = Q::from(42) / &i;
481 let _: Q = Q::from(42) / &j;
482 let _: Q = Q::from(42) / &k;
483
484 let _: Q = b / &a;
485 let _: Q = c / &a;
486 let _: Q = d / &a;
487 let _: Q = e / &a;
488 let _: Q = f / &a;
489 let _: Q = g / &a;
490 let _: Q = h / &a;
491 let _: Q = i / &a;
492 let _: Q = j / &a;
493 let _: Q = k / &a;
494
495 let _: Q = Q::from(42) / b;
496 let _: Q = Q::from(42) / c;
497 let _: Q = Q::from(42) / d;
498 let _: Q = Q::from(42) / e;
499 let _: Q = Q::from(42) / f;
500 let _: Q = Q::from(42) / g;
501 let _: Q = Q::from(42) / h;
502 let _: Q = Q::from(42) / i;
503 let _: Q = Q::from(42) / j;
504 let _: Q = Q::from(42) / k;
505
506 let _: Q = b / Q::from(42);
507 let _: Q = c / Q::from(42);
508 let _: Q = d / Q::from(42);
509 let _: Q = e / Q::from(42);
510 let _: Q = f / Q::from(42);
511 let _: Q = g / Q::from(42);
512 let _: Q = h / Q::from(42);
513 let _: Q = i / Q::from(42);
514 let _: Q = j / Q::from(42);
515 let _: Q = k / Q::from(42);
516 }
517
518 #[test]
520 #[should_panic]
521 fn div_by_zero_u64() {
522 let a: Q = Q::from(23);
523 let b: u64 = 0;
524 let _c = a / b;
525 }
526
527 #[test]
529 #[should_panic]
530 fn div_by_zero_u32() {
531 let a: Q = Q::from(23);
532 let b: u32 = 0;
533 let _c = a / b;
534 }
535
536 #[test]
538 #[should_panic]
539 fn div_by_zero_u16() {
540 let a: Q = Q::from(23);
541 let b: u16 = 0;
542 let _c = a / b;
543 }
544
545 #[test]
547 #[should_panic]
548 fn div_by_zero_u8() {
549 let a: Q = Q::from(23);
550 let b: u8 = 0;
551 let _c = a / b;
552 }
553
554 #[test]
556 #[should_panic]
557 fn div_by_zero_i64() {
558 let a: Q = Q::from(23);
559 let b: i64 = 0;
560 let _c = a / b;
561 }
562
563 #[test]
565 #[should_panic]
566 fn div_by_zero_i32() {
567 let a: Q = Q::from(23);
568 let b: i32 = 0;
569 let _c = a / b;
570 }
571
572 #[test]
574 #[should_panic]
575 fn div_by_zero_i16() {
576 let a: Q = Q::from(23);
577 let b: i16 = 0;
578 let _c = a / b;
579 }
580
581 #[test]
583 #[should_panic]
584 fn div_by_zero_i8() {
585 let a: Q = Q::from(23);
586 let b: i8 = 0;
587 let _c = a / b;
588 }
589
590 #[test]
592 #[should_panic]
593 fn div_by_zero_f32() {
594 let a: Q = Q::from(23);
595 let b: f32 = 0.0;
596 let _c = a / b;
597 }
598
599 #[test]
601 #[should_panic]
602 fn div_by_zero_f64() {
603 let a: Q = Q::from(23);
604 let b: f64 = 0.0;
605 let _c = a / b;
606 }
607
608 #[test]
610 fn div_correct_i32() {
611 let a: i32 = 1;
612 let b: Q = Q::from(23);
613
614 let c = a / &b;
615 let d = &b / a;
616
617 assert_eq!(c, Q::from((1, 23)));
618 assert_eq!(d, Q::from(23));
619 }
620}