1#![cfg_attr(feature = "__internal_inject_debug", recursion_limit = "16")]
2use num_traits::{One, Zero};
3use std::ops::{Add, AddAssign, BitAnd, Mul, MulAssign, Rem, ShrAssign};
4#[cfg(feature = "__internal_inject_debug")]
5mod sealed {
6 pub trait SizedExt: std::marker::Sized + std::fmt::Debug + std::fmt::Display {}
7 impl<T> SizedExt for T where T: std::marker::Sized + std::fmt::Debug + std::fmt::Display {}
8 pub use SizedExt as Sized;
9}
10#[cfg(not(feature = "__internal_inject_debug"))]
11mod sealed {
12 pub use std::marker::Sized;
13}
14mod ring_traits;
15#[cfg(test)]
16mod test;
17pub use ring_traits::{
18 EuclideanRingOperation, EuclideanRingOperationFrom, RingNormalize, RingOperation,
19 RingOperationFrom,
20};
21
22pub fn times<T, U>(a: T, p: U) -> T
29where
30 T: sealed::Sized + Zero + for<'x> AddAssign<&'x T> + for<'x> From<<&'x T as Add>::Output>,
31 for<'x> &'x T: Add,
32 U: sealed::Sized
33 + Zero
34 + One
35 + Eq
36 + for<'x> ShrAssign<usize>
37 + for<'x> From<<&'x U as BitAnd>::Output>,
38 for<'x> &'x U: BitAnd,
39{
40 add_times(T::zero(), a, p)
41}
42
43pub fn add_times<T, U>(b: T, a: T, mut p: U) -> T
52where
53 T: sealed::Sized + for<'x> AddAssign<&'x T> + for<'x> From<<&'x T as Add>::Output>,
54 for<'x> &'x T: Add,
55 U: sealed::Sized
56 + Zero
57 + One
58 + Eq
59 + for<'x> ShrAssign<usize>
60 + for<'x> From<<&'x U as BitAnd>::Output>,
61 for<'x> &'x U: BitAnd,
62{
63 let mut x = b;
64 let mut y = a;
65 loop {
66 if U::from(&p & &U::one()) == U::one() {
67 x += &y;
68 }
69 p >>= 1;
70 if p == U::zero() {
71 break;
72 }
73 y = T::from(&y + &y);
74 }
75 x
76}
77
78pub fn power<T, U>(a: T, p: U) -> T
85where
86 T: sealed::Sized + One + for<'x> MulAssign<&'x T> + for<'x> From<<&'x T as Mul>::Output>,
87 for<'x> &'x T: Mul,
88 U: sealed::Sized
89 + Zero
90 + One
91 + Eq
92 + for<'x> ShrAssign<usize>
93 + for<'x> From<<&'x U as BitAnd>::Output>,
94 for<'x> &'x U: BitAnd,
95{
96 mul_power(T::one(), a, p)
97}
98
99pub fn mul_power<T, U>(b: T, a: T, mut p: U) -> T
108where
109 T: sealed::Sized + for<'x> MulAssign<&'x T> + for<'x> From<<&'x T as Mul>::Output>,
110 for<'x> &'x T: Mul,
111 U: sealed::Sized
112 + Zero
113 + One
114 + Eq
115 + for<'x> ShrAssign<usize>
116 + for<'x> From<<&'x U as BitAnd>::Output>,
117 for<'x> &'x U: BitAnd,
118{
119 let mut x = b;
120 let mut y = a;
121 loop {
122 if U::from(&p & &U::one()) == U::one() {
123 x *= &y;
124 }
125 p >>= 1;
126 if p == U::zero() {
127 break;
128 }
129 y = T::from(&y * &y);
130 }
131 x
132}
133
134pub fn gcd<T>(mut x: T, mut y: T) -> T
144where
145 T: sealed::Sized + Zero + for<'x> From<<&'x T as Rem>::Output>,
146 for<'x> &'x T: Rem,
147{
148 while !y.is_zero() {
149 let r = T::from(&x % &y);
150 x = y;
151 y = r;
152 }
153 x
154}
155
156pub fn is_coprime<T>(x: T, y: T) -> bool
159where
160 T: sealed::Sized + Eq + Zero + One + RingNormalize + for<'x> From<<&'x T as Rem>::Output>,
161 for<'x> &'x T: Rem,
162{
163 gcd::<T>(x, y).into_normalize().is_one()
164}
165
166pub fn extended_euclidian_algorithm<T>(x: T, y: T) -> (T, T, T)
179where
180 T: sealed::Sized + Zero + One + EuclideanRingOperationFrom,
181 for<'x> &'x T: EuclideanRingOperation,
182{
183 let mut old = (x, T::one(), T::zero());
184 let mut now = (y, T::zero(), T::one());
185 while !now.0.is_zero() {
186 let q = T::from(&old.0 / &now.0);
187 let new = (
188 T::from(&old.0 - &T::from(&q * &now.0)),
189 T::from(&old.1 - &T::from(&q * &now.1)),
190 T::from(&old.2 - &T::from(&q * &now.2)),
191 );
192 old = now;
193 now = new;
194 }
195 old
196}
197
198pub fn normalized_extended_euclidian_algorithm<T>(x: T, y: T) -> (T, T, T)
209where
210 T: sealed::Sized + Zero + One + RingNormalize + EuclideanRingOperationFrom,
211 for<'x> &'x T: EuclideanRingOperation,
212{
213 let lc_x = x.leading_unit();
214 let lc_y = y.leading_unit();
215 let mut old = (x.into_normalize(), T::from(&T::one() / &lc_x), T::zero());
216 let mut now = (y.into_normalize(), T::zero(), T::from(&T::one() / &lc_y));
217 while !now.0.is_zero() {
218 let q = T::from(&old.0 / &now.0);
219 let r = T::from(&old.0 % &now.0);
220 let lc_r = r.leading_unit();
221 let new = (
222 r.into_normalize(),
223 T::from(&T::from(&old.1 - &T::from(&q * &now.1)) / &lc_r),
224 T::from(&T::from(&old.2 - &T::from(&q * &now.2)) / &lc_r),
225 );
226 old = now;
227 now = new;
228 }
229 old
230}
231
232pub fn modulo_inverse<T>(a: T, m: T) -> Option<T>
244where
245 T: sealed::Sized + Eq + Zero + One + RingNormalize + EuclideanRingOperationFrom,
246 for<'x> &'x T: EuclideanRingOperation,
247{
248 if m.is_zero() || a.is_zero() {
249 return None;
250 }
251 let (gcd, inv_a, _) = normalized_extended_euclidian_algorithm::<T>(a, m);
252 if gcd.is_one() {
253 Some(inv_a)
254 } else {
255 None
256 }
257}
258
259pub fn modulo_division<T>(a: T, b: T, m: T) -> Option<T>
272where
273 T: sealed::Sized + Clone + Eq + Zero + One + RingNormalize + EuclideanRingOperationFrom,
274 for<'x> &'x T: EuclideanRingOperation,
275{
276 if m.is_zero() || b.is_zero() {
277 return None;
278 }
279 let (gcd, inv_b, _) = normalized_extended_euclidian_algorithm::<T>(b, m.clone());
280 if T::from(&a % &gcd).is_zero() {
281 let q = T::from(&a / &gcd);
282 let t = q * inv_b;
283 Some(T::from(&t % &m))
284 } else {
285 None
286 }
287}
288
289pub fn chinese_remainder_theorem<T>(u: &[T], m: &[T]) -> Option<T>
302where
303 T: sealed::Sized + Clone + Eq + Zero + One + RingNormalize + EuclideanRingOperationFrom,
304 for<'x> &'x T: EuclideanRingOperation,
305{
306 if u.len() != m.len() {
307 return None;
308 }
309 let len = u.len();
310 let mut v = Vec::with_capacity(len);
311 v.push(u[0].clone());
312 for (i, (u_i, m_i)) in u.iter().zip(m.iter()).enumerate().skip(1) {
313 let p = (v[i - 1].clone(), m[i - 1].clone());
314 let (t, n) = m
315 .iter()
316 .zip(v.iter())
317 .rev()
318 .skip(1)
319 .fold(p, |(t, n), (m_j, v_j)| {
320 (
321 T::from(&T::from(v_j + &T::from(m_j * &t)) % m_i),
322 T::from(&T::from(&n * m_j) % m_i),
323 )
324 });
325 v.push(modulo_division::<T>(
326 T::from(u_i + &T::from(m_i - &t)),
327 n,
328 m_i.clone(),
329 )?);
330 }
331 let mut ret = v.pop().unwrap();
332 for (v_i, m_i) in v.iter().zip(m.iter()).rev() {
333 ret = T::from(&T::from(&ret * m_i) + v_i);
334 }
335 Some(ret)
336}
337
338pub fn build_subproduct_tree<T>(a: Vec<T>) -> Vec<T>
361where
362 T: sealed::Sized + Clone + One + for<'x> From<<&'x T as Mul>::Output>,
363 for<'x> &'x T: Mul,
364{
365 let mut len = a.len().next_power_of_two();
366 let mut r = vec![T::one(); 2 * len - 1];
367 a.into_iter()
368 .zip(r.iter_mut().skip(len - 1))
369 .for_each(|(a, r)| *r = a);
370 while len >= 2 {
371 let (ro, ri) = r.split_at_mut(len - 1);
372 let (_, ro) = ro.split_at_mut(len / 2 - 1);
373 ro.iter_mut()
374 .zip(ri.chunks_exact(2))
375 .for_each(|(ro, ri)| *ro = T::from(&ri[0] * &ri[1]));
376 len >>= 1;
377 }
378 r
379}
380
381pub fn build_subsum_tree<T>(a: Vec<T>) -> Vec<T>
404where
405 T: sealed::Sized + Clone + Zero + for<'x> From<<&'x T as Add>::Output>,
406 for<'x> &'x T: Add,
407{
408 let mut len = a.len().next_power_of_two();
409 let mut r = vec![T::zero(); 2 * len - 1];
410 a.into_iter()
411 .zip(r.iter_mut().skip(len - 1))
412 .for_each(|(a, r)| *r = a);
413 while len >= 2 {
414 let (ro, ri) = r.split_at_mut(len - 1);
415 let (_, ro) = ro.split_at_mut(len / 2 - 1);
416 ro.iter_mut()
417 .zip(ri.chunks_exact(2))
418 .for_each(|(ro, ri)| *ro = T::from(&ri[0] + &ri[1]));
419 len >>= 1;
420 }
421 r
422}
423
424fn modular_reduction_aux<T, U>(f: &U, v: &[T], sv: usize, start: usize, end: usize) -> Vec<U>
425where
426 T: sealed::Sized,
427 U: sealed::Sized + for<'x> From<<&'x U as Rem<&'x T>>::Output>,
428 for<'x> &'x U: Rem<&'x T>,
429{
430 let s = (end - start) / 2;
431 let mid = start + s;
432 let ev = sv * 2 + 1;
433 if s == 1 {
434 let f0 = U::from(f % &v[sv + start]);
435 let f1 = U::from(f % &v[sv + start + 1]);
436 vec![f0, f1]
437 } else {
438 let mut v0 = {
439 let f0 = U::from(f % &v[sv + start / s]);
440 modular_reduction_aux::<T, U>(&f0, v, ev, start, mid)
441 };
442 let mut v1 = {
443 let f1 = U::from(f % &v[sv + start / s + 1]);
444 modular_reduction_aux::<T, U>(&f1, v, ev, mid, end)
445 };
446 v0.append(&mut v1);
447 v0
448 }
449}
450
451pub fn modular_reduction<T, U>(f: &U, m: &[T]) -> Vec<U>
465where
466 T: sealed::Sized + Clone + One + for<'x> From<<&'x T as Mul>::Output>,
467 for<'x> &'x T: Mul,
468 U: sealed::Sized + for<'x> From<<&'x U as Rem<&'x T>>::Output>,
469 for<'x> &'x U: Rem<&'x T>,
470{
471 let len = m.len();
472 assert!(len >= 2 && len.is_power_of_two());
473 let v = build_subproduct_tree::<T>(m.to_vec());
474 modular_reduction_aux::<T, U>(f, &v, 1, 0, len)
475}
476
477fn crt_inverses<T>(m: &[T], big_m: &T) -> Vec<T>
478where
479 T: sealed::Sized + Clone + Eq + Zero + One + RingNormalize + EuclideanRingOperationFrom,
480 for<'x> &'x T: EuclideanRingOperation,
481{
482 let m2 = m.iter().map(|m| T::from(m * m)).collect::<Vec<_>>();
483 modular_reduction::<T, T>(big_m, &m2)
484 .into_iter()
485 .zip(m.iter())
486 .map(|(v, m)| modulo_inverse::<T>(T::from(&v / m), m.clone()).unwrap())
487 .collect()
488}
489
490fn crt_combination<T>(c: &[T], m: &[T], v: &[T], sv: usize, start: usize, end: usize) -> T
491where
492 T: sealed::Sized + Clone + Eq + Zero + One + RingNormalize + EuclideanRingOperationFrom,
493 for<'x> &'x T: EuclideanRingOperation,
494{
495 if end - start == 1 {
496 c[0].clone()
497 } else {
498 let s = (end - start) / 2;
499 let mid = start + s;
500 let ev = sv * 2 + 1;
501 let (c0, c1) = c.split_at(s);
502 let (m0, m1) = m.split_at(s);
503 let r0 = crt_combination::<T>(c0, m0, v, ev, start, mid);
504 let r1 = crt_combination::<T>(c1, m1, v, ev, mid, end);
505 T::from(&T::from(&r0 * &v[sv + start / s + 1]) + &T::from(&r1 * &v[sv + start / s]))
506 }
507}
508
509pub fn fast_chinese_remainder_theorem<T>(u: &[T], m: &[T]) -> T
523where
524 T: sealed::Sized + Clone + Eq + Zero + One + RingNormalize + EuclideanRingOperationFrom,
525 for<'x> &'x T: EuclideanRingOperation,
526{
527 assert_eq!(u.len(), m.len());
528 let len = m.len();
529 assert!(len >= 2 && len.is_power_of_two());
530 let v = build_subproduct_tree::<T>(m.to_vec());
531 let s = crt_inverses::<T>(m, &v[0]);
532 let c = s
533 .iter()
534 .zip(u.iter())
535 .map(|(s, u)| T::from(s * u))
536 .collect::<Vec<_>>();
537 crt_combination::<T>(&c, m, &v, 1, 0, len)
538}
539
540pub fn modulo_power<T, U>(a: T, mut p: U, m: &T) -> T
551where
552 T: sealed::Sized
553 + One
554 + for<'x> MulAssign<&'x T>
555 + for<'x> From<<&'x T as Mul>::Output>
556 + for<'x> From<<&'x T as Rem>::Output>,
557 for<'x> &'x T: Mul + Rem,
558 U: sealed::Sized
559 + Zero
560 + One
561 + Eq
562 + for<'x> ShrAssign<usize>
563 + for<'x> From<<&'x U as BitAnd>::Output>,
564 for<'x> &'x U: BitAnd,
565{
566 let mut x = T::one();
567 let mut y = T::from(&a % m);
568 loop {
569 if U::from(&p & &U::one()) == U::one() {
570 x = T::from(&T::from(&x * &y) % m);
571 }
572 p >>= 1;
573 if p == U::zero() {
574 break;
575 }
576 y = T::from(&T::from(&y * &y) % m);
577 }
578 x
579}