1use std::fmt::Debug;
10use std::hash::Hash;
11
12use crate::algebraic::Algebraic;
13
14pub trait OrderedField: Clone + PartialEq + Eq + Hash + Debug {
16 fn zero() -> Self;
17 fn one() -> Self;
18 fn from_i64(n: i64) -> Self;
19 fn is_zero(&self) -> bool;
20 fn add(&self, o: &Self) -> Self;
21 fn neg(&self) -> Self;
22 fn mul(&self, o: &Self) -> Self;
23 fn recip(&self) -> Option<Self>;
25 fn signum(&self) -> i32;
27
28 fn sub(&self, o: &Self) -> Self {
29 self.add(&o.neg())
30 }
31}
32
33impl OrderedField for Algebraic {
34 fn zero() -> Self {
35 Algebraic::from_i64(0)
36 }
37 fn one() -> Self {
38 Algebraic::from_i64(1)
39 }
40 fn from_i64(n: i64) -> Self {
41 Algebraic::from_i64(n)
42 }
43 fn is_zero(&self) -> bool {
44 Algebraic::is_zero(self)
45 }
46 fn add(&self, o: &Self) -> Self {
47 Algebraic::add(self, o)
48 }
49 fn neg(&self) -> Self {
50 Algebraic::neg(self)
51 }
52 fn mul(&self, o: &Self) -> Self {
53 Algebraic::mul(self, o)
54 }
55 fn recip(&self) -> Option<Self> {
56 Algebraic::recip(self)
57 }
58 fn signum(&self) -> i32 {
59 Algebraic::signum(self)
60 }
61 fn sub(&self, o: &Self) -> Self {
62 Algebraic::sub(self, o)
63 }
64}
65
66#[derive(Clone, Debug, PartialEq, Eq, Hash)]
68pub struct PolyOver<K> {
69 pub(crate) c: Vec<K>,
70}
71
72impl<K: OrderedField> PolyOver<K> {
73 pub fn from(c: Vec<K>) -> PolyOver<K> {
74 let mut c = c;
75 while c.last().is_some_and(K::is_zero) {
76 c.pop();
77 }
78 PolyOver { c }
79 }
80
81 pub fn constant(a: K) -> PolyOver<K> {
82 PolyOver::from(vec![a])
83 }
84
85 pub fn zero() -> PolyOver<K> {
86 PolyOver { c: Vec::new() }
87 }
88
89 pub fn one() -> PolyOver<K> {
90 PolyOver::constant(K::one())
91 }
92
93 pub fn variable() -> PolyOver<K> {
95 PolyOver::from(vec![K::zero(), K::one()])
96 }
97
98 pub fn is_zero(&self) -> bool {
99 self.c.is_empty()
100 }
101
102 pub fn degree(&self) -> Option<usize> {
103 self.c.len().checked_sub(1)
104 }
105
106 pub fn order(&self) -> Option<usize> {
108 self.c.iter().position(|a| !a.is_zero())
109 }
110
111 pub fn coeff(&self, i: usize) -> K {
112 self.c.get(i).cloned().unwrap_or_else(K::zero)
113 }
114
115 pub fn add(&self, o: &PolyOver<K>) -> PolyOver<K> {
116 let n = self.c.len().max(o.c.len());
117 PolyOver::from((0..n).map(|i| self.coeff(i).add(&o.coeff(i))).collect())
118 }
119
120 pub fn neg(&self) -> PolyOver<K> {
121 PolyOver {
122 c: self.c.iter().map(K::neg).collect(),
123 }
124 }
125
126 pub fn mul(&self, o: &PolyOver<K>) -> PolyOver<K> {
127 if self.is_zero() || o.is_zero() {
128 return PolyOver::zero();
129 }
130 let mut out = vec![K::zero(); self.c.len() + o.c.len() - 1];
131 for (i, a) in self.c.iter().enumerate() {
132 if a.is_zero() {
133 continue;
134 }
135 for (j, b) in o.c.iter().enumerate() {
136 if b.is_zero() {
137 continue;
138 }
139 out[i + j] = out[i + j].add(&a.mul(b));
140 }
141 }
142 PolyOver::from(out)
143 }
144
145 pub fn scale(&self, k: &K) -> PolyOver<K> {
146 PolyOver::from(self.c.iter().map(|a| a.mul(k)).collect())
147 }
148
149 pub fn div_rem(&self, d: &PolyOver<K>) -> (PolyOver<K>, PolyOver<K>) {
151 let dd = d.degree().expect("the divisor is nonzero");
152 let inv = d.c[dd].recip().expect("the leading coefficient is nonzero");
153 if self.c.len() <= dd {
154 return (PolyOver::zero(), self.clone());
155 }
156 let mut r = self.c.clone();
157 let mut q = vec![K::zero(); r.len() - dd];
158 for k in (0..q.len()).rev() {
159 let coef = r[k + dd].mul(&inv);
160 if !coef.is_zero() {
161 for (j, dj) in d.c.iter().enumerate() {
162 r[k + j] = r[k + j].sub(&coef.mul(dj));
163 }
164 }
165 q[k] = coef;
166 }
167 r.truncate(dd);
168 (PolyOver::from(q), PolyOver::from(r))
169 }
170
171 pub fn monic(&self) -> PolyOver<K> {
172 match self.c.last() {
173 None => PolyOver::zero(),
174 Some(lc) => self.scale(&lc.recip().expect("nonzero")),
175 }
176 }
177
178 pub fn gcd(&self, o: &PolyOver<K>) -> PolyOver<K> {
180 let (mut a, mut b) = (self.monic(), o.monic());
181 while !b.is_zero() {
182 let r = a.div_rem(&b).1;
183 a = b;
184 b = r.monic();
185 }
186 a
187 }
188
189 pub fn derivative(&self) -> PolyOver<K> {
190 PolyOver::from(
191 self.c
192 .iter()
193 .enumerate()
194 .skip(1)
195 .map(|(i, a)| a.mul(&K::from_i64(i as i64)))
196 .collect(),
197 )
198 }
199
200 pub fn squarefree_parts(&self) -> (K, Vec<(PolyOver<K>, usize)>) {
203 let lc = self.c.last().cloned().unwrap_or_else(K::zero);
204 if self.degree().unwrap_or(0) == 0 {
205 return (lc, Vec::new());
206 }
207 let f = self.monic();
208 let g = f.gcd(&f.derivative());
209 let mut b = f.div_rem(&g).0;
210 let c = f.derivative().div_rem(&g).0;
211 let mut d = c.add(&b.derivative().neg());
212 let mut parts = Vec::new();
213 let mut i = 1;
214 while b.degree().unwrap_or(0) > 0 {
215 let a = b.gcd(&d);
216 b = b.div_rem(&a).0;
217 let c = d.div_rem(&a).0;
218 d = c.add(&b.derivative().neg());
219 if a.degree().unwrap_or(0) > 0 {
220 parts.push((a, i));
221 }
222 i += 1;
223 }
224 (lc, parts)
225 }
226
227 pub fn eval(&self, t: &K) -> K {
228 self.c.iter().rev().fold(K::zero(), |acc, a| acc.mul(t).add(a))
229 }
230
231 pub fn spread(&self, m: usize) -> PolyOver<K> {
233 let mut c = vec![K::zero(); self.c.len().saturating_sub(1) * m + 1];
234 for (i, a) in self.c.iter().enumerate() {
235 c[i * m] = a.clone();
236 }
237 PolyOver::from(c)
238 }
239
240 pub fn squarefree(&self) -> PolyOver<K> {
242 if self.degree().unwrap_or(0) == 0 {
243 return self.monic();
244 }
245 let g = self.gcd(&self.derivative());
246 self.div_rem(&g).0.monic()
247 }
248
249 pub fn shift(&self, a: &K) -> PolyOver<K> {
251 let linear = PolyOver::from(vec![a.clone(), K::one()]);
252 self.c
253 .iter()
254 .rev()
255 .fold(PolyOver::zero(), |acc, c| acc.mul(&linear).add(&PolyOver::constant(c.clone())))
256 }
257
258 pub fn neg_var(&self) -> PolyOver<K> {
260 PolyOver::from(
261 self.c
262 .iter()
263 .enumerate()
264 .map(|(i, a)| if i % 2 == 1 { a.neg() } else { a.clone() })
265 .collect(),
266 )
267 }
268
269 pub fn without_zero_root(&self) -> PolyOver<K> {
271 match self.order() {
272 Some(k) => PolyOver::from(self.c[k..].to_vec()),
273 None => PolyOver::zero(),
274 }
275 }
276
277 pub fn reversed(&self) -> PolyOver<K> {
280 let mut c = self.without_zero_root().c;
281 c.reverse();
282 PolyOver::from(c)
283 }
284
285 pub fn resultant(&self, o: &PolyOver<K>) -> K {
287 let (Some(m), Some(n)) = (self.degree(), o.degree()) else {
288 return K::zero();
289 };
290 let power = |h: &K, k: usize| (0..k).fold(K::one(), |acc, _| acc.mul(h));
291 if n == 0 {
292 return power(&o.c[0], m);
293 }
294 if m == 0 {
295 return power(&self.c[0], n);
296 }
297 let r = self.div_rem(o).1;
298 let Some(dr) = r.degree() else {
299 return K::zero();
300 };
301 let v = power(&o.c[n], m - dr).mul(&o.resultant(&r));
302 if (m * n) % 2 == 1 {
303 v.neg()
304 } else {
305 v
306 }
307 }
308
309 pub fn interpolate(degree: usize, at: impl Fn(i64) -> K) -> PolyOver<K> {
312 let nodes: Vec<i64> = (0..=degree as i64).collect();
313 let mut values: Vec<K> = nodes.iter().map(|j| at(*j)).collect();
314 let n = nodes.len();
315 for j in 1..n {
316 for i in (j..n).rev() {
317 let gap = K::from_i64(nodes[i] - nodes[i - j]);
318 values[i] = values[i]
319 .sub(&values[i - 1])
320 .mul(&gap.recip().expect("the nodes are distinct"));
321 }
322 }
323 let mut out = PolyOver::constant(values[n - 1].clone());
324 for i in (0..n - 1).rev() {
325 let factor = PolyOver::from(vec![K::from_i64(-nodes[i]), K::one()]);
326 out = out.mul(&factor).add(&PolyOver::constant(values[i].clone()));
327 }
328 out
329 }
330
331 pub fn sum_poly(p: &PolyOver<K>, q: &PolyOver<K>) -> PolyOver<K> {
335 let (Some(dp), Some(dq)) = (p.degree(), q.degree()) else {
336 return PolyOver::one();
337 };
338 let degree = dp * dq;
339 let (sp, sq) = (p.power_sums(degree), q.power_sums(degree));
340 let mut sums = vec![K::zero(); degree + 1];
341 for (m, sum) in sums.iter_mut().enumerate().skip(1) {
342 let mut choose = K::one();
343 for k in 0..=m {
344 if k > 0 {
345 choose = choose
346 .mul(&K::from_i64((m - k + 1) as i64))
347 .mul(&K::from_i64(k as i64).recip().expect("a positive integer is nonzero"));
348 }
349 *sum = sum.add(&choose.mul(&sp[k]).mul(&sq[m - k]));
350 }
351 }
352 PolyOver::from_power_sums(&sums, degree)
353 }
354
355 pub fn product_poly(p: &PolyOver<K>, q: &PolyOver<K>) -> PolyOver<K> {
359 let (Some(dp), Some(dq)) = (p.degree(), q.degree()) else {
360 return PolyOver::one();
361 };
362 let degree = dp * dq;
363 let (sp, sq) = (p.power_sums(degree), q.power_sums(degree));
364 let sums: Vec<K> = (0..=degree).map(|m| sp[m].mul(&sq[m])).collect();
365 PolyOver::from_power_sums(&sums, degree)
366 }
367
368 fn power_sums(&self, n: usize) -> Vec<K> {
371 let d = self.degree().unwrap_or(0);
372 let mut sums = vec![K::zero(); n + 1];
373 sums[0] = K::from_i64(d as i64);
374 if d == 0 {
375 return sums;
376 }
377 let lead = self.coeff(d).recip().expect("a leading coefficient is nonzero");
378 let a: Vec<K> = (0..=d).map(|i| if i == 0 { K::one() } else { self.coeff(d - i).mul(&lead) }).collect();
379 for m in 1..=n {
380 let mut acc = if m <= d { a[m].mul(&K::from_i64(m as i64)) } else { K::zero() };
381 for i in 1..m.min(d + 1) {
382 acc = acc.add(&a[i].mul(&sums[m - i]));
383 }
384 sums[m] = acc.neg();
385 }
386 sums
387 }
388
389 fn from_power_sums(sums: &[K], d: usize) -> PolyOver<K> {
391 let mut b = vec![K::one(); d + 1];
392 for j in 1..=d {
393 let mut acc = sums[j].clone();
394 for i in 1..j {
395 acc = acc.add(&b[i].mul(&sums[j - i]));
396 }
397 b[j] = acc.mul(&K::from_i64(j as i64).recip().expect("a positive integer is nonzero")).neg();
398 }
399 PolyOver::from((0..=d).map(|i| b[d - i].clone()).collect())
400 }
401
402 pub fn pade(series: &[K], l: usize, m: usize) -> Option<(PolyOver<K>, PolyOver<K>)> {
407 let n = l + m + 1;
408 let mut top = vec![K::zero(); n + 1];
409 top[n] = K::one();
410 let truncated: Vec<K> = (0..n).map(|i| series.get(i).cloned().unwrap_or_else(K::zero)).collect();
411 let (mut r0, mut r1) = (PolyOver::from(top), PolyOver::from(truncated));
412 let (mut t0, mut t1) = (PolyOver::zero(), PolyOver::one());
413 while r1.degree().is_some_and(|d| d > l) {
414 let (q, r) = r0.div_rem(&r1);
415 let t = t0.add(&q.mul(&t1).neg());
416 r0 = std::mem::replace(&mut r1, r);
417 t0 = std::mem::replace(&mut t1, t);
418 }
419 if t1.degree().unwrap_or(0) > m || t1.coeff(0).is_zero() {
420 return None;
421 }
422 Some((r1, t1))
423 }
424
425 pub fn power_poly(p: &PolyOver<K>, k: u32) -> PolyOver<K> {
433 let Some(d) = p.degree().filter(|d| *d >= 1) else {
434 return p.clone();
435 };
436 if (1..d).all(|i| p.coeff(i).is_zero()) {
437 let c = p.coeff(0).neg().mul(&p.coeff(d).recip().expect("a leading coefficient is nonzero"));
438 let (mut a, mut b) = (d as u64, u64::from(k));
439 while b != 0 {
440 (a, b) = (b, a % b);
441 }
442 let (degree, exponent) = (d / a as usize, u64::from(k) / a);
443 let power = (0..exponent).fold(K::one(), |acc, _| acc.mul(&c));
444 let mut out = vec![K::zero(); degree + 1];
445 out[0] = power.neg();
446 out[degree] = K::one();
447 return PolyOver::from(out);
448 }
449 let k = k as usize;
450 let sums = p.power_sums(d * k);
451 let powers: Vec<K> = (0..=d).map(|j| sums[j * k].clone()).collect();
452 PolyOver::from_power_sums(&powers, d)
453 }
454}
455
456#[cfg(test)]
457#[path = "../../logicaffeine_tests/unit/logicaffeine_base/ordered_field/tests.rs"]
458mod tests;