haar_lib/math/polynomial/
sparse.rs1use std::collections::BTreeMap;
3
4use crate::math::prime_mod::PrimeMod;
5use crate::num::const_modint::*;
6
7#[derive(Clone, Debug, Default)]
9pub struct SparsePolynomial<P: PrimeMod> {
10 data: BTreeMap<usize, ConstModInt<P>>,
11}
12
13impl<P: PrimeMod> SparsePolynomial<P> {
14 pub fn zero() -> Self {
16 Self {
17 data: BTreeMap::new(),
18 }
19 }
20
21 pub fn constant(a: ConstModInt<P>) -> Self {
23 if a.value() == 0 {
24 Self::zero()
25 } else {
26 Self {
27 data: BTreeMap::from([(0, a)]),
28 }
29 }
30 }
31
32 pub fn add_one_term<T>(&mut self, i: usize, k: T)
34 where
35 ConstModInt<P>: From<T>,
36 {
37 *self.data.entry(i).or_default() += k.into();
38 }
39
40 pub fn coeff_of(&self, i: usize) -> ConstModInt<P> {
42 self.data
43 .iter()
44 .find(|(&j, _)| j == i)
45 .map_or(0.into(), |(_, x)| *x)
46 }
47
48 pub fn differential(&mut self) {
50 let a = self
51 .data
52 .iter()
53 .filter_map(|(&i, &x)| {
54 if i == 0 {
55 None
56 } else {
57 Some((i - 1, x * i.into()))
58 }
59 })
60 .collect();
61
62 self.data = a;
63 }
64
65 pub fn integral(&mut self) {
67 let a = self
68 .data
69 .iter()
70 .map(|(&i, &x)| (i + 1, x * ConstModInt::new(i as u32 + 1).inv()))
71 .collect();
72
73 self.data = a;
74 }
75
76 pub fn scale(&mut self, k: ConstModInt<P>) {
78 self.data.iter_mut().for_each(|(_, x)| *x *= k);
79 }
80
81 pub fn shift_lower(&mut self, k: usize) {
83 self.data = self
84 .data
85 .iter()
86 .filter_map(|(&i, &x)| if i < k { None } else { Some((i - k, x)) })
87 .collect();
88 }
89
90 pub fn shift_higher(&mut self, k: usize) {
92 self.data = self.data.iter().map(|(&i, &x)| (i + k, x)).collect();
93 }
94
95 pub fn iter(&self) -> impl Iterator<Item = (&usize, &ConstModInt<P>)> {
97 self.data.iter()
98 }
99}
100
101impl<P: PrimeMod, T> From<Vec<(usize, T)>> for SparsePolynomial<P>
102where
103 ConstModInt<P>: From<T>,
104{
105 fn from(value: Vec<(usize, T)>) -> Self {
106 let mut ret = Self::zero();
107 for (i, x) in value {
108 ret.add_one_term(i, x);
109 }
110 ret
111 }
112}