
polynom Specification SheetComputer Algebra Kit (c) 1993,00 by Comp.Alg.Objects. All Rights Reserved.
PolynomialInherits from: CAObjectMaturity Index: Relatively mature
Class DescriptionPolynomials are sums of products of scalar objects and symbols raised to small, nonnegative integer exponents. The scalars and symbols can be arbitrary Computer Algebra Kit objects. Polynomial supports arithmetic over floatingpoint scalars, or elements of a field (see inField), or scalars that are elements of an integral domain (see inIntegralDomain).
RepresentationsAll together, the Polynomial object presents eight different representations for polynomial arithmetic. A recursive polynomial is a sum of terms, where each term consists of a coefficient, that is either a scalar object or again a polynomial, multiplied by a symbol raised to an exponent (see Term). An expanded polynomial is a sum of monomials, each monomial consists of a scalar multiplied by a product of terms (see Monomial). If the polynomial is variable dense, the collection of possible symbols is fixed and symbols raised to the exponent zero are internally stored; if the polynomial is variable sparse, it's not defined a priori what symbols are allowed to occur in the polynomial. A polynomial can be either degree dense or degree sparse. If the polynomial is degree dense, terms or monomials can have a zero coefficient, otherwise the polynomial is internally stored as a linked list of nonzero terms or monomials.As an example, consider the recursive polynomial in two variables (2 x^2 + 1) y^3 + x y; it's a sum of two terms. The same polynomial in expanded representation is the sum of three monomials : 2 x^2 y^3 + y^3 + x y. Not all representations are implemented. Some representations (notably the variable sparse ones) are implemented in Objective C, and can already be used, but may be slow. The following table summarizes the current state of implementation of Polynomial :
Symbols and Variable OrderingNote: Symbols can be arbitrary objects. Any object that implements isEqual:, and for variable sparse polynomials, compare:, will serve (in the variable dense case it's not necessary to compare symbols because the ordering is fixed by the collection of symbols). We always refer to the objects in question as symbols, even when they are not instances of the Symbol class.For a variable dense polynomial, the collection of symbols is fixed when the monomial is created; you can't insert terms in a different symbol. In the variable sparse case, the collection of symbols is dynamically adapted as you insert terms, but is kept sorted alphabetically. Note that in the variable dense case, the collection of symbols contains the actual set of symbols (those that actually occur in the polynomial with nonzero exponent) as a subset. See the documentation on symbols. The variable ordering imposed by the collection of symbols is called lexicographic (currently the variable ordering is always lexicographic). Note that in the variable dense case, the lexicographic order need not be alphabetical.
Accessing Terms and Monomials in a PolynomialThe methods eachTerm, removeTerm and insertTerm: apply to recursive polynomials. For example, to obtain a collection of nonzero terms from a polynomial :
If the polynomial is variable sparse, the coefficients of the terms are either scalar objects or again variable sparse polynomials and each symbol can be different. If the polynomial is variable dense, all symbols of all terms are equal, and the coefficients are either all scalar objects or again all variable dense polynomials. In a degree dense polynomial, the coefficients of the terms can be zero; eachTerm might in effect return a zero term. It never does so for a degree sparse polynomial.while (aTerm = [aRecursivePolynomial removeTerm]) [aCollection add:aTerm]; The methods eachMonomial, removeMonomial and insertMonomial: apply to polynomials in expanded representation. For example, to obtain a collection of monomials from a polynomial :
The coefficients of the monomials are scalar objects. If the polynomial is variable sparse, the monomials are too. For degree dense polynomials eachMonomial also returns monomials with a zero coefficient. The leading monomial, returned by removeMonomial is never zero.aSequence = [anExpandedPolynomial eachMonomial]; while (aMonomial = [aSequence next]) [aCollection add:aMonomial];
Greatest Common DivisorsThere is an implementation of an algorithm to compute the GCD of (multivariate) polynomials. For univariate polynomials over a field, the Euclidean algorithm is being used. See gcd: for more details.
Counting Real RootsPolynomial implements for univariate polynomials with coefficients taken from an ordered domain (such as the integers) an algorithm to count the (total) number of real roots of the polynomial. See the documentation on numRealRoots.
FactorizationPolynomial implements a method to factor a polynomial into its squarefree parts, over fields or integral domains (zero or nonzero characteristic). See factorSquareFree for more details. There is also an implementation of an algorithm to factor a polynomial over a finite field into its irreducible factors. See the documentation on factor.
Method typesCreationIdentity
Coercion
Symbols and VariablesDegree and OrderNumber of Terms and MonomialsRemoving and InsertingSequencesRepresentation
Leading Term or MonomialMonic PolynomialsAdditionMultiplication
Polynomial DivisionPseudo DivisionContents and Primitive PartsResultant and Greatest Common DivisorCounting Real RootsFactoringTruncationCharacteristicEvaluation and SubstitutionDerivation and IntegrationPrintingMethodsscalar:+scalar:aScalarCreates and returns a polynomial in the recursive, variable sparse and degree sparse representation, containing the scalar object aScalar.
copycopyMakes a copy of all the terms or monomials of the polynomial. The original polynomial and the copy don't share any terms or monomials.
deepCopydeepCopyMakes a full independent copy of the polynomial by copying all terms or monomials and by sending deepCopy messages to the scalar objects. The original polynomial and the copy don't share any scalars, terms or monomials.
emptyemptyReturns a new empty polynomial i.e. a polynomial that is equal to zero and not a copy of another polynomial. The representation of the new polynomial is the same as the representation of the object that received the message.
scalarZeroscalarZeroReturns the zero (base) scalar element.
termZerotermZeroReturns the zero term for a recursive polynomial. In the variable dense case, you may depend upon the fact that the symbol of this term is set to the main symbol of the polynomial (the exponent is set to one).
monomialZeromonomialZeroReturns the zero monomial for an expanded polynomial.
isRecursive (BOOL)isRecursiveReturns YES if the polynomial is in recursive representation. Implies that the polynomial is not in expanded representation.
isExpanded (BOOL)isExpandedReturns YES if the polynomial is in expanded representation. Implies that the polynomial is not in recursive representation.
isVariableSparse (BOOL)isVariableSparseReturns YES if the polynomial is variable sparse. Implies that the polynomial is not variable dense.
isVariableDense (BOOL)isVariableDenseReturns YES if the polynomial is variable dense. Implies that the polynomial is not variable sparse.
isDegreeDense (BOOL)isDegreeDenseReturns YES if the polynomial is degree dense. Implies that the polynomial is not degree sparse.
isDegreeSparse (BOOL)isDegreeSparseReturns YES if the polynomial is degree sparse. Implies that the polynomial is not degree dense.
isUnivariate (BOOL)isUnivariateWhether the number of symbols equals one.
inUnivariateDomain (BOOL)inUnivariateDomainWhether the polynomial is variable dense and the number of symbols equals one.
isMultivariate (BOOL)isMultivariate intValue (int)intValueReturns zero if the polynomial is zero. If the polynomial consists of a single term or monomial, returns the int value of that object. Otherwise generates an error.
intValue:intValue:(int)aValueReturns a polynomial (of the same representation as the polynomial that receives the message) with value equal to aValue.
floatValue (float)floatValueReturns zero if the polynomial is zero. If the polynomial consists of a single term or monomial, returns the float value of that object. Otherwise generates an error.
floatValue:floatValue:(float)aValueReturns a polynomial (of the same representation as the polynomial that receives the message) with value equal to aValue.
asScalarasScalarIf the polynomial consists of just one term or monomial that is a scalar, this method returns a copy of the scalar. Otherwise it returns nil.
asSymbolasSymbolIf the polynomial consists of a single symbol (with exponent one and coefficient one), this method returns a copy of the symbol. Otherwise it returns nil. The method returns nil if the polynomial is a scalar that is a symbol...
asTermasTermReturns, for a recursive polynomial that consists of a single term, a copy of that term. Returns nil if the polynomial is zero (not considered to be a term) or a polynomial that consists of two or more terms.
asMonomialasMonomialReturns, for an expanded polynomial that consists of a single monomial, a copy of that monomial. Returns nil if the polynomial is zero (not considered to be a monomial) or a polynomial that consists of two or more monomials.
asCoefficientasCoefficientThis method applies only to recursive polynomials. If the polynomial is a term, this method returns a copy of its coefficient. Otherwise it returns nil.
asNumericalasNumericalReturns a numerical polynomial, ie. a polynomial in the same representation as the original polynomial but with the scalars are replaced by their numerical value. For example, for a polynomial with integer coefficients, this method returns a polynomial with floatingpoint objects as coefficients.
asModp:asModp:(unsigned short)pReturns a new polynomial, of the same representation as the original polynomial, but with the scalars replaced by their value modulo p, a small prime number.
symbolssymbolsReturns a collection of symbols. If the polynomial is variable dense, beware that some symbols may occur with a zero exponent in the polynomial. If the polynomial is variable sparse, this method returns an alphabetically sorted collection of all the symbols that occur in the polynomial with nonzero exponent. Don' modify the collection returned by this method; do not attempt to insert new symbols, or change their order.
degree (int)degreeFor a recursive polynomial, returns the maximum of the exponents of the terms. For an expanded polynomial, returns the maximum of the degrees of the monomials (the method first checks whether the variable order is degree or reverse degree compatible, because if it is, the maximum is not really computed). Returns minus one if the polynomial is equal to zero.
order (int)orderFor a recursive polynomial, returns the minimum of the exponents of the terms. For an expanded polynomial, returns the minimum of the degrees of the monomials (the method first checks whether the variable order is degree or reverse degree compatible, because if it is, the minimum is not really computed). Returns minus one if the polynomial is equal to zero. See also: termContent, monomialContent
numTerms (int)numTermsReturns the number of nonzero terms in the polynomial. Returns zero if the polynomial is equal to zero. In the case of a degree dense polynomial, the actual number of terms (including zero terms) can be obtained as the number of members of the associated sequence, or, for a univariate polynomial, as the degree of the polynomial plus one.
numMonomials (int)numMonomialsReturns the number of a nonzero monomials in the polynomial. Returns zero if the polynomial is equal to zero. In the case of a degree dense polynomial, the actual number of monomials (including zero monomials) can be obtained as the number of members of the associated sequence.
removeTermremoveTermRemoves (and returns) the leading nonzero term of the polynomial. Returns nil if the polynomial is equal to zero. The polynomial must be in recursive representation, but may be either degree sparse or degree dense, variable sparse or variable dense. To remove a term, the polynomial may not be a copy of another polynomial. If the polynomial is variable dense, the coefficient of the term is either a scalar, or a variable dense polynomial in a variable less. If the polynomial is variable sparse, the coefficient of the term is the same kind of variable sparse polynomial as the original ie., there is no difference between coefficient domain and polynomial domain in the variable sparse case. If the polynomial is degree dense, this method cannot be used to obtain the zero terms in the polynomial (because the leading term is defined as the first nonzero term in the sequence of terms). The method eachTerm returns all terms, including zero terms.
insertTerm:insertTerm:aTermInserts aTerm into the recursive polynomial and returns self. If the polynomial already contains a term with the same exponent, then the coefficients of the terms are added together. Otherwise, aTerm is inserted in the collection of terms. In any case, after insertion, aTerm belongs to the polynomial. To insert a term, the polynomial may not be a copy of another polynomial. As always, if the exponent of the term is zero, the symbol of the term must be nil. If the polynomial is variable sparse, the coefficient of the term must be either a scalar object or a <<nonscalar>> variable sparse polynomial. In the variable dense case, the symbol of the term must be equal to the main symbol of the variable dense polynomial; the coefficient domain of the polynomial must match the coefficient of the term; it may be either a scalar object or a variable dense polynomial. If the polynomial is degree sparse, insertion is fast at head or tail of the linked list of terms. If the polynomial is degree dense, the array of coefficients is automatically expanded to make room for new terms. Therefore, it's better to insert terms of higher degree before terms of smaller degree in the degree dense case.
removeMonomialremoveMonomialRemoves the leading monomial of the polynomial. Returns nil if the polynomial is equal to zero. The polynomial may be variable sparse or variable dense, degree sparse or degree dense, but must be in expanded representation. To remove a monomial, the polynomial may not be a copy of another polynomial.
insertMonomial:insertMonomial:aMonomialInserts aMonomial into the expanded polynomial and returns self. If the polynomial already contains a monomial with the same terms, then the scalars of the monomials are added together. Otherwise, aMonomial is inserted in the collection of monomials. In any case, after insertion, aMonomial belongs to the polynomial. The polynomial may not be a copy of another polynomial.
eachTermeachTermReturns, for a recursive polynomial, a sequence of terms. You may not modify the terms in the sequence or alter the polynomial in any other way while sequencing over its contents. A zero polynomial is represented by an empty sequence. If the polynomial is variable dense, all the terms in the sequence have the same symbol; if it is variable sparse, the symbols may be different. The terms are ordered with decreasing exponents (and in the variable sparse case, with respect to the symbols). The first member of the sequence is the leading term of the polynomial; this term is never equal to zero. If the polynomial is degree sparse, the sequence doesn't contain any terms with zero coefficient. If the polynomial is degree dense, the sequence also contains the terms with zero coefficient (unlike removeTerm). See also: CASequence
eachMonomialeachMonomialLike eachTerm but for expanded polynomial; returns a sequence of monomials. A zero polynomial is represented by an empty sequence. If the polynomial is variable dense, all the monomials in the sequence are variable dense; they are variable sparse if the polynomial is variable sparse. The monomials are ordered with respect to Monomials compareTerms: method. The first member of the sequence is the leading monomial of the polynomial; it's never equal to zero. If the polynomial is degree sparse, the sequence doesn't contain any monomials with zero coefficient. If the polynomial is degree dense, the sequence also contains the monomials with zero coefficient (unlike removeMonomial). See also: CASequence
eachSequenceeachSequenceNote: Not implemented. Returns, for recursive or expanded polynomials, a sequence whose members are either monomials or again sequences. At the deepest level of recursion the members of this sequence are monomials, even for recursive polynomials. The following example shows how to access the leading monomial of a recursive, nonzero polynomial (such a polynomial is not a sum of monomials) :
aSequence = [aRecursivePolynomial eachSequence]; aMember = [aSequence firstElement]; while ([aMember isKindOfSequence]) aMember = [aMember firstElement]; printf("leading monomial is %s",[aMember str]); eachScalareachScalarReturns a sequence of the scalar objects in the polynomial. If the polynomial is in expanded representation, this sequence contains the scalars of the monomials in the polynomial. If it is recursive, then the sequence contains the (base) scalars in the polynomial. Note: The sequence returned by this method doesn't respond to at: messages.
eachCoefficienteachCoefficientReturns, for a recursive and variable dense polynomial, a sequence of the coefficients of the terms in the polynomial.
makeDegreeDensemakeDegreeDenseIf the polynomial is degree dense, this method merely returns a copy of self. Otherwise, it creates a new degree dense polynomial and converts the polynomial into this new representation (making copies of the terms or monomials of the polynomial). The resulting polynomial may be recursive, expanded, variable sparse or variable dense, depending on the representation of the original polynomial.
makeDegreeSparsemakeDegreeSparseIf the polynomial is degree sparse, this method merely returns a copy of self. Otherwise, it creates a new degree sparse polynomial and converts the polynomial into this new representation (making copies of the terms or monomials of the polynomial). The resulting polynomial may be recursive, expanded, variable sparse or variable dense, depending on the representation of the original polynomial.
makeRecursivemakeRecursiveReturns, for an expanded polynomial, a new polynomial over the same domain of scalars and with the same value, but in the recursive representation. The polynomial may be degree dense or degree sparse, variable sparse or variable dense.
makeExpandedmakeExpandedReturns, for a recursive polynomial, a new polynomial over the same domain of scalars and with the same value, but in the expanded representation. The polynomial may be degree dense or degree sparse, variable sparse or variable dense.
makeVariableSparsemakeVariableSparseReturns, for a variable dense polynomial, a new polynomial over the same domain of scalars and with the same value, but in the variable sparse representation. The polynomial may be degree dense or degree sparse, recursive or expanded.
makeVariableDensemakeVariableDenseReturns, for a variable sparse or variable dense polynomial, a new polynomial over the same domain of scalars and with the same value, but in the variable dense representation. The polynomial may be degree dense or degree sparse, recursive or expanded. This method invokes collect:. See also: collect
collect:collect:symbolsNote: <<The case of symbols a collection with less members than the number of variables of the polynomial is not yet implemented. Currenlty symbols must contain the same number, or more symbols than the original polynomial>> Returns, for a variable sparse or variable dense polynomial, a new variable dense polynomial in the symbols indicated by the collection symbols. The collection must contain at least one symbol. The original polynomial may be degree dense or degree sparse, recursive or expanded, and the resulting polynomial will be of the same representation. The following examples show how to convert a variable sparse polynomial into variable dense representation, how to convert two variable sparse polynomials into the same variable dense representation, and finally how to change the variable order of a variable dense polynomial :
{ dense = [sparse collect:[sparse symbols]]; } { symbols = [[a symbols] union:[b symbols]]; c = [a collect:symbols]; d = [b collect:symbols]; } { symbols = [[b symbols] copy]; /* ... do something with "symbols" here... */ d = [b collect:symbols]; } leadingTermleadingTermReturns the leading term of the (recursive) polynomial. Returns nil if the polynomial is equal to zero.
leadingCoefficientleadingCoefficientReturns the leading coefficient of the (recursive) polynomial. Returns nil if the polynomial is equal to zero.
leadingSign (int)leadingSignFor a recursive polynomial, returns the sign of the leading coefficient. For a polynomial in expanded representation, returns the sign of the leading scalar. Returns zero if the polynomial is equal to zero.
leadingMonomialleadingMonomialReturns the leading monomial of the polynomial (in expanded representation). Returns nil if the polynomial is equal to zero.
leadingScalarleadingScalarReturns the scalar of the leading monomial of the polynomial. Returns nil if the polynomial is equal to zero.
isMonic (BOOL)isMonicFor a recursive polynomial, returns YES if the leading coefficient of the polynomial is equal to one. For an expanded polynomial, tests whether the leading scalar is equal to one. It follows that the same polynomial x y + 1 is monic in expanded representation, but is not monic in recursive representation (because the leading coefficient is x). The method returns NO if the polynomial is equal to zero.
notMonic (BOOL)notMonicWhether isMonic returns NO.
makeMonicmakeMonic zerozeroReturns a copy of the zero polynomial (same representation as polynomial that receives the message). The only difference with empty is that the latter method creates a new object, while this method just returns a copy of an already existing object. For example, it's not possible to insert terms in the polynomial returned by zero. See also: empty
addScalar:addScalar:sReturns a new polynomial; adds the (base) scalar s to the original polynomial.
subtractScalar:subtractScalar:sReturns a new polynomial; subtracts the (base) scalar s to the original polynomial.
oneoneReturns a copy of the unity polynomial (same representation as polynomial that receives the message).
isOne (BOOL)isOneWhether the polynomial is equal to one.
isMinusOne (BOOL)isMinusOneWhether the polynomial is equal to minus one.
multiply:multiply:bReturns a new polynomial. Computes the product of the polynomials by the classical polynomial multiplication algorithm, except if the polynomials are equal in which case the method invokes square.
squaresquareReturns a new polynomial. Computes the square of the polynomial by the classical polynomial multiplication algorithm using symmetry.
inverseinverseReturns a new polynomial that is the inverse of the polynomial, or nil if the polynomial cannot be inverted. A polynomial over a field or integral domain can be inverted if and only if it consists of a single term that is invertible.
remainder:quotient:remainder:bquotient:(id *)qReturns new polynomials R and, by reference, Q such that self = Q b + R. If q is a NULL pointer, the quotient Q is not computed. Returns nil (and sets the value pointed to by q to nil) if the polynomial division fails.
If the polynomials are variable sparse, they are converted into variable dense representation. The division algorithm itself, works for univariate and multivariate variable dense polynomials, in recursive or expanded representation, over fields or integral domains. However, in the multivariate case, a nonzero remainder need not be unique. In the case of division of polynomials with coefficients in an integral domain (such as the integers), the division possibly fails when a coefficient division fails; it is still possible to do a pseudodivision. See pseudoRemainder:quotient: for more details.id q,r; r = [self remainder:b quotient:&q]; /* do something with r and q */
divide:divide:bReturns the exact quotient (a new polynomial) of the polynomial division. Returns nil if the polynomial division fails or if the division was not exact (if there was a nonzero remainder). The polynomial may be expanded or recursive.
pseudoRemainder:quotient:pseudoRemainder:bquotient:(id *)qIf the polynomials are variable sparse or expanded, they are temporarily converted into variable dense and recursive representation for this operation. If n and m are the degrees of self and b respectively, and if c is the leading coefficient of b, than this method computes the pseudoremainder R and, if q is not a NULL pointer, the pseudoquotient Q such that c^(nm+1) self = Q b + R. Returns nil if the pseudodivision fails.
pseudoRemainder:pseudoRemainder:bComputes the pseudoremainder of the polynomials by invoking pseudoRemainder:quotient: with a NULL argument.
contentcontentReturns the content of the sequence of scalars of the polynomial (the greatest common divisor of the scalars in the polynomial); the result is a new scalar object. If the polynomial is zero, this method returns nil.
divideContentdivideContentIf the polynomial is zero, this method returns a copy of itself. Otherwise, this method returns the quotient (a new polynomial) on division by the scalar returned by content.
coefficientContentcoefficientContentReturns for a variable dense and recursive polynomial, the greatest common divisor of the coefficients (not scalars) of the polynomial. If the polynomial is equal to zero, this method returns nil.
divideCoefficientContentdivideCoefficientContentIf the polynomial is zero, this method returns a copy of itself. Otherwise, this method returns the quotient (a new polynomial) on division by the coefficient returned by coefficientContent.
termContenttermContentReturns for a variable dense and recursive polynomial, the monic greatest common divisor of the terms of the polynomial. In other words, this method returns the main symbol of the polynomial raised to the order of the polynomial. See also: order
monomialContentmonomialContentReturns the greatest common divisor (a monic monomial) of the monomials in an expanded polynomial. If the polynomial is equal to zero, this method returns nil.
truncateAtDegree:truncateAtDegree:(int)dDrops terms or monomials of degree greater than d. Returns a new polynomial.
frobeniusfrobeniusReturns a new polynomial that is the image of the polynomial under the frobenius map by sending frobenius messages to each term or monomial.
frobeniusInversefrobeniusInverseReturns a new polynomial that is the image of the polynomial under the inverse of the frobenius map by sending frobeniusInverse messages to each term or monomial. Returns nil if the polynomial is not the image of a polynomial under the frobenius map.
evaluate:evaluate:aScalarNote: Not implemented. Replaces the main variable of the polynomial by aScalar, and if the polynomial is univariate, returns a scalar object. If the polynomial is not univariate, it must be recursive and variable dense and the method returns again a recursive and variable dense polynomial in a variable less (ie. a coefficient object), obtained by replacing the main variable by aScalar.
evaluate:at:evaluate:(STR)aSymbolat:aScalarNote: Not implemented. Returns a new polynomial object, obtained by replacing the variable named aSymbol by aScalar.
evaluateAll:evaluateAll:cltnOfScalarsReturns a new scalar object, obtained by replacing all variables of the polynomial by the scalar objects in the collection cltnOfScalars i.e., the first member in the collection returned by variables is replaced by the first member in cltnOfScalars and so on. Variable sparse or expanded polynomials are temporarily converted into recursive and variable dense representation by this method.
substitute:substitute:aPolynomialReturns a new (variable dense) polynomial, obtained by replacing the main variable of a variable dense polynomial by aPolynomial.
substitute:by:substitute:(STR)aSymbolby:aPolynomialReturns a new polynomial, obtained by replacing the variable named aSymbol by aPolynomial. Implemented for recursive and variable sparse polynomials only.
substituteAll:substituteAll:cltnOfPolynomialsNote: Not implemented. Returns a new polynomial, obtained by replacing all variables simultaneously by the polynomials in the collectioncltnOfPolynomials. Change of Variables  Permuting (Swapping) Variables = substituteAll
derivederiveReturns the derivative of a variable dense polynomial with respect to the main variable (the last member in the collection returned by variables).
deriveWrt:deriveWrt:(STR)aSymbolNote: Not implemented. Returns the derivative of the polynomial with respect to the variable named aSymbol. For example, to integrate a polynomial with respect to x :
pdx = [p deriveWrt:"x"]; integrateintegrateIntegrates a variable dense polynomial with respect to the main variable (the last member in the collection returned by variables). Because the resulting polynomial is a polynomial over the same domain of scalars as the integrandum, this operation might fail and returns nil if the scalars are not taken from a field.
integrateWrt:integrateWrt:(STR)aSymbolNote: Not implemented. Integrates the polynomial with respect to the variable named aSymbol.
printsLeadingSign (BOOL)printsLeadingSignWhether the polynomial prints a leading minus sign.
printsSum (BOOL)printsSumWhether the polynomial prints multiple terms or monomials separated by a plus or minus signs.
printsProduct (BOOL)printsProductWhether the polynomial prints a single product.
printOn:printOn:(IOD)aFilePrints the polynomial, by sending printOn: messages to the terms or monomials.
