MonicMonomial.java
package edu.udel.cis.vsl.tass.symbolic.monic;
import java.util.Arrays;
import edu.udel.cis.vsl.tass.number.Numbers;
import edu.udel.cis.vsl.tass.number.IF.IntegerNumberIF;
import edu.udel.cis.vsl.tass.number.IF.NumberFactoryIF;
import edu.udel.cis.vsl.tass.symbolic.NumericPrimitive;
import edu.udel.cis.vsl.tass.symbolic.IF.tree.NumericConcreteExpressionIF;
import edu.udel.cis.vsl.tass.symbolic.IF.tree.TreeExpressionIF;
import edu.udel.cis.vsl.tass.symbolic.IF.type.SymbolicTypeIF;
import edu.udel.cis.vsl.tass.symbolic.expression.SymbolicExpression;
import edu.udel.cis.vsl.tass.symbolic.power.PowerExpression;
/**
* A monic monomial is a product of primitive expressions.
*
* It is structured as a sequence of primitive expressions and exponents:
* (x_0^n_0)...(x_r^n_r).
*
* The primitive expressions are ordered from least to greatest by id.
*
* The primitive expressions are unique (x_i=x_j => i=j).
*
* The exponents are all positive integers.
*
* It is possible for r=0. This represents the empty product, i.e., 1.
*
* The degree of the monomial is the sum of the exponents. (If r=0, the degree
* is 0.)
*
* The set of monomials has an order. In this order, a monomial of higher degree
* always comes before a monomial of lower degree. For two monomials of the same
* degree, the id numbers of the primitive factors are used; see the comments
* for the compareTo method below.
*
* Note that a MonicMonomial cannot be 0. (On the other hand, a monomial can be
* 0: it can be the product of the constant 0 and the MonicMonomial 1.)
*/
public class MonicMonomial extends SymbolicExpression implements
TreeExpressionIF, Comparable<MonicMonomial> {
private static NumberFactoryIF numberFactory = Numbers.REAL_FACTORY;
/**
* The factors are listed in increasing order. Factors are ordered by
* increasing id. Each factorPower is of the form e^n where e is a
* NumericPrimitive expression and n is ConcreteNumericExpressionIF
* (wrapping a non-negative concrete integer).
*/
private PowerExpression[] factorPowers;
MonicMonomial(SymbolicTypeIF numericType, PowerExpression[] factorPowers) {
super(numericType);
assert factorPowers != null;
for (PowerExpression factorPower : factorPowers) {
assert numericType.equals(factorPower.type());
assert factorPower.exponent().value().signum() > 0;
assert factorPower.base() instanceof NumericPrimitive;
}
this.factorPowers = factorPowers;
}
public PowerExpression[] factorPowers() {
return factorPowers;
}
public PowerExpression factorPower(int index) {
return factorPowers[index];
}
public NumericPrimitive factor(int index) {
return (NumericPrimitive) factorPowers[index].base();
}
public NumericConcreteExpressionIF exponent(int index) {
return factorPowers[index].exponent();
}
protected int intrinsicHashCode() {
return MonicMonomial.class.hashCode() + type().hashCode()
+ Arrays.hashCode(factorPowers);
}
protected boolean intrinsicEquals(SymbolicExpression expression) {
if (expression instanceof MonicMonomial) {
MonicMonomial that = (MonicMonomial) expression;
return type().equals(that.type())
&& Arrays.equals(factorPowers, that.factorPowers);
}
return false;
}
public String toString() {
String result = "";
for (int i = 0; i < factorPowers.length; i++) {
if (i > 0)
result += "*";
result += factorPowers[i].atomString();
}
return result;
}
public String atomString() {
return "(" + toString() + ")";
}
/**
* Order: (1) A monomial of higher degree comes before a monomial of lower
* degree. (2) If X and Y are primitives and X comes before Y, and m1 = pXq1
* (where p and q1 are some monomials) and m2 = pYq2 (where q2 is some
* monomial), then m1 comes before m2.
*
* This assumes that the factors are already ordered in increasing order.
*
* + : this-that>0, i.e. this>that, i.e. that comes first in list of
* increasing order
*/
public int compareTo(MonicMonomial that) {
if (equals(that))
return 0;
int compare = numberFactory.compare(that.degree(), degree());
if (compare != 0)
return compare;
int numFactors1 = factorPowers.length;
int numFactors2 = that.factorPowers.length;
int i = 0;
while (true) {
if (i >= numFactors1 || i >= numFactors2) {
throw new RuntimeException(
"TASS Internal Error on monomial ordering\n" + this
+ "\n" + that);
}
compare = SymbolicExpression.compare(
(SymbolicExpression) factorPowers[i].base(),
(SymbolicExpression) that.factorPowers[i].base());
if (compare != 0)
return compare;
compare = numberFactory.compare(that.factorPowers[i].exponent()
.value(), factorPowers[i].exponent().value());
if (compare != 0)
return compare;
i++;
}
}
public IntegerNumberIF degree() {
IntegerNumberIF sum = numberFactory.zeroInteger();
for (int i = 0; i < factorPowers.length; i++)
sum = numberFactory.add(sum, (IntegerNumberIF) factorPowers[i]
.exponent().value());
return sum;
}
public boolean isOne() {
return factorPowers.length == 0;
}
public TreeExpressionIF argument(int index) {
return factorPowers[index];
}
public SymbolicKind kind() {
return SymbolicKind.MULTIPLY;
}
public int numArguments() {
return factorPowers.length;
}
}