10
10
//! - The type of the argument of `pow` is `u64`, not `i64`.
11
11
//! - Modints implement `FromStr` and `Display`. Modints in the original ACL don't have `operator<<` or `operator>>`.
12
12
13
- use crate :: internal_math:: { self , Barrett } ;
13
+ use crate :: internal_math;
14
14
use std:: {
15
15
cell:: RefCell ,
16
16
convert:: { Infallible , TryInto as _} ,
@@ -20,11 +20,12 @@ use std::{
20
20
marker:: PhantomData ,
21
21
ops:: { Add , AddAssign , Div , DivAssign , Mul , MulAssign , Neg , Sub , SubAssign } ,
22
22
str:: FromStr ,
23
+ thread:: LocalKey ,
23
24
} ;
24
25
25
26
pub type ModInt1000000007 = StaticModInt < Mod1000000007 > ;
26
27
pub type ModInt998244353 = StaticModInt < Mod998244353 > ;
27
- pub type ModInt = DynamicModInt < Id0 > ;
28
+ pub type ModInt = DynamicModInt < DefaultId > ;
28
29
29
30
/// Corresponds to `atcoder::static_modint` in the original ACL.
30
31
#[ derive( Copy , Clone , Eq , PartialEq ) ]
@@ -146,27 +147,15 @@ pub struct DynamicModInt<I> {
146
147
impl < I : Id > DynamicModInt < I > {
147
148
#[ inline]
148
149
pub fn modulus ( ) -> u32 {
149
- BARRETTS . with ( |bts| {
150
- let mut bts = bts. borrow_mut ( ) ;
151
- if bts. len ( ) <= I :: VALUE {
152
- bts. resize_with ( I :: VALUE + 1 , default_barrett) ;
153
- }
154
- bts[ I :: VALUE ] . umod ( )
155
- } )
150
+ I :: companion_barrett ( ) . with ( |bt| bt. borrow ( ) . umod ( ) )
156
151
}
157
152
158
153
#[ inline]
159
154
pub fn set_modulus ( modulus : u32 ) {
160
155
if modulus == 0 {
161
156
panic ! ( "the modulus must not be 0" ) ;
162
157
}
163
- BARRETTS . with ( |bts| {
164
- let mut bts = bts. borrow_mut ( ) ;
165
- if bts. len ( ) <= I :: VALUE {
166
- bts. resize_with ( I :: VALUE + 1 , default_barrett) ;
167
- }
168
- bts[ I :: VALUE ] = Barrett :: new ( modulus) ;
169
- } )
158
+ I :: companion_barrett ( ) . with ( |bt| * bt. borrow_mut ( ) = Barrett :: new ( modulus) )
170
159
}
171
160
172
161
#[ inline]
@@ -221,23 +210,46 @@ impl<I: Id> ModIntBase for DynamicModInt<I> {
221
210
}
222
211
223
212
pub trait Id : ' static + Copy + Eq {
224
- const VALUE : usize ;
213
+ // TODO: Make `internal_math::Barret` `Copy`.
214
+ fn companion_barrett ( ) -> & ' static LocalKey < RefCell < Barrett > > ;
225
215
}
226
216
227
217
#[ derive( Copy , Clone , Ord , PartialOrd , Eq , PartialEq , Hash , Debug ) ]
228
- pub enum Id0 { }
218
+ pub enum DefaultId { }
229
219
230
- impl Id for Id0 {
231
- const VALUE : usize = 0 ;
220
+ impl Id for DefaultId {
221
+ fn companion_barrett ( ) -> & ' static LocalKey < RefCell < Barrett > > {
222
+ thread_local ! {
223
+ static BARRETT : RefCell <Barrett > = RefCell :: default ( ) ;
224
+ }
225
+ & BARRETT
226
+ }
232
227
}
233
228
234
- thread_local ! {
235
- static BARRETTS : RefCell <Vec <Barrett >> = RefCell :: new( vec![ default_barrett( ) ] ) ;
229
+ pub struct Barrett ( internal_math:: Barrett ) ;
230
+
231
+ impl Barrett {
232
+ #[ inline]
233
+ pub fn new ( m : u32 ) -> Self {
234
+ Self ( internal_math:: Barrett :: new ( m) )
235
+ }
236
+
237
+ #[ inline]
238
+ fn umod ( & self ) -> u32 {
239
+ self . 0 . umod ( )
240
+ }
241
+
242
+ #[ inline]
243
+ fn mul ( & self , a : u32 , b : u32 ) -> u32 {
244
+ self . 0 . mul ( a, b)
245
+ }
236
246
}
237
247
238
- #[ inline]
239
- fn default_barrett ( ) -> Barrett {
240
- Barrett :: new ( 998_244_353 )
248
+ impl Default for Barrett {
249
+ #[ inline]
250
+ fn default ( ) -> Self {
251
+ Self ( internal_math:: Barrett :: new ( 998_244_353 ) )
252
+ }
241
253
}
242
254
243
255
pub trait ModIntBase :
@@ -434,13 +446,7 @@ impl<M: Modulus> InternalImplementations for StaticModInt<M> {
434
446
impl < I : Id > InternalImplementations for DynamicModInt < I > {
435
447
#[ inline]
436
448
fn mul_impl ( lhs : Self , rhs : Self ) -> Self {
437
- BARRETTS . with ( |bts| {
438
- let mut bts = bts. borrow_mut ( ) ;
439
- if bts. len ( ) <= I :: VALUE {
440
- bts. resize_with ( I :: VALUE + 1 , default_barrett) ;
441
- }
442
- Self :: raw ( bts[ I :: VALUE ] . mul ( lhs. val , rhs. val ) )
443
- } )
449
+ I :: companion_barrett ( ) . with ( |bt| Self :: raw ( bt. borrow ( ) . mul ( lhs. val , rhs. val ) ) )
444
450
}
445
451
}
446
452
0 commit comments