Skip to main content

relp_num/rational/big/with_integer/
mod.rs

1use std::cmp::Ordering;
2use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
3
4use num_traits::{One, Zero};
5use smallvec::SmallVec;
6
7use crate::{Negateable, NonZero, NonZeroUbig, Sign, Ubig};
8use crate::integer::big::ops::building_blocks::is_well_formed_non_zero;
9use crate::integer::big::ops::non_zero::{add_assign, mul_non_zero, subtracting_cmp};
10use crate::integer::big::ops::normalize::simplify_fraction_without_info;
11use crate::rational::big::{Big, NonZeroBig};
12
13mod small;
14
15impl<const S: usize> Add<Ubig<S>> for Big<S> {
16    type Output = Self;
17
18    #[inline]
19    fn add(mut self, rhs: Ubig<S>) -> Self::Output {
20        AddAssign::add_assign(&mut self, rhs);
21        self
22    }
23}
24
25impl<const S: usize> Add<&Ubig<S>> for Big<S> {
26    type Output = Self;
27
28    #[inline]
29    fn add(mut self, rhs: &Ubig<S>) -> Self::Output {
30        AddAssign::add_assign(&mut self, rhs);
31        self
32    }
33}
34
35impl<const S: usize> AddAssign<Ubig<S>> for Big<S> {
36    #[inline]
37    fn add_assign(&mut self, rhs: Ubig<S>) {
38        // TODO(PERFORMANCE): Utilize ownership of `rhs`.
39        AddAssign::add_assign(self, &rhs);
40    }
41}
42
43impl<const S: usize> AddAssign<&Ubig<S>> for Big<S> {
44    #[inline]
45    fn add_assign(&mut self, rhs: &Ubig<S>) {
46        if rhs.is_not_zero() {
47            unsafe {
48                // SAFETY: rhs is non zero
49                self.add_assign_int_non_zero(rhs);
50            }
51        }
52    }
53}
54
55impl<const S: usize> Add<NonZeroUbig<S>> for Big<S> {
56    type Output = Self;
57
58    #[inline]
59    fn add(mut self, rhs: NonZeroUbig<S>) -> Self::Output {
60        AddAssign::add_assign(&mut self, rhs);
61        self
62    }
63}
64
65impl<const S: usize> Add<&NonZeroUbig<S>> for Big<S> {
66    type Output = Self;
67
68    #[inline]
69    fn add(mut self, rhs: &NonZeroUbig<S>) -> Self::Output {
70        AddAssign::add_assign(&mut self, rhs);
71        self
72    }
73}
74
75impl<const S: usize> AddAssign<NonZeroUbig<S>> for Big<S> {
76    #[inline]
77    fn add_assign(&mut self, rhs: NonZeroUbig<S>) {
78        // TODO(PERFORMANCE): Utilize ownership of `rhs`.
79        AddAssign::add_assign(self, &rhs);
80    }
81}
82
83impl<const S: usize> AddAssign<&NonZeroUbig<S>> for Big<S> {
84    #[inline]
85    fn add_assign(&mut self, rhs: &NonZeroUbig<S>) {
86        unsafe {
87            // SAFETY: rhs is non zero
88            self.add_assign_int_non_zero(rhs);
89        }
90    }
91}
92
93impl<const S: usize> Big<S> {
94    #[inline]
95    unsafe fn add_assign_int_non_zero(&mut self, rhs: &[usize]) {
96        debug_assert!(is_well_formed_non_zero(rhs));
97
98        match self.sign {
99            Sign::Positive => {
100                // SAFETY: A `NonZeroUbig` is never empty and always well formed, and the caller
101                // guarantees the same of `rhs`. The `inner_mut` hands out the numerator's words;
102                // adding a magnitude to a non zero numerator leaves it well formed and non zero,
103                // and leaves the fraction in lowest terms, because the added term is a multiple of
104                // the denominator and so shares no new factor with it.
105                unsafe {
106                    let difference = mul_non_zero::<S>(&self.denominator, rhs);
107                    add_assign(self.numerator.inner_mut(), &difference)
108                }
109            },
110            Sign::Zero => {
111                // SAFETY: `rhs` is well formed and non zero by the caller's guarantee, so writing
112                // it into the numerator and setting the sign to match leaves the value well
113                // formed. The denominator is one for a zero value, so the fraction stays in
114                // lowest terms.
115                unsafe { *self.numerator.inner_mut() = SmallVec::from_slice(rhs) };
116                self.sign = Sign::Positive;
117                debug_assert!(self.denominator.is_one());
118            }
119            Sign::Negative => {
120                // SAFETY: As in the positive arm. `subtracting_cmp` leaves the numerator holding
121                // the magnitude of the difference, which may be zero; the match below restores the
122                // sign, and with it the invariant, for each of the three outcomes.
123                let ordering = unsafe {
124                    let difference = mul_non_zero::<S>(&self.denominator, rhs);
125                    subtracting_cmp(self.numerator.inner_mut(), &difference)
126                };
127
128                match ordering {
129                    Ordering::Less => self.sign.negate(),
130                    Ordering::Equal => self.set_zero(),
131                    Ordering::Greater => {}
132                }
133            }
134        }
135    }
136}
137
138impl<const S: usize> Sub<Ubig<S>> for Big<S> {
139    type Output = Self;
140
141    #[inline]
142    fn sub(mut self, rhs: Ubig<S>) -> Self::Output {
143        SubAssign::sub_assign(&mut self, rhs);
144        self
145    }
146}
147
148impl<const S: usize> Sub<&Ubig<S>> for Big<S> {
149    type Output = Self;
150
151    #[inline]
152    fn sub(mut self, rhs: &Ubig<S>) -> Self::Output {
153        SubAssign::sub_assign(&mut self, rhs);
154        self
155    }
156}
157
158impl<const S: usize> SubAssign<Ubig<S>> for Big<S> {
159    #[inline]
160    fn sub_assign(&mut self, rhs: Ubig<S>) {
161        // TODO(PERFORMANCE): Utilize ownership of `rhs`.
162        SubAssign::sub_assign(self, &rhs);
163    }
164}
165
166impl<const S: usize> SubAssign<&Ubig<S>> for Big<S> {
167    #[inline]
168    fn sub_assign(&mut self, rhs: &Ubig<S>) {
169        if rhs.is_not_zero() {
170            unsafe {
171                // SAFETY: rhs is non zero
172                self.sub_assign_int_non_zero(rhs);
173            }
174        }
175    }
176}
177
178impl<const S: usize> Sub<NonZeroUbig<S>> for Big<S> {
179    type Output = Self;
180
181    #[inline]
182    fn sub(mut self, rhs: NonZeroUbig<S>) -> Self::Output {
183        SubAssign::sub_assign(&mut self, rhs);
184        self
185    }
186}
187
188impl<const S: usize> Sub<&NonZeroUbig<S>> for Big<S> {
189    type Output = Self;
190
191    #[inline]
192    fn sub(mut self, rhs: &NonZeroUbig<S>) -> Self::Output {
193        SubAssign::sub_assign(&mut self, rhs);
194        self
195    }
196}
197
198impl<const S: usize> SubAssign<NonZeroUbig<S>> for Big<S> {
199    #[inline]
200    fn sub_assign(&mut self, rhs: NonZeroUbig<S>) {
201        // TODO(PERFORMANCE): Utilize ownership of `rhs`.
202        SubAssign::sub_assign(self, &rhs);
203    }
204}
205
206impl<const S: usize> SubAssign<&NonZeroUbig<S>> for Big<S> {
207    #[inline]
208    fn sub_assign(&mut self, rhs: &NonZeroUbig<S>) {
209        unsafe {
210            // SAFETY: rhs is non zero
211            self.sub_assign_int_non_zero(rhs);
212        }
213    }
214}
215
216impl<const S: usize> Big<S> {
217    #[inline]
218    unsafe fn sub_assign_int_non_zero(&mut self, rhs: &[usize]) {
219        debug_assert!(is_well_formed_non_zero(rhs));
220
221        match self.sign {
222            Sign::Positive => {
223                // SAFETY: A `NonZeroUbig` is never empty and always well formed, and the caller
224                // guarantees the same of `rhs`. The `inner_mut` hands out the numerator's words;
225                // `subtracting_cmp` leaves it holding the magnitude of the difference, which may be
226                // zero, and the match below restores the sign, and with it the invariant, for each
227                // of the three outcomes.
228                let ordering = unsafe {
229                    let difference = mul_non_zero::<S>(&self.denominator, rhs);
230                    subtracting_cmp(self.numerator.inner_mut(), &difference)
231                };
232
233                match ordering {
234                    Ordering::Less => self.sign.negate(),
235                    Ordering::Equal => self.set_zero(),
236                    Ordering::Greater => {}
237                }
238            }
239            Sign::Zero => {
240                // SAFETY: `rhs` is well formed and non zero by the caller's guarantee, so writing
241                // it into the numerator and setting the sign to match leaves the value well
242                // formed. The denominator is one for a zero value, so the fraction stays in
243                // lowest terms.
244                unsafe { *self.numerator.inner_mut() = SmallVec::from_slice(rhs) };
245                self.sign = Sign::Negative;
246                debug_assert!(self.denominator.is_one());
247            }
248            Sign::Negative => {
249                // SAFETY: As in the positive arm. Adding a magnitude to a non zero numerator leaves
250                // it well formed and non zero, and leaves the fraction in lowest terms, because the
251                // added term is a multiple of the denominator.
252                unsafe {
253                    let difference = mul_non_zero::<S>(&self.denominator, rhs);
254                    add_assign(self.numerator.inner_mut(), &difference)
255                }
256            },
257        }
258    }
259}
260
261impl<const S: usize> Mul<Ubig<S>> for Big<S> {
262    type Output = Self;
263
264    #[inline]
265    fn mul(mut self, rhs: Ubig<S>) -> Self::Output {
266        MulAssign::mul_assign(&mut self, rhs);
267        self
268    }
269}
270
271impl<const S: usize> MulAssign<Ubig<S>> for Big<S> {
272    #[inline]
273    fn mul_assign(&mut self, rhs: Ubig<S>) {
274        if !rhs.is_zero() {
275            if self.is_not_zero() {
276                // SAFETY: Every operand is well formed and not empty: `rhs` is non zero (by its type, or by
277                // the check just above), and `self` is not zero, so its numerator is not either.
278                // The two `inner_mut` calls hand out the words behind the lowest terms invariant,
279                // which `mul_assign_int_owning` restores before returning.
280                unsafe {
281                    mul_assign_int_owning(
282                        self.numerator.inner_mut(),
283                        self.denominator.inner_mut(),
284                        rhs.into_inner(),
285                    );
286                }
287            }
288        } else {
289            self.set_zero();
290        }
291    }
292}
293
294impl<const S: usize> Mul<NonZeroUbig<S>> for Big<S> {
295    type Output = Self;
296
297    #[inline]
298    fn mul(mut self, rhs: NonZeroUbig<S>) -> Self::Output {
299        MulAssign::mul_assign(&mut self, rhs);
300        self
301    }
302}
303
304impl<const S: usize> MulAssign<NonZeroUbig<S>> for Big<S> {
305    #[inline]
306    fn mul_assign(&mut self, rhs: NonZeroUbig<S>) {
307        if self.is_not_zero() {
308            // SAFETY: Every operand is well formed and not empty: `rhs` is non zero (by its type, or by the
309            // check just above), and `self` is not zero, so its numerator is not either. The two
310            // `inner_mut` calls hand out the words behind the lowest terms invariant, which
311            // `mul_assign_int_owning` restores before returning.
312            unsafe {
313                mul_assign_int_owning(
314                    self.numerator.inner_mut(),
315                    self.denominator.inner_mut(),
316                    rhs.into_inner(),
317                );
318            }
319        }
320    }
321}
322
323impl<const S: usize> Mul<NonZeroUbig<S>> for NonZeroBig<S> {
324    type Output = Self;
325
326    #[inline]
327    fn mul(mut self, rhs: NonZeroUbig<S>) -> Self::Output {
328        MulAssign::mul_assign(&mut self, rhs);
329        self
330    }
331}
332
333impl<const S: usize> MulAssign<NonZeroUbig<S>> for NonZeroBig<S> {
334    #[inline]
335    fn mul_assign(&mut self, rhs: NonZeroUbig<S>) {
336        // SAFETY: Every operand is well formed and not empty: `rhs` is non zero (by its type, or by the
337        // check just above), and a `NonZeroBig` is never zero, so its numerator is not either. The
338        // two `inner_mut` calls hand out the words behind the lowest terms invariant, which
339        // `mul_assign_int_owning` restores before returning.
340        unsafe {
341            mul_assign_int_owning(
342                self.numerator.inner_mut(),
343                self.denominator.inner_mut(),
344                rhs.into_inner(),
345            );
346        }
347    }
348}
349
350impl<const S: usize> Mul<&NonZeroUbig<S>> for NonZeroBig<S> {
351    type Output = Self;
352
353    #[inline]
354    fn mul(mut self, rhs: &NonZeroUbig<S>) -> Self::Output {
355        MulAssign::mul_assign(&mut self, rhs);
356        self
357    }
358}
359
360impl<const S: usize> MulAssign<&NonZeroUbig<S>> for NonZeroBig<S> {
361    #[inline]
362    fn mul_assign(&mut self, rhs: &NonZeroUbig<S>) {
363        // SAFETY: Every operand is well formed and not empty: `rhs` is non zero (by its type, or by the
364        // check just above), and a `NonZeroBig` is never zero, so its numerator is not either. The
365        // two `inner_mut` calls hand out the words behind the lowest terms invariant, which
366        // `mul_assign_int` restores before returning.
367        unsafe {
368            mul_assign_int(
369                self.numerator.inner_mut(),
370                self.denominator.inner_mut(),
371                rhs.inner(),
372            );
373        }
374    }
375}
376
377impl<const S: usize> MulAssign<&NonZeroUbig<S>> for Big<S> {
378    #[inline]
379    fn mul_assign(&mut self, rhs: &NonZeroUbig<S>) {
380        if self.is_not_zero() {
381            // SAFETY: Every operand is well formed and not empty: `rhs` is non zero (by its type, or by the
382            // check just above), and `self` is not zero, so its numerator is not either. The two
383            // `inner_mut` calls hand out the words behind the lowest terms invariant, which
384            // `mul_assign_int` restores before returning.
385            unsafe {
386                mul_assign_int(
387                    self.numerator.inner_mut(),
388                    self.denominator.inner_mut(),
389                    rhs.inner(),
390                );
391            }
392        }
393    }
394}
395
396impl<const S: usize> Div<NonZeroUbig<S>> for Big<S> {
397    type Output = Self;
398
399    #[inline]
400    fn div(mut self, rhs: NonZeroUbig<S>) -> Self::Output {
401        DivAssign::div_assign(&mut self, rhs);
402        self
403    }
404}
405
406impl<const S: usize> DivAssign<NonZeroUbig<S>> for Big<S> {
407    #[inline]
408    fn div_assign(&mut self, rhs: NonZeroUbig<S>) {
409        if self.is_not_zero() {
410            // SAFETY: Every operand is well formed and not empty: `rhs` is non zero (by its type, or by the
411            // check just above), and `self` is not zero, so its numerator is not either. The two
412            // `inner_mut` calls hand out the words behind the lowest terms invariant, which
413            // `mul_assign_int_owning` restores before returning. The numerator and denominator are
414            // passed the other way around, because dividing a fraction by an integer is multiplying
415            // its denominator by it.
416            unsafe {
417                mul_assign_int_owning(
418                    self.denominator.inner_mut(),
419                    self.numerator.inner_mut(),
420                    rhs.into_inner(),
421                );
422            }
423        }
424    }
425}
426
427impl<const S: usize> DivAssign<&NonZeroUbig<S>> for Big<S> {
428    #[inline]
429    fn div_assign(&mut self, rhs: &NonZeroUbig<S>) {
430        if self.is_not_zero() {
431            // SAFETY: Every operand is well formed and not empty: `rhs` is non zero (by its type, or by the
432            // check just above), and `self` is not zero, so its numerator is not either. The two
433            // `inner_mut` calls hand out the words behind the lowest terms invariant, which
434            // `mul_assign_int` restores before returning. The numerator and denominator are passed
435            // the other way around, because dividing a fraction by an integer is multiplying its
436            // denominator by it.
437            unsafe {
438                mul_assign_int(
439                    self.denominator.inner_mut(),
440                    self.numerator.inner_mut(),
441                    rhs.inner(),
442                );
443            }
444        }
445    }
446}
447
448impl<const S: usize> Div<Ubig<S>> for Big<S> {
449    type Output = Self;
450
451    #[inline]
452    fn div(mut self, rhs: Ubig<S>) -> Self::Output {
453        DivAssign::div_assign(&mut self, rhs);
454        self
455    }
456}
457
458impl<const S: usize> DivAssign<Ubig<S>> for Big<S> {
459    #[inline]
460    fn div_assign(&mut self, rhs: Ubig<S>) {
461        if !rhs.is_zero() {
462            if self.is_not_zero() {
463                // SAFETY: Every operand is well formed and not empty: `rhs` is non zero (by its type, or by
464                // the check just above), and `self` is not zero, so its numerator is not either.
465                // The two `inner_mut` calls hand out the words behind the lowest terms invariant,
466                // which `mul_assign_int_owning` restores before returning. The numerator and
467                // denominator are passed the other way around, because dividing a fraction by an
468                // integer is multiplying its denominator by it.
469                unsafe {
470                    mul_assign_int_owning(
471                        self.denominator.inner_mut(),
472                        self.numerator.inner_mut(),
473                        rhs.into_inner(),
474                    );
475                }
476            }
477        } else {
478            panic!("attempt to divide by zero");
479        }
480    }
481}
482
483impl<const S: usize> Div<NonZeroUbig<S>> for NonZeroBig<S> {
484    type Output = Self;
485
486    #[inline]
487    fn div(mut self, rhs: NonZeroUbig<S>) -> Self::Output {
488        DivAssign::div_assign(&mut self, rhs);
489        self
490    }
491}
492
493impl<const S: usize> DivAssign<NonZeroUbig<S>> for NonZeroBig<S> {
494    #[inline]
495    fn div_assign(&mut self, rhs: NonZeroUbig<S>) {
496        // SAFETY: Every operand is well formed and not empty: `rhs` is non zero (by its type, or by the
497        // check just above), and a `NonZeroBig` is never zero, so its numerator is not either. The
498        // two `inner_mut` calls hand out the words behind the lowest terms invariant, which
499        // `mul_assign_int_owning` restores before returning. The numerator and denominator are
500        // passed the other way around, because dividing a fraction by an integer is multiplying its
501        // denominator by it.
502        unsafe {
503            mul_assign_int_owning(
504                self.denominator.inner_mut(),
505                self.numerator.inner_mut(),
506                rhs.into_inner(),
507            );
508        }
509    }
510}
511
512impl<const S: usize> Div<&NonZeroUbig<S>> for NonZeroBig<S> {
513    type Output = Self;
514
515    #[inline]
516    fn div(mut self, rhs: &NonZeroUbig<S>) -> Self::Output {
517        DivAssign::div_assign(&mut self, rhs);
518        self
519    }
520}
521
522impl<const S: usize> DivAssign<&NonZeroUbig<S>> for NonZeroBig<S> {
523    #[inline]
524    fn div_assign(&mut self, rhs: &NonZeroUbig<S>) {
525        // SAFETY: Every operand is well formed and not empty: `rhs` is non zero (by its type, or by the
526        // check just above), and a `NonZeroBig` is never zero, so its numerator is not either. The
527        // two `inner_mut` calls hand out the words behind the lowest terms invariant, which
528        // `mul_assign_int` restores before returning. The numerator and denominator are passed the
529        // other way around, because dividing a fraction by an integer is multiplying its
530        // denominator by it.
531        unsafe {
532            mul_assign_int(
533                self.denominator.inner_mut(),
534                self.numerator.inner_mut(),
535                rhs.inner(),
536            );
537        }
538    }
539}
540
541#[inline]
542unsafe fn mul_assign_int<const S: usize>(
543    left_numerator: &mut SmallVec<[usize; S]>, left_denominator: &mut SmallVec<[usize; S]>,
544    right: &[usize],
545) {
546    debug_assert!(is_well_formed_non_zero(left_numerator));
547    debug_assert!(is_well_formed_non_zero(left_denominator));
548    debug_assert!(is_well_formed_non_zero(right));
549
550    // SAFETY: All three operands are well formed and not empty, so the product is too, which is
551    // what the simplification then needs of both of its operands.
552    unsafe {
553        *left_numerator = mul_non_zero(left_numerator, right);
554        simplify_fraction_without_info(left_numerator, left_denominator);
555    }
556}
557
558#[inline]
559unsafe fn mul_assign_int_owning<const S: usize>(
560    left_numerator: &mut SmallVec<[usize; S]>, left_denominator: &mut SmallVec<[usize; S]>,
561    mut right: SmallVec<[usize; S]>,
562) {
563    debug_assert!(is_well_formed_non_zero(left_numerator));
564    debug_assert!(is_well_formed_non_zero(left_denominator));
565    debug_assert!(is_well_formed_non_zero(&right));
566
567    // SAFETY: All three operands are well formed and not empty. The simplification cancels the
568    // denominator against the integer before the multiplication rather than after, and leaves both
569    // of them well formed and not empty, so the product that follows is well defined too.
570    unsafe {
571        simplify_fraction_without_info(left_denominator, &mut right);
572        *left_numerator = mul_non_zero(left_numerator, &right);
573    }
574}
575
576#[cfg(test)]
577mod test {
578    use std::ops::DivAssign;
579
580    use num_traits::{One, Zero};
581
582    use crate::{NonZeroUbig, RationalBig, Ubig};
583    use crate::rational::big::NonZeroBig;
584    use crate::RB;
585
586    #[test]
587    fn add() {
588        assert_eq!(RB!(2, 3) + NonZeroUbig::new(2).unwrap(), RB!(8, 3));
589        assert_eq!(RB!(-2, 3) + NonZeroUbig::new(2).unwrap(), RB!(4, 3));
590        assert_eq!(RB!(2, 3) + Ubig::zero(), RB!(2, 3));
591        assert_eq!(RB!(2, 3) - NonZeroUbig::new(2).unwrap(), RB!(-4, 3));
592        assert_eq!(RB!(0) - NonZeroUbig::one(), RB!(-1));
593        assert_eq!(RB!(-2, 3) - NonZeroUbig::new(2).unwrap(), RB!(-8, 3));
594    }
595
596    #[test]
597    fn mul_assign() {
598        assert_eq!(RB!(2, 3) * NonZeroUbig::new(2).unwrap(), RB!(4, 3));
599        assert_eq!(RB!(2, 3) * Ubig::zero(), RB!(0));
600        assert_eq!(RB!(2, 3) / NonZeroUbig::new(2).unwrap(), RB!(1, 3));
601        assert_eq!(RB!(0) * NonZeroUbig::one(), RB!(0));
602    }
603
604    #[test]
605    #[should_panic]
606    #[allow(unused_must_use)]
607    fn mul_panic() {
608        RationalBig::one() / Ubig::zero();
609    }
610
611    /// `-a / b + n` can cancel exactly: `subtracting_cmp` then returns `Ordering::Equal` and leaves
612    /// the numerator empty, so the sign has to be reset as well.
613    #[test]
614    fn add_int_cancelling_to_zero() {
615        let mut x = RB!(-5);
616        x += NonZeroUbig::new(5).unwrap();
617        assert!(x.is_zero());
618        assert_eq!(x, RB!(0));
619        assert_eq!(format!("{:?}", x), "0");
620
621        let mut y = RB!(-5);
622        y += Ubig::new(5);
623        assert!(y.is_zero());
624        assert_eq!(y, RB!(0));
625        assert_eq!(format!("{:?}", y), "0");
626    }
627
628    /// See `add_int_cancelling_to_zero`, the mirrored case `a / b - n`.
629    #[test]
630    fn sub_int_cancelling_to_zero() {
631        let mut x = RB!(5);
632        x -= NonZeroUbig::new(5).unwrap();
633        assert!(x.is_zero());
634        assert_eq!(x, RB!(0));
635        assert_eq!(format!("{:?}", x), "0");
636
637        let mut y = RB!(5);
638        y -= Ubig::new(5);
639        assert!(y.is_zero());
640        assert_eq!(y, RB!(0));
641        assert_eq!(format!("{:?}", y), "0");
642    }
643
644    /// Adding to zero has to set the sign, just like subtracting from zero does.
645    #[test]
646    fn add_int_to_zero_sets_sign() {
647        let mut x = RB!(0);
648        x += NonZeroUbig::new(5).unwrap();
649        assert!(!x.is_zero());
650        assert_eq!(x, RB!(5));
651        assert_eq!(format!("{:?}", x), "5");
652
653        let mut y = RB!(0);
654        y += Ubig::new(5);
655        assert!(!y.is_zero());
656        assert_eq!(y, RB!(5));
657        assert_eq!(format!("{:?}", y), "5");
658    }
659
660    /// `Div` on `NonZeroBig` should divide, not multiply.
661    #[test]
662    fn div_non_zero_big_by_non_zero_ubig() {
663        let two = NonZeroUbig::new(2).unwrap();
664
665        let mut expected = NonZeroBig::<8>::one();
666        DivAssign::div_assign(&mut expected, two.clone());
667
668        let owned = NonZeroBig::<8>::one() / two.clone();
669        assert!(owned == expected);
670        assert!(owned * two.clone() == NonZeroBig::<8>::one());
671
672        let borrowed = NonZeroBig::<8>::one() / &two;
673        assert!(borrowed == expected);
674        assert!(borrowed * &two == NonZeroBig::<8>::one());
675    }
676
677    /// Dividing zero by a `Ubig` should be a no-op instead of touching the empty numerator.
678    #[test]
679    fn div_zero_by_ubig() {
680        let mut x = RB!(0);
681        x /= Ubig::<8>::new(2);
682        assert!(x.is_zero());
683        assert_eq!(x, RB!(0));
684        assert_eq!(format!("{:?}", x), "0");
685
686        let y = RB!(0) / Ubig::<8>::new(2);
687        assert!(y.is_zero());
688        assert_eq!(y, RB!(0));
689    }
690}