package org.matheclipse.core.reflection.system;
import org.matheclipse.core.builtin.function.NumericQ;
import org.matheclipse.core.eval.exception.Validate;
import org.matheclipse.core.eval.interfaces.AbstractFunctionEvaluator;
import org.matheclipse.core.expression.F;
import org.matheclipse.core.generic.ITernaryComparator;
import org.matheclipse.core.interfaces.IAST;
import org.matheclipse.core.interfaces.IExpr;
import org.matheclipse.core.interfaces.ISignedNumber;
import org.matheclipse.core.interfaces.ISymbol;
public class Greater extends AbstractFunctionEvaluator implements ITernaryComparator {
public final static Greater CONST = new Greater();
public Greater() {
}
/**
* Try to simplify a comparator expression. Example: 3*x > 6 wll be simplified to x> 2.
*
* @param a1
* left-hand-side of the comparator expression
* @param a2
* right-hand-side of the comparator expression
* @return the simplified comparator expression or null if no simplification was found
*/
protected IExpr simplifyCompare(IExpr a1, IExpr a2) {
return simplifyCompare(a1, a2, F.Greater, F.Less);
}
/**
* Try to simplify a comparator expression. Example: 3*x > 6 wll be simplified to x> 2.
*
* @param a1
* left-hand-side of the comparator expression
* @param a2
* right-hand-side of the comparator expression
* @param originalHead
* symbol for which the simplification was started
* @param oppositeHead
* opposite of the symbol for which the comparison was started
* @return the simplified comparator expression or null if no simplification was found
*/
final protected IExpr simplifyCompare(IExpr a1, IExpr a2, ISymbol originalHead, ISymbol oppositeHead) {
IExpr lhs;
ISignedNumber rhs;
boolean useOppositeHeader = false;
if (a2.isSignedNumber()) {
lhs = a1;
rhs = (ISignedNumber) a2;
} else if (a1.isSignedNumber()) {
lhs = a2;
rhs = (ISignedNumber) a1;
useOppositeHeader = true;
} else {
lhs = F.eval(F.Subtract(a1,a2));
rhs = F.C0;
}
if (lhs.isAST()) {
IAST lhsAST = (IAST) lhs;
if (lhsAST.isTimes()) {
if (lhsAST.arg1().isSignedNumber()) {
ISignedNumber sn = (ISignedNumber) lhsAST.arg1();
if (sn.isNegative()) {
useOppositeHeader = !useOppositeHeader;
}
rhs = rhs.divideBy(sn);
return createComparatorResult(lhsAST, rhs, useOppositeHeader, originalHead, oppositeHead);
}
} else if (lhsAST.isPlus()) {
if (lhsAST.arg1().isSignedNumber()) {
ISignedNumber sn = (ISignedNumber) lhsAST.arg1();
rhs = rhs.subtractFrom(sn);
return createComparatorResult(lhsAST, rhs, useOppositeHeader, originalHead, oppositeHead);
}
}
}
return null;
}
/**
* Create the result for a simplifyCompare() step.
*
* @param lhsAST
* @param rhs
* @param useOppositeHeader
* @param originalHead
* @param oppositeHead
* @return
*/
private IExpr createComparatorResult(IAST lhsAST, IExpr rhs, boolean useOppositeHeader, ISymbol originalHead,
ISymbol oppositeHead) {
IAST lhsClone = lhsAST.clone();
lhsClone.remove(1);
if (useOppositeHeader) {
return F.binary(oppositeHead, lhsClone, rhs);
} else {
return F.binary(originalHead, lhsClone, rhs);
}
}
@Override
public IExpr evaluate(final IAST ast) {
Validate.checkRange(ast, 3);
if (ast.size() == 3) {
IExpr result = simplifyCompare(ast.arg1(), ast.arg2());
if (result != null) {
return result;
}
}
COMPARE_RESULT b = COMPARE_RESULT.UNDEFINED;
boolean evaled = false;
IAST result = ast.clone();
COMPARE_RESULT[] cResult = new COMPARE_RESULT[ast.size()];
cResult[0] = COMPARE_RESULT.TRUE;
for (int i = 1; i < ast.size() - 1; i++) {
b = prepareCompare(result.get(i), result.get(i + 1));
if (b == COMPARE_RESULT.FALSE) {
return F.False;
}
if (b == COMPARE_RESULT.TRUE) {
evaled = true;
}
cResult[i] = b;
}
cResult[ast.size() - 1] = COMPARE_RESULT.TRUE;
if (!evaled) {
// expression doesn't change
return null;
}
int i = 2;
evaled = false;
for (int j = 1; j < ast.size(); j++) {
if (cResult[j - 1] == COMPARE_RESULT.TRUE && cResult[j] == COMPARE_RESULT.TRUE) {
evaled = true;
result.remove(i - 1);
} else {
i++;
}
}
if (evaled) {
if (result.size() <= 2) {
return F.True;
}
return result;
}
return null;
}
public COMPARE_RESULT prepareCompare(final IExpr o0, final IExpr o1) {
// don't compare strings
IExpr a0 = o0;
IExpr a1 = o1;
if (!(a0.isSignedNumber()) && NumericQ.CONST.apply(a0)) {
a0 = F.evaln(a0);
}
if (!(a1.isSignedNumber()) && NumericQ.CONST.apply(a1)) {
a1 = F.evaln(a1);
}
if (a0.isNumeric() && a1.isRational()) {
a1 = F.evaln(a1);
}
if (a1.isNumeric() && a0.isRational()) {
a0 = F.evaln(a0);
}
return compare(a0, a1);
}
public COMPARE_RESULT compare(final IExpr a0, final IExpr a1) {
// don't compare strings
if (a0.isSignedNumber() && a1.isSignedNumber()) {
if (a1.isLTOrdered(a0)) {
return COMPARE_RESULT.TRUE;
}
return COMPARE_RESULT.FALSE;
}
return COMPARE_RESULT.UNDEFINED;
}
@Override
public void setUp(final ISymbol symbol) {
symbol.setAttributes(ISymbol.FLAT);
}
}
Ads help maintain this website.