use crate::{
modular_inverse_euclidean_u64::modinv,
static_modular_arithmetic_trait::ModularArithmetic,
static_modulus_trait::Get,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
pub struct DefaultStatic<T, M: Get<T = T>>(std::marker::PhantomData<(T, M)>);
macro_rules! impl_default_static {
($uint:ty, $mul_cast_uint:ty) => {
impl<M: Get<T = $uint>> ModularArithmetic for DefaultStatic<$uint, M> {
type T = $uint;
fn modulus() -> Self::T {
M::get()
}
fn add(
lhs: Self::T,
rhs: Self::T,
) -> Self::T {
assert!(lhs < M::get() && rhs < M::get());
let mut x = lhs;
x += rhs;
if x >= M::get() {
x -= M::get();
}
x
}
fn neg(x: Self::T) -> Self::T {
assert!(x < M::get());
if x == 0 {
0
} else {
M::get() - x
}
}
fn mul(
lhs: Self::T,
rhs: Self::T,
) -> Self::T {
let mut x = lhs as $mul_cast_uint;
x *= rhs as $mul_cast_uint;
x %= M::get() as $mul_cast_uint;
x as Self::T
}
fn inv(x: $uint) -> Self::T {
assert!(x > 0);
modinv(M::get() as u64, x as u64).unwrap() as Self::T
}
}
};
}
impl_default_static!(u32, u64);
impl_default_static!(u64, u128);
use crate::define_const_modulus_macro::{
Mod1_000_000_007,
Mod998_244_353,
};
#[allow(dead_code)]
pub type Modular1_000_000_007 = DefaultStatic<u32, Mod1_000_000_007>;
#[allow(dead_code)]
pub type Modular998_244_353 = DefaultStatic<u32, Mod998_244_353>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
use crate::modular_int_with_arithmetic::Modint;
type Mint = Modint<u32, Modular1_000_000_007>;
let a = Mint::from(1_000_000_008);
assert_eq!(a.value(), 1);
}
}