in gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Expression.java [648:1041]
public Expression(String expression) {
this.expression = expression;
addOperator(new Assignment("=", 5) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
return v2;
}
});
addOperator(new Assignment("+=", 5) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
return v1.add(v2, mc);
}
@Override
public Object eval(String v1, String v2) {
return v1 + v2;
}
});
addOperator(new Assignment("-=", 5) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
return v1.subtract(v2, mc);
}
});
addOperator(new Assignment("*=", 5) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
return v1.multiply(v2, mc);
}
});
addOperator(new Assignment("/=", 5) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
return v1.divide(v2, mc);
}
});
addOperator(new Assignment("%=", 5) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
return v1.remainder(v2, mc);
}
});
addOperator(new Assignment("|=", 5) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
return new BigDecimal(v1.toBigInteger().or(v2.toBigInteger()), mc);
}
});
addOperator(new Assignment("&=", 5) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
return new BigDecimal(v1.toBigInteger().and(v2.toBigInteger()), mc);
}
});
addOperator(new Assignment("^=", 5) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
return new BigDecimal(v1.toBigInteger().xor(v2.toBigInteger()), mc);
}
});
addOperator(new Assignment("<<=", 5) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
return new BigDecimal(v1.toBigInteger().shiftLeft(v2.intValue()), mc);
}
});
addOperator(new Assignment(">>=", 5) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
return new BigDecimal(v1.toBigInteger().shiftRight(v2.intValue()), mc);
}
});
addOperator(new Operator("<<", 10, true) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
return new BigDecimal(v1.toBigInteger().shiftLeft(v2.intValue()), mc);
}
});
addOperator(new Operator(">>", 10, true) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
return new BigDecimal(v1.toBigInteger().shiftRight(v2.intValue()), mc);
}
});
addOperator(new Operator("|", 15, true) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
return new BigDecimal(v1.toBigInteger().or(v2.toBigInteger()), mc);
}
});
addOperator(new Operator("&", 15, true) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
return new BigDecimal(v1.toBigInteger().and(v2.toBigInteger()), mc);
}
});
addOperator(new Operator("^", 15, true) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
return new BigDecimal(v1.toBigInteger().xor(v2.toBigInteger()), mc);
}
});
addOperator(new Operator("+", 20, true) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
return v1.add(v2, mc);
}
@Override
public Object eval(String v1, String v2) {
return v1 + v2;
}
});
addOperator(new Operator("-", 20, true) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
return v1.subtract(v2, mc);
}
});
addOperator(new Operator("*", 30, true) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
return v1.multiply(v2, mc);
}
});
addOperator(new Operator("/", 30, true) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
return v1.divide(v2, mc);
}
});
addOperator(new Operator("%", 30, true) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
return v1.remainder(v2, mc);
}
});
addOperator(new Operator("**", 40, false) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
/*-
* Thanks to Gene Marin:
* http://stackoverflow.com/questions/3579779/how-to-do-a-fractional-power-on-bigdecimal-in-java
*/
int signOf2 = v2.signum();
double dn1 = v1.doubleValue();
v2 = v2.multiply(new BigDecimal(signOf2)); // n2 is now positive
BigDecimal remainderOf2 = v2.remainder(BigDecimal.ONE);
BigDecimal n2IntPart = v2.subtract(remainderOf2);
BigDecimal intPow = v1.pow(n2IntPart.intValueExact(), mc);
BigDecimal doublePow = new BigDecimal(Math.pow(dn1,
remainderOf2.doubleValue()));
BigDecimal result = intPow.multiply(doublePow, mc);
if (signOf2 == -1) {
result = BigDecimal.ONE.divide(result, mc.getPrecision(),
RoundingMode.HALF_UP);
}
return result;
}
});
addOperator(new Operator("&&", 4, false) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
boolean b1 = !v1.equals(BigDecimal.ZERO);
boolean b2 = !v2.equals(BigDecimal.ZERO);
return b1 && b2 ? BigDecimal.ONE : BigDecimal.ZERO;
}
});
addOperator(new Operator("||", 2, false) {
@Override
public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
boolean b1 = !v1.equals(BigDecimal.ZERO);
boolean b2 = !v2.equals(BigDecimal.ZERO);
return b1 || b2 ? BigDecimal.ONE : BigDecimal.ZERO;
}
});
addOperator(new Comparator(">", 10) {
@Override @SuppressWarnings({ "unchecked", "rawtypes" })
public boolean compare(Comparable v1, Comparable v2) {
return v1.compareTo(v2) > 0;
}
});
addOperator(new Comparator(">=", 10) {
@Override @SuppressWarnings({ "unchecked", "rawtypes" })
public boolean compare(Comparable v1, Comparable v2) {
return v1.compareTo(v2) >= 0;
}
});
addOperator(new Comparator("<", 10) {
@Override @SuppressWarnings({ "unchecked", "rawtypes" })
public boolean compare(Comparable v1, Comparable v2) {
return v1.compareTo(v2) < 0;
}
});
addOperator(new Comparator("<=", 10) {
@Override @SuppressWarnings({ "unchecked", "rawtypes" })
public boolean compare(Comparable v1, Comparable v2) {
return v1.compareTo(v2) <= 0;
}
});
addOperator(new Comparator("==", 7) {
@Override @SuppressWarnings({ "unchecked", "rawtypes" })
public boolean compare(Comparable v1, Comparable v2) {
return v1.compareTo(v2) == 0;
}
});
addOperator(new Comparator("!=", 7) {
@Override @SuppressWarnings({ "unchecked", "rawtypes" })
public boolean compare(Comparable v1, Comparable v2) {
return v1.compareTo(v2) != 0;
}
});
addFunction(new Function("NOT", 1) {
@Override
public BigDecimal eval(List<BigDecimal> parameters) {
boolean zero = parameters.get(0).compareTo(BigDecimal.ZERO) == 0;
return zero ? BigDecimal.ONE : BigDecimal.ZERO;
}
});
addFunction(new Function("IF", 3) {
@Override
public BigDecimal eval(List<BigDecimal> parameters) {
boolean isTrue = !parameters.get(0).equals(BigDecimal.ZERO);
return isTrue ? parameters.get(1) : parameters.get(2);
}
});
addFunction(new Function("RANDOM", 0) {
@Override
public BigDecimal eval(List<BigDecimal> parameters) {
double d = Math.random();
return new BigDecimal(d, mc);
}
});
addFunction(new Function("SIN", 1) {
@Override
public BigDecimal eval(List<BigDecimal> parameters) {
double d = Math.sin(Math.toRadians(parameters.get(0)
.doubleValue()));
return new BigDecimal(d, mc);
}
});
addFunction(new Function("COS", 1) {
@Override
public BigDecimal eval(List<BigDecimal> parameters) {
double d = Math.cos(Math.toRadians(parameters.get(0)
.doubleValue()));
return new BigDecimal(d, mc);
}
});
addFunction(new Function("TAN", 1) {
@Override
public BigDecimal eval(List<BigDecimal> parameters) {
double d = Math.tan(Math.toRadians(parameters.get(0)
.doubleValue()));
return new BigDecimal(d, mc);
}
});
addFunction(new Function("SINH", 1) {
@Override
public BigDecimal eval(List<BigDecimal> parameters) {
double d = Math.sinh(parameters.get(0).doubleValue());
return new BigDecimal(d, mc);
}
});
addFunction(new Function("COSH", 1) {
@Override
public BigDecimal eval(List<BigDecimal> parameters) {
double d = Math.cosh(parameters.get(0).doubleValue());
return new BigDecimal(d, mc);
}
});
addFunction(new Function("TANH", 1) {
@Override
public BigDecimal eval(List<BigDecimal> parameters) {
double d = Math.tanh(parameters.get(0).doubleValue());
return new BigDecimal(d, mc);
}
});
addFunction(new Function("RAD", 1) {
@Override
public BigDecimal eval(List<BigDecimal> parameters) {
double d = Math.toRadians(parameters.get(0).doubleValue());
return new BigDecimal(d, mc);
}
});
addFunction(new Function("DEG", 1) {
@Override
public BigDecimal eval(List<BigDecimal> parameters) {
double d = Math.toDegrees(parameters.get(0).doubleValue());
return new BigDecimal(d, mc);
}
});
addFunction(new Function("MAX", 2) {
@Override
public BigDecimal eval(List<BigDecimal> parameters) {
BigDecimal v1 = parameters.get(0);
BigDecimal v2 = parameters.get(1);
return v1.compareTo(v2) > 0 ? v1 : v2;
}
});
addFunction(new Function("MIN", 2) {
@Override
public BigDecimal eval(List<BigDecimal> parameters) {
BigDecimal v1 = parameters.get(0);
BigDecimal v2 = parameters.get(1);
return v1.compareTo(v2) < 0 ? v1 : v2;
}
});
addFunction(new Function("ABS", 1) {
@Override
public BigDecimal eval(List<BigDecimal> parameters) {
return parameters.get(0).abs(mc);
}
});
addFunction(new Function("LOG", 1) {
@Override
public BigDecimal eval(List<BigDecimal> parameters) {
double d = Math.log(parameters.get(0).doubleValue());
return new BigDecimal(d, mc);
}
});
addFunction(new Function("ROUND", 2) {
@Override
public BigDecimal eval(List<BigDecimal> parameters) {
BigDecimal toRound = parameters.get(0);
int precision = parameters.get(1).intValue();
return toRound.setScale(precision, mc.getRoundingMode());
}
});
addFunction(new Function("FLOOR", 1) {
@Override
public BigDecimal eval(List<BigDecimal> parameters) {
BigDecimal toRound = parameters.get(0);
return toRound.setScale(0, RoundingMode.FLOOR);
}
});
addFunction(new Function("CEILING", 1) {
@Override
public BigDecimal eval(List<BigDecimal> parameters) {
BigDecimal toRound = parameters.get(0);
return toRound.setScale(0, RoundingMode.CEILING);
}
});
addFunction(new Function("SQRT", 1) {
@Override
public BigDecimal eval(List<BigDecimal> parameters) {
/*
* From The Java Programmers Guide To numerical Computing
* (Ronald Mak, 2003)
*/
BigDecimal x = parameters.get(0);
if (x.compareTo(BigDecimal.ZERO) == 0) {
return new BigDecimal(0);
}
if (x.signum() < 0) {
throw new ExpressionException(
"Argument to SQRT() function must not be negative");
}
BigInteger n = x.movePointRight(mc.getPrecision() << 1)
.toBigInteger();
int bits = (n.bitLength() + 1) >> 1;
BigInteger ix = n.shiftRight(bits);
BigInteger ixPrev;
do {
ixPrev = ix;
ix = ix.add(n.divide(ix)).shiftRight(1);
// Give other threads a chance to work;
Thread.yield();
} while (ix.compareTo(ixPrev) != 0);
return new BigDecimal(ix, mc.getPrecision());
}
});
constants.put("PI", PI);
constants.put("TRUE", Boolean.TRUE);
constants.put("FALSE", Boolean.FALSE);
}