;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; Copyright (C) 1999, 2002, 2009, 2015 Marek Rychlik ;;; ;;; This program is free software; you can redistribute it and/or modify ;;; it under the terms of the GNU General Public License as published by ;;; the Free Software Foundation; either version 2 of the License, or ;;; (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;---------------------------------------------------------------- ;; This package implements BASIC OPERATIONS ON MONOMIALS ;;---------------------------------------------------------------- ;; DATA STRUCTURES: Conceptually, monomials can be 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) ;; ;;---------------------------------------------------------------- (defpackage "MONOMIAL" (:use :cl) (:export "MONOM" "EXPONENT" "MAKE-MONOM" "MONOM-ELT" "MONOM-DIMENSION" "MONOM-TOTAL-DEGREE" "MONOM-SUGAR" "MONOM-DIV" "MONOM-MUL" "MONOM-DIVIDES-P" "MONOM-DIVIDES-MONOM-LCM-P" "MONOM-LCM-DIVIDES-MONOM-LCM-P" "MONOM-LCM-EQUAL-MONOM-LCM-P" "MONOM-DIVISIBLE-BY-P" "MONOM-REL-PRIME-P" "MONOM-EQUAL-P" "MONOM-LCM" "MONOM-GCD" "MONOM-DEPENDS-P" "MONOM-MAP" "MONOM-APPEND" "MONOM-CONTRACT" "MONOM-EXPONENTS")) (in-package :monomial) (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))