relp_num/rational/big/ops/
mul_div.rs1use std::ops::{Div, DivAssign, Mul, MulAssign};
2
3use num_traits::Zero;
4
5use crate::rational::big::{Big, NonZeroBig};
6use crate::rational::big::ops::building_blocks::mul_assign_fraction_non_zero;
7use crate::Sign;
8
9impl<const S: usize> Mul for Big<S> {
10 type Output = Self;
11
12 #[inline]
13 fn mul(mut self, rhs: Self) -> Self::Output {
14 MulAssign::mul_assign(&mut self, rhs);
15 self
16 }
17}
18
19impl<const S: usize> Mul for NonZeroBig<S> {
20 type Output = Self;
21
22 #[inline]
23 fn mul(mut self, rhs: Self) -> Self::Output {
24 MulAssign::mul_assign(&mut self, rhs);
25 self
26 }
27}
28
29impl<const S: usize> Mul<&Big<S>> for Big<S> {
30 type Output = Self;
31
32 #[inline]
33 fn mul(mut self, rhs: &Big<S>) -> Self::Output {
34 MulAssign::mul_assign(&mut self, rhs.clone());
36 self
37 }
38}
39
40impl<const S: usize> Mul<Big<S>> for &Big<S> {
41 type Output = Big<S>;
42
43 #[inline]
44 fn mul(self, rhs: Big<S>) -> Self::Output {
45 Mul::mul(rhs, self)
46 }
47}
48
49impl<const S: usize> Mul<&Big<S>> for &Big<S> {
50 type Output = Big<S>;
51
52 #[inline]
53 fn mul(self, rhs: &Big<S>) -> Self::Output {
54 let mut x = self.clone();
55 MulAssign::mul_assign(&mut x, rhs.clone());
57 x
58 }
59}
60
61impl<const S: usize> MulAssign for Big<S> {
62 #[inline]
63 fn mul_assign(&mut self, rhs: Self) {
64 match (self.sign, rhs.sign) {
65 (Sign::Positive | Sign::Negative, Sign::Positive | Sign::Negative) => {
66 self.sign *= rhs.sign;
67 unsafe {
68 mul_assign_fraction_non_zero(
70 self.numerator.inner_mut(),
71 self.denominator.inner_mut(),
72 rhs.numerator.inner().clone(),
73 rhs.denominator.inner().clone(),
74 );
75 }
76 }
77 (Sign::Positive | Sign::Negative, Sign::Zero) => {
78 self.set_zero();
79 }
80 (Sign::Zero, _) => {}
81 }
82 }
83}
84
85impl<const S: usize> MulAssign for NonZeroBig<S> {
86 #[inline]
87 fn mul_assign(&mut self, rhs: Self) {
88 self.sign *= rhs.sign;
89 unsafe {
90 mul_assign_fraction_non_zero(
92 self.numerator.inner_mut(),
93 self.denominator.inner_mut(),
94 rhs.numerator.inner().clone(),
95 rhs.denominator.inner().clone(),
96 );
97 }
98 }
99}
100
101impl<const S: usize> Mul<&NonZeroBig<S>> for NonZeroBig<S> {
102 type Output = Self;
103
104 #[inline]
105 fn mul(mut self, rhs: &NonZeroBig<S>) -> Self::Output {
106 MulAssign::mul_assign(&mut self, rhs.clone());
108 self
109 }
110}
111
112impl<const S: usize> Mul for &NonZeroBig<S> {
113 type Output = NonZeroBig<S>;
114
115 #[inline]
116 fn mul(self, rhs: &NonZeroBig<S>) -> Self::Output {
117 let mut x = self.clone();
118 MulAssign::mul_assign(&mut x, rhs.clone());
120 x
121 }
122}
123
124impl<const S: usize> MulAssign<&NonZeroBig<S>> for NonZeroBig<S> {
125 #[inline]
126 fn mul_assign(&mut self, rhs: &Self) {
127 self.sign *= rhs.sign;
128 unsafe {
129 mul_assign_fraction_non_zero(
131 self.numerator.inner_mut(),
132 self.denominator.inner_mut(),
133 rhs.numerator.inner().clone(),
134 rhs.denominator.inner().clone(),
135 );
136 }
137 }
138}
139
140impl<const S: usize> MulAssign<&Big<S>> for Big<S> {
141 #[inline]
142 fn mul_assign(&mut self, rhs: &Self) {
143 match (self.sign, rhs.sign) {
144 (Sign::Positive | Sign::Negative, Sign::Positive | Sign::Negative) => {
145 self.sign *= rhs.sign;
146 unsafe {
147 mul_assign_fraction_non_zero(
149 self.numerator.inner_mut(),
150 self.denominator.inner_mut(),
151 rhs.numerator.inner().clone(),
152 rhs.denominator.inner().clone(),
153 );
154 }
155 }
156 (Sign::Positive | Sign::Negative, Sign::Zero) => {
157 self.set_zero();
158 }
159 (Sign::Zero, _) => {}
160 }
161 }
162}
163impl<const S: usize> Div for Big<S> {
164 type Output = Big<S>;
165
166 #[inline]
167 fn div(mut self, rhs: Big<S>) -> Self::Output {
168 DivAssign::div_assign(&mut self, rhs);
169 self
170 }
171}
172
173impl<const S: usize> Div<&Big<S>> for Big<S> {
174 type Output = Big<S>;
175
176 #[inline]
177 fn div(mut self, rhs: &Big<S>) -> Self::Output {
178 DivAssign::div_assign(&mut self, rhs.clone());
179 self
180 }
181}
182
183impl<const S: usize> Div<Big<S>> for &Big<S> {
184 type Output = Big<S>;
185
186 #[inline]
187 fn div(self, rhs: Big<S>) -> Self::Output {
188 let mut x = self.clone();
189 DivAssign::div_assign(&mut x, rhs);
191 x
192 }
193}
194
195impl<const S: usize> Div for &Big<S> {
196 type Output = Big<S>;
197
198 #[inline]
199 fn div(self, rhs: &Big<S>) -> Self::Output {
200 let mut x = self.clone();
201 DivAssign::div_assign(&mut x, rhs.clone());
203 x
204 }
205}
206
207impl<const S: usize> DivAssign<&Big<S>> for Big<S> {
208 #[inline]
209 fn div_assign(&mut self, rhs: &Big<S>) {
210 DivAssign::div_assign(self, rhs.clone());
211 }
212}
213
214impl<const S: usize> Div<&NonZeroBig<S>> for &NonZeroBig<S> {
215 type Output = NonZeroBig<S>;
216
217 #[inline]
218 fn div(self, rhs: &NonZeroBig<S>) -> Self::Output {
219 let mut x = self.clone();
220 DivAssign::div_assign(&mut x, rhs.clone());
222 x
223 }
224}
225
226#[allow(clippy::suspicious_op_assign_impl)]
228impl<const S: usize> DivAssign for Big<S> {
229 #[inline]
230 fn div_assign(&mut self, rhs: Self) {
231 match (self.sign, rhs.sign) {
232 (Sign::Positive | Sign::Negative, Sign::Positive | Sign::Negative) => {
233 self.sign *= rhs.sign;
234 unsafe {
235 mul_assign_fraction_non_zero(
237 self.numerator.inner_mut(),
238 self.denominator.inner_mut(),
239 rhs.denominator.into_inner(),
240 rhs.numerator.into_inner(),
241 );
242 }
243 }
244 (_, Sign::Zero) => panic!("attempt to divide by zero"),
247 (Sign::Zero, _) => {}
248 }
249 }
250}
251
252#[allow(clippy::suspicious_op_assign_impl)]
254impl<const S: usize> DivAssign for NonZeroBig<S> {
255 #[inline]
256 fn div_assign(&mut self, rhs: Self) {
257 self.sign *= rhs.sign;
258 unsafe {
259 mul_assign_fraction_non_zero(
261 self.numerator.inner_mut(),
262 self.denominator.inner_mut(),
263 rhs.denominator.into_inner(),
264 rhs.numerator.into_inner(),
265 );
266 }
267 }
268}
269
270#[allow(clippy::suspicious_op_assign_impl)]
272impl<const S: usize> DivAssign<&NonZeroBig<S>> for NonZeroBig<S> {
273 #[inline]
274 fn div_assign(&mut self, rhs: &Self) {
275 self.sign *= rhs.sign;
276 unsafe {
277 mul_assign_fraction_non_zero(
279 self.numerator.inner_mut(),
280 self.denominator.inner_mut(),
281 rhs.denominator.inner().clone(),
282 rhs.numerator.inner().clone(),
283 );
284 }
285 }
286}
287
288
289#[cfg(test)]
290mod test {
291 use crate::RB;
292
293 #[test]
294 fn test_mul() {
295 let mut x = RB!(3, 4);
296 x *= RB!(-5, 6);
297 assert_eq!(x, RB!(-3 * 5, 4 * 6));
298
299 let mut x = RB!(3, 4);
300 x *= RB!(5, 6);
301 assert_eq!(x, RB!(3 * 5, 4 * 6));
302
303 let mut x = RB!(0);
304 x *= &RB!(-5, 6);
305 assert_eq!(x, RB!(0));
306
307 let mut x = RB!(-5, 6);
308 x *= RB!(0);
309 assert_eq!(x, RB!(0));
310 }
311
312 #[test]
313 fn test_div() {
314 let mut x = RB!(3, 4);
315 x /= RB!(-5, 6);
316 assert_eq!(x, RB!(-3 * 6, 5 * 4));
317
318 let mut x = RB!(3, 4);
319 x /= &RB!(5, 6);
320 assert_eq!(x, RB!(3 * 6, 5 * 4));
321
322 let mut x = RB!(0);
323 x /= RB!(-5, 6);
324 assert_eq!(x, RB!(0));
325 }
326
327 #[test]
328 #[should_panic]
329 fn test_div_by_zero() {
330 let mut x = RB!(-5, 6);
331 x /= RB!(0);
332 assert_eq!(x, RB!(-5, 6));
333 }
334
335 #[test]
340 #[should_panic(expected = "attempt to divide by zero")]
341 fn test_div_zero_by_zero() {
342 let _ = RB!(0) / RB!(0);
343 }
344
345 #[test]
346 #[should_panic(expected = "attempt to divide by zero")]
347 fn test_div_assign_zero_by_zero() {
348 let mut x = RB!(0);
349 x /= RB!(0);
350 }
351}