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