/*
* KernelProlog Expanded - Pure Java based Prolog Engine
* Copyright (C) 1999 Paul Tarau (original KernelProlog)
* Copyright (C) 2009 Michiel Hendriks
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package net.sf.kpex.builtins;
import net.sf.kpex.io.IO;
import net.sf.kpex.prolog.Const;
import net.sf.kpex.prolog.FunBuiltin;
import net.sf.kpex.prolog.Int;
import net.sf.kpex.prolog.Num;
import net.sf.kpex.prolog.Prog;
import net.sf.kpex.prolog.Real;
import net.sf.kpex.prolog.Term;
/**
* Performs simple arithmetic operations like compute('+',1,2,Result)
*/
public class Compute extends FunBuiltin
{
public Compute()
{
super("compute", 4);
}
/*
* (non-Javadoc)
* @see net.sf.kpex.prolog.FunBuiltin#exec(net.sf.kpex.prolog.Prog)
*/
@Override
public int exec(Prog p)
{
Term o = getArg(0);
Term a = getArg(1);
Term b = getArg(2);
if (!(o instanceof Const) || !(a instanceof Num) || !(b instanceof Num))
{
IO.errmes("bad arithmetic operation (" + o + "): " + a + "," + b + "\nprog: " + p.toString());
}
String opname = ((Const) o).getName();
double x = ((Num) a).getValue();
double y = ((Num) b).getValue();
double r;
char op = opname.charAt(0);
switch (op)
{
case '+':
r = x + y;
break;
case '-':
r = x - y;
break;
case '*':
r = x * y;
break;
case '/':
r = x / y;
break;
case ':':
r = (int) (x / y);
break;
case '%':
r = x % y;
break;
case '?':
r = x < y ? -1 : x == y ? 0 : 1;
break; // compares!
case 'p':
r = Math.pow(x, y);
break;
case 'l':
r = Math.log(y) / Math.log(x);
break;
case 'r':
r = x * Math.random() + y;
break;
case '<':
r = (long) x << (long) y;
break;
case '>':
r = (long) x >> (long) y;
break;
default:
IO.errmes("bad arithmetic operation <" + op + "> on " + x + " and " + y);
return 0;
}
Num R = Math.floor(r) == r ? (Num) new Int((long) r) : (Num) new Real(r);
return putArg(3, R, p);
}
}