;;---------------------------------------------------------------- ;; This package implements BASIC OPERATIONS ON MONOMIALS ;;---------------------------------------------------------------- ;; DATA STRUCTURES: Monomials are represented as lists: ;; ;; monom: (n1 n2 ... nk) where ni are non-negative integers ;; ;; However, lists may be implemented as other sequence types, ;; so the flexibility to change the representation should be ;; maintained in the code to use general operations on sequences ;; whenever possible. The optimization for the actual representation ;; should be left to declarations and the compiler. ;;---------------------------------------------------------------- ;; EXAMPLES: Suppose that variables are x and y. Then ;; ;; Monom x*y^2 ---> (1 2) ;; ;;---------------------------------------------------------------- (deftype exponent () "Type of exponent in a monomial." 'fixnum) (deftype monom (&optional dim) "Type of monomial." `(simple-array exponent (,dim))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Construction of monomials ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defmacro make-monom (dim &key (initial-contents nil initial-contents-supplied-p) (initial-element 0 initial-element-supplied-p)) "Make a monomial with DIM variables. Additional argument INITIAL-CONTENTS specifies the list of powers of the consecutive variables. The alternative additional argument INITIAL-ELEMENT specifies the common power for all variables." ;;(declare (fixnum dim)) `(make-array ,dim :element-type 'exponent ,@(when initial-contents-supplied-p `(:initial-contents ,initial-contents)) ,@(when initial-element-supplied-p `(:initial-element ,initial-element)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Operations on monomials ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defmacro monom-elt (m index) "Return the power in the monomial M of variable number INDEX." `(elt ,m ,index)) (defun monom-dimension (m) "Return the number of variables in the monomial M." (length m)) (defun monom-total-degree (m &optional (start 0) (end (length m))) "Return the todal degree of a monomoal M. Optinally, a range of variables may be specified with arguments START and END." (declare (type monom m) (fixnum start end)) (reduce #'+ m :start start :end end)) (defun monom-sugar (m &aux (start 0) (end (length m))) "Return the sugar of a monomial M. Optinally, a range of variables may be specified with arguments START and END." (declare (type monom m) (fixnum start end)) (monom-total-degree m start end)) (defun monom-div (m1 m2 &aux (result (copy-seq m1))) "Divide monomial M1 by monomial M2." (declare (type monom m1 m2 result)) (map-into result #'- m1 m2)) (defun monom-mul (m1 m2 &aux (result (copy-seq m1))) "Multiply monomial M1 by monomial M2." (declare (type monom m1 m2 result)) (map-into result #'+ m1 m2)) (defun monom-divides-p (m1 m2) "Returns T if monomial M1 divides monomial M2, NIL otherwise." (declare (type monom m1 m2)) (every #'<= m1 m2)) (defun monom-divides-monom-lcm-p (m1 m2 m3) "Returns T if monomial M1 divides MONOM-LCM(M2,M3), NIL otherwise." (declare (type monom m1 m2 m3)) (every #'(lambda (x y z) (declare (type exponent x y z)) (<= x (max y z))) m1 m2 m3)) (defun monom-lcm-divides-monom-lcm-p (m1 m2 m3 m4) "Returns T if monomial MONOM-LCM(M1,M2) divides MONOM-LCM(M3,M4), NIL otherwise." (declare (type monom m1 m2 m3 m4)) (every #'(lambda (x y z w) (declare (type exponent x y z w)) (<= (max x y) (max z w))) m1 m2 m3 m4)) (defun monom-lcm-equal-monom-lcm-p (m1 m2 m3 m4) "Returns T if monomial MONOM-LCM(M1,M2) equals MONOM-LCM(M3,M4), NIL otherwise." (declare (type monom m1 m2 m3 m4)) (every #'(lambda (x y z w) (declare (type exponent x y z w)) (= (max x y) (max z w))) m1 m2 m3 m4)) (defun monom-divisible-by-p (m1 m2) "Returns T if monomial M1 is divisible by monomial M2, NIL otherwise." (declare (type monom m1 m2)) (every #'>= m1 m2)) (defun monom-rel-prime-p (m1 m2) "Returns T if two monomials M1 and M2 are relatively prime (disjoint)." (declare (type monom m1 m2)) (every #'(lambda (x y) (declare (type exponent x y)) (zerop (min x y))) m1 m2)) (defun monom-equal-p (m1 m2) "Returns T if two monomials M1 and M2 are equal." (declare (type monom m1 m2)) (every #'= m1 m2)) (defun monom-lcm (m1 m2 &aux (result (copy-seq m1))) "Returns least common multiple of monomials M1 and M2." (declare (type monom m1 m2)) (map-into result #'max m1 m2)) (defun monom-gcd (m1 m2 &aux (result (copy-seq m1))) "Returns greatest common divisor of monomials M1 and M2." (declare (type monom m1 m2)) (map-into result #'min m1 m2)) (defun monom-depends-p (m k) "Return T if the monomial M depends on variable number K." (declare (type monom m) (fixnum k)) (plusp (elt m k))) (defmacro monom-map (fun m &rest ml &aux (result `(copy-seq ,m))) `(map-into ,result ,fun ,m ,@ml)) (defmacro monom-append (m1 m2) `(concatenate 'monom ,m1 ,m2)) (defmacro monom-contract (k m) `(subseq ,m ,k)) (defun monom-exponents (m) (declare (type monom m)) (coerce m 'list))