source: CGBLisp/trunk/src/poly-gcd.lisp@ 14

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

Moving sources to trunk

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(proclaim '(optimize (speed 0) (debug 3)))
19
20;; This package calculates GCD of polynomials over integers.
21;; They are assumed to be ordered lexicographically.
22;;
23;; The algorithm is that on p. 57 of Geddes, Czapor, Labahn
24;; Given polynomials a(x),b(x) in D[x] where D is a UFD, we
25;; compute g(x)=GCD(a(x),b(x))
26;; Assume that the poly's are sorted lexicographically
27
28(defun poly-gcd (a b)
29 (cond
30 ((endp a) b)
31 ((endp b) a)
32 ((endp (caar a)) ;scalar
33 (list (cons nil (gcd (cdar a) (cdar b)))))
34 (t
35 (do* ((r nil (poly-pseudo-remainder c d))
36 (c (poly-primitive-part a) d)
37 (d (poly-primitive-part b) (poly-primitive-part r)))
38 ((endp d)
39 (poly* (poly-extend
40 (poly-gcd (poly-content a) (poly-content b)))
41 c))))))
42
43;; Perform a pseudo-division in k[x2,....,xn][x1]
44;; Assume that the terms are sorted according to decreasing powers of x1
45;; p.297 of Cox
46(defun poly-pseudo-divide (f g)
47 (multiple-value-bind (lg grest)
48 (lpart g)
49 (do* ((m (mdeg g))
50 (dm (poly-extend lg))
51 (lpart nil (multiple-value-list (lpart r)))
52 (lr nil (car lpart))
53 (lrest nil (cadr lpart))
54 (term nil (poly-extend lr (list (- (mdeg r) m))))
55 (r f (poly- (poly* dm lrest)
56 (poly* term grest)))
57 (q nil (append (poly* dm q) term)))
58 ((or (endp r) (< (mdeg r) m))
59 (values q r)))))
60
61
62(defun poly-pseudo-remainder (f g)
63 (second (multiple-value-list (poly-pseudo-divide f g))))
64
65;; Degree in main variable
66(defun mdeg (b) (caaar b))
67
68;; Leading coefficient in the first variable; a poly in k[x2,...,xn]
69(defun lcoeff (b)
70 (first (multiple-value-list (lpart b))))
71
72(defun lrest (b)
73 (second (multiple-value-list (lpart b))))
74
75(defun lpart (b)
76 (do ((mdeg (mdeg b))
77 (b b (rest b))
78 (b1 nil (cons (cons (cdaar b) (cdar b)) b1)))
79 ((or (endp b) (/= (caaar b) mdeg))
80 (values (reverse b1) b))))
81
82;; Divide f by its content
83(defun poly-primitive-part (f)
84 (cond
85 ((endp (caar f)) ;scalar
86 f)
87 (t
88 (poly-exact-divide f (poly-extend (poly-content f))))))
89
90
91(defun poly-content (f)
92 (cond
93 ((endp f) (error "Zero argument"))
94 (t (multiple-value-bind (lc r)
95 (lpart f)
96 (cond
97 ((endp r) lc)
98 ((and (= (length lc) 1)
99 (every #'zerop (caar lc))
100 (or (= (cdar lc) 1)
101 (= (cdar lc) -1))) ;lc is 1 or -1
102 lc)
103 (t (poly-gcd lc (poly-content r))))))))
Note: See TracBrowser for help on using the repository browser.