carl  24.04
Computer ARithmetic Library
Operators

The classes used to build polynomials are (almost) fully compatible with respect to the following operators, that means that any two objects of these types can be combined if there is a directed path between them within the class hierarchy. The exception are shown and explained below. All the operators have the usual meaning.

  • Comparison operators
    • operator==(lhs, rhs)
    • operator!=(lhs, rhs)
    • operator<(lhs, rhs)
    • operator<=(lhs, rhs)
    • operator>(lhs, rhs)
    • operator>=(lhs, rhs)
  • Arithmetic operators
    • operator+(lhs, rhs)
    • operator+=(lhs, rhs)
    • operator-(lhs, rhs)
    • operator-(rhs)
    • operator-=(lhs, rhs)
    • operator*(lhs, rhs)
    • operator*=(lhs, rhs)

Comparison operators

All of these operators are defined for all combination of types. We use the following ordering:

  • For two variables x and y, x < y if the id of x is smaller then the id of y. The id is generated automatically by the VariablePool.
  • For two monomials a and b, we use a lexicographical ordering with total degree, that is a < b if
    • the total degree of a is smaller than the total degree of b, or
    • the total degrees are the same and
      • the exponent of some variable v in a is greater than in b and
      • the exponents of all variables smaller than v are the same in a and in b.
    • The intuition is that the monomials are considered as a sorted product of plain variables.
  • For two terms a and b, a < b if
    • the monomial of a is smaller than the monomial of b, or
    • the monomials of a and b are the same and the coefficient of a is smaller than the coefficient of b.
  • For two polynomials a and b, we use a lexicographical ordering, that is a < b if
    • term(a,i) < term(b,i) and
    • term(a,j) = term(b,j) for all j=0, ..., i-1, where term(a,0) is the leading term of a, that is the largest term with respect to the term ordering.

Arithmetic operators

We now give a table for all (classes of) operators with the result type or a reason why it is not implemented for any combination of these types.

<tt>operator+(lhs, rhs)</tt>, <tt>operator-(lhs, rhs)</tt>

+ C V M T MP
C C MP MP MP MP
V MP 1) 1) MP MP
M MP 1) 1) MP MP
T MP MP MP MP MP
MP MP MP MP MP MP

<tt>operator-(lhs)</tt> (unary minus)

- C V M T MP
- C 1) 1) T MP

operator*(lhs, rhs)

* C V M T MP
C C T T T MP
V T M M T MP
M T M M T MP
T T T T T MP
MP MP MP MP MP MP

<tt>operator+=(rhs)</tt>, <tt>operator-=(rhs)</tt>

+= C V M T MP
C C 2) 2) 2) 2)
V 2) 2) 2) 2) 2)
M 2) 2) 2) 2) 2)
T 2) 2) 2) 2) 2)
MP MP MP MP MP MP

<tt>operator*=(rhs)</tt>

*= C V M T MP
C C 3) 3) 3) 3)
V 3) 3) 3) 3) 3)
M 3) M M 3) 3)
T T T T T 3)
MP MP MP MP MP MP
  1. A coefficient type is needed to construct the desired result type, but none can be extracted from the argument types.
  2. The type of the left hand side can not represent sums of these objects.
  3. The type of the left hand side can not represent products of these objects.

UnivariatePolynomial operators

Implementation

We follow a few rules when implementing these operators:

  • Of the comparison operators, only operator== and operator< contain a real implementation. The others are implemented like this:
    • operator!=(lhs, rhs): !(lhs == rhs)
    • operator<=(lhs, rhs): !(rhs < lhs)
    • operator>(lhs, rhs): rhs < lhs
    • operator>=(lhs, rhs): rhs <= lhs
  • Of all operator==, only those where lhs is the most general type contain a real implementation. The others are implemented like this:
    • operator==(lhs, rhs): rhs == lhs
  • They are ordered like in the list above.
  • Operators are implemented in the file of the most general type involved (either an argument or the return type).
  • Operators are not implemented as friend methods. Those are usually only found by the compiler due to ADL, but as we need to declare operator+(Term, Term) -> MultivariatePolynomial next to the MultivariatePolynomial, this will not work. If a friend declaration is necessary, it will be done as a forward declaration.
  • Overloaded versions of the same operator are ordered in decreasing lexicographical order, like in this example:
    • operator(Term,Term)
    • operator(Term,Monomial)
    • operator(Term,Variable)
    • operator(Term,Coefficient)
    • operator(Monomial,Term)
    • operator(Variable,Term)
    • operator(Coefficient,Term)
  • Other versions are below those.

Testing the operators

There are two stages for testing these operators: a syntactical check that these operators exist and have the correct signature and a semantical check that they actually work as expected.

Syntactical checks

The syntactical check for all operators specified here is done in tests/core/Test_Operators.cpp. We use boost::concept_check to check the existence of the operators. There are the following concepts:

  • Comparison: Checks for all comparison operators. (==, !=, <, <=, >, >=)
  • Addition: Checks for out-of-place addition operators. (+, -)
  • UnaryMinus: Checks for unary minus operators. (-)
  • Multiplication: Checks for out-of-place multiplication operators. (*)
  • InplaceAddition: Checks for all in-place addition operators. (+=, -=)
  • InplaceMultiplication: Checks for all in-place multiplication operators. (*=)

Semantical checks

Semantical checking is done within the test for each class.