dsalgo/
modular_int_with_const_modulus_i64.rs

1use std::{
2    marker::PhantomData,
3    ops::*,
4};
5
6use crate::{
7    const_modulus_trait::Modulus,
8    modular_inverse_euclidean_i64_no_error::modinv,
9    multiplicative_inverse::MulInv,
10};
11
12#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
13
14pub struct Modint<M>(pub i64, PhantomData<M>);
15
16impl<M> std::fmt::Display for Modint<M> {
17    fn fmt(
18        &self,
19        f: &mut std::fmt::Formatter,
20    ) -> std::fmt::Result {
21        write!(f, "{}", self.0)
22    }
23}
24
25impl<M: Modulus<T = i64>> Modint<M> {
26    pub fn modulus() -> i64 {
27        M::MOD
28    }
29
30    pub fn normalize(mut v: i64) -> i64 {
31        let m = M::MOD;
32
33        if v < -M::MOD || v >= m {
34            v %= m;
35        }
36
37        if v < 0 {
38            v += m;
39        }
40
41        v
42    }
43
44    pub fn new(v: i64) -> Self {
45        Self(Self::normalize(v), PhantomData)
46    }
47}
48
49impl<M: Modulus<T = i64>> Add for Modint<M> {
50    type Output = Self;
51
52    fn add(
53        mut self,
54        rhs: Self,
55    ) -> Self::Output {
56        self.0 += rhs.0;
57
58        if self.0 >= M::MOD {
59            self.0 -= M::MOD;
60        }
61
62        self
63    }
64}
65
66impl<M: Modulus<T = i64>> Neg for Modint<M> {
67    type Output = Self;
68
69    fn neg(mut self) -> Self::Output {
70        if self.0 != 0 {
71            self.0 = M::MOD - self.0;
72        }
73
74        self
75    }
76}
77
78impl<M: Modulus<T = i64>> Mul for Modint<M> {
79    type Output = Self;
80
81    fn mul(
82        mut self,
83        rhs: Self,
84    ) -> Self::Output {
85        self.0 *= rhs.0;
86
87        if self.0 >= M::MOD {
88            self.0 %= M::MOD;
89        }
90
91        self
92    }
93}
94
95impl<M: Modulus<T = i64>> MulInv for Modint<M> {
96    type Output = Self;
97
98    fn mul_inv(mut self) -> Self::Output {
99        self.0 = modinv(M::MOD, self.0);
100
101        self
102    }
103}
104
105impl<M: Modulus<T = i64>> Sub for Modint<M> {
106    type Output = Self;
107
108    fn sub(
109        self,
110        rhs: Self,
111    ) -> Self::Output {
112        self + -rhs
113    }
114}
115
116impl<M: Modulus<T = i64>> Div for Modint<M> {
117    type Output = Self;
118
119    fn div(
120        self,
121        rhs: Self,
122    ) -> Self::Output {
123        self * rhs.mul_inv()
124    }
125}
126
127impl<M: Modulus<T = i64>> Add<i64> for Modint<M> {
128    type Output = Self;
129
130    fn add(
131        self,
132        rhs: i64,
133    ) -> Self::Output {
134        self + Self::new(rhs)
135    }
136}
137
138impl<M: Modulus<T = i64>> Sub<i64> for Modint<M> {
139    type Output = Self;
140
141    fn sub(
142        self,
143        rhs: i64,
144    ) -> Self::Output {
145        self - Self::new(rhs)
146    }
147}
148
149impl<M: Modulus<T = i64>> Mul<i64> for Modint<M> {
150    type Output = Self;
151
152    fn mul(
153        self,
154        rhs: i64,
155    ) -> Self::Output {
156        self * Self::new(rhs)
157    }
158}
159
160impl<M: Modulus<T = i64>> Div<i64> for Modint<M> {
161    type Output = Self;
162
163    fn div(
164        self,
165        rhs: i64,
166    ) -> Self::Output {
167        self / Self::new(rhs)
168    }
169}
170
171impl<M: Modulus<T = i64>> Add<Modint<M>> for i64 {
172    type Output = Modint<M>;
173
174    fn add(
175        self,
176        rhs: Modint<M>,
177    ) -> Self::Output {
178        Modint::<M>::new(self) + rhs
179    }
180}
181
182impl<M: Modulus<T = i64>> Sub<Modint<M>> for i64 {
183    type Output = Modint<M>;
184
185    fn sub(
186        self,
187        rhs: Modint<M>,
188    ) -> Self::Output {
189        Modint::<M>::new(self) - rhs
190    }
191}
192
193impl<M: Modulus<T = i64>> Mul<Modint<M>> for i64 {
194    type Output = Modint<M>;
195
196    fn mul(
197        self,
198        rhs: Modint<M>,
199    ) -> Self::Output {
200        Modint::<M>::new(self) * rhs
201    }
202}
203
204impl<M: Modulus<T = i64>> Div<Modint<M>> for i64 {
205    type Output = Modint<M>;
206
207    fn div(
208        self,
209        rhs: Modint<M>,
210    ) -> Self::Output {
211        Modint::<M>::new(self) / rhs
212    }
213}
214
215impl<M: Modulus<T = i64> + Copy, T> AddAssign<T> for Modint<M>
216where
217    Self: Add<T, Output = Self>,
218{
219    fn add_assign(
220        &mut self,
221        rhs: T,
222    ) {
223        *self = *self + rhs;
224    }
225}
226
227impl<M: Modulus<T = i64> + Copy, T> SubAssign<T> for Modint<M>
228where
229    Self: Sub<T, Output = Self>,
230{
231    fn sub_assign(
232        &mut self,
233        rhs: T,
234    ) {
235        *self = *self - rhs;
236    }
237}
238
239impl<M: Modulus<T = i64> + Copy, T> MulAssign<T> for Modint<M>
240where
241    Self: Mul<T, Output = Self>,
242{
243    fn mul_assign(
244        &mut self,
245        rhs: T,
246    ) {
247        *self = *self * rhs;
248    }
249}
250
251impl<M: Modulus<T = i64> + Copy, T> DivAssign<T> for Modint<M>
252where
253    Self: Div<T, Output = Self>,
254{
255    fn div_assign(
256        &mut self,
257        rhs: T,
258    ) {
259        *self = *self / rhs;
260    }
261}
262
263impl<M: Modulus<T = i64> + Copy> Modint<M> {
264    pub fn pow(
265        self,
266        n: i64,
267    ) -> Self {
268        if n < 0 {
269            return self.mul_inv().pow(-n);
270        }
271
272        if n == 0 {
273            return Self::new(1);
274        }
275
276        let mut y = self.pow(n >> 1);
277
278        y *= y;
279
280        if n & 1 == 1 {
281            y *= self;
282        }
283
284        y
285    }
286}
287
288impl<M: Modulus<T = i64>> From<i32> for Modint<M> {
289    fn from(x: i32) -> Self {
290        Self::new(x as i64)
291    }
292}
293
294impl<M: Modulus<T = i64>> From<usize> for Modint<M> {
295    fn from(x: usize) -> Self {
296        Self::new(x as i64)
297    }
298}
299
300#[cfg(test)]
301
302mod tests {
303
304    use super::*;
305
306    #[test]
307
308    fn test() {
309        use crate::define_const_modulus_macro::Mod1_000_000_007I64;
310
311        type Mint = Modint<Mod1_000_000_007I64>;
312
313        let mut x = Mint::new(-1);
314
315        assert_eq!(x.0, 1_000_000_006);
316
317        x += 2;
318
319        assert_eq!(x.0, 1);
320
321        assert_eq!((5 * x).0, 5);
322
323        x.0 = 2;
324
325        assert_eq!(x.pow(-1).0, (Mint::modulus() + 1) >> 1);
326    }
327}