1010//! - The type of the argument of `pow` is `u64`, not `i64`.
1111//! - Modints implement `FromStr` and `Display`. Modints in the original ACL don't have `operator<<` or `operator>>`.
1212
13- use crate :: internal_math:: { self , Barrett } ;
13+ use crate :: internal_math;
1414use std:: {
1515 cell:: RefCell ,
1616 convert:: { Infallible , TryInto as _} ,
@@ -20,11 +20,12 @@ use std::{
2020 marker:: PhantomData ,
2121 ops:: { Add , AddAssign , Div , DivAssign , Mul , MulAssign , Neg , Sub , SubAssign } ,
2222 str:: FromStr ,
23+ thread:: LocalKey ,
2324} ;
2425
2526pub type ModInt1000000007 = StaticModInt < Mod1000000007 > ;
2627pub type ModInt998244353 = StaticModInt < Mod998244353 > ;
27- pub type ModInt = DynamicModInt < Id0 > ;
28+ pub type ModInt = DynamicModInt < DefaultId > ;
2829
2930/// Corresponds to `atcoder::static_modint` in the original ACL.
3031#[ derive( Copy , Clone , Eq , PartialEq ) ]
@@ -146,27 +147,15 @@ pub struct DynamicModInt<I> {
146147impl < I : Id > DynamicModInt < I > {
147148 #[ inline]
148149 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 ( ) )
156151 }
157152
158153 #[ inline]
159154 pub fn set_modulus ( modulus : u32 ) {
160155 if modulus == 0 {
161156 panic ! ( "the modulus must not be 0" ) ;
162157 }
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) )
170159 }
171160
172161 #[ inline]
@@ -221,23 +210,46 @@ impl<I: Id> ModIntBase for DynamicModInt<I> {
221210}
222211
223212pub trait Id : ' static + Copy + Eq {
224- const VALUE : usize ;
213+ // TODO: Make `internal_math::Barret` `Copy`.
214+ fn companion_barrett ( ) -> & ' static LocalKey < RefCell < Barrett > > ;
225215}
226216
227217#[ derive( Copy , Clone , Ord , PartialOrd , Eq , PartialEq , Hash , Debug ) ]
228- pub enum Id0 { }
218+ pub enum DefaultId { }
229219
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+ }
232227}
233228
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+ }
236246}
237247
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+ }
241253}
242254
243255pub trait ModIntBase :
@@ -434,13 +446,7 @@ impl<M: Modulus> InternalImplementations for StaticModInt<M> {
434446impl < I : Id > InternalImplementations for DynamicModInt < I > {
435447 #[ inline]
436448 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 ) ) )
444450 }
445451}
446452
0 commit comments