series 0.15.0

Laurent series and polynomials
Documentation
use std::ops::{Add, AddAssign, 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, integer::BorrowInteger};

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 Integer(pub rug::Integer);

impl Integer {
    pub const ZERO: Integer = Integer(rug::Integer::ZERO);
}

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

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

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

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

impl Add for &Integer {
    type Output = Integer;

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

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

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

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

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

impl Sub for &Integer {
    type Output = Integer;

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

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

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

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

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

impl Mul for Integer {
    type Output = Integer;

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

impl Mul for &Integer {
    type Output = Integer;

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

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

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

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

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

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

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

impl Zero for Integer {
    fn zero() -> Self {
        Self::ZERO
    }

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

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

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

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

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

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

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

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

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

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

macro_rules! impl_try_from {
    ($($t:ty), *) => {
        $(
            impl TryFrom<Integer> for $t {
                type Error = <$t as TryFrom<rug::Integer>>::Error;

                fn try_from(val: Integer) -> Result<Self, Self::Error> {
                    Self::try_from(val.0)
                }
            }

            impl<'a> TryFrom<&'a Integer> for $t {
                type Error = <$t as TryFrom<&'a rug::Integer>>::Error;

                fn try_from(val: &'a Integer) -> Result<Self, Self::Error> {
                    Self::try_from(&val.0)
                }
            }
        )*
    };
}

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

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

impl<'a> SplitSign<'a> for Integer {
    type Signless = SignlessInteger<'a>;

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

pub struct SignlessInteger<'a>(BorrowInteger<'a>);

impl<'a> Mul for SignlessInteger<'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 SignlessInteger<'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 SignlessInteger<'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 SignlessInteger<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        std::fmt::Display::fmt(&self.0, f)
    }
}