haar_lib/math/fps/
sqrt.rs1use crate::num::ff::*;
3use crate::{
4 math::{
5 fps::inv::FpsInv,
6 mod_ops::sqrt::mod_sqrt,
7 polynomial::{Polynomial, PolynomialOperator},
8 },
9 num::const_modint::ConstModInt,
10};
11
12pub trait FpsSqrt {
14 type Poly;
16
17 fn fps_sqrt(&self, f: Self::Poly) -> Result<Self::Poly, &'static str>;
19}
20
21impl<const P: u32, const PR: u32> FpsSqrt for PolynomialOperator<'_, P, PR> {
22 type Poly = Polynomial<P>;
23
24 fn fps_sqrt(&self, f: Self::Poly) -> Result<Self::Poly, &'static str> {
25 let f: Vec<_> = f.into();
26
27 let n = f.len();
28 let k = f
29 .iter()
30 .enumerate()
31 .find(|(_, &x)| x.value() != 0)
32 .map_or(n, |(k, _)| k);
33
34 if k == n {
35 return Ok(f.into());
36 }
37 if k % 2 == 1 {
38 return Err("最小次数が偶数ではない。");
39 }
40
41 let x = mod_sqrt(f[k].value() as u64, P as u64)
42 .ok_or("最小次数項の係数に平方根が存在しない。")?;
43 let m = n - k;
44
45 let half = ConstModInt::new(2).inv();
46 let mut t = 1;
47 let mut ret = vec![ConstModInt::new(x as u32)];
48
49 loop {
50 let mut f = f[k..k + t.min(m)].to_vec();
51 f.resize(t, 0.into());
52
53 ret.resize(t, 0.into());
54 let h = self.fps_inv(ret.clone().into())?;
55 let h = self.mul(f.into(), h);
56 let h: Vec<_> = h.into();
57
58 for (x, y) in ret.iter_mut().zip(h) {
59 *x = (*x + y) * half;
60 }
61
62 if t >= m {
63 break;
64 }
65
66 t <<= 1;
67 }
68
69 ret.resize(n, 0.into());
70 let mut ret: Polynomial<P> = ret.into();
71 ret.shift_higher(k / 2);
72 Ok(ret)
73 }
74}