@@ -165,87 +165,88 @@ impl Div for Complex {
165
165
}
166
166
}
167
167
168
- //github.com/ Represents an element of the finite (Galois) field of prime order, given by
169
- //github.com/ MOD. Until Rust gets const generics, MOD must be hardcoded, but any prime in
170
- //github.com/ [1, 2^31.5] will work. If MOD is not prime, ring operations are still valid
168
+ //github.com/ Represents an element of the finite (Galois) field of prime order M, where
169
+ //github.com/ 1 <= M < 2^31.5. If M is not prime, ring operations are still valid
171
170
//github.com/ but recip() and division are not. Note that the latter operations are also
172
171
//github.com/ the slowest, so precompute any inverses that you intend to use frequently.
173
172
#[ derive( Clone , Copy , Eq , PartialEq , Debug , Hash ) ]
174
- pub struct Field {
173
+ pub struct Modulo < const M : i64 > {
175
174
pub val : i64 ,
176
175
}
177
- impl Field {
178
- pub const MOD : i64 = 998_244_353 ; // 2^23 * 7 * 17 + 1
179
-
180
- //github.com/ Computes self^exp in O(log(exp)) time
181
- pub fn pow ( mut self , mut exp : u64 ) -> Self {
176
+ impl < const M : i64 > Modulo < M > {
177
+ //github.com/ Computes self^n in O(log n) time
178
+ pub fn pow ( mut self , mut n : u64 ) -> Self {
182
179
let mut result = Self :: from_small ( 1 ) ;
183
- while exp > 0 {
184
- if exp % 2 == 1 {
180
+ while n > 0 {
181
+ if n % 2 == 1 {
185
182
result = result * self ;
186
183
}
187
184
self = self * self ;
188
- exp /= 2 ;
185
+ n /= 2 ;
189
186
}
190
187
result
191
188
}
192
189
//github.com/ Computes inverses of 1 to n in O(n) time
193
190
pub fn vec_of_recips ( n : i64 ) -> Vec < Self > {
194
191
let mut recips = vec ! [ Self :: from( 0 ) , Self :: from( 1 ) ] ;
195
192
for i in 2 ..=n {
196
- let ( md, dv) = ( Self :: MOD % i, Self :: MOD / i) ;
193
+ let ( md, dv) = ( M % i, M / i) ;
197
194
recips. push ( recips[ md as usize ] * Self :: from_small ( -dv) ) ;
198
195
}
199
196
recips
200
197
}
201
- //github.com/ Computes self^-1 in O(log(Self::MOD) ) time
198
+ //github.com/ Computes self^-1 in O(log M ) time
202
199
pub fn recip ( self ) -> Self {
203
- self . pow ( Self :: MOD as u64 - 2 )
200
+ self . pow ( M as u64 - 2 )
204
201
}
205
- //github.com/ Avoids the % operation but requires -Self::MOD <= x < Self::MOD
202
+ //github.com/ Avoids the % operation but requires -M <= x < M
206
203
fn from_small ( s : i64 ) -> Self {
207
- let val = if s < 0 { s + Self :: MOD } else { s } ;
204
+ let val = if s < 0 { s + M } else { s } ;
208
205
Self { val }
209
206
}
210
207
}
211
- impl From < i64 > for Field {
208
+ impl < const M : i64 > From < i64 > for Modulo < M > {
212
209
fn from ( val : i64 ) -> Self {
213
- // Self { val: val.rem_euclid(Self::MOD ) }
214
- Self :: from_small ( val % Self :: MOD )
210
+ // Self { val: val.rem_euclid(M ) }
211
+ Self :: from_small ( val % M )
215
212
}
216
213
}
217
- impl Neg for Field {
214
+ impl < const M : i64 > Neg for Modulo < M > {
218
215
type Output = Self ;
219
216
fn neg ( self ) -> Self {
220
217
Self :: from_small ( -self . val )
221
218
}
222
219
}
223
- impl Add for Field {
220
+ impl < const M : i64 > Add for Modulo < M > {
224
221
type Output = Self ;
225
222
fn add ( self , other : Self ) -> Self {
226
- Self :: from_small ( self . val + other. val - Self :: MOD )
223
+ Self :: from_small ( self . val + other. val - M )
227
224
}
228
225
}
229
- impl Sub for Field {
226
+ impl < const M : i64 > Sub for Modulo < M > {
230
227
type Output = Self ;
231
228
fn sub ( self , other : Self ) -> Self {
232
229
Self :: from_small ( self . val - other. val )
233
230
}
234
231
}
235
- impl Mul for Field {
232
+ impl < const M : i64 > Mul for Modulo < M > {
236
233
type Output = Self ;
237
234
fn mul ( self , other : Self ) -> Self {
238
235
Self :: from ( self . val * other. val )
239
236
}
240
237
}
241
238
#[ allow( clippy:: suspicious_arithmetic_impl) ]
242
- impl Div for Field {
239
+ impl < const M : i64 > Div for Modulo < M > {
243
240
type Output = Self ;
244
241
fn div ( self , other : Self ) -> Self {
245
242
self * other. recip ( )
246
243
}
247
244
}
248
245
246
+ //github.com/ Prime modulus that's commonly used in programming competitions
247
+ pub const COMMON_PRIME : i64 = 998_244_353 ; // 2^23 * 7 * 17 + 1;
248
+ pub type CommonField = Modulo < COMMON_PRIME > ;
249
+
249
250
#[ derive( Clone , PartialEq , Debug ) ]
250
251
pub struct Matrix {
251
252
cols : usize ,
@@ -268,15 +269,15 @@ impl Matrix {
268
269
let inner = vec. to_vec ( ) . into_boxed_slice ( ) ;
269
270
Self { cols, inner }
270
271
}
271
- pub fn pow ( & self , mut exp : u64 ) -> Self {
272
+ pub fn pow ( & self , mut n : u64 ) -> Self {
272
273
let mut base = self . clone ( ) ;
273
274
let mut result = Self :: one ( self . cols ) ;
274
- while exp > 0 {
275
- if exp % 2 == 1 {
275
+ while n > 0 {
276
+ if n % 2 == 1 {
276
277
result = & result * & base;
277
278
}
278
279
base = & base * & base;
279
- exp /= 2 ;
280
+ n /= 2 ;
280
281
}
281
282
result
282
283
}
@@ -417,10 +418,10 @@ mod test {
417
418
418
419
#[ test]
419
420
fn test_field ( ) {
420
- let base = Field :: from ( 1234 ) ;
421
+ let base = CommonField :: from ( 1234 ) ;
421
422
let zero = base - base;
422
423
let one = base. recip ( ) * base;
423
- let two = Field :: from ( 2 - 5 * Field :: MOD ) ;
424
+ let two = CommonField :: from ( 2 - 5 * COMMON_PRIME ) ;
424
425
425
426
assert_eq ! ( zero. val, 0 ) ;
426
427
assert_eq ! ( one. val, 1 ) ;
@@ -430,11 +431,11 @@ mod test {
430
431
431
432
#[ test]
432
433
fn test_vec_of_recips ( ) {
433
- let recips = Field :: vec_of_recips ( 20 ) ;
434
+ let recips = CommonField :: vec_of_recips ( 20 ) ;
434
435
435
436
assert_eq ! ( recips. len( ) , 21 ) ;
436
437
for i in 1 ..recips. len ( ) {
437
- assert_eq ! ( recips[ i] , Field :: from( i as i64 ) . recip( ) ) ;
438
+ assert_eq ! ( recips[ i] , CommonField :: from( i as i64 ) . recip( ) ) ;
438
439
}
439
440
}
440
441
0 commit comments