Skip to content

Commit 25019f1

Browse files
committed
Declare &LocalKey<Barrett> in Id
1 parent 123c360 commit 25019f1

File tree

2 files changed

+39
-33
lines changed

2 files changed

+39
-33
lines changed

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ pub(crate) mod internal_type_traits;
1919

2020
pub use fenwicktree::FenwickTree;
2121
pub use modint::{
22-
DynamicModInt, Id, Id0, IntoRepresentative, Mod1000000007, Mod998244353, ModInt,
22+
Barrett, DefaultId, DynamicModInt, Id, IntoRepresentative, Mod1000000007, Mod998244353, ModInt,
2323
ModInt1000000007, ModInt998244353, Modulus, StaticModInt,
2424
};

src/modint.rs

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
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;
1414
use 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

2526
pub type ModInt1000000007 = StaticModInt<Mod1000000007>;
2627
pub 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> {
146147
impl<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

223212
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>>;
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

243255
pub trait ModIntBase:
@@ -434,13 +446,7 @@ impl<M: Modulus> InternalImplementations for StaticModInt<M> {
434446
impl<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

Comments
 (0)