dsalgo 0.2.6

A package for Datastructures and Algorithms.
Documentation
use crate::{abstract_traits, power::Power};

pub trait IsPrime {}

pub trait Modulo {
    const VALUE: usize;
}

pub struct Add;
pub struct Mul;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Modular<M> {
    phantom: std::marker::PhantomData<M>,
    value: usize,
}

impl<M> std::fmt::Display for Modular<M> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.value)
    }
}
impl<M> Modular<M> {
    pub const fn value(&self) -> usize { self.value }
}

impl<M: Modulo> Modular<M> {
    pub fn new(n: usize) -> Self {
        Self {
            phantom: std::marker::PhantomData,
            value: n % M::VALUE,
        }
    }
}

impl<M: Modulo> From<usize> for Modular<M> {
    fn from(value: usize) -> Self { Self::new(value) }
}

impl<M: Modulo> abstract_traits::Identity<Add> for Modular<M> {
    fn identity() -> Self { 0.into() }
}

impl<M: Modulo> abstract_traits::Identity<Mul> for Modular<M> {
    fn identity() -> Self { 1.into() }
}

impl<M: Modulo> abstract_traits::Semigroup<Add> for Modular<M> {
    fn operate(lhs: &Self, rhs: &Self) -> Self {
        (lhs.value + rhs.value).into()
    }
}

impl<M: Modulo> abstract_traits::Semigroup<Mul> for Modular<M> {
    fn operate(lhs: &Self, rhs: &Self) -> Self {
        (lhs.value * rhs.value).into()
    }
}

impl<M: Modulo + Copy> std::ops::AddAssign<Self> for Modular<M> {
    fn add_assign(&mut self, rhs: Self) { *self = *self + rhs; }
}

impl<M: Modulo> std::ops::Add<Self> for Modular<M> {
    type Output = Self;

    fn add(self, rhs: Self) -> Self::Output { (self.value + rhs.value).into() }
}

impl<M: Modulo> std::ops::Neg for Modular<M> {
    type Output = Self;

    fn neg(self) -> Self::Output { (M::VALUE - self.value).into() }
}

impl<M: Modulo + Copy> std::ops::SubAssign<Self> for Modular<M> {
    fn sub_assign(&mut self, rhs: Self) { *self += -rhs; }
}

impl<M: Modulo> std::ops::Sub<Self> for Modular<M> {
    type Output = Self;

    fn sub(self, rhs: Self) -> Self { self + -rhs }
}

impl<M: Modulo> std::ops::Mul<Self> for Modular<M> {
    type Output = Self;

    fn mul(self, rhs: Self) -> Self { (self.value * rhs.value).into() }
}

impl<M: Modulo + Copy> std::ops::MulAssign<Self> for Modular<M> {
    fn mul_assign(&mut self, rhs: Self) { *self = *self * rhs; }
}

impl<M: Modulo + IsPrime> Modular<M>
where
    Self: Power<Self, Mul>,
{
    pub fn invert(&self) -> Self { Self::pow(self, M::VALUE - 2) }
}

impl<M: Modulo + IsPrime> std::ops::Div<Self> for Modular<M> {
    type Output = Self;

    fn div(self, rhs: Self) -> Self { self * rhs.invert() }
}

impl<M: Modulo + IsPrime + Copy> std::ops::DivAssign<Self> for Modular<M> {
    fn div_assign(&mut self, rhs: Self) { *self = *self / rhs; }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MOD998_244_353;
impl Modulo for MOD998_244_353 {
    const VALUE: usize = 998_244_353;
}
impl IsPrime for MOD998_244_353 {}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MOD1_000_000_007;
impl Modulo for MOD1_000_000_007 {
    const VALUE: usize = 1_000_000_007;
}
impl IsPrime for MOD1_000_000_007 {}

#[cfg(test)]
mod tests {
    #[test]
    fn test() {
        type Mint = super::Modular<super::MOD998_244_353>;

        let mut x = Mint::new(998_244_353);
        assert_eq!(x.value(), 0);
        x += Mint::new(10);
        assert_eq!(x.value(), 10);
        x -= Mint::new(9);
        assert_eq!(x.value(), 1);
        x /= Mint::new(2);
        assert_eq!(x.value(), 499122177);
    }
}