relp_num/rational/big/
properties.rs1use std::cmp::Ordering;
2
3use num_traits::{One, Zero};
4
5use crate::{NonZero, NonZeroSign, Sign};
6use crate::integer::big::ops::non_zero::mul_non_zero;
7use crate::integer::big::ops::normalize::simplify_fraction_without_info;
8use crate::integer::big::properties::cmp;
9use crate::rational::big::{Big, NonZeroBig};
10
11impl<const S: usize> Big<S> {
12 #[allow(unused)]
13 pub(crate) unsafe fn is_well_formed(&self) -> bool {
14 if !unsafe { self.numerator.is_well_formed() } {
17 return false;
18 }
19 if !unsafe { self.denominator.is_well_formed() } {
21 return false;
22 }
23
24 match self.sign {
25 Sign::Zero => {
26 self.numerator.is_zero() && self.denominator.is_one()
27 }
28 Sign::Positive | Sign::Negative => {
29 if self.numerator.is_zero() {
30 return false;
31 }
32 if !self.denominator.is_not_zero() {
33 return false;
34 }
35
36 let mut n_clone = self.numerator.clone();
37 let mut d_clone = self.denominator.clone();
38 unsafe {
44 simplify_fraction_without_info(n_clone.inner_mut(), d_clone.inner_mut());
45 }
46
47 n_clone == self.numerator && d_clone == self.denominator
48 }
49 }
50 }
51}
52
53impl<const S: usize> PartialEq for Big<S> {
54 #[inline]
55 fn eq(&self, other: &Self) -> bool {
56 match (self.sign, other.sign) {
57 (Sign::Positive, Sign::Negative) |
58 (Sign::Negative, Sign::Positive) => false,
59 (Sign::Zero, Sign::Zero) => true,
60 (Sign::Positive, Sign::Positive) | (Sign::Negative, Sign::Negative) => {
61 self.numerator == other.numerator && self.denominator == other.denominator
62 }
63 (Sign::Zero, Sign::Positive | Sign::Negative) |
64 (Sign::Positive | Sign::Negative, Sign::Zero) => false,
65 }
66 }
67}
68impl<const S: usize> Eq for Big<S> {}
69
70impl<const S: usize> PartialEq for NonZeroBig<S> {
71 #[inline]
72 fn eq(&self, other: &Self) -> bool {
73 self.sign == other.sign && self.numerator == other.numerator && self.denominator == other.denominator
74 }
75}
76impl<const S: usize> Eq for NonZeroBig<S> {}
77
78macro_rules! rational {
79 ($name:ident, $sign:ident) => {
80 impl<const S: usize> PartialOrd for $name<S> {
81 #[inline]
82 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
83 Some(self.cmp(other))
84 }
85 }
86
87 impl<const S: usize> Ord for $name<S> {
88 #[inline]
89 #[allow(unreachable_patterns)]
90 fn cmp(&self, other: &Self) -> Ordering {
91 match self.sign.cmp(&other.sign) {
92 Ordering::Less => return Ordering::Less,
93 Ordering::Greater => return Ordering::Greater,
94 Ordering::Equal => {}
96 }
97
98 if !self.sign.is_not_zero() {
99 return Ordering::Equal;
101 }
102
103 let left = self.numerator.len() + other.denominator.len();
106 let right = other.numerator.len() + self.denominator.len();
107 if left > right + 1 {
108 return match self.sign {
109 $sign::Positive => Ordering::Greater,
110 $sign::Negative => Ordering::Less,
111 _ => unreachable!("sign was checked to be nonzero"),
112 };
113 }
114 if right > left + 1 {
115 return match self.sign {
116 $sign::Positive => Ordering::Less,
117 $sign::Negative => Ordering::Greater,
118 _ => unreachable!("sign was checked to be nonzero"),
119 };
120 }
121
122 if self.numerator == other.numerator && self.denominator == other.denominator {
123 return Ordering::Equal;
124 }
125
126 let (ad, bc) = unsafe {
127 (
129 mul_non_zero::<S>(&self.numerator, &other.denominator),
130 mul_non_zero::<S>(&other.numerator, &self.denominator),
131 )
132 };
133
134 match (cmp(&ad, &bc), self.sign) {
135 (Ordering::Less, $sign::Positive) | (Ordering::Greater, $sign::Negative) => Ordering::Less,
136 (Ordering::Equal, _) => Ordering::Equal,
137 (Ordering::Greater, $sign::Positive) | (Ordering::Less, $sign::Negative) => Ordering::Greater,
138 _ => unreachable!("sign was checked to be nonzero"),
139 }
140 }
141 }
142 }
143}
144
145rational!(Big, Sign);
146rational!(NonZeroBig, NonZeroSign);