blob: 54295ef27ea1ff9c01304c74d8887a5492610e51 [file] [log] [blame]
package jp.ac.kobe_u.cs.prolog.lang;
/**
* The <code>Arithmetic</code> class contains a method
* for evaluating arithmetic expressions.<br>
* This class is mainly used by the builtin predicate <code>is/2</code>.
*
* @author Mutsunori Banbara (banbara@kobe-u.ac.jp)
* @author Naoyuki Tamura (tamura@kobe-u.ac.jp)
* @version 1.0
*/
public class Arithmetic {
static SymbolTerm SYM_RANDOM = SymbolTerm.makeSymbol("random");
static SymbolTerm SYM_PI = SymbolTerm.makeSymbol("pi");
static SymbolTerm SYM_E = SymbolTerm.makeSymbol("e");
static SymbolTerm SYM_ADD_1 = SymbolTerm.makeSymbol("+", 1);
static SymbolTerm SYM_NEGATE_1 = SymbolTerm.makeSymbol("-", 1);
static SymbolTerm SYM_ADD_2 = SymbolTerm.makeSymbol("+", 2);
static SymbolTerm SYM_SUBTRACT_2 = SymbolTerm.makeSymbol("-", 2);
static SymbolTerm SYM_MULTIPLY_2 = SymbolTerm.makeSymbol("*", 2);
static SymbolTerm SYM_DIVIDE_2 = SymbolTerm.makeSymbol("/", 2);
static SymbolTerm SYM_INTDIVIDE_2 = SymbolTerm.makeSymbol("//", 2);
static SymbolTerm SYM_MOD_2 = SymbolTerm.makeSymbol("mod", 2);
static SymbolTerm SYM_SHIFTLEFT_2 = SymbolTerm.makeSymbol("<<", 2);
static SymbolTerm SYM_SHIFTRIGHT_2 = SymbolTerm.makeSymbol(">>", 2);
static SymbolTerm SYM_NOT_1 = SymbolTerm.makeSymbol("\\", 1);
static SymbolTerm SYM_AND_2 = SymbolTerm.makeSymbol("/\\", 2);
static SymbolTerm SYM_OR_2 = SymbolTerm.makeSymbol("\\/", 2);
static SymbolTerm SYM_XOR_2 = SymbolTerm.makeSymbol("#", 2);
static SymbolTerm SYM_POW_2 = SymbolTerm.makeSymbol("**", 2);
static SymbolTerm SYM_ABS_1 = SymbolTerm.makeSymbol("abs", 1);
static SymbolTerm SYM_ACOS_1 = SymbolTerm.makeSymbol("acos", 1);
static SymbolTerm SYM_ASIN_1 = SymbolTerm.makeSymbol("asin", 1);
static SymbolTerm SYM_ATAN_1 = SymbolTerm.makeSymbol("atan", 1);
static SymbolTerm SYM_CEIL_1 = SymbolTerm.makeSymbol("ceiling", 1);
static SymbolTerm SYM_COS_1 = SymbolTerm.makeSymbol("cos", 1);
static SymbolTerm SYM_DEGREES_1 = SymbolTerm.makeSymbol("degrees", 1);
static SymbolTerm SYM_EXP_1 = SymbolTerm.makeSymbol("exp", 1);
static SymbolTerm SYM_FLOOR_1 = SymbolTerm.makeSymbol("floor", 1);
static SymbolTerm SYM_LOG_1 = SymbolTerm.makeSymbol("log", 1);
static SymbolTerm SYM_MAX_2 = SymbolTerm.makeSymbol("max", 2);
static SymbolTerm SYM_MIN_2 = SymbolTerm.makeSymbol("min", 2);
static SymbolTerm SYM_RADIANS_1 = SymbolTerm.makeSymbol("radians", 1);
static SymbolTerm SYM_RINT_1 = SymbolTerm.makeSymbol("rint", 1);
static SymbolTerm SYM_ROUND_1 = SymbolTerm.makeSymbol("round", 1);
static SymbolTerm SYM_SIN_1 = SymbolTerm.makeSymbol("sin", 1);
static SymbolTerm SYM_SQRT_1 = SymbolTerm.makeSymbol("sqrt", 1);
static SymbolTerm SYM_TAN_1 = SymbolTerm.makeSymbol("tan", 1);
static SymbolTerm SYM_REM_2 = SymbolTerm.makeSymbol("rem", 2);
static SymbolTerm SYM_SIGN_1 = SymbolTerm.makeSymbol("sign", 1);
static SymbolTerm SYM_FLOAT_1 = SymbolTerm.makeSymbol("float", 1);
static SymbolTerm SYM_INTPART_1 = SymbolTerm.makeSymbol("float_integer_part", 1);
static SymbolTerm SYM_FRACTPART_1 = SymbolTerm.makeSymbol("float_fractional_part", 1);
static SymbolTerm SYM_TRUNCATE_1 = SymbolTerm.makeSymbol("truncate", 1);
/**
* Evaluates <code>_t</code> as an arithmetic expression,
* and returns the resulting number as <code>NumberTerm</code>.
*
* @exception PInstantiationException if <code>_t</code> contains unbound variables.
* @exception IllegalDomainException if <code>_t</code> is not an arithmetic expression.
*/
public static NumberTerm evaluate(Term _t)
throws PInstantiationException,IllegalDomainException {
Term t = _t.dereference();
if (t.isVariable())
throw new PInstantiationException();
else if (t.isInteger())
return (IntegerTerm)t;
else if (t.isDouble())
return (DoubleTerm)t;
else if (t.equals(SYM_RANDOM))
return new DoubleTerm(Math.random());
else if (t.equals(SYM_PI))
return new DoubleTerm(Math.PI);
else if (t.equals(SYM_E))
return new DoubleTerm(Math.E);
else if (t.isList())
return evaluate(((ListTerm)t).car());
else if (! t.isStructure())
throw new IllegalDomainException("arithmetic expression", t);
SymbolTerm func = ((StructureTerm)t).functor();
Term[] args = ((StructureTerm)t).args();
if (func.equals(SYM_ADD_1))
return evaluate(args[0]);
else if (func.equals(SYM_NEGATE_1))
return evaluate(args[0]).negate();
else if (func.equals(SYM_ADD_2))
return evaluate(args[0]).add(evaluate(args[1]));
else if (func.equals(SYM_SUBTRACT_2))
return evaluate(args[0]).subtract(evaluate(args[1]));
else if (func.equals(SYM_MULTIPLY_2))
return evaluate(args[0]).multiply(evaluate(args[1]));
else if (func.equals(SYM_INTDIVIDE_2))
return evaluate(args[0]).intDivide(evaluate(args[1]));
else if (func.equals(SYM_DIVIDE_2))
return evaluate(args[0]).divide(evaluate(args[1]));
else if (func.equals(SYM_MOD_2))
return evaluate(args[0]).mod(evaluate(args[1]));
else if (func.equals(SYM_REM_2))
return evaluate(args[0]).mod(evaluate(args[1]));
else if (func.equals(SYM_AND_2))
return evaluate(args[0]).and(evaluate(args[1]));
else if (func.equals(SYM_OR_2))
return evaluate(args[0]).or(evaluate(args[1]));
else if (func.equals(SYM_XOR_2))
return evaluate(args[0]).xor(evaluate(args[1]));
else if (func.equals(SYM_NOT_1))
return evaluate(args[0]).not();
else if (func.equals(SYM_SHIFTLEFT_2))
return evaluate(args[0]).shiftLeft(evaluate(args[1]));
else if (func.equals(SYM_SHIFTRIGHT_2))
return evaluate(args[0]).shiftRight(evaluate(args[1]));
else if (func.equals(SYM_ABS_1))
return evaluate(args[0]).abs();
else if (func.equals(SYM_MIN_2))
return evaluate(args[0]).min(evaluate(args[1]));
else if (func.equals(SYM_MAX_2))
return evaluate(args[0]).max(evaluate(args[1]));
else if (func.equals(SYM_RINT_1))
return evaluate(args[0]).rint();
else if (func.equals(SYM_ROUND_1))
return evaluate(args[0]).round();
else if (func.equals(SYM_FLOOR_1))
return evaluate(args[0]).floor();
else if (func.equals(SYM_CEIL_1))
return evaluate(args[0]).ceil();
else if (func.equals(SYM_SIN_1))
return evaluate(args[0]).sin();
else if (func.equals(SYM_COS_1))
return evaluate(args[0]).cos();
else if (func.equals(SYM_TAN_1))
return evaluate(args[0]).tan();
else if (func.equals(SYM_ASIN_1))
return evaluate(args[0]).asin();
else if (func.equals(SYM_ACOS_1))
return evaluate(args[0]).acos();
else if (func.equals(SYM_ATAN_1))
return evaluate(args[0]).atan();
else if (func.equals(SYM_SQRT_1))
return evaluate(args[0]).sqrt();
else if (func.equals(SYM_LOG_1))
return evaluate(args[0]).log();
else if (func.equals(SYM_EXP_1))
return evaluate(args[0]).exp();
else if (func.equals(SYM_POW_2))
return evaluate(args[0]).pow(evaluate(args[1]));
else if (func.equals(SYM_DEGREES_1))
return evaluate(args[0]).toDegrees();
else if (func.equals(SYM_RADIANS_1))
return evaluate(args[0]).toRadians();
else if (func.equals(SYM_SIGN_1))
return evaluate(args[0]).signum();
else if (func.equals(SYM_FLOAT_1))
return evaluate(args[0]).toFloat();
else if (func.equals(SYM_INTPART_1))
return evaluate(args[0]).floatIntPart();
else if (func.equals(SYM_FRACTPART_1))
return evaluate(args[0]).floatFractPart();
else if (func.equals(SYM_TRUNCATE_1))
return evaluate(args[0]).truncate();
else
throw new IllegalDomainException("arithmetic expression", t);
}
}