(uiop:define-package :st-buchberger/src/term (:mix :cl) (:mix-reexport :st-buchberger/src/ring-element) (:export #:term #:initialize-instance #:ring-zero-p #:print-object #:element->string #:ring-equal-p)) (in-package :st-buchberger/src/term) (defclass term (ring-element) ((coefficient :initarg :coefficient :initform 0 :accessor coefficient) (monomial :type vector :initarg :monomial :initform (make-array 0) :accessor monomial))) (defmethod initialize-instance :after ((tm term) &key ring) (unless (monomial tm) (setf (monomial tm) ; zero-polynomial (make-array (length (variables ring)) :element-type 'integer :initial-element 0)))) (defmethod ring-zero-p ((tm term)) (and (zerop (coefficient tm)) (vector-zero-p (monomial tm)))) (defmethod print-object ((tm term) stream) (print-unreadable-object (tm stream :type t) (format stream "~a ~a" (coefficient tm) (monomial tm)))) (defmethod element->string ((tm term) &key ring leading-term) (with-output-to-string (s) (with-slots (coefficient monomial) tm (flet ((independent-term-p (monomial) (every #'zerop monomial)) (print-variables () (dotimes (i (length monomial)) (let ((exponent (aref monomial i))) (unless (zerop exponent) (format s "~a" (string-downcase (elt (variables ring) i))) (when (/= 1 exponent) (format s "^~d" exponent))))))) (if (plusp (signum coefficient)) (format s (if leading-term "" "+ ")) (format s (if leading-term "-" "- "))) (if (independent-term-p monomial) (format s "~d" (abs coefficient)) (progn (when (/= 1 (abs coefficient)) (format s "~d" (abs coefficient))) (print-variables))))))) (defmethod ring-equal-p ((t1 term) (t2 term)) (with-slots ((c1 coefficient) (m1 monomial)) t1 (with-slots ((c2 coefficient) (m2 monomial)) t2 (and (= c1 c2) (vector-equal-p m1 m2)))))