@@ -58,6 +58,7 @@ use std::{
5858 marker:: PhantomData ,
5959 ops:: { Add , AddAssign , Div , DivAssign , Mul , MulAssign , Neg , Sub , SubAssign } ,
6060 str:: FromStr ,
61+ sync:: atomic:: { self , AtomicU32 , AtomicU64 } ,
6162 thread:: LocalKey ,
6263} ;
6364
@@ -330,7 +331,7 @@ impl<I: Id> DynamicModInt<I> {
330331 /// ```
331332 #[ inline]
332333 pub fn modulus ( ) -> u32 {
333- I :: companion_barrett ( ) . with ( |bt| bt . borrow ( ) . umod ( ) )
334+ I :: companion_barrett ( ) . umod ( )
334335 }
335336
336337 /// Sets a modulus.
@@ -354,7 +355,7 @@ impl<I: Id> DynamicModInt<I> {
354355 if modulus == 0 {
355356 panic ! ( "the modulus must not be 0" ) ;
356357 }
357- I :: companion_barrett ( ) . with ( |bt| * bt . borrow_mut ( ) = Barrett :: new ( modulus) )
358+ I :: companion_barrett ( ) . store ( modulus) ;
358359 }
359360
360361 /// Creates a new `DynamicModInt`.
@@ -442,47 +443,64 @@ impl<I: Id> ModIntBase for DynamicModInt<I> {
442443}
443444
444445pub 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 ;
447447}
448448
449449#[ derive( Copy , Clone , Ord , PartialOrd , Eq , PartialEq , Hash , Debug ) ]
450450pub enum DefaultId { }
451451
452452impl 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 ( ) ;
457455 & BARRETT
458456 }
459457}
460458
461- /// Pair of _m_ and _ceil(2⁶⁴/m)_.
462- pub struct Barrett ( internal_math:: Barrett ) ;
459+ /// $(m, \lceil 2^{64}/m \rceil)$ for barrett reduction.
460+ pub struct Barrett {
461+ m : AtomicU32 ,
462+ im : AtomicU64 ,
463+ }
463464
464465impl Barrett {
465466 /// Creates a new `Barrett`.
466467 #[ 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 store ( & 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 ) ;
469485 }
470486
471487 #[ inline]
472488 fn umod ( & self ) -> u32 {
473- self . 0 . umod ( )
489+ self . m . load ( atomic :: Ordering :: SeqCst )
474490 }
475491
476492 #[ inline]
477493 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)
479497 }
480498}
481499
482500impl Default for Barrett {
483501 #[ inline]
484502 fn default ( ) -> Self {
485- Self ( internal_math :: Barrett :: new ( 998_244_353 ) )
503+ Self :: default ( )
486504 }
487505}
488506
@@ -810,7 +828,7 @@ impl<M: Modulus> InternalImplementations for StaticModInt<M> {
810828impl < I : Id > InternalImplementations for DynamicModInt < I > {
811829 #[ inline]
812830 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 ) )
814832 }
815833}
816834
0 commit comments