relp-num 0.2.1

Number types for the relp crate
Documentation
use std::cmp::Ordering;
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};

use num_traits::Zero;

use crate::{Rational128, Rational16, Rational32, Rational64, Rational8, Sign};
use crate::fixed::One;

macro_rules! impls {
    ($name:ty) => {
        impl From<One> for $name {
            #[inline]
            fn from(_: One) -> Self {
                num_traits::One::one()
            }
        }

        impl From<&One> for $name {
            #[inline]
            fn from(_: &One) -> Self {
                num_traits::One::one()
            }
        }

        impl Add<One> for $name {
            type Output = Self;

            #[inline]
            fn add(mut self, _: One) -> Self::Output {
                AddAssign::add_assign(&mut self, One);
                self
            }
        }

        impl Add<&One> for $name {
            type Output = Self;

            #[inline]
            fn add(mut self, _: &One) -> Self::Output {
                AddAssign::add_assign(&mut self, &One);
                self
            }
        }

        impl AddAssign<One> for $name {
            #[inline]
            fn add_assign(&mut self, _: One) {
                AddAssign::add_assign(self, &One);
            }
        }

        impl AddAssign<&One> for $name {
            #[inline]
            fn add_assign(&mut self, _: &One) {
                match self.sign {
                    Sign::Positive => self.numerator += self.denominator,
                    Sign::Zero => {
                        self.sign = Sign::Positive;
                        debug_assert!(self.numerator.is_zero());
                        num_traits::One::set_one(&mut self.numerator);
                        debug_assert!(num_traits::One::is_one(&self.denominator));
                    }
                    Sign::Negative => {
                        if self.numerator != 1 || self.denominator != 1 {
                            match self.numerator.cmp(&self.denominator) {
                                Ordering::Less => {
                                    self.numerator = self.denominator - self.numerator;
                                    self.sign = Sign::Positive;
                                }
                                Ordering::Equal => panic!(),
                                Ordering::Greater => self.numerator -= self.denominator,
                            }
                        } else {
                            self.set_zero();
                        }
                    }
                }
            }
        }

        impl Sub<One> for $name {
            type Output = Self;

            #[inline]
            fn sub(mut self, _: One) -> Self::Output {
                SubAssign::sub_assign(&mut self, One);
                self
            }
        }

        impl Sub<&One> for $name {
            type Output = Self;

            #[inline]
            fn sub(mut self, _: &One) -> Self::Output {
                SubAssign::sub_assign(&mut self, One);
                self
            }
        }

        impl SubAssign<One> for $name {
            #[inline]
            fn sub_assign(&mut self, _: One) {
                SubAssign::sub_assign(self, &One);
            }
        }

        impl SubAssign<&One> for $name {
            #[inline]
            fn sub_assign(&mut self, _: &One) {
                match self.sign {
                    Sign::Positive => {
                        if self.numerator != 1 || self.denominator != 1 {
                            match self.numerator.cmp(&self.denominator) {
                                Ordering::Less => {
                                    self.numerator = self.denominator - self.numerator;
                                    self.sign = Sign::Negative;
                                }
                                Ordering::Equal => panic!(),
                                Ordering::Greater => self.numerator -= self.denominator,
                            }
                        } else {
                            self.set_zero();
                        }
                    }
                    Sign::Zero => {
                        self.sign = Sign::Negative;
                        debug_assert_eq!(self.numerator, 0);
                        self.numerator = 1;
                        debug_assert_eq!(self.denominator, 1);
                    }
                    Sign::Negative => self.numerator += self.denominator,
                }
            }
        }

        impl Mul<One> for $name {
            type Output = Self;

            #[inline]
            fn mul(self, _: One) -> Self::Output {
                self
            }
        }

        impl Mul<&One> for $name {
            type Output = Self;

            #[inline]
            fn mul(self, _: &One) -> Self::Output {
                self
            }
        }

        impl Mul<&One> for &$name {
            type Output = $name;

            #[inline]
            fn mul(self, _: &One) -> Self::Output {
                self.clone()
            }
        }

        impl Mul<One> for &$name {
            type Output = $name;

            #[inline]
            fn mul(self, _: One) -> Self::Output {
                self.clone()
            }
        }

        impl MulAssign<One> for $name {
            #[inline]
            fn mul_assign(&mut self, _: One) {
                MulAssign::mul_assign(self, &One);
            }
        }

        impl MulAssign<&One> for $name {
            #[inline]
            fn mul_assign(&mut self, _: &One) {
            }
        }

        impl Div<One> for $name {
            type Output = Self;

            #[inline]
            fn div(self, _: One) -> Self::Output {
                self
            }
        }

        impl Div<&One> for $name {
            type Output = Self;

            #[inline]
            fn div(self, _: &One) -> Self::Output {
                self
            }
        }

        impl Div<&One> for &$name {
            type Output = $name;

            #[inline]
            fn div(self, _: &One) -> Self::Output {
                self.clone()
            }
        }

        impl Div<One> for &$name {
            type Output = $name;

            #[inline]
            fn div(self, _: One) -> Self::Output {
                self.clone()
            }
        }

        impl DivAssign<One> for $name {
            #[inline]
            fn div_assign(&mut self, _: One) {
                DivAssign::div_assign(self, &One);
            }
        }

        impl DivAssign<&One> for $name {
            #[inline]
            fn div_assign(&mut self, _: &One) {
            }
        }
    }
}

impls!(Rational8);
impls!(Rational16);
impls!(Rational32);
impls!(Rational64);
impls!(Rational128);

#[cfg(test)]
mod test {
    use crate::{R8};
    use crate::fixed::One;

    #[test]
    fn test_add_sub() {
        assert_eq!(R8!(1) + One, R8!(2));
        assert_eq!(R8!(0) + One, R8!(1));
        assert_eq!(R8!(0) - One, R8!(-1));
        assert_eq!(R8!(1) - One, R8!(0));
        assert_eq!(R8!(1, 2) - One, R8!(-1, 2));
        assert_eq!(R8!(-1, 2) + One, R8!(1, 2));
        assert_eq!(R8!(-1, 2) - One, R8!(-3, 2));

        assert_eq!(R8!(1) * &One, R8!(1));
        assert_eq!(R8!(1) / &One, R8!(1));
    }
}