1use crate::math::polynomial::{Polynomial, PolynomialOperator};
3use crate::num::ff::*;
4
5pub trait FpsInv {
7 type Poly;
9
10 fn fps_inv(&self, f: Self::Poly) -> Self::Poly;
12}
13
14impl<const P: u32, const PR: u32> FpsInv for PolynomialOperator<'_, P, PR> {
15 type Poly = Polynomial<P>;
16
17 fn fps_inv(&self, f: Self::Poly) -> Self::Poly {
18 let f: Vec<_> = f.into();
19 assert_ne!(f[0].value(), 0);
20 let n = f.len();
21
22 let mut t = 1;
23 let mut ret = vec![f[0].inv()];
24 ret.reserve(2 * n);
25
26 loop {
27 let mut f = f[0..(2 * t).min(n)].to_vec();
28 f.resize(2 * t, 0.into());
29 self.ntt.ntt(&mut f);
30
31 let mut g = ret.clone();
32 g.resize(2 * t, 0.into());
33 self.ntt.ntt(&mut g);
34
35 for (f, g) in f.iter_mut().zip(g.iter()) {
36 *f *= *g;
37 }
38 self.ntt.intt(&mut f);
39
40 let h = f;
41
42 let mut h = h[t..2 * t].to_vec();
43 h.resize(2 * t, 0.into());
44 self.ntt.ntt(&mut h);
45
46 for (h, g) in h.iter_mut().zip(g.iter()) {
47 *h *= *g;
48 }
49 self.ntt.intt(&mut h);
50
51 let g = h;
52
53 ret.resize(2 * t, 0.into());
54
55 for (ret, x) in ret.iter_mut().skip(t).zip(g.into_iter().take(t)) {
56 *ret = -x;
57 }
58
59 t <<= 1;
60
61 if t >= n {
62 break;
63 }
64 }
65
66 ret.truncate(n);
67 ret.into()
68 }
69}