relp_num/rational/small/ops/
with_one.rs

1use std::cmp::Ordering;
2use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
3
4use num_traits::Zero;
5
6use crate::{Rational128, Rational16, Rational32, Rational64, Rational8, Sign};
7use crate::one::One;
8
9macro_rules! impls {
10    ($name:ty) => {
11        impl From<One> for $name {
12            #[inline]
13            #[must_use]
14            fn from(_: One) -> Self {
15                num_traits::One::one()
16            }
17        }
18
19        impl From<&One> for $name {
20            #[inline]
21            #[must_use]
22            fn from(_: &One) -> Self {
23                num_traits::One::one()
24            }
25        }
26
27        impl Add<One> for $name {
28            type Output = Self;
29
30            #[inline]
31            #[must_use]
32            fn add(mut self, _: One) -> Self::Output {
33                AddAssign::add_assign(&mut self, One);
34                self
35            }
36        }
37
38        impl Add<&One> for $name {
39            type Output = Self;
40
41            #[inline]
42            #[must_use]
43            fn add(mut self, _: &One) -> Self::Output {
44                AddAssign::add_assign(&mut self, &One);
45                self
46            }
47        }
48
49        impl AddAssign<One> for $name {
50            #[inline]
51            fn add_assign(&mut self, _: One) {
52                AddAssign::add_assign(self, &One);
53            }
54        }
55
56        impl AddAssign<&One> for $name {
57            #[inline]
58            fn add_assign(&mut self, _: &One) {
59                match self.sign {
60                    Sign::Positive => self.numerator += self.denominator,
61                    Sign::Zero => {
62                        self.sign = Sign::Positive;
63                        debug_assert!(self.numerator.is_zero());
64                        num_traits::One::set_one(&mut self.numerator);
65                        debug_assert!(num_traits::One::is_one(&self.denominator));
66                    }
67                    Sign::Negative => {
68                        if self.numerator != 1 || self.denominator != 1 {
69                            match self.numerator.cmp(&self.denominator) {
70                                Ordering::Less => {
71                                    self.numerator = self.denominator - self.numerator;
72                                    self.sign = Sign::Positive;
73                                }
74                                Ordering::Equal => panic!(),
75                                Ordering::Greater => self.numerator -= self.denominator,
76                            }
77                        } else {
78                            self.set_zero();
79                        }
80                    }
81                }
82            }
83        }
84
85        impl Sub<One> for $name {
86            type Output = Self;
87
88            #[must_use]
89            #[inline]
90            fn sub(mut self, _: One) -> Self::Output {
91                SubAssign::sub_assign(&mut self, One);
92                self
93            }
94        }
95
96        impl Sub<&One> for $name {
97            type Output = Self;
98
99            #[must_use]
100            #[inline]
101            fn sub(mut self, _: &One) -> Self::Output {
102                SubAssign::sub_assign(&mut self, One);
103                self
104            }
105        }
106
107        impl SubAssign<One> for $name {
108            #[inline]
109            fn sub_assign(&mut self, _: One) {
110                SubAssign::sub_assign(self, &One);
111            }
112        }
113
114        impl SubAssign<&One> for $name {
115            #[inline]
116            fn sub_assign(&mut self, _: &One) {
117                match self.sign {
118                    Sign::Positive => {
119                        if self.numerator != 1 || self.denominator != 1 {
120                            match self.numerator.cmp(&self.denominator) {
121                                Ordering::Less => {
122                                    self.numerator = self.denominator - self.numerator;
123                                    self.sign = Sign::Negative;
124                                }
125                                Ordering::Equal => panic!(),
126                                Ordering::Greater => self.numerator -= self.denominator,
127                            }
128                        } else {
129                            self.set_zero();
130                        }
131                    }
132                    Sign::Zero => {
133                        self.sign = Sign::Negative;
134                        debug_assert_eq!(self.numerator, 0);
135                        self.numerator = 1;
136                        debug_assert_eq!(self.denominator, 1);
137                    }
138                    Sign::Negative => self.numerator += self.denominator,
139                }
140            }
141        }
142
143        impl Mul<One> for $name {
144            type Output = Self;
145
146            #[inline]
147            #[must_use]
148            fn mul(self, _: One) -> Self::Output {
149                self
150            }
151        }
152
153        impl Mul<&One> for $name {
154            type Output = Self;
155
156            #[inline]
157            #[must_use]
158            fn mul(self, _: &One) -> Self::Output {
159                self
160            }
161        }
162
163        impl Mul<&One> for &$name {
164            type Output = $name;
165
166            #[inline]
167            #[must_use]
168            fn mul(self, _: &One) -> Self::Output {
169                self.clone()
170            }
171        }
172
173        impl Mul<One> for &$name {
174            type Output = $name;
175
176            #[inline]
177            #[must_use]
178            fn mul(self, _: One) -> Self::Output {
179                self.clone()
180            }
181        }
182
183        impl MulAssign<One> for $name {
184            #[inline]
185            fn mul_assign(&mut self, _: One) {
186                MulAssign::mul_assign(self, &One);
187            }
188        }
189
190        impl MulAssign<&One> for $name {
191            #[inline]
192            fn mul_assign(&mut self, _: &One) {
193            }
194        }
195
196        impl Div<One> for $name {
197            type Output = Self;
198
199            #[inline]
200            #[must_use]
201            fn div(self, _: One) -> Self::Output {
202                self
203            }
204        }
205
206        impl Div<&One> for $name {
207            type Output = Self;
208
209            #[inline]
210            #[must_use]
211            fn div(self, _: &One) -> Self::Output {
212                self
213            }
214        }
215
216        impl Div<&One> for &$name {
217            type Output = $name;
218
219            #[inline]
220            #[must_use]
221            fn div(self, _: &One) -> Self::Output {
222                self.clone()
223            }
224        }
225
226        impl Div<One> for &$name {
227            type Output = $name;
228
229            #[inline]
230            #[must_use]
231            fn div(self, _: One) -> Self::Output {
232                self.clone()
233            }
234        }
235
236        impl DivAssign<One> for $name {
237            #[inline]
238            fn div_assign(&mut self, _: One) {
239                DivAssign::div_assign(self, &One);
240            }
241        }
242
243        impl DivAssign<&One> for $name {
244            #[inline]
245            fn div_assign(&mut self, _: &One) {
246            }
247        }
248    }
249}
250
251impls!(Rational8);
252impls!(Rational16);
253impls!(Rational32);
254impls!(Rational64);
255impls!(Rational128);
256
257#[cfg(test)]
258mod test {
259    use crate::{One, R8};
260
261    #[test]
262    fn test_add_sub() {
263        assert_eq!(R8!(1) + One, R8!(2));
264        assert_eq!(R8!(0) + One, R8!(1));
265        assert_eq!(R8!(0) - One, R8!(-1));
266        assert_eq!(R8!(1) - One, R8!(0));
267        assert_eq!(R8!(1, 2) - One, R8!(-1, 2));
268        assert_eq!(R8!(-1, 2) + One, R8!(1, 2));
269        assert_eq!(R8!(-1, 2) - One, R8!(-3, 2));
270
271        assert_eq!(R8!(1) * &One, R8!(1));
272        assert_eq!(R8!(1) / &One, R8!(1));
273    }
274}