haar_lib/math/
polynomial_taylor_shift.rs1use crate::math::polynomial::*;
7use crate::num::const_modint::*;
8
9pub trait TaylorShift {
11 type Poly;
13 type Value;
15
16 fn taylor_shift(&self, p: Self::Poly, c: Self::Value) -> Self::Poly;
20}
21
22impl<const P: u32, const PR: u32> TaylorShift for PolynomialOperator<'_, P, PR> {
23 type Poly = Polynomial<P>;
24 type Value = ConstModInt<P>;
25
26 fn taylor_shift(&self, p: Self::Poly, c: Self::Value) -> Self::Poly {
27 let p: Vec<_> = p.into();
28 let n = p.len();
29 let mut f = ConstModInt::new(1);
30
31 let mut a = vec![ConstModInt::new(0); 2 * n - 1];
32 for (i, (a, p)) in a.iter_mut().skip(n - 1).zip(p.into_iter()).enumerate() {
33 if i != 0 {
34 f *= ConstModInt::new(i as u32);
35 }
36 *a = p * f;
37 }
38
39 let mut g = vec![ConstModInt::new(0); n];
40 g[n - 1] = f.inv();
41 for i in (0..n - 1).rev() {
42 g[i] = g[i + 1] * ConstModInt::new(i as u32 + 1);
43 }
44
45 let mut d = ConstModInt::new(1);
46 let mut b = vec![ConstModInt::new(0); 2 * n - 1];
47 for (b, g) in b.iter_mut().take(n).rev().zip(g.iter()) {
48 *b = d * *g;
49 d *= c;
50 }
51
52 let c: Vec<_> = self.mul(a.into(), b.into()).into();
54 c.into_iter()
55 .skip((n - 1) * 2)
56 .zip(g)
57 .map(|(c, g)| c * g)
58 .collect::<Vec<_>>()
59 .into()
60 }
61}