series 0.15.0

Laurent series and polynomials
Documentation
use std::ops::{
    Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign,
};

use derive_more::{
    Add, AddAssign, AsMut, AsRef, Debug, Display, From, FromStr, Into,
    MulAssign, Neg, Sub, SubAssign,
};
use num_traits::{One, Zero};
use rug::{Complete, rational::BorrowRational};

use crate::{
    Laurent, NeedsCoeffBracket, Polynomial, PolynomialSlice, Series,
    SeriesSlice, Sign, SplitSign, anon_series::AnonSeries,
    anon_series_slice::AnonSeriesSlice,
};

#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(
    Clone,
    Default,
    Eq,
    PartialEq,
    Ord,
    PartialOrd,
    Hash,
    Add,
    AddAssign,
    AsMut,
    AsRef,
    Debug,
    Display,
    From,
    FromStr,
    Into,
    MulAssign,
    Neg,
    Sub,
    SubAssign,
)]
pub struct Rational(pub rug::Rational);

impl<'a> AddAssign<&'a Rational> for Rational {
    fn add_assign(&mut self, rhs: &'a Rational) {
        self.0.add_assign(&rhs.0);
    }
}

impl<'a> SubAssign<&'a Rational> for Rational {
    fn sub_assign(&mut self, rhs: &'a Rational) {
        self.0.sub_assign(&rhs.0);
    }
}

impl<'a> MulAssign<&'a Rational> for Rational {
    fn mul_assign(&mut self, rhs: &'a Self) {
        self.0.mul_assign(&rhs.0);
    }
}

impl<'a> DivAssign<&'a Rational> for Rational {
    fn div_assign(&mut self, rhs: &'a Self) {
        self.0.div_assign(&rhs.0);
    }
}

impl MulAssign for Rational {
    fn mul_assign(&mut self, rhs: Self) {
        self.0.mul_assign(rhs.0);
    }
}

impl DivAssign for Rational {
    fn div_assign(&mut self, rhs: Self) {
        self.0.div_assign(rhs.0);
    }
}

impl Add for &Rational {
    type Output = Rational;

    fn add(self, rhs: Self) -> Self::Output {
        Rational((&self.0).add(&rhs.0).complete())
    }
}

impl Add<&Rational> for Rational {
    type Output = Rational;

    fn add(self, rhs: &Self) -> Self::Output {
        Rational(self.0.add(&rhs.0))
    }
}

impl Add<Rational> for &Rational {
    type Output = Rational;

    fn add(self, rhs: Rational) -> Self::Output {
        Rational((&self.0).add(rhs.0))
    }
}

impl Sub for &Rational {
    type Output = Rational;

    fn sub(self, rhs: Self) -> Self::Output {
        Rational((&self.0).sub(&rhs.0).complete())
    }
}

impl Sub<&Rational> for Rational {
    type Output = Rational;

    fn sub(self, rhs: &Self) -> Self::Output {
        Rational(self.0.sub(&rhs.0))
    }
}

impl Sub<Rational> for &Rational {
    type Output = Rational;

    fn sub(self, rhs: Rational) -> Self::Output {
        Rational((&self.0).sub(rhs.0))
    }
}

impl Mul for Rational {
    type Output = Rational;

    fn mul(self, rhs: Self) -> Self::Output {
        Rational(self.0.mul(rhs.0))
    }
}

impl Mul for &Rational {
    type Output = Rational;

    fn mul(self, rhs: Self) -> Self::Output {
        Rational((&self.0).mul(&rhs.0).complete())
    }
}

impl Mul<&Rational> for Rational {
    type Output = Rational;

    fn mul(self, rhs: &Self) -> Self::Output {
        Rational(self.0.mul(&rhs.0))
    }
}

impl Mul<Rational> for &Rational {
    type Output = Rational;

    fn mul(self, rhs: Rational) -> Self::Output {
        Rational((&self.0).mul(rhs.0))
    }
}

impl Div for Rational {
    type Output = Rational;

    fn div(self, rhs: Self) -> Self::Output {
        Rational(self.0.div(rhs.0))
    }
}

impl Div for &Rational {
    type Output = Rational;

    fn div(self, rhs: Self) -> Self::Output {
        Rational((&self.0).div(&rhs.0).complete())
    }
}

impl Div<&Rational> for Rational {
    type Output = Rational;

    fn div(self, rhs: &Self) -> Self::Output {
        Rational(self.0.div(&rhs.0))
    }
}

impl Div<Rational> for &Rational {
    type Output = Rational;

    fn div(self, rhs: Rational) -> Self::Output {
        Rational((&self.0).div(rhs.0))
    }
}

impl std::ops::Neg for &Rational {
    type Output = Rational;

    fn neg(self) -> Self::Output {
        Rational((-&self.0).complete())
    }
}

impl Zero for Rational {
    fn zero() -> Self {
        Self(rug::Rational::zero())
    }

    fn is_zero(&self) -> bool {
        self.0.is_zero()
    }
}

impl One for Rational {
    fn one() -> Self {
        Self(rug::Rational::one())
    }

    fn is_one(&self) -> bool {
        self.0.is_one()
    }
}

macro_rules! impl_mul {
    ($($t:ty), *) => {
        $(
            impl<'a, Var> Mul<$t> for Rational
            where $t: Mul<Rational>
            {
                type Output = <$t as Mul<Rational>>::Output;

                fn mul(self, other: $t) -> Self::Output {
                    other.mul(self)
                }
            }
        )*
    };
}

impl_mul!(
    Polynomial<Var, Rational>, &'a Polynomial<Var, Rational>, PolynomialSlice<'a, Var, Rational>,
    Series<Var, Rational>, &'a Series<Var, Rational>, SeriesSlice<'a, Var, Rational>,
    Laurent<Var, Rational>, &'a Laurent<Var, Rational>
);

macro_rules! impl_mul_anon {
    ($($t:ty), *) => {
        $(
            impl<'a> Mul<$t> for Rational {
                type Output = <$t as Mul<Rational>>::Output;

                fn mul(self, other: $t) -> Self::Output {
                    other.mul(self)
                }
            }
        )*
    };
}
impl_mul_anon!(
    AnonSeries<Rational>,
    &'a AnonSeries<Rational>,
    AnonSeriesSlice<'a, Rational>
);

macro_rules! impl_from {
    ($($t:ty), *) => {
        $(
            impl From<$t> for Rational {
                fn from(val: $t) -> Self {
                    Self(rug::Rational::from(val))
                }
            }
        )*
    };
}

impl_from!(
    i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize
);

#[cfg(feature = "rug-integer")]
impl_from!(rug::Integer);

#[cfg(feature = "rug-integer")]
impl From<(rug::Integer, rug::Integer)> for Rational {
    fn from(val: (rug::Integer, rug::Integer)) -> Self {
        Self(rug::Rational::from(val))
    }
}

#[cfg(feature = "rug-integer")]
impl From<super::Integer> for Rational {
    fn from(value: super::Integer) -> Self {
        Self::from(value.0)
    }
}

#[cfg(feature = "rug-integer")]
impl From<(super::Integer, super::Integer)> for Rational {
    fn from(value: (super::Integer, super::Integer)) -> Self {
        Self::from((value.0.0, value.1.0))
    }
}

impl NeedsCoeffBracket for Rational {
    fn needs_coeff_bracket(&self) -> bool {
        false
    }
}

impl<'a> SplitSign<'a> for Rational {
    type Signless = SignlessRational<'a>;

    fn split_sign(&'a self) -> (Sign, Self::Signless) {
        let sign = if self.0.is_negative() {
            Sign::Minus
        } else {
            Sign::Plus
        };
        (sign, SignlessRational(self.0.as_abs()))
    }
}

pub struct SignlessRational<'a>(BorrowRational<'a>);

impl<'a> Mul for SignlessRational<'a> {
    type Output = Self;

    fn mul(self, _: Self) -> Self::Output {
        unimplemented!(
            "`Mul` is only implemented to satisfy the trait bounds for `One`."
        )
    }
}

impl<'a> One for SignlessRational<'a> {
    fn one() -> Self {
        unimplemented!(
            "`One` is only implemented to satisfy trait bounds. Only the `is_one` function should be used"
        )
    }

    fn is_one(&self) -> bool {
        self.0.is_one()
    }
}

impl<'a> PartialEq for SignlessRational<'a> {
    fn eq(&self, _: &Self) -> bool {
        unimplemented!(
            "`PartialEq` is only implemented to satisfy the trait bounds for `One::is_one`."
        )
    }
}

impl<'a> std::fmt::Display for SignlessRational<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        std::fmt::Display::fmt(&self.0, f)
    }
}