source: CGBLisp/src/poly-gcd.lisp@ 1

Last change on this file since 1 was 1, checked in by Marek Rychlik, 15 years ago

First import of a version circa 1997.

File size: 3.1 KB
Line 
1#|
2 $Id: poly-gcd.lisp,v 1.4 2009/01/22 04:05:32 marek Exp $
3 *--------------------------------------------------------------------------*
4 | Copyright (C) 1994, Marek Rychlik (e-mail: rychlik@math.arizona.edu) |
5 | Department of Mathematics, University of Arizona, Tucson, AZ 85721 |
6 | |
7 | Everyone is permitted to copy, distribute and modify the code in this |
8 | directory, as long as this copyright note is preserved verbatim. |
9 *--------------------------------------------------------------------------*
10|#
11(defpackage "POLY-GCD"
12 (:export poly-gcd poly-content poly-pseudo-divide poly-primitive-part
13 poly-pseudo-remainder)
14 (:use "ORDER" "POLY" "DIVISION" "COMMON-LISP"))
15
16(in-package "POLY-GCD")
17
18#+debug(proclaim '(optimize (speed 0) (debug 3)))
19#-debug(proclaim '(optimize (speed 3) (debug 0)))
20
21;; This package calculates GCD of polynomials over integers.
22;; They are assumed to be ordered lexicographically.
23;;
24;; The algorithm is that on p. 57 of Geddes, Czapor, Labahn
25;; Given polynomials a(x),b(x) in D[x] where D is a UFD, we
26;; compute g(x)=GCD(a(x),b(x))
27;; Assume that the poly's are sorted lexicographically
28
29(defun poly-gcd (a b)
30 (cond
31 ((endp a) b)
32 ((endp b) a)
33 ((endp (caar a)) ;scalar
34 (list (cons nil (gcd (cdar a) (cdar b)))))
35 (t
36 (do* ((r nil (poly-pseudo-remainder c d))
37 (c (poly-primitive-part a) d)
38 (d (poly-primitive-part b) (poly-primitive-part r)))
39 ((endp d)
40 (poly* (poly-extend
41 (poly-gcd (poly-content a) (poly-content b)))
42 c))))))
43
44;; Perform a pseudo-division in k[x2,....,xn][x1]
45;; Assume that the terms are sorted according to decreasing powers of x1
46;; p.297 of Cox
47(defun poly-pseudo-divide (f g)
48 (multiple-value-bind (lg grest)
49 (lpart g)
50 (do* ((m (mdeg g))
51 (dm (poly-extend lg))
52 (lpart nil (multiple-value-list (lpart r)))
53 (lr nil (car lpart))
54 (lrest nil (cadr lpart))
55 (term nil (poly-extend lr (list (- (mdeg r) m))))
56 (r f (poly- (poly* dm lrest)
57 (poly* term grest)))
58 (q nil (append (poly* dm q) term)))
59 ((or (endp r) (< (mdeg r) m))
60 (values q r)))))
61
62
63(defun poly-pseudo-remainder (f g)
64 (second (multiple-value-list (poly-pseudo-divide f g))))
65
66;; Degree in main variable
67(defun mdeg (b) (caaar b))
68
69;; Leading coefficient in the first variable; a poly in k[x2,...,xn]
70(defun lcoeff (b)
71 (first (multiple-value-list (lpart b))))
72
73(defun lrest (b)
74 (second (multiple-value-list (lpart b))))
75
76(defun lpart (b)
77 (do ((mdeg (mdeg b))
78 (b b (rest b))
79 (b1 nil (cons (cons (cdaar b) (cdar b)) b1)))
80 ((or (endp b) (/= (caaar b) mdeg))
81 (values (reverse b1) b))))
82
83;; Divide f by its content
84(defun poly-primitive-part (f)
85 (cond
86 ((endp (caar f)) ;scalar
87 f)
88 (t
89 (poly-exact-divide f (poly-extend (poly-content f))))))
90
91
92(defun poly-content (f)
93 (cond
94 ((endp f) (error "Zero argument"))
95 (t (multiple-value-bind (lc r)
96 (lpart f)
97 (cond
98 ((endp r) lc)
99 ((and (= (length lc) 1)
100 (every #'zerop (caar lc))
101 (or (= (cdar lc) 1)
102 (= (cdar lc) -1))) ;lc is 1 or -1
103 lc)
104 (t (poly-gcd lc (poly-content r))))))))
Note: See TracBrowser for help on using the repository browser.