Skip to content

Commit 7bf928b

Browse files
Added internal_math
1 parent 459bd7c commit 7bf928b

File tree

2 files changed

+221
-0
lines changed

2 files changed

+221
-0
lines changed

src/internal_math.rs

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
mod atcoder {
2+
mod internal {
3+
use std::mem::swap;
4+
5+
/// # Arguments
6+
/// * `m` `1 <= m`
7+
///
8+
/// # Returns
9+
/// x mod m
10+
/* const */
11+
fn safe_mod(mut x: i64, m: i64) -> i64 {
12+
x %= m;
13+
if x < 0 {
14+
x += m;
15+
}
16+
x
17+
}
18+
19+
/// Fast moduler by barrett reduction
20+
/// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
21+
/// NOTE: reconsider after Ice Lake
22+
struct Barrett {
23+
_m: u32,
24+
im: u64,
25+
}
26+
27+
impl Barrett {
28+
/// # Arguments
29+
/// * `m` `1 <= m`
30+
fn new(m: u32) -> Barrett {
31+
Barrett {
32+
_m: m,
33+
im: (-1i64 as u64) / (m as u64) + 1,
34+
}
35+
}
36+
37+
/// # Returns
38+
/// `m`
39+
fn umod(&self) -> u32 {
40+
self._m
41+
}
42+
43+
/// # Parameters
44+
/// * `a` `0 <= a < m`
45+
/// * `b` `0 <= b < m`
46+
///
47+
/// # Returns
48+
/// a * b % m
49+
fn mul(&self, a: u32, b: u32) -> u32 {
50+
// [1] m = 1
51+
// a = b = im = 0, so okay
52+
53+
// [2] m >= 2
54+
// im = ceil(2^64 / m)
55+
// -> im * m = 2^64 + r (0 <= r < m)
56+
// let z = a*b = c*m + d (0 <= c, d < m)
57+
// a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
58+
// c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2
59+
// ((ab * im) >> 64) == c or c + 1
60+
let mut z = a as u64;
61+
z *= b as u64;
62+
let x = (((z as u128) * (self.im as u128)) >> 64) as u64;
63+
let mut v = (z - x * self._m as u64) as u32;
64+
if self._m <= v {
65+
v += self._m;
66+
}
67+
v
68+
}
69+
}
70+
71+
/// # Parameters
72+
/// * `n` `0 <= n`
73+
/// * `m` `1 <= m`
74+
///
75+
/// # Returns
76+
/// `(x ** n) % m`
77+
/* const */
78+
fn pow_mod_constexpr(x: i64, mut n: i64, m: i32) -> i64 {
79+
if m == 1 {
80+
return 0;
81+
}
82+
let _m = m as u32;
83+
let mut r: u64 = 1;
84+
let mut y: u64 = safe_mod(x, m as i64) as u64;
85+
while n != 0 {
86+
if (n & 1) > 0 {
87+
r = (r * y) % (_m as u64);
88+
}
89+
y = (y * y) % (_m as u64);
90+
n >>= 1;
91+
}
92+
r as i64
93+
}
94+
95+
/// Reference:
96+
/// M. Forisek and J. Jancina,
97+
/// Fast Primality Testing for Integers That Fit into a Machine Word
98+
///
99+
/// # Parameters
100+
/// * `n` `0 <= n`
101+
/* const */
102+
fn is_prime_constexpr(n: i32) -> bool {
103+
let n = n as i64;
104+
match n {
105+
_ if n <= 1 => return false,
106+
2 | 7 | 61 => return true,
107+
_ if n % 2 == 0 => return false,
108+
_ => {}
109+
}
110+
let mut d = n - 1;
111+
while d % 2 == 0 {
112+
d /= 2;
113+
}
114+
for a in [2, 7, 61].iter().copied() {
115+
let mut t = d;
116+
let mut y = pow_mod_constexpr(a, t, n as i32);
117+
while t != n - 1 && y != 1 && y != n - 1 {
118+
y = y * y % n;
119+
t <<= 1;
120+
}
121+
if y != n - 1 && t % 2 == 0 {
122+
return false;
123+
}
124+
}
125+
true
126+
}
127+
128+
// omitted
129+
// template <int n> constexpr bool is_prime = is_prime_constexpr(n);
130+
131+
/// # Parameters
132+
/// * `b` `1 <= b`
133+
///
134+
/// # Returns
135+
/// (g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
136+
/* const */
137+
fn inv_gcd(a: i64, b: i64) -> (i64, i64) {
138+
let a = safe_mod(a, b);
139+
if a == 0 {
140+
return (b, 0);
141+
}
142+
143+
// Contracts:
144+
// [1] s - m0 * a = 0 (mod b)
145+
// [2] t - m1 * a = 0 (mod b)
146+
// [3] s * |m1| + t * |m0| <= b
147+
let mut s = b;
148+
let mut t = a;
149+
let mut m0 = 0;
150+
let mut m1 = 1;
151+
152+
while t != 0 {
153+
let u = s / t;
154+
s -= t * u;
155+
m0 -= m1 * u; // |m1 * u| <= |m1| * s <= b
156+
157+
// [3]:
158+
// (s - t * u) * |m1| + t * |m0 - m1 * u|
159+
// <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
160+
// = s * |m1| + t * |m0| <= b
161+
162+
swap(&mut s, &mut t);
163+
swap(&mut m0, &mut m1);
164+
}
165+
// by [3]: |m0| <= b/g
166+
// by g != b: |m0| < b/g
167+
if m0 < 0 {
168+
m0 += b / s;
169+
}
170+
(s, m0)
171+
}
172+
173+
/// Compile time (currently not) primitive root
174+
/// @param m must be prime
175+
/// @return primitive root (and minimum in now)
176+
/* const */
177+
fn primitive_root_constexpr(m: i32) -> i32 {
178+
match m {
179+
2 => return 1,
180+
167_772_161 => return 3,
181+
469_762_049 => return 3,
182+
754_974_721 => return 11,
183+
998_244_353 => return 3,
184+
_ => {}
185+
}
186+
187+
let mut divs = [0; 20];
188+
divs[0] = 2;
189+
let mut cnt = 1;
190+
let mut x = (m - 1) / 2;
191+
while x % 2 == 0 {
192+
x /= 2;
193+
}
194+
for i in (3..std::i32::MAX).step_by(2) {
195+
if (i as i64) * (i as i64) <= (x as i64) {
196+
break;
197+
}
198+
if x % i == 0 {
199+
divs[cnt] = i;
200+
cnt += 1;
201+
while x % i == 0 {
202+
x /= i;
203+
}
204+
}
205+
}
206+
if x > 1 {
207+
divs[cnt] = x;
208+
cnt += 1;
209+
}
210+
let mut g = 2;
211+
loop {
212+
if (0..cnt).any(|i| pow_mod_constexpr(g, ((m - 1) / divs[i]) as i64, m) == 1) {
213+
break g as i32;
214+
}
215+
g += 1;
216+
}
217+
}
218+
}
219+
}

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@ mod scc;
1010
mod segtree;
1111
mod string;
1212
mod twosat;
13+
14+
mod internal_math;

0 commit comments

Comments
 (0)