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