/**
* Copyright 2004-2016 Riccardo Solmi. All rights reserved.
* This file is part of the Whole Platform.
*
* The Whole Platform is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Whole Platform is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whole.lang.math.visitors;
import java.math.RoundingMode;
import java.util.List;
import org.whole.lang.bindings.BindingManagerFactory;
import org.whole.lang.exceptions.WholeIllegalArgumentException;
import org.whole.lang.math.model.AbsoluteValue;
import org.whole.lang.math.model.Addition;
import org.whole.lang.math.model.And;
import org.whole.lang.math.model.ApproximatelyEqual;
import org.whole.lang.math.model.Arccosine;
import org.whole.lang.math.model.Arcsine;
import org.whole.lang.math.model.Arctangent;
import org.whole.lang.math.model.BigDecimal;
import org.whole.lang.math.model.BigInteger;
import org.whole.lang.math.model.Boolean;
import org.whole.lang.math.model.Builder;
import org.whole.lang.math.model.ByteInteger;
import org.whole.lang.math.model.Cardinality;
import org.whole.lang.math.model.Ceiling;
import org.whole.lang.math.model.Constant;
import org.whole.lang.math.model.ConstantEnum;
import org.whole.lang.math.model.Cosine;
import org.whole.lang.math.model.Difference;
import org.whole.lang.math.model.Division;
import org.whole.lang.math.model.Double;
import org.whole.lang.math.model.Empty;
import org.whole.lang.math.model.Enumeration;
import org.whole.lang.math.model.Equals;
import org.whole.lang.math.model.ExclusiveOr;
import org.whole.lang.math.model.Exponential;
import org.whole.lang.math.model.Exponentiation;
import org.whole.lang.math.model.Expression;
import org.whole.lang.math.model.FactorOf;
import org.whole.lang.math.model.Factorial;
import org.whole.lang.math.model.Float;
import org.whole.lang.math.model.Floor;
import org.whole.lang.math.model.GreaterOrEqual;
import org.whole.lang.math.model.GreaterThan;
import org.whole.lang.math.model.GreatestCommonDivisor;
import org.whole.lang.math.model.HyperbolicCosine;
import org.whole.lang.math.model.HyperbolicSine;
import org.whole.lang.math.model.HyperbolicTangent;
import org.whole.lang.math.model.Identifier;
import org.whole.lang.math.model.Implies;
import org.whole.lang.math.model.In;
import org.whole.lang.math.model.Integer;
import org.whole.lang.math.model.Intersection;
import org.whole.lang.math.model.LessOrEqual;
import org.whole.lang.math.model.LessThan;
import org.whole.lang.math.model.Logarithm;
import org.whole.lang.math.model.LongInteger;
import org.whole.lang.math.model.LowestCommonMultiple;
import org.whole.lang.math.model.Maximum;
import org.whole.lang.math.model.Minimum;
import org.whole.lang.math.model.Minus;
import org.whole.lang.math.model.Multiplication;
import org.whole.lang.math.model.NaturalLogarithm;
import org.whole.lang.math.model.Not;
import org.whole.lang.math.model.NotANumber;
import org.whole.lang.math.model.NotEquals;
import org.whole.lang.math.model.NotIn;
import org.whole.lang.math.model.NotProperSubset;
import org.whole.lang.math.model.NotSubset;
import org.whole.lang.math.model.Or;
import org.whole.lang.math.model.OrderedPair;
import org.whole.lang.math.model.ProperSubset;
import org.whole.lang.math.model.Quotient;
import org.whole.lang.math.model.Remainder;
import org.whole.lang.math.model.Root;
import org.whole.lang.math.model.Selector;
import org.whole.lang.math.model.Set;
import org.whole.lang.math.model.ShortInteger;
import org.whole.lang.math.model.Sine;
import org.whole.lang.math.model.Stream;
import org.whole.lang.math.model.Subset;
import org.whole.lang.math.model.Subtraction;
import org.whole.lang.math.model.Tangent;
import org.whole.lang.math.model.Tuple;
import org.whole.lang.math.model.Union;
import org.whole.lang.model.IEntity;
import org.whole.lang.reflect.DataKinds;
import org.whole.lang.util.DataTypeUtils;
import org.whole.lang.util.EntityUtils;
import org.whole.lang.util.WholeMessages;
/**
* @author Riccardo Solmi
*/
public class MathInterpreterVisitor extends MathIdentityDefaultVisitor {
protected void setLiteral(IEntity entity) {
setResult(BindingManagerFactory.instance.createSpecificValue(entity));
}
protected final IEntity createBooleanLiteral(boolean value) {
return BindingManagerFactory.instance.createValue(value);
}
protected final IEntity createFloatLiteral(float value) {
return BindingManagerFactory.instance.createValue(value);
}
protected final IEntity createDoubleLiteral(double value) {
return BindingManagerFactory.instance.createValue(value);
}
protected final IEntity createBigDecimalLiteral(java.math.BigDecimal value) {
return BindingManagerFactory.instance.createValue(value);
}
protected final IEntity createIntLiteral(int value) {
return BindingManagerFactory.instance.createValue(value);
}
protected final IEntity createLongLiteral(long value) {
return BindingManagerFactory.instance.createValue(value);
}
protected final IEntity createBigIntegerLiteral(java.math.BigInteger value) {
return BindingManagerFactory.instance.createValue(value);
}
protected final IEntity createStringLiteral(String value) {
return BindingManagerFactory.instance.createValue(value);
}
protected IEntity evaluateOptional(Expression entity) {
entity.accept(this);
return getResult();
}
protected IEntity evaluate(Expression entity) {
IEntity result = evaluateOptional(entity);
if (result == null)
throw new WholeIllegalArgumentException(WholeMessages.null_value_argument).withSourceEntity(entity).withBindings(getBindings());
return result;
}
public static enum ToKind {
INT, LONG, BIG_INTEGER, FLOAT, DOUBLE, BIG_DECIMAL
}
public static ToKind maxKind(ToKind kind1, ToKind kind2) {
if ((kind1.equals(ToKind.BIG_INTEGER) && kind1.compareTo(kind2) < 0) ||
(kind2.equals(ToKind.BIG_INTEGER) && kind2.compareTo(kind1) < 0))
return ToKind.BIG_DECIMAL;
return kind1.compareTo(kind2) < 0 ? kind2 : kind1;
}
public ToKind maxKind(ToKind kind1, IEntity entity) {
DataKinds dataKinds = DataTypeUtils.getUnboxedDataKind(entity);
if (dataKinds.isNotAData())
throw new WholeIllegalArgumentException(WholeMessages.no_data).withSourceEntity(entity).withBindings(getBindings());
else if (dataKinds.isObject() && entity.wGetValue() instanceof java.math.BigDecimal)
return ToKind.BIG_DECIMAL;
else if (dataKinds.isDouble())
return maxKind(kind1, ToKind.DOUBLE);
else if (dataKinds.isFloat())
return maxKind(kind1, ToKind.FLOAT);
else if (dataKinds.isObject() && entity.wGetValue() instanceof java.math.BigInteger)
return maxKind(kind1, ToKind.BIG_INTEGER);
else if (dataKinds.isLong())
return maxKind(kind1, ToKind.LONG);
else
return maxKind(kind1, ToKind.INT);
}
protected ToKind evaluateMaxKind(IEntity[] results, List<Expression> entity) {
ToKind resultKind = ToKind.INT;
for (int i=0, size=entity.size(); i<size; i++)
resultKind = maxKind(resultKind, results[i] = evaluate(entity.get(i)));
return resultKind;
}
protected ToKind evaluateMaxKind(IEntity[] results, Expression... entity) {
ToKind resultKind = ToKind.INT;
for (int i=0, size=entity.length; i<size; i++)
resultKind = maxKind(resultKind, results[i] = evaluate(entity[i]));
return resultKind;
}
@Override
public void visit(Addition entity) {
IEntity[] results = new IEntity[entity.size()];
ToKind resultKind = evaluateMaxKind(results, entity);
IEntity result;
switch (resultKind) {
case BIG_DECIMAL:
java.math.BigDecimal bdvalue = java.math.BigDecimal.ZERO;
for (IEntity r : results)
bdvalue = bdvalue.add(DataTypeUtils.toBigDecimal(r));
result = createBigDecimalLiteral(bdvalue);
break;
case DOUBLE:
double dvalue = 0d;
for (IEntity r : results)
dvalue += DataTypeUtils.toDouble(r);
result = createDoubleLiteral(dvalue);
break;
case FLOAT:
float fvalue = 0f;
for (IEntity r : results)
fvalue += DataTypeUtils.toFloat(r);
result = createFloatLiteral(fvalue);
break;
case BIG_INTEGER:
java.math.BigInteger bivalue = java.math.BigInteger.ZERO;
for (IEntity r : results)
bivalue = bivalue.add(DataTypeUtils.toBigInteger(r));
result = createBigIntegerLiteral(bivalue);
break;
case LONG:
long lvalue = 0l;
for (IEntity r : results)
lvalue += DataTypeUtils.toLong(r);
result = createLongLiteral(lvalue);
break;
default:
case INT:
int ivalue = 0;
for (IEntity r : results)
ivalue += DataTypeUtils.toInt(r);
result = createIntLiteral(ivalue);
break;
}
setResult(result);
}
@Override
public void visit(Multiplication entity) {
IEntity[] results = new IEntity[entity.size()];
ToKind resultKind = evaluateMaxKind(results, entity);
IEntity result;
switch (resultKind) {
case BIG_DECIMAL:
java.math.BigDecimal bdvalue = java.math.BigDecimal.ONE;
for (IEntity r : results)
bdvalue = bdvalue.multiply(DataTypeUtils.toBigDecimal(r));
result = createBigDecimalLiteral(bdvalue);
break;
case DOUBLE:
double dvalue = 1d;
for (IEntity r : results)
dvalue *= DataTypeUtils.toDouble(r);
result = createDoubleLiteral(dvalue);
break;
case FLOAT:
float fvalue = 1f;
for (IEntity r : results)
fvalue *= DataTypeUtils.toFloat(r);
result = createFloatLiteral(fvalue);
break;
case BIG_INTEGER:
java.math.BigInteger bivalue = java.math.BigInteger.ONE;
for (IEntity r : results)
bivalue = bivalue.multiply(DataTypeUtils.toBigInteger(r));
result = createBigIntegerLiteral(bivalue);
break;
case LONG:
long lvalue = 1l;
for (IEntity r : results)
lvalue *= DataTypeUtils.toLong(r);
result = createLongLiteral(lvalue);
break;
default:
case INT:
int ivalue = 1;
for (IEntity r : results)
ivalue *= DataTypeUtils.toInt(r);
result = createIntLiteral(ivalue);
break;
}
setResult(result);
}
@Override
public void visit(Subtraction entity) {
IEntity[] results = new IEntity[2];
ToKind resultKind = evaluateMaxKind(results, entity.getMinuend(), entity.getSubtrahend());
IEntity result;
switch (resultKind) {
case BIG_DECIMAL:
result = createBigDecimalLiteral(
DataTypeUtils.toBigDecimal(results[0]).subtract(DataTypeUtils.toBigDecimal(results[1])));
break;
case DOUBLE:
result = createDoubleLiteral(
DataTypeUtils.toDouble(results[0]) - DataTypeUtils.toDouble(results[1]));
break;
case FLOAT:
result = createFloatLiteral(
DataTypeUtils.toFloat(results[0]) - DataTypeUtils.toFloat(results[1]));
break;
case BIG_INTEGER:
result = createBigIntegerLiteral(
DataTypeUtils.toBigInteger(results[0]).subtract(DataTypeUtils.toBigInteger(results[1])));
break;
case LONG:
result = createLongLiteral(
DataTypeUtils.toLong(results[0]) - DataTypeUtils.toLong(results[1]));
break;
default:
case INT:
result = createIntLiteral(
DataTypeUtils.toInt(results[0]) - DataTypeUtils.toInt(results[1]));
break;
}
setResult(result);
}
@Override
public void visit(Division entity) {
IEntity[] results = new IEntity[2];
ToKind resultKind = evaluateMaxKind(results, entity.getDividend(), entity.getDivisor());
IEntity result;
switch (resultKind) {
case BIG_INTEGER:
case BIG_DECIMAL:
result = createBigDecimalLiteral(
DataTypeUtils.toBigDecimal(results[0]).divide(DataTypeUtils.toBigDecimal(results[1])));
break;
default:
case LONG:
case INT:
case DOUBLE:
result = createDoubleLiteral(
DataTypeUtils.toDouble(results[0]) / DataTypeUtils.toDouble(results[1]));
break;
case FLOAT:
result = createFloatLiteral(
DataTypeUtils.toFloat(results[0]) / DataTypeUtils.toFloat(results[1]));
break;
}
setResult(result);
};
@Override
public void visit(Quotient entity) {
IEntity[] results = new IEntity[2];
ToKind resultKind = evaluateMaxKind(results, entity.getDividend(), entity.getDivisor());
IEntity result;
switch (resultKind) {
case BIG_DECIMAL:
result = createBigDecimalLiteral(
DataTypeUtils.toBigDecimal(results[0]).divideToIntegralValue(DataTypeUtils.toBigDecimal(results[1])));
break;
default:
case DOUBLE:
result = createDoubleLiteral(Math.floor(
DataTypeUtils.toDouble(results[0]) / DataTypeUtils.toDouble(results[1])));
break;
case FLOAT:
result = createFloatLiteral((float) Math.floor(
DataTypeUtils.toFloat(results[0]) / DataTypeUtils.toFloat(results[1])));
break;
case BIG_INTEGER:
result = createBigIntegerLiteral(
DataTypeUtils.toBigInteger(results[0]).divide(DataTypeUtils.toBigInteger(results[1])));
break;
case LONG:
result = createLongLiteral(
DataTypeUtils.toLong(results[0]) / DataTypeUtils.toLong(results[1]));
break;
case INT:
result = createIntLiteral(
DataTypeUtils.toInt(results[0]) / DataTypeUtils.toInt(results[1]));
break;
}
setResult(result);
}
@Override
public void visit(Remainder entity) {
IEntity[] results = new IEntity[2];
ToKind resultKind = evaluateMaxKind(results, entity.getDividend(), entity.getDivisor());
IEntity result;
switch (resultKind) {
case BIG_DECIMAL:
result = createBigDecimalLiteral(
DataTypeUtils.toBigDecimal(results[0]).remainder(DataTypeUtils.toBigDecimal(results[1])));
break;
default:
case DOUBLE:
result = createDoubleLiteral(
DataTypeUtils.toDouble(results[0]) % DataTypeUtils.toDouble(results[1]));
break;
case FLOAT:
result = createFloatLiteral(
DataTypeUtils.toFloat(results[0]) % DataTypeUtils.toFloat(results[1]));
break;
case BIG_INTEGER:
result = createBigIntegerLiteral(
DataTypeUtils.toBigInteger(results[0]).remainder(DataTypeUtils.toBigInteger(results[1])));
break;
case LONG:
result = createLongLiteral(
DataTypeUtils.toLong(results[0]) % DataTypeUtils.toLong(results[1]));
break;
case INT:
result = createIntLiteral(
DataTypeUtils.toInt(results[0]) % DataTypeUtils.toInt(results[1]));
break;
}
setResult(result);
}
@Override
public void visit(Exponentiation entity) {
IEntity[] results = new IEntity[2];
ToKind resultKind = evaluateMaxKind(results, entity.getBase(), entity.getExponent());
IEntity result;
switch (resultKind) {
case BIG_INTEGER:
case BIG_DECIMAL:
result = createBigDecimalLiteral(
DataTypeUtils.toBigDecimal(results[0]).pow(DataTypeUtils.toInt(results[1])));
break;
default:
case LONG:
case INT:
case FLOAT:
case DOUBLE:
result = createDoubleLiteral(Math.pow(
DataTypeUtils.toDouble(results[0]), DataTypeUtils.toDouble(results[1])));
break;
}
setResult(result);
}
@Override
public void visit(Root entity) {
IEntity result1 = evaluate(entity.getExpression());
IEntity result2 = evaluate(entity.getDegree());
DataKinds dataKind2 = DataTypeUtils.getUnboxedDataKind(result2);
// ToKind resultKind = maxKind(ToKind.INT, result1);
IEntity result;
if (dataKind2.isInt() && result2.wIntValue() == 2)
result = createDoubleLiteral(
Math.sqrt(DataTypeUtils.toDouble(result1)));
else if (dataKind2.isInt() && result2.wIntValue() == 3)
result = createDoubleLiteral(
Math.cbrt(DataTypeUtils.toDouble(result1)));
else
result = createDoubleLiteral(
Math.pow(DataTypeUtils.toDouble(result1), 1.0 / DataTypeUtils.toDouble(result2)));
setResult(result);
}
@Override
public void visit(Minus entity) {
IEntity result1 = evaluate(entity.getExpression());
ToKind dataKind1 = maxKind(ToKind.INT, result1);
IEntity result;
switch (dataKind1) {
case BIG_DECIMAL:
result = createBigDecimalLiteral(DataTypeUtils.toBigDecimal(result1).negate());
break;
case DOUBLE:
result = createDoubleLiteral(-DataTypeUtils.toDouble(result1));
break;
case FLOAT:
result = createFloatLiteral(-DataTypeUtils.toFloat(result1));
break;
case BIG_INTEGER:
result = createBigIntegerLiteral(DataTypeUtils.toBigInteger(result1).negate());
break;
case LONG:
result = createLongLiteral(-DataTypeUtils.toLong(result1));
break;
default:
case INT:
result = createIntLiteral(-DataTypeUtils.toInt(result1));
break;
}
setResult(result);
}
@Override
public void visit(AbsoluteValue entity) {
IEntity result1 = evaluate(entity.getExpression());
ToKind dataKind1 = maxKind(ToKind.INT, result1);
IEntity result;
switch (dataKind1) {
case BIG_DECIMAL:
result = createBigDecimalLiteral(DataTypeUtils.toBigDecimal(result1).abs());
break;
case DOUBLE:
result = createDoubleLiteral(Math.abs(DataTypeUtils.toDouble(result1)));
break;
case FLOAT:
result = createFloatLiteral(Math.abs(DataTypeUtils.toFloat(result1)));
break;
case BIG_INTEGER:
result = createBigIntegerLiteral(DataTypeUtils.toBigInteger(result1).abs());
break;
case LONG:
result = createLongLiteral(Math.abs(DataTypeUtils.toLong(result1)));
break;
default:
case INT:
result = createIntLiteral(Math.abs(DataTypeUtils.toInt(result1)));
break;
}
setResult(result);
}
@Override
public void visit(Floor entity) {
IEntity result1 = evaluate(entity.getExpression());
ToKind dataKind1 = maxKind(ToKind.INT, result1);
IEntity result;
switch (dataKind1) {
case BIG_DECIMAL:
result = createBigDecimalLiteral(
DataTypeUtils.toBigDecimal(result1).setScale(0, RoundingMode.FLOOR));
break;
case DOUBLE:
result = createDoubleLiteral(Math.floor(DataTypeUtils.toDouble(result1)));
break;
case FLOAT:
result = createFloatLiteral((float) Math.floor(DataTypeUtils.toFloat(result1)));
break;
case BIG_INTEGER:
case LONG:
result = result1;
break;
default:
case INT:
result = createIntLiteral(DataTypeUtils.toInt(result1));
break;
}
setResult(result);
}
@Override
public void visit(Ceiling entity) {
IEntity result1 = evaluate(entity.getExpression());
ToKind dataKind1 = maxKind(ToKind.INT, result1);
IEntity result;
switch (dataKind1) {
case BIG_DECIMAL:
result = createBigDecimalLiteral(
DataTypeUtils.toBigDecimal(result1).setScale(0, RoundingMode.CEILING));
break;
case DOUBLE:
result = createDoubleLiteral(Math.ceil(DataTypeUtils.toDouble(result1)));
break;
case FLOAT:
result = createFloatLiteral((float) Math.ceil(DataTypeUtils.toFloat(result1)));
break;
case BIG_INTEGER:
case LONG:
result = result1;
break;
default:
case INT:
result = createIntLiteral(DataTypeUtils.toInt(result1));
break;
}
setResult(result);
}
@Override
public void visit(Factorial entity) {
IEntity result;
IEntity result1 = evaluate(entity.getExpression());
long lvalue = DataTypeUtils.toLong(result1);
if (lvalue < 0l)
throw new WholeIllegalArgumentException("Underflow error in factorial").withSourceEntity(entity).withBindings(getBindings());
else if (lvalue < 21l)
result = createLongLiteral(factorial((int) lvalue));
else
result = createBigIntegerLiteral(factorial(
java.math.BigInteger.valueOf(lvalue)));
setResult(result);
}
public static long factorial(int n) {
return n <= 1 ? 1 : n * factorial(n-1);
}
public static java.math.BigInteger factorial(java.math.BigInteger n) {
return n.compareTo(java.math.BigInteger.ONE) <= 0 ?
java.math.BigInteger.ONE : n.multiply(factorial(n.subtract(java.math.BigInteger.ONE)));
}
@Override
public void visit(GreatestCommonDivisor entity) {
// TODO Auto-generated method stub
super.visit(entity);
}
public static long gcd(long a, long b) {
return b==0 ? a : gcd(b, a % b);
}
@Override
public void visit(LowestCommonMultiple entity) {
// TODO Auto-generated method stub
super.visit(entity);
}
@Override
public void visit(Maximum entity) {
IEntity[] results = new IEntity[entity.size()];
ToKind resultKind = evaluateMaxKind(results, entity);
IEntity result;
switch (resultKind) {
case BIG_DECIMAL:
java.math.BigDecimal bdvalue = DataTypeUtils.toBigDecimal(results[0]);
for (IEntity r : results)
bdvalue = bdvalue.max(DataTypeUtils.toBigDecimal(r));
result = createBigDecimalLiteral(bdvalue);
break;
case DOUBLE:
double dvalue = java.lang.Double.MIN_VALUE;
for (IEntity r : results)
dvalue = Math.max(dvalue, DataTypeUtils.toDouble(r));
result = createDoubleLiteral(dvalue);
break;
case FLOAT:
float fvalue = java.lang.Float.MIN_VALUE;
for (IEntity r : results)
fvalue = Math.max(fvalue, DataTypeUtils.toFloat(r));
result = createFloatLiteral(fvalue);
break;
case BIG_INTEGER:
java.math.BigInteger bivalue = DataTypeUtils.toBigInteger(results[0]);
for (IEntity r : results)
bivalue = bivalue.max(DataTypeUtils.toBigInteger(r));
result = createBigIntegerLiteral(bivalue);
break;
case LONG:
long lvalue = java.lang.Long.MIN_VALUE;
for (IEntity r : results)
lvalue = Math.max(lvalue, DataTypeUtils.toLong(r));
result = createLongLiteral(lvalue);
break;
default:
case INT:
int ivalue = java.lang.Integer.MIN_VALUE;
for (IEntity r : results)
ivalue = Math.max(ivalue, DataTypeUtils.toInt(r));
result = createIntLiteral(ivalue);
break;
}
setResult(result);
}
@Override
public void visit(Minimum entity) {
IEntity[] results = new IEntity[entity.size()];
ToKind resultKind = evaluateMaxKind(results, entity);
IEntity result;
switch (resultKind) {
case BIG_DECIMAL:
java.math.BigDecimal bdvalue = DataTypeUtils.toBigDecimal(results[0]);
for (IEntity r : results)
bdvalue = bdvalue.min(DataTypeUtils.toBigDecimal(r));
result = createBigDecimalLiteral(bdvalue);
break;
case DOUBLE:
double dvalue = java.lang.Double.MAX_VALUE;
for (IEntity r : results)
dvalue = Math.min(dvalue, DataTypeUtils.toDouble(r));
result = createDoubleLiteral(dvalue);
break;
case FLOAT:
float fvalue = java.lang.Float.MAX_VALUE;
for (IEntity r : results)
fvalue = Math.min(fvalue, DataTypeUtils.toFloat(r));
result = createFloatLiteral(fvalue);
break;
case BIG_INTEGER:
java.math.BigInteger bivalue = DataTypeUtils.toBigInteger(results[0]);
for (IEntity r : results)
bivalue = bivalue.min(DataTypeUtils.toBigInteger(r));
result = createBigIntegerLiteral(bivalue);
break;
case LONG:
long lvalue = java.lang.Long.MAX_VALUE;
for (IEntity r : results)
lvalue = Math.min(lvalue, DataTypeUtils.toLong(r));
result = createLongLiteral(lvalue);
break;
default:
case INT:
int ivalue = java.lang.Integer.MAX_VALUE;
for (IEntity r : results)
ivalue = Math.min(ivalue, DataTypeUtils.toInt(r));
result = createIntLiteral(ivalue);
break;
}
setResult(result);
}
@Override
public void visit(And entity) {
boolean value = true;
for (int i=0, size=entity.size(); i<size; i++) {
IEntity result = evaluate(entity.get(i));
DataKinds dataKinds = DataTypeUtils.getUnboxedDataKind(result);
if (dataKinds.isNotAData())
throw new WholeIllegalArgumentException(WholeMessages.no_data).withSourceEntity(entity).withBindings(getBindings());
else if (!dataKinds.isBoolean())
throw new WholeIllegalArgumentException(WholeMessages.illegal_data_conversion).withSourceEntity(entity).withBindings(getBindings());
else if (!(value &= result.wBooleanValue()))
break;
}
setResult(createBooleanLiteral(value));
}
@Override
public void visit(Or entity) {
boolean value = false;
for (int i=0, size=entity.size(); i<size; i++) {
IEntity result = evaluate(entity.get(i));
DataKinds dataKinds = DataTypeUtils.getUnboxedDataKind(result);
if (dataKinds.isNotAData())
throw new WholeIllegalArgumentException(WholeMessages.no_data).withSourceEntity(entity).withBindings(getBindings());
else if (!dataKinds.isBoolean())
throw new WholeIllegalArgumentException(WholeMessages.illegal_data_conversion).withSourceEntity(entity).withBindings(getBindings());
else if (value |= result.wBooleanValue())
break;
}
setResult(createBooleanLiteral(value));
}
@Override
public void visit(ExclusiveOr entity) {
boolean value = false;
for (int i=0, size=entity.size(); i<size; i++) {
IEntity result = evaluate(entity.get(i));
DataKinds dataKinds = DataTypeUtils.getUnboxedDataKind(result);
if (dataKinds.isNotAData())
throw new WholeIllegalArgumentException(WholeMessages.no_data).withSourceEntity(entity).withBindings(getBindings());
else if (!dataKinds.isBoolean())
throw new WholeIllegalArgumentException(WholeMessages.illegal_data_conversion).withSourceEntity(entity).withBindings(getBindings());
else
value ^= result.wBooleanValue();
}
setResult(createBooleanLiteral(value));
}
@Override
public void visit(Not entity) {
IEntity result = evaluate(entity.getExpression());
DataKinds dataKinds = DataTypeUtils.getUnboxedDataKind(result);
if (dataKinds.isNotAData())
throw new WholeIllegalArgumentException(WholeMessages.no_data).withSourceEntity(entity).withBindings(getBindings());
else if (!dataKinds.isBoolean())
throw new WholeIllegalArgumentException(WholeMessages.illegal_data_conversion).withSourceEntity(entity).withBindings(getBindings());
else
setResult(createBooleanLiteral(!result.wBooleanValue()));
}
@Override
public void visit(Implies entity) {
IEntity result1 = evaluate(entity.getExp1());
IEntity result2 = evaluate(entity.getExp2());
DataKinds dataKind1 = DataTypeUtils.getUnboxedDataKind(result1);
DataKinds dataKind2 = DataTypeUtils.getUnboxedDataKind(result2);
if (dataKind1.isNotAData() || dataKind2.isNotAData())
throw new WholeIllegalArgumentException(WholeMessages.no_data).withSourceEntity(entity).withBindings(getBindings());
else if (!dataKind1.isBoolean() || !dataKind2.isBoolean())
throw new WholeIllegalArgumentException(WholeMessages.illegal_data_conversion).withSourceEntity(entity).withBindings(getBindings());
else
setResult(createBooleanLiteral(!(result1.wBooleanValue() && !result2.wBooleanValue())));
}
@Override
public void visit(Equals entity) {
int size = entity.size();
IEntity[] results = new IEntity[size];
ToKind resultKind = evaluateMaxKind(results, entity);
boolean value = true;
switch (resultKind) {
case BIG_DECIMAL:
java.math.BigDecimal bdvalue = DataTypeUtils.toBigDecimal(results[0]);
for (int i=1; i<size; i++)
if (!(value = (bdvalue.compareTo(DataTypeUtils.toBigDecimal(results[i])) == 0)))
break;
break;
case DOUBLE:
double dvalue = DataTypeUtils.toDouble(results[0]);
for (int i=1; i<size; i++)
if (!(value = (java.lang.Double.compare(dvalue, DataTypeUtils.toDouble(results[i])) == 0)))
break;
break;
case FLOAT:
float fvalue = DataTypeUtils.toFloat(results[0]);
for (int i=1; i<size; i++)
if (!(value = (java.lang.Float.compare(fvalue, DataTypeUtils.toFloat(results[i])) == 0)))
break;
break;
case BIG_INTEGER:
java.math.BigInteger bivalue = DataTypeUtils.toBigInteger(results[0]);
for (int i=1; i<size; i++)
if (!(value = (bivalue.compareTo(DataTypeUtils.toBigInteger(results[i])) == 0)))
break;
break;
case LONG:
long lvalue = DataTypeUtils.toLong(results[0]);
for (int i=1; i<size; i++)
if (!(value = (lvalue == DataTypeUtils.toLong(results[i]))))
break;
break;
default:
case INT:
int ivalue = DataTypeUtils.toInt(results[0]);
for (int i=1; i<size; i++)
if (!(value = (ivalue == DataTypeUtils.toInt(results[i]))))
break;
break;
}
setResult(createBooleanLiteral(value));
}
@Override
public void visit(NotEquals entity) {
IEntity[] results = new IEntity[2];
ToKind resultKind = evaluateMaxKind(results, entity.getExp1(), entity.getExp2());
boolean value = true;
switch (resultKind) {
case BIG_DECIMAL:
value = DataTypeUtils.toBigDecimal(results[0]).compareTo(DataTypeUtils.toBigDecimal(results[1])) != 0;
break;
case DOUBLE:
value = java.lang.Double.compare(DataTypeUtils.toDouble(results[0]), DataTypeUtils.toDouble(results[1])) != 0;
break;
case FLOAT:
value = java.lang.Float.compare(DataTypeUtils.toFloat(results[0]), DataTypeUtils.toFloat(results[1])) != 0;
break;
case BIG_INTEGER:
value = DataTypeUtils.toBigInteger(results[0]).compareTo(DataTypeUtils.toBigInteger(results[1])) != 0;
break;
case LONG:
value = DataTypeUtils.toLong(results[0]) != DataTypeUtils.toLong(results[1]);
break;
default:
case INT:
value = DataTypeUtils.toInt(results[0]) != DataTypeUtils.toInt(results[1]);
break;
}
setResult(createBooleanLiteral(value));
}
@Override
public void visit(ApproximatelyEqual entity) {
IEntity[] results = new IEntity[2];
ToKind resultKind = evaluateMaxKind(results, entity.getExp1(), entity.getExp2());
boolean value = true;
switch (resultKind) {
case BIG_DECIMAL:
case DOUBLE:
case FLOAT:
java.math.BigDecimal bdvalue1 = DataTypeUtils.toBigDecimal(results[0]);
java.math.BigDecimal bdvalue2 = DataTypeUtils.toBigDecimal(results[1]);
int scale = Math.min(bdvalue1.scale(), bdvalue2.scale());
value = bdvalue1.setScale(scale, RoundingMode.HALF_EVEN).compareTo(bdvalue2.setScale(scale, RoundingMode.HALF_EVEN)) == 0;
break;
// case BIG_DECIMAL:
// value = DataTypeUtils.toBigDecimal(results[0]).compareTo(DataTypeUtils.toBigDecimal(results[1])) == 0;
// break;
// case DOUBLE:
// value = java.lang.Double.compare(DataTypeUtils.toDouble(results[0]), DataTypeUtils.toDouble(results[1])) == 0;
// break;
// case FLOAT:
// value = java.lang.Float.compare(DataTypeUtils.toFloat(results[0]), DataTypeUtils.toFloat(results[1])) == 0;
// break;
case BIG_INTEGER:
value = DataTypeUtils.toBigInteger(results[0]).compareTo(DataTypeUtils.toBigInteger(results[1])) == 0;
break;
case LONG:
value = DataTypeUtils.toLong(results[0]) == DataTypeUtils.toLong(results[1]);
break;
default:
case INT:
value = DataTypeUtils.toInt(results[0]) == DataTypeUtils.toInt(results[1]);
break;
}
setResult(createBooleanLiteral(value));
}
@Override
public void visit(GreaterThan entity) {
int size = entity.size();
IEntity[] results = new IEntity[size];
ToKind resultKind = evaluateMaxKind(results, entity);
boolean value = true;
switch (resultKind) {
case BIG_DECIMAL:
java.math.BigDecimal bdvalue = DataTypeUtils.toBigDecimal(results[0]);
for (int i=1; i<size; i++)
if (!(value = (bdvalue.compareTo(DataTypeUtils.toBigDecimal(results[i])) > 0)))
break;
break;
case DOUBLE:
double dvalue = DataTypeUtils.toDouble(results[0]);
for (int i=1; i<size; i++)
if (!(value = (java.lang.Double.compare(dvalue, DataTypeUtils.toDouble(results[i])) > 0)))
break;
break;
case FLOAT:
float fvalue = DataTypeUtils.toFloat(results[0]);
for (int i=1; i<size; i++)
if (!(value = (java.lang.Float.compare(fvalue, DataTypeUtils.toFloat(results[i])) > 0)))
break;
break;
case BIG_INTEGER:
java.math.BigInteger bivalue = DataTypeUtils.toBigInteger(results[0]);
for (int i=1; i<size; i++)
if (!(value = (bivalue.compareTo(DataTypeUtils.toBigInteger(results[i])) > 0)))
break;
break;
case LONG:
long lvalue = DataTypeUtils.toLong(results[0]);
for (int i=1; i<size; i++)
if (!(value = (lvalue > DataTypeUtils.toLong(results[i]))))
break;
break;
default:
case INT:
int ivalue = DataTypeUtils.toInt(results[0]);
for (int i=1; i<size; i++)
if (!(value = (ivalue > DataTypeUtils.toInt(results[i]))))
break;
break;
}
setResult(createBooleanLiteral(value));
}
@Override
public void visit(LessThan entity) {
int size = entity.size();
IEntity[] results = new IEntity[size];
ToKind resultKind = evaluateMaxKind(results, entity);
boolean value = true;
switch (resultKind) {
case BIG_DECIMAL:
java.math.BigDecimal bdvalue = DataTypeUtils.toBigDecimal(results[0]);
for (int i=1; i<size; i++)
if (!(value = (bdvalue.compareTo(DataTypeUtils.toBigDecimal(results[i])) < 0)))
break;
break;
case DOUBLE:
double dvalue = DataTypeUtils.toDouble(results[0]);
for (int i=1; i<size; i++)
if (!(value = (java.lang.Double.compare(dvalue, DataTypeUtils.toDouble(results[i])) < 0)))
break;
break;
case FLOAT:
float fvalue = DataTypeUtils.toFloat(results[0]);
for (int i=1; i<size; i++)
if (!(value = (java.lang.Float.compare(fvalue, DataTypeUtils.toFloat(results[i])) < 0)))
break;
break;
case BIG_INTEGER:
java.math.BigInteger bivalue = DataTypeUtils.toBigInteger(results[0]);
for (int i=1; i<size; i++)
if (!(value = (bivalue.compareTo(DataTypeUtils.toBigInteger(results[i])) < 0)))
break;
break;
case LONG:
long lvalue = DataTypeUtils.toLong(results[0]);
for (int i=1; i<size; i++)
if (!(value = (lvalue < DataTypeUtils.toLong(results[i]))))
break;
break;
default:
case INT:
int ivalue = DataTypeUtils.toInt(results[0]);
for (int i=1; i<size; i++)
if (!(value = (ivalue < DataTypeUtils.toInt(results[i]))))
break;
break;
}
setResult(createBooleanLiteral(value));
}
@Override
public void visit(GreaterOrEqual entity) {
int size = entity.size();
IEntity[] results = new IEntity[size];
ToKind resultKind = evaluateMaxKind(results, entity);
boolean value = true;
switch (resultKind) {
case BIG_DECIMAL:
java.math.BigDecimal bdvalue = DataTypeUtils.toBigDecimal(results[0]);
for (int i=1; i<size; i++)
if (!(value = (bdvalue.compareTo(DataTypeUtils.toBigDecimal(results[i])) >= 0)))
break;
break;
case DOUBLE:
double dvalue = DataTypeUtils.toDouble(results[0]);
for (int i=1; i<size; i++)
if (!(value = (java.lang.Double.compare(dvalue, DataTypeUtils.toDouble(results[i])) >= 0)))
break;
break;
case FLOAT:
float fvalue = DataTypeUtils.toFloat(results[0]);
for (int i=1; i<size; i++)
if (!(value = (java.lang.Float.compare(fvalue, DataTypeUtils.toFloat(results[i])) >= 0)))
break;
break;
case BIG_INTEGER:
java.math.BigInteger bivalue = DataTypeUtils.toBigInteger(results[0]);
for (int i=1; i<size; i++)
if (!(value = (bivalue.compareTo(DataTypeUtils.toBigInteger(results[i])) >= 0)))
break;
break;
case LONG:
long lvalue = DataTypeUtils.toLong(results[0]);
for (int i=1; i<size; i++)
if (!(value = (lvalue >= DataTypeUtils.toLong(results[i]))))
break;
break;
default:
case INT:
int ivalue = DataTypeUtils.toInt(results[0]);
for (int i=1; i<size; i++)
if (!(value = (ivalue >= DataTypeUtils.toInt(results[i]))))
break;
break;
}
setResult(createBooleanLiteral(value));
}
@Override
public void visit(LessOrEqual entity) {
int size = entity.size();
IEntity[] results = new IEntity[size];
ToKind resultKind = evaluateMaxKind(results, entity);
boolean value = true;
switch (resultKind) {
case BIG_DECIMAL:
java.math.BigDecimal bdvalue = DataTypeUtils.toBigDecimal(results[0]);
for (int i=1; i<size; i++)
if (!(value = (bdvalue.compareTo(DataTypeUtils.toBigDecimal(results[i])) <= 0)))
break;
break;
case DOUBLE:
double dvalue = DataTypeUtils.toDouble(results[0]);
for (int i=1; i<size; i++)
if (!(value = (java.lang.Double.compare(dvalue, DataTypeUtils.toDouble(results[i])) <= 0)))
break;
break;
case FLOAT:
float fvalue = DataTypeUtils.toFloat(results[0]);
for (int i=1; i<size; i++)
if (!(value = (java.lang.Float.compare(fvalue, DataTypeUtils.toFloat(results[i])) <= 0)))
break;
break;
case BIG_INTEGER:
java.math.BigInteger bivalue = DataTypeUtils.toBigInteger(results[0]);
for (int i=1; i<size; i++)
if (!(value = (bivalue.compareTo(DataTypeUtils.toBigInteger(results[i])) <= 0)))
break;
break;
case LONG:
long lvalue = DataTypeUtils.toLong(results[0]);
for (int i=1; i<size; i++)
if (!(value = (lvalue <= DataTypeUtils.toLong(results[i]))))
break;
break;
default:
case INT:
int ivalue = DataTypeUtils.toInt(results[0]);
for (int i=1; i<size; i++)
if (!(value = (ivalue <= DataTypeUtils.toInt(results[i]))))
break;
break;
}
setResult(createBooleanLiteral(value));
}
@Override
public void visit(FactorOf entity) {
IEntity[] results = new IEntity[2];
ToKind resultKind = evaluateMaxKind(results, entity.getExp2(), entity.getExp1());
boolean value = false;
switch (resultKind) {
default:
case BIG_DECIMAL:
value = DataTypeUtils.toBigDecimal(results[0]).remainder(DataTypeUtils.toBigDecimal(results[1])).compareTo(java.math.BigDecimal.ZERO) == 0;
break;
case DOUBLE:
value = Math.abs(DataTypeUtils.toDouble(results[0]) % DataTypeUtils.toDouble(results[1])) < 0.00001;
break;
case FLOAT:
value = Math.abs(DataTypeUtils.toFloat(results[0]) % DataTypeUtils.toFloat(results[1])) < 0.00001;
break;
case BIG_INTEGER:
value = DataTypeUtils.toBigInteger(results[0]).remainder(DataTypeUtils.toBigInteger(results[1])).compareTo(java.math.BigInteger.ZERO) == 0;
break;
case LONG:
value = DataTypeUtils.toLong(results[0]) % DataTypeUtils.toLong(results[1]) == 0;
break;
case INT:
value = DataTypeUtils.toInt(results[0]) % DataTypeUtils.toInt(results[1]) == 0;
break;
}
setResult(createBooleanLiteral(value));
}
@Override
public void visit(Exponential entity) {
setResult(createDoubleLiteral(
Math.exp(DataTypeUtils.toDouble(
evaluate(entity.getExpression())))));
}
@Override
public void visit(NaturalLogarithm entity) {
setResult(createDoubleLiteral(
Math.log(DataTypeUtils.toDouble(
evaluate(entity.getExpression())))));
}
@Override
public void visit(Logarithm entity) {
setResult(createDoubleLiteral(
Math.log(DataTypeUtils.toDouble(evaluate(entity.getExpression()))) / Math.log(DataTypeUtils.toDouble(evaluate(entity.getBase())))));
}
@Override
public void visit(Sine entity) {
setResult(createDoubleLiteral(
Math.sin(DataTypeUtils.toDouble(
evaluate(entity.getExpression())))));
}
@Override
public void visit(Cosine entity) {
setResult(createDoubleLiteral(
Math.cos(DataTypeUtils.toDouble(
evaluate(entity.getExpression())))));
}
@Override
public void visit(Tangent entity) {
setResult(createDoubleLiteral(
Math.tan(DataTypeUtils.toDouble(
evaluate(entity.getExpression())))));
}
@Override
public void visit(Arcsine entity) {
setResult(createDoubleLiteral(
Math.asin(DataTypeUtils.toDouble(
evaluate(entity.getExpression())))));
}
@Override
public void visit(Arccosine entity) {
setResult(createDoubleLiteral(
Math.acos(DataTypeUtils.toDouble(
evaluate(entity.getExpression())))));
}
@Override
public void visit(Arctangent entity) {
setResult(createDoubleLiteral(
Math.atan(DataTypeUtils.toDouble(
evaluate(entity.getExpression())))));
}
@Override
public void visit(HyperbolicSine entity) {
setResult(createDoubleLiteral(
Math.sinh(DataTypeUtils.toDouble(
evaluate(entity.getExpression())))));
}
@Override
public void visit(HyperbolicCosine entity) {
setResult(createDoubleLiteral(
Math.cosh(DataTypeUtils.toDouble(
evaluate(entity.getExpression())))));
}
@Override
public void visit(HyperbolicTangent entity) {
setResult(createDoubleLiteral(
Math.tanh(DataTypeUtils.toDouble(
evaluate(entity.getExpression())))));
}
@Override
public void visit(Empty entity) {
// TODO Auto-generated method stub
super.visit(entity);
}
@Override
public void visit(Set entity) {
// TODO Auto-generated method stub
super.visit(entity);
}
@Override
public void visit(OrderedPair entity) {
// TODO Auto-generated method stub
super.visit(entity);
}
@Override
public void visit(Tuple entity) {
// TODO Auto-generated method stub
super.visit(entity);
}
@Override
public void visit(org.whole.lang.math.model.List entity) {
// TODO Auto-generated method stub
super.visit(entity);
}
@Override
public void visit(Stream entity) {
// TODO Auto-generated method stub
super.visit(entity);
}
@Override
public void visit(Enumeration entity) {
// TODO Auto-generated method stub
super.visit(entity);
}
@Override
public void visit(Builder entity) {
// TODO Auto-generated method stub
super.visit(entity);
}
@Override
public void visit(Union entity) {
// TODO Auto-generated method stub
super.visit(entity);
}
@Override
public void visit(Intersection entity) {
// TODO Auto-generated method stub
super.visit(entity);
}
@Override
public void visit(Difference entity) {
// TODO Auto-generated method stub
super.visit(entity);
}
@Override
public void visit(In entity) {
// TODO Auto-generated method stub
super.visit(entity);
}
@Override
public void visit(NotIn entity) {
// TODO Auto-generated method stub
super.visit(entity);
}
@Override
public void visit(Subset entity) {
// TODO Auto-generated method stub
super.visit(entity);
}
@Override
public void visit(ProperSubset entity) {
// TODO Auto-generated method stub
super.visit(entity);
}
@Override
public void visit(NotSubset entity) {
// TODO Auto-generated method stub
super.visit(entity);
}
@Override
public void visit(NotProperSubset entity) {
// TODO Auto-generated method stub
super.visit(entity);
}
@Override
public void visit(Cardinality entity) {
// TODO Auto-generated method stub
super.visit(entity);
}
@Override
public void visit(Selector entity) {
// TODO Auto-generated method stub
super.visit(entity);
}
@Override
public void visit(Identifier entity) {
// TODO Auto-generated method stub
super.visit(entity);
}
@Override
public void visit(Boolean entity) {
setLiteral(entity);
}
@Override
public void visit(ByteInteger entity) {
setLiteral(entity);
}
@Override
public void visit(ShortInteger entity) {
setLiteral(entity);
}
@Override
public void visit(Integer entity) {
setLiteral(entity);
}
@Override
public void visit(LongInteger entity) {
setLiteral(entity);
}
@Override
public void visit(BigInteger entity) {
setResult(EntityUtils.clone(entity));
}
@Override
public void visit(Float entity) {
setLiteral(entity);
}
@Override
public void visit(Double entity) {
setLiteral(entity);
}
@Override
public void visit(BigDecimal entity) {
setResult(EntityUtils.clone(entity));
}
@Override
public void visit(Constant entity) {
switch (entity.getValue().getOrdinal()) {
case ConstantEnum.pi_ord:
setResult(createDoubleLiteral(Math.PI));
break;
case ConstantEnum.e_ord:
setResult(createDoubleLiteral(Math.E));
break;
case ConstantEnum.i_ord:
setResult(EntityUtils.clone(entity));
break;
case ConstantEnum.gamma_ord:
setResult(createDoubleLiteral(0.5772156649d));
break;
case ConstantEnum.infinity_ord:
setResult(createDoubleLiteral(java.lang.Double.POSITIVE_INFINITY));
break;
}
}
@Override
public void visit(NotANumber entity) {
setResult(createDoubleLiteral(java.lang.Double.NaN));
}
}