(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)))))