1use crate::{MonOrder, Poly, PolyRing, cmp_monomials};
12use cas_domain::{Integer, Rational};
13use std::collections::HashMap;
14use std::sync::Arc;
15
16impl PolyRing {
17 fn tail(&self, idx: usize) -> Arc<PolyRing> {
19 let vars: Vec<Box<str>> = self
20 .vars
21 .iter()
22 .enumerate()
23 .filter(|(i, _)| *i != idx)
24 .map(|(_, v)| v.clone())
25 .collect();
26 PolyRing::new(vars, self.order)
27 }
28}
29
30impl Poly<Rational> {
31 pub fn div_rem(&self, divs: &[&Self]) -> (Vec<Self>, Self) {
34 for d in divs {
35 assert!(!d.is_zero(), "除式为零");
36 assert_eq!(&*self.ring, &*d.ring, "多项式须属于同一 PolyRing");
37 }
38 let n = self.ring.nvars();
39 let order = self.ring.order;
40 let divs_lt: Vec<(Vec<u32>, Rational)> = divs
42 .iter()
43 .map(|d| {
44 let (e, c) = d.terms().last().expect("除式非零");
45 (e.to_vec(), c.clone())
46 })
47 .collect();
48 let mut qs: Vec<HashMap<Vec<u32>, Rational>> = vec![HashMap::new(); divs.len()];
49 let mut rem: HashMap<Vec<u32>, Rational> = HashMap::new();
50 let mut p: HashMap<Vec<u32>, Rational> =
51 self.terms().map(|(e, c)| (e.to_vec(), c.clone())).collect();
52
53 while let Some((lt_e, lt_c)) = leading(&p, order) {
54 let mut matched = None;
55 for (i, (le, lc)) in divs_lt.iter().enumerate() {
56 if (0..n).all(|j| lt_e[j] >= le[j]) {
57 let qe: Vec<u32> = lt_e.iter().zip(le).map(|(&a, &b)| a - b).collect();
58 let qc = lt_c.div(lc).expect("主系数非零");
59 matched = Some((i, qe, qc));
60 break;
61 }
62 }
63 match matched {
64 Some((i, qe, qc)) => {
65 let qslot = qs[i].entry(qe.clone()).or_insert_with(Rational::zero);
66 *qslot = qslot.add(&qc);
67 for (de, dc) in divs[i].terms() {
68 let key: Vec<u32> = de.iter().zip(&qe).map(|(&a, &b)| a + b).collect();
69 let slot = p.entry(key).or_insert_with(Rational::zero);
70 *slot = slot.sub(&qc.mul(dc));
71 }
72 }
73 None => {
74 let slot = rem.entry(lt_e.clone()).or_insert_with(Rational::zero);
75 *slot = slot.add(<_c);
76 p.remove(<_e);
77 continue;
78 }
79 }
80 p.retain(|_, c| !c.is_zero());
81 }
82
83 let qs: Vec<Poly<Rational>> = qs
84 .into_iter()
85 .map(|q| Poly::from_terms(self.ring.clone(), q))
86 .collect();
87 let r = Poly::from_terms(self.ring.clone(), rem);
88 (qs, r)
89 }
90
91 pub fn exact_div(&self, g: &Self) -> Option<Self> {
93 let (mut qs, r) = self.div_rem(&[g]);
94 if r.is_zero() && qs.len() == 1 {
95 qs.pop()
96 } else {
97 None
98 }
99 }
100
101 pub fn gcd(&self, other: &Self) -> Self {
104 assert_eq!(&*self.ring, &*other.ring, "多项式须属于同一 PolyRing");
105 self.gcd_raw(other).normalize_primitive()
106 }
107
108 fn gcd_raw(&self, other: &Self) -> Self {
109 if self.is_zero() {
110 return other.clone();
111 }
112 if other.is_zero() {
113 return self.clone();
114 }
115 if self.ring.nvars() == 1 {
116 let (mut a, mut b) = (self.clone(), other.clone());
118 while !b.is_zero() {
119 let (_, r) = a.div_rem(&[&b]);
120 a = b;
121 b = r;
122 }
123 return a;
124 }
125 let ring0 = self.ring.tail(0);
127 let ua = Uni::from_poly(self, &ring0);
128 let ub = Uni::from_poly(other, &ring0);
129 let ca = ua.content();
130 let cb = ub.content();
131 let c = ca.gcd_raw(&cb);
132 let mut a = ua.exact_div_content(&ca);
133 let mut b = ub.exact_div_content(&cb);
134 while !b.is_zero() {
135 let r = a.pseudo_rem(&b);
136 if r.is_zero() {
137 a = b;
138 break;
139 }
140 let cr = r.content();
141 let r = r.exact_div_content(&cr);
142 a = b;
143 b = r;
144 }
145 let g = a.to_poly(self.ring.clone());
147 let c_full = embed_tail(&c, &self.ring.clone());
148 g.mul(&c_full)
149 }
150
151 pub fn normalize_primitive(&self) -> Self {
154 if self.is_zero() {
155 return self.clone();
156 }
157 let mut d_lcm = Integer::one();
158 for (_, c) in self.terms() {
159 d_lcm = lcm(&d_lcm, &c.den());
160 }
161 let mut m = Integer::zero();
162 for (_, c) in self.terms() {
163 let scaled = c.num().mul(&d_lcm.div_exact(&c.den()));
164 m = if m.is_zero() { scaled } else { m.gcd(&scaled) };
165 }
166 if m.is_zero() {
167 m = Integer::one();
168 }
169 let mut terms: Vec<(Vec<u32>, Rational)> = self
171 .terms()
172 .map(|(e, c)| {
173 let scaled = c.mul(&Rational::from_integer(&d_lcm));
174 let v = scaled.div(&Rational::from_integer(&m)).expect("内容整除");
175 (e.to_vec(), v)
176 })
177 .collect();
178 if let Some((_, lc)) = terms.last() {
179 if lc.is_negative() {
180 for (_, c) in &mut terms {
181 *c = c.neg();
182 }
183 }
184 }
185 Poly::from_terms(self.ring.clone(), terms)
186 }
187}
188
189fn leading(p: &HashMap<Vec<u32>, Rational>, order: MonOrder) -> Option<(Vec<u32>, Rational)> {
191 p.iter()
192 .filter(|(_, c)| !c.is_zero())
193 .max_by(|(a, _), (b, _)| cmp_monomials(order, a, b))
194 .map(|(e, c)| (e.clone(), c.clone()))
195}
196
197fn lcm(a: &Integer, b: &Integer) -> Integer {
198 if a.is_zero() || b.is_zero() {
199 return Integer::zero();
200 }
201 a.div_exact(&a.gcd(b)).mul(b)
202}
203
204fn embed_tail(p: &Poly<Rational>, ring: &Arc<PolyRing>) -> Poly<Rational> {
206 let items: Vec<(Vec<u32>, Rational)> = p
207 .terms()
208 .map(|(e, c)| {
209 let mut full = Vec::with_capacity(e.len() + 1);
210 full.push(0);
211 full.extend_from_slice(e);
212 (full, c.clone())
213 })
214 .collect();
215 Poly::from_terms(ring.clone(), items)
216}
217
218#[derive(Clone)]
220pub(crate) struct Uni {
221 terms: Vec<(u32, Poly<Rational>)>,
223 ring0: Arc<PolyRing>,
224}
225
226impl Uni {
227 pub(crate) fn from_poly(p: &Poly<Rational>, ring0: &Arc<PolyRing>) -> Self {
228 let mut by_deg: HashMap<u32, Vec<(Vec<u32>, Rational)>> = HashMap::new();
229 for (e, c) in p.terms() {
230 by_deg
231 .entry(e[0])
232 .or_default()
233 .push((e[1..].to_vec(), c.clone()));
234 }
235 let mut terms: Vec<(u32, Poly<Rational>)> = by_deg
236 .into_iter()
237 .map(|(d, items)| (d, Poly::from_terms(ring0.clone(), items)))
238 .filter(|(_, p)| !p.is_zero())
239 .collect();
240 terms.sort_by_key(|(d, _)| std::cmp::Reverse(*d));
241 Uni {
242 terms,
243 ring0: ring0.clone(),
244 }
245 }
246
247 fn is_zero(&self) -> bool {
248 self.terms.is_empty()
249 }
250
251 fn deg(&self) -> u32 {
252 self.terms[0].0
253 }
254
255 fn lc(&self) -> &Poly<Rational> {
256 &self.terms[0].1
257 }
258
259 pub(crate) fn content(&self) -> Poly<Rational> {
261 let mut acc = Poly::zero(self.ring0.clone());
262 for (_, c) in &self.terms {
263 acc = acc.gcd_raw(c);
264 }
265 acc
266 }
267
268 pub(crate) fn exact_div_content(&self, c: &Poly<Rational>) -> Self {
270 let terms: Vec<(u32, Poly<Rational>)> = self
271 .terms
272 .iter()
273 .map(|(d, p)| (*d, p.exact_div(c).expect("内容必整除")))
274 .collect();
275 Uni {
276 terms,
277 ring0: self.ring0.clone(),
278 }
279 }
280
281 fn pseudo_rem(&self, b: &Uni) -> Self {
284 let db = b.deg();
285 let mut r = self.clone();
286 while !r.is_zero() && r.deg() >= db {
287 let shift = r.deg() - db;
288 let lcb = b.lc().clone();
289 let lcr = r.lc().clone();
290 let mut acc: HashMap<u32, Poly<Rational>> = HashMap::new();
291 for (d, c) in &r.terms {
292 let slot = acc
293 .entry(*d)
294 .or_insert_with(|| Poly::zero(self.ring0.clone()));
295 *slot = slot.add(&lcb.mul(c));
296 }
297 for (d, c) in &b.terms {
298 let slot = acc
299 .entry(d + shift)
300 .or_insert_with(|| Poly::zero(self.ring0.clone()));
301 *slot = slot.sub(&lcr.mul(c));
302 }
303 let mut terms: Vec<(u32, Poly<Rational>)> =
304 acc.into_iter().filter(|(_, p)| !p.is_zero()).collect();
305 terms.sort_by_key(|(d, _)| std::cmp::Reverse(*d));
306 r = Uni {
310 terms,
311 ring0: self.ring0.clone(),
312 };
313 }
314 r
315 }
316
317 pub(crate) fn to_poly(&self, ring: Arc<PolyRing>) -> Poly<Rational> {
319 let mut items: Vec<(Vec<u32>, Rational)> = Vec::new();
320 for (d, coef) in &self.terms {
321 for (e, c) in coef.terms() {
322 let mut full = Vec::with_capacity(ring.nvars());
323 full.push(*d);
324 full.extend_from_slice(e);
325 items.push((full, c.clone()));
326 }
327 }
328 Poly::from_terms(ring, items)
329 }
330}
331
332#[cfg(test)]
333mod tests {
334 use super::*;
335 use crate::MonOrder;
336
337 fn ringn(names: &[&str]) -> Arc<PolyRing> {
338 PolyRing::new(names.iter().copied(), MonOrder::DegRevLex)
339 }
340
341 fn rat(n: i64, d: i64) -> Rational {
342 Rational::from_ints(&Integer::from_i64(n), &Integer::from_i64(d)).unwrap()
343 }
344
345 fn t(e: Vec<u32>, c: (i64, i64)) -> (Vec<u32>, Rational) {
346 (e, rat(c.0, c.1))
347 }
348
349 #[test]
350 fn 一元_gcd() {
351 let ring = ringn(&["x"]);
352 let f = Poly::from_terms(ring.clone(), [t(vec![2], (1, 1)), t(vec![0], (-1, 1))]);
354 let g = Poly::from_terms(ring.clone(), [t(vec![1], (1, 1)), t(vec![0], (-1, 1))]);
355 let d = f.gcd(&g);
356 assert_eq!(d.nterms(), 2);
357 assert_eq!(d.terms().next().unwrap(), (&[0][..], &rat(-1, 1)));
358 assert_eq!(d.terms().nth(1).unwrap(), (&[1][..], &rat(1, 1)));
359
360 let c = Poly::from_terms(ring.clone(), [t(vec![0], (4, 6))]);
362 assert!(g.gcd(&c).is_constant());
363
364 let h = Poly::from_terms(ring.clone(), [t(vec![3], (2, 1)), t(vec![1], (1, 1))]);
366 let d1 = f.mul(&h).gcd(&g.mul(&h));
367 let d2 = f.gcd(&g).mul(&h).normalize_primitive();
368 assert_eq!(d1, d2);
369 }
370
371 #[test]
372 fn 多元_gcd_六变元() {
373 let ring = ringn(&["q1", "q2", "q3", "p1", "p2", "p3"]);
374 let mk = |e: [u32; 6], c: (i64, i64)| t(e.to_vec(), c);
375 let h = Poly::from_terms(
377 ring.clone(),
378 [
379 mk([0, 1, 0, 1, 0, 0], (1, 1)),
380 mk([0, 0, 1, 0, 0, 0], (1, 1)),
381 ],
382 );
383 let f = Poly::from_terms(
384 ring.clone(),
385 [
386 mk([1, 0, 0, 0, 0, 0], (1, 1)),
387 mk([0, 0, 0, 0, 1, 0], (-2, 3)),
388 ],
389 );
390 let g = Poly::from_terms(
391 ring.clone(),
392 [
393 mk([0, 0, 0, 0, 0, 1], (5, 1)),
394 mk([2, 0, 0, 1, 0, 0], (1, 2)),
395 ],
396 );
397 let d = f.mul(&h).gcd(&g.mul(&h));
398 assert_eq!(d, h);
399 assert!(f.gcd(&g).is_constant());
401 }
402
403 #[test]
404 fn 精确除法与除法不变量() {
405 let ring = ringn(&["x", "y"]);
406 let mk = |e: [u32; 2], c: (i64, i64)| t(e.to_vec(), c);
407 let f = Poly::from_terms(
408 ring.clone(),
409 [mk([2, 0], (1, 1)), mk([1, 1], (3, 2)), mk([0, 2], (-1, 5))],
410 );
411 let g = Poly::from_terms(ring.clone(), [mk([1, 0], (2, 1)), mk([0, 1], (1, 1))]);
412 let q = f.mul(&g).exact_div(&g);
414 assert_eq!(q.as_ref(), Some(&f));
415 let x = Poly::from_terms(ring.clone(), [mk([1, 0], (1, 1))]);
417 let y = Poly::from_terms(ring.clone(), [mk([0, 1], (1, 1))]);
418 assert_eq!(x.exact_div(&y), None);
419 let p = f.mul(&g);
421 let (qs, r) = p.div_rem(&[&f]);
422 let lhs = qs[0].mul(&f).add(&r);
423 assert_eq!(lhs, p);
424 assert!(r.is_zero());
425 }
426
427 #[test]
428 fn 随机性质() {
429 let ring = ringn(&["q1", "q2", "q3", "p1", "p2", "p3"]);
431 let mut xs = 4242u64;
432 let mut nxt = move || {
433 xs ^= xs << 13;
434 xs ^= xs >> 7;
435 xs ^= xs << 17;
436 xs
437 };
438 fn rand_poly(
439 nxt: &mut dyn FnMut() -> u64,
440 deg: u64,
441 ring: &Arc<PolyRing>,
442 ) -> Poly<Rational> {
443 let items: Vec<(Vec<u32>, Rational)> = (0..4)
444 .map(|_| {
445 let r = nxt();
446 let e: Vec<u32> = (0..6)
447 .map(|k| ((r >> (k * 4)) % (deg + 1) % 3) as u32)
448 .collect();
449 (e, rat((r % 13) as i64 - 6, 1))
450 })
451 .collect();
452 Poly::from_terms(ring.clone(), items)
453 }
454 for _ in 0..10 {
455 let f = rand_poly(&mut nxt, 2, &ring);
456 let g = rand_poly(&mut nxt, 2, &ring);
457 let h = Poly::from_terms(
459 ring.clone(),
460 [
461 t(vec![1, 0, 0, 0, 0, 0], (1, 1)),
462 t(vec![0, 0, 0, 1, 1, 0], ((nxt() % 7) as i64, 1)),
463 ],
464 );
465 if f.is_zero() || g.is_zero() || h.is_zero() {
466 continue;
467 }
468 let d1 = f.mul(&h).gcd(&g.mul(&h));
469 let d2 = f.gcd(&g).mul(&h).normalize_primitive();
470 assert_eq!(d1, d2, "f={f:?} g={g:?} h={h:?}");
471 assert!(f.mul(&h).exact_div(&d1).is_some());
473 assert!(g.mul(&h).exact_div(&d1).is_some());
474 }
475 }
476
477 #[test]
478 fn 本原规范化() {
479 let ring = ringn(&["x", "y"]);
480 let p = Poly::from_terms(ring.clone(), [t(vec![1, 0], (2, 3)), t(vec![0, 0], (4, 1))]);
482 let n = p.normalize_primitive();
483 let items: Vec<_> = n.terms().map(|(e, c)| (e.to_vec(), c.clone())).collect();
484 assert_eq!(
485 items,
486 vec![(vec![0, 0], rat(6, 1)), (vec![1, 0], rat(1, 1))]
487 );
488 let p = Poly::from_terms(ring.clone(), [t(vec![1, 0], (-1, 1))]);
490 let n = p.normalize_primitive();
491 assert_eq!(n.terms().next().unwrap().1, &rat(1, 1));
492 }
493}