qfall_math/rational/q/
cmp.rs1use super::Q;
13use crate::{
14 integer::Z,
15 integer_mod_q::Modulus,
16 macros::for_others::{implement_for_others, implement_trait_reverse},
17};
18use flint_sys::{
19 fmpq::{fmpq_cmp, fmpq_equal},
20 fmpz::{fmpz, fmpz_equal},
21};
22use std::cmp::Ordering;
23
24impl PartialEq for Q {
25 fn eq(&self, other: &Self) -> bool {
50 unsafe { 1 == fmpq_equal(&self.value, &other.value) }
51 }
52}
53
54impl Eq for Q {}
58
59impl PartialEq<Z> for Q {
60 fn eq(&self, other: &Z) -> bool {
94 unsafe {
95 (1 == fmpz_equal(&self.value.den, &fmpz(1)))
96 && (1 == fmpz_equal(&self.value.num, &other.value))
97 }
98 }
99}
100
101implement_trait_reverse!(PartialEq, eq, Z, Q, bool);
102
103impl PartialEq<Modulus> for Q {
104 fn eq(&self, other: &Modulus) -> bool {
138 unsafe {
139 (1 == fmpz_equal(&self.value.den, &fmpz(1)))
140 && (1 == fmpz_equal(&self.value.num, &other.modulus.n[0]))
141 }
142 }
143}
144
145implement_trait_reverse!(PartialEq, eq, Modulus, Q, bool);
146
147implement_for_others!(Z, Q, PartialEq for fmpz i8 i16 i32 i64 u8 u16 u32 u64);
148
149impl PartialOrd for Q {
150 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
174 Some(self.cmp(other))
175 }
176}
177
178impl Ord for Q {
179 fn cmp(&self, other: &Self) -> Ordering {
214 unsafe { fmpq_cmp(&self.value, &other.value).cmp(&0) }
215 }
216}
217
218implement_for_others!(Q, Q, PartialOrd for Modulus Z fmpz i8 i16 i32 i64 u8 u16 u32 u64);
219
220#[cfg(test)]
222mod test_partial_eq_q {
223 use super::Q;
229 use std::str::FromStr;
230
231 #[test]
233 #[allow(clippy::op_ref)]
234 fn availability() {
235 let q = Q::ONE;
236
237 assert!(q == q);
238 assert!(&q == &q);
239 }
240
241 #[test]
244 #[allow(clippy::op_ref)]
245 fn equal_call_methods() {
246 let one_1 = Q::ONE;
247 let one_2 = Q::ONE;
248
249 assert!(one_1 == one_2);
250 assert!(&one_1 == &one_2);
251 assert!(one_1.eq(&one_2));
252 assert!(Q::eq(&one_1, &one_2));
253 assert_eq!(one_1, one_2);
254 }
255
256 #[test]
259 #[allow(clippy::op_ref)]
260 fn not_equal_call_methods() {
261 let one = Q::ONE;
262 let two = Q::from(2);
263
264 assert!(one != two);
265 assert!(&one != &two);
266 assert!(one.ne(&two));
267 assert!(Q::ne(&one, &two));
268 assert_ne!(one, two);
269 }
270
271 #[test]
273 fn equal_small() {
274 let small_1 = Q::from(10);
275 let small_2 = Q::from(10);
276
277 assert!(small_1 == small_2);
278 assert!(small_2 == small_1);
279 assert!(small_1 == small_1);
280 }
281
282 #[test]
284 fn not_equal_small() {
285 let small_1 = Q::from(10);
286 let negative = Q::MINUS_ONE;
287
288 assert!(small_1 != negative);
289 assert!(negative != small_1);
290 }
291
292 #[test]
295 fn equal_large() {
296 let max_1 = Q::from_str(&"1".repeat(65)).unwrap();
297 let max_2 = Q::from_str(&"1".repeat(65)).unwrap();
298 let large_negative_str = format!("-{:1<65}", "1");
299 let min = Q::from_str(&large_negative_str).unwrap();
300
301 assert!(max_1 == max_2);
302 assert!(max_2 == max_1);
303 assert!(max_1 == max_1);
304 assert!(min == min);
305 }
306
307 #[test]
310 fn not_equal_large() {
311 let max_1 = Q::from_str(&"1".repeat(65)).unwrap();
312 let large_negative_str = format!("-{:1<65}", "1");
313 let min = Q::from_str(&large_negative_str).unwrap();
314
315 assert!(max_1 != min);
316 assert!(min != max_1);
317 }
318
319 #[test]
322 fn not_equal_large_small() {
323 let max = Q::from_str(&"1".repeat(65)).unwrap();
324 let small_positive = Q::ONE;
325 let small_negative = Q::MINUS_ONE;
326 let large_negative_str = format!("-{:1<65}", "1");
327 let min = Q::from_str(&large_negative_str).unwrap();
328
329 assert!(max != small_negative);
330 assert!(small_negative != max);
331 assert!(max != small_positive);
332 assert!(small_positive != max);
333
334 assert!(min != small_negative);
335 assert!(small_negative != min);
336 assert!(min != small_positive);
337 assert!(small_positive != min);
338 }
339
340 #[test]
343 fn equal_large_denominator() {
344 let large_denominator_str = format!("1/{:1<200}", "1");
345 let large_denominator_less_str = format!("1/{:1<201}", "1");
346
347 let small_1 = Q::from_str(&large_denominator_str).unwrap();
348 let small_2 = Q::from_str(&large_denominator_str).unwrap();
349 let less = Q::from_str(&large_denominator_less_str).unwrap();
350
351 assert!(small_1 == small_2);
352 assert!(small_2 == small_1);
353 assert!(small_1 == small_1);
354
355 assert!(less == less);
356 }
357
358 #[test]
361 fn equal_large_numerator_denominator() {
362 let large_denominator_str = format!("{:5<200}/{:4<200}", "1", "1");
365 let large_denominator_less_str = format!("{:5<201}/{:4<201}", "1", "1");
366
367 let small_1 = Q::from_str(&large_denominator_str).unwrap();
368 let small_2 = Q::from_str(&large_denominator_str).unwrap();
369 let less = Q::from_str(&large_denominator_less_str).unwrap();
370
371 assert!(small_1 == small_2);
372 assert!(small_2 == small_1);
373 assert!(small_1 == small_1);
374
375 assert!(less == less);
376 }
377
378 #[test]
380 fn equal_rational() {
381 let a = Q::from((1, 2));
382 let b = Q::from((2, 4));
383
384 assert_eq!(a, b);
385 }
386
387 #[test]
389 fn not_equal_different_denominator() {
390 let a = Q::from((1, 2));
391 let b = Q::from((1, 4));
392
393 assert_ne!(a, b);
394 }
395
396 #[test]
398 fn zero_equal_different_denominator() {
399 let a = Q::from((0, 2));
400 let b = Q::from((0, 4));
401
402 assert_eq!(a, b);
403 }
404}
405
406#[cfg(test)]
408mod test_partial_eq_q_other {
409 use super::Q;
410 use crate::{integer::Z, integer_mod_q::Modulus};
411
412 #[test]
414 #[allow(clippy::op_ref)]
415 fn availability() {
416 let q = Q::from((2, 1));
417 let z = Z::from(2);
418 let modulus = Modulus::from(2);
419
420 assert!(q == z);
421 assert!(q == modulus);
422 assert!(q == z.value);
423 assert!(q == 2i8);
424 assert!(q == 2u8);
425 assert!(q == 2i16);
426 assert!(q == 2u16);
427 assert!(q == 2i32);
428 assert!(q == 2u32);
429 assert!(q == 2i64);
430 assert!(q == 2u64);
431
432 assert!(z == q);
433 assert!(modulus == q);
434 assert!(z.value == q);
435 assert!(2i8 == q);
436 assert!(2u8 == q);
437 assert!(2i16 == q);
438 assert!(2u16 == q);
439 assert!(2i32 == q);
440 assert!(2u32 == q);
441 assert!(2i64 == q);
442 assert!(2u64 == q);
443
444 assert!(&q == &z);
445 assert!(&z == &q);
446 assert!(&q == &modulus);
447 assert!(&modulus == &q);
448 assert!(&q == &2i8);
449 assert!(&2i8 == &q);
450 }
451
452 #[test]
454 fn equal_large() {
455 let q = Q::from((u64::MAX, 1));
456 let z = Z::from(u64::MAX);
457 let modulus1 = Modulus::from(u64::MAX);
458 let modulus2 = Modulus::from(u64::MAX - 1);
459
460 assert!(q == z);
461 assert!(q == modulus1);
462 assert!(q != z + 1);
463 assert!(q != modulus2);
464 }
465}
466
467#[cfg(test)]
469#[allow(clippy::neg_cmp_op_on_partial_ord)]
470mod test_partial_ord {
471 use super::Q;
472
473 #[test]
475 fn call_methods() {
476 let one = Q::ONE;
477 let zero = Q::ZERO;
478
479 assert!(one >= zero);
480 assert!(one > zero);
481 }
482
483 #[test]
486 fn less_small() {
487 let one_1 = Q::ONE;
488 let small_negative = Q::MINUS_ONE;
489 let one_half = Q::from((1, 2));
490
491 assert!(small_negative < one_1);
492
493 assert!(one_half < one_1);
494 assert!(small_negative < one_half);
495 }
496
497 #[test]
500 fn less_large_small() {
501 let large = Q::from((u64::MAX, 2));
502 let small_positive = Q::ONE;
503 let small_negative = Q::from((i64::MIN + 1, i64::MAX));
504 let large_negative = Q::from(i64::MIN);
505
506 assert!(small_positive < large);
508 assert!(small_negative < large);
509
510 assert!(large_negative < small_positive);
512 assert!(large_negative < small_negative);
513 }
514
515 #[test]
518 fn less_large() {
519 let max_1 = Q::from(u64::MAX);
520 let max_negative = Q::from(i64::MIN);
521
522 assert!(max_negative < max_1);
523 }
524
525 #[test]
528 fn less_equal_small() {
529 let small_positive_1 = Q::ONE;
530 let small_positive_2 = Q::ONE;
531 let small_negative = Q::MINUS_ONE;
532
533 assert!(small_positive_1 <= small_positive_2);
534 assert!(small_positive_2 <= small_positive_1);
535 assert!(small_positive_1 <= small_positive_1);
536
537 assert!(small_negative <= small_positive_1);
538 assert!(small_negative <= small_negative);
539 }
540
541 #[test]
544 fn less_equal_large_small() {
545 let max = Q::from(u64::MAX);
546 let small_positive = Q::ONE;
547 let small_negative = Q::MINUS_ONE;
548 let max_negative = Q::from(i64::MIN);
549
550 assert!(small_positive <= max);
552 assert!(small_negative <= max);
553
554 assert!(max_negative <= small_positive);
556 assert!(max_negative <= small_negative);
557 }
558
559 #[test]
562 fn less_equal_large() {
563 let max_1 = Q::from(u64::MAX);
564 let max_2 = Q::from(u64::MAX);
565 let max_negative = Q::from(i64::MIN);
566
567 assert!(max_1 <= max_2);
568 assert!(max_2 <= max_1);
569 assert!(max_1 <= max_1);
570
571 assert!(max_negative <= max_1);
572 assert!(max_negative <= max_negative);
573 }
574
575 #[test]
578 fn greater_small() {
579 let small_positive_1 = Q::ONE;
580 let small_negative = Q::MINUS_ONE;
581
582 assert!(small_positive_1 > small_negative);
583 }
584
585 #[test]
588 fn greater_large_small() {
589 let max = Q::from(u64::MAX);
590 let small_positive = Q::ONE;
591 let small_negative = Q::MINUS_ONE;
592 let max_negative = Q::from(i64::MIN);
593
594 assert!(max > small_positive);
596 assert!(max > small_negative);
597
598 assert!(small_positive > max_negative);
600 assert!(small_negative > max_negative);
601 }
602
603 #[test]
606 fn greater_large() {
607 let max_1 = Q::from(u64::MAX);
608 let max_negative = Q::from(i64::MIN);
609
610 assert!(max_1 > max_negative);
611 }
612
613 #[test]
616 fn greater_equal_small() {
617 let small_positive_1 = Q::ONE;
618 let small_positive_2 = Q::ONE;
619 let small_negative = Q::MINUS_ONE;
620
621 assert!(small_positive_1 >= small_positive_2);
622 assert!(small_positive_2 >= small_positive_1);
623 assert!(small_positive_1 >= small_positive_1);
624
625 assert!(small_positive_1 >= small_negative);
626 assert!(small_negative >= small_negative);
627 }
628
629 #[test]
632 fn greater_equal_large_small() {
633 let max = Q::from(u64::MAX);
634 let small_positive = Q::ONE;
635 let small_negative = Q::MINUS_ONE;
636 let max_negative = Q::from(i64::MIN);
637
638 assert!(max >= small_positive);
640 assert!(max >= small_negative);
641
642 assert!(small_positive >= max_negative);
644 assert!(small_negative >= max_negative);
645 }
646
647 #[test]
650 fn greater_equal_large() {
651 let max_1 = Q::from(u64::MAX);
652 let max_2 = Q::from(u64::MAX);
653 let max_negative = Q::from(i64::MIN);
654
655 assert!(max_1 >= max_2);
656 assert!(max_2 >= max_1);
657 assert!(max_1 >= max_1);
658
659 assert!(max_1 >= max_negative);
660 assert!(max_negative >= max_negative);
661 }
662
663 #[test]
665 fn close_to_zero() {
666 let small = Q::from((1, u64::MAX));
667 let zero = Q::ZERO;
668
669 assert!(small > zero);
670 assert!(small >= zero);
671 }
672}
673
674#[cfg(test)]
676mod test_partial_ord_q_other {
677 use super::Q;
678 use crate::{integer::Z, integer_mod_q::Modulus};
679
680 #[test]
682 #[allow(clippy::op_ref)]
683 fn availability() {
684 let q = Q::from((2, 1));
685 let z = Z::from(2);
686 let modulus = Modulus::from(2);
687
688 assert!(q <= z);
689 assert!(q <= modulus);
690 assert!(q <= z.value);
691 assert!(q <= 2i8);
692 assert!(q <= 2u8);
693 assert!(q <= 2i16);
694 assert!(q <= 2u16);
695 assert!(q <= 2i32);
696 assert!(q <= 2u32);
697 assert!(q <= 2i64);
698 assert!(q <= 2u64);
699
700 assert!(z >= q);
701 assert!(modulus >= q);
702 assert!(z.value >= q);
703 assert!(2i8 >= q);
704 assert!(2u8 >= q);
705 assert!(2i16 >= q);
706 assert!(2u16 >= q);
707 assert!(2i32 >= q);
708 assert!(2u32 >= q);
709 assert!(2i64 >= q);
710 assert!(2u64 >= q);
711
712 assert!(&q <= &z);
713 assert!(&z >= &q);
714 assert!(&q <= &modulus);
715 assert!(&modulus >= &q);
716 assert!(&q <= &2i8);
717 assert!(&2i8 >= &q);
718 }
719}
720
721#[cfg(test)]
722mod test_ord {
723 use super::Q;
724 use std::cmp::{max, min};
725
726 #[test]
731 fn default_implementations_small() {
732 let a: Q = Q::from((10, 3));
733 let b: Q = Q::from((42, 4));
734
735 assert_eq!(b, max(a.clone(), b.clone()));
736 assert_eq!(a, min(a.clone(), b.clone()));
737
738 assert_eq!(a, Q::ZERO.clamp(a.clone(), b.clone()));
739 assert_eq!(a, a.clone().clamp(Q::ZERO, b.clone()));
740 assert_eq!(a, b.clamp(Q::ZERO, a.clone()));
741 }
742
743 #[test]
746 fn default_implementations_large() {
747 let a: Q = Q::from(i64::MAX);
748 let b: Q = Q::from(u64::MAX);
749
750 assert_eq!(b, max(a.clone(), b.clone()));
751 assert_eq!(a, min(a.clone(), b.clone()));
752
753 assert_eq!(a, Q::ZERO.clamp(a.clone(), b.clone()));
754 assert_eq!(a, a.clone().clamp(Q::ZERO, b.clone()));
755 assert_eq!(a, b.clamp(Q::ZERO, a.clone()));
756 }
757}