/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package jmathexpr.number.set;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import jmathexpr.AbstractExpression;
import jmathexpr.Expression;
import jmathexpr.Precedence;
import jmathexpr.bool.TruthValue;
import jmathexpr.arithmetic.ANumber;
import jmathexpr.arithmetic.natural.Naturals;
import jmathexpr.arithmetic.real.Infinity;
import jmathexpr.arithmetic.real.Reals;
import jmathexpr.arithmetic.relation.LE;
import jmathexpr.arithmetic.relation.LT;
import jmathexpr.set.Cardinality;
import jmathexpr.set.Set;
import jmathexpr.util.pattern.ExpressionPattern;
import jmathexpr.util.rule.Rule;
/**
* An interval between two numbers. An interval may be opened or closed and it
* may be bounded or unbounded.
*
* @author Elemér Furka
*/
public class Interval extends AbstractExpression implements Set {
/**
* A number or minus infinity.
*/
private final Expression a;
/**
* A number or plus infinity.
*/
private final Expression b;
private final boolean leftClosed;
private final boolean rightClosed;
public Interval(boolean leftClosed, Expression a, Expression b, boolean rightClosed) {
this.leftClosed = leftClosed;
this.a = a;
this.b = b;
this.rightClosed = rightClosed;
}
public boolean isLeftBounded() {
return !a.equals(Infinity.MINUS_INFINITY);
}
public boolean isRightBounded() {
return !b.equals(Infinity.PLUS_INFINITY);
}
@Override
public Set evaluate() {
return new Interval(leftClosed, a.evaluate(), b.evaluate(), rightClosed);
}
@Override
public TruthValue contains(Expression element) {
if (element instanceof ANumber) {
Expression leftTest = leftClosed ? new LE(a, element).evaluate() : new LT(a, element).evaluate();
Expression rightTest = rightClosed ? new LE(element, b).evaluate() : new LT(element, b).evaluate();
if (leftTest instanceof TruthValue && rightTest instanceof TruthValue) {
return ((TruthValue) leftTest).and((TruthValue) rightTest);
}
}
throw new IllegalArgumentException("Relation cannot be determined: " + element);
}
@Override
public boolean subsetOf(Set set) {
if (equals(set)) {
return true;
} else if (set.equals(Reals.getInstance())) {
return true;
}
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public boolean equals(Object object) {
if (object == null) return false;
if (this == object) return true;
if (object instanceof Interval) {
Interval other = (Interval) object;
return leftClosed == other.leftClosed && a.equals(other.a) && b.equals(other.b) && rightClosed == other.rightClosed;
}
return false;
}
@Override
public int hashCode() {
int hash = 7;
hash = 83 * hash + Objects.hashCode(this.a);
hash = 83 * hash + Objects.hashCode(this.b);
hash = 83 * hash + (this.leftClosed ? 1 : 0);
hash = 83 * hash + (this.rightClosed ? 1 : 0);
return hash;
}
@Override
public String toString() {
return String.format("%s%s, %s%s", leftClosed ? "[" : "(",
a, b, rightClosed ? "]" : ")");
}
@Override
public String toUnicode() {
return toString();
}
@Override
public boolean isConstant() {
return a.isConstant() && b.isConstant();
}
@Override
public Precedence getPrecedence() {
return Precedence.Evaluation;
}
@Override
public Set union(Set set) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public Set domain() {
return Reals.getInstance();
}
@Override
public Set codomain() {
return Reals.getInstance();
}
@Override
public List<Expression> getChildren() {
List<Expression> children = new ArrayList();
children.add(a);
children.add(b);
return Collections.unmodifiableList(children);
}
@Override
public Cardinality cardinality() {
if (a instanceof ANumber && b instanceof ANumber) {
ANumber l = (ANumber) a;
ANumber r = (ANumber) b;
if (l.lt(r)) {
return Reals.getInstance().cardinality();
} else if (l.equals(r)) {
if (leftClosed && rightClosed) {
return new Cardinality(Naturals.one());
} else {
return new Cardinality(Naturals.zero());
}
}
}
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}