@@ -58,6 +58,7 @@ use std::{
58
58
marker:: PhantomData ,
59
59
ops:: { Add , AddAssign , Div , DivAssign , Mul , MulAssign , Neg , Sub , SubAssign } ,
60
60
str:: FromStr ,
61
+ sync:: atomic:: { self , AtomicU32 , AtomicU64 } ,
61
62
thread:: LocalKey ,
62
63
} ;
63
64
@@ -330,7 +331,7 @@ impl<I: Id> DynamicModInt<I> {
330
331
/// ```
331
332
#[ inline]
332
333
pub fn modulus ( ) -> u32 {
333
- I :: companion_barrett ( ) . with ( |bt| bt . borrow ( ) . umod ( ) )
334
+ I :: companion_barrett ( ) . umod ( )
334
335
}
335
336
336
337
/// Sets a modulus.
@@ -354,7 +355,7 @@ impl<I: Id> DynamicModInt<I> {
354
355
if modulus == 0 {
355
356
panic ! ( "the modulus must not be 0" ) ;
356
357
}
357
- I :: companion_barrett ( ) . with ( |bt| * bt . borrow_mut ( ) = Barrett :: new ( modulus) )
358
+ I :: companion_barrett ( ) . update ( modulus) ;
358
359
}
359
360
360
361
/// Creates a new `DynamicModInt`.
@@ -442,47 +443,64 @@ impl<I: Id> ModIntBase for DynamicModInt<I> {
442
443
}
443
444
444
445
pub trait Id : ' static + Copy + Eq {
445
- // TODO: Make `internal_math::Barret` `Copy`.
446
- fn companion_barrett ( ) -> & ' static LocalKey < RefCell < Barrett > > ;
446
+ fn companion_barrett ( ) -> & ' static Barrett ;
447
447
}
448
448
449
449
#[ derive( Copy , Clone , Ord , PartialOrd , Eq , PartialEq , Hash , Debug ) ]
450
450
pub enum DefaultId { }
451
451
452
452
impl Id for DefaultId {
453
- fn companion_barrett ( ) -> & ' static LocalKey < RefCell < Barrett > > {
454
- thread_local ! {
455
- static BARRETT : RefCell <Barrett > = RefCell :: default ( ) ;
456
- }
453
+ fn companion_barrett ( ) -> & ' static Barrett {
454
+ static BARRETT : Barrett = Barrett :: default ( ) ;
457
455
& BARRETT
458
456
}
459
457
}
460
458
461
459
/// Pair of _m_ and _ceil(2⁶⁴/m)_.
462
- pub struct Barrett ( internal_math:: Barrett ) ;
460
+ pub struct Barrett {
461
+ m : AtomicU32 ,
462
+ im : AtomicU64 ,
463
+ }
463
464
464
465
impl Barrett {
465
466
/// Creates a new `Barrett`.
466
467
#[ inline]
467
- pub fn new ( m : u32 ) -> Self {
468
- Self ( internal_math:: Barrett :: new ( m) )
468
+ pub const fn new ( m : u32 ) -> Self {
469
+ Self {
470
+ m : AtomicU32 :: new ( m) ,
471
+ im : AtomicU64 :: new ( ( -1i64 as u64 / m as u64 ) . wrapping_add ( 1 ) ) ,
472
+ }
473
+ }
474
+
475
+ #[ inline]
476
+ const fn default ( ) -> Self {
477
+ Self :: new ( 998_244_353 )
478
+ }
479
+
480
+ #[ inline]
481
+ fn update ( & self , m : u32 ) {
482
+ let im = ( -1i64 as u64 / m as u64 ) . wrapping_add ( 1 ) ;
483
+ self . m . store ( m, atomic:: Ordering :: SeqCst ) ;
484
+ self . im . store ( im, atomic:: Ordering :: SeqCst ) ;
469
485
}
470
486
471
487
#[ inline]
472
488
fn umod ( & self ) -> u32 {
473
- self . 0 . umod ( )
489
+ self . m . load ( atomic :: Ordering :: SeqCst )
474
490
}
475
491
476
492
#[ inline]
477
493
fn mul ( & self , a : u32 , b : u32 ) -> u32 {
478
- self . 0 . mul ( a, b)
494
+ let m = self . m . load ( atomic:: Ordering :: SeqCst ) ;
495
+ let im = self . im . load ( atomic:: Ordering :: SeqCst ) ;
496
+ internal_math:: mul_mod ( a, b, m, im)
479
497
}
480
498
}
481
499
482
500
impl Default for Barrett {
483
501
#[ inline]
484
502
fn default ( ) -> Self {
485
- Self ( internal_math :: Barrett :: new ( 998_244_353 ) )
503
+ Self :: default ( )
486
504
}
487
505
}
488
506
@@ -810,7 +828,7 @@ impl<M: Modulus> InternalImplementations for StaticModInt<M> {
810
828
impl < I : Id > InternalImplementations for DynamicModInt < I > {
811
829
#[ inline]
812
830
fn mul_impl ( lhs : Self , rhs : Self ) -> Self {
813
- I :: companion_barrett ( ) . with ( |bt| Self :: raw ( bt . borrow ( ) . mul ( lhs. val , rhs. val ) ) )
831
+ Self :: raw ( I :: companion_barrett ( ) . mul ( lhs. val , rhs. val ) )
814
832
}
815
833
}
816
834
0 commit comments