package org.basex.query.func; import static java.lang.StrictMath.*; import org.basex.query.QueryContext; import org.basex.query.QueryException; import org.basex.query.expr.Expr; import org.basex.query.item.Dbl; import org.basex.query.item.Item; import org.basex.util.InputInfo; /** * Math functions. * * @author BaseX Team 2005-12, BSD License * @author Christian Gruen */ public final class FNMath extends StandardFunc { /** * Constructor. * @param ii input info * @param f function definition * @param e arguments */ public FNMath(final InputInfo ii, final Function f, final Expr... e) { super(ii, f, e); } @Override public Item item(final QueryContext ctx, final InputInfo ii) throws QueryException { double d = 0; if(expr.length > 0) { if(expr[0].isEmpty()) return null; d = checkDbl(expr[0], ctx); } final double e = expr.length == 2 ? checkDbl(expr[1], ctx) : 0; switch(sig) { case _MATH_PI: return Dbl.get(PI); case _MATH_E: return Dbl.get(E); case _MATH_SQRT: return Dbl.get(sqrt(d)); case _MATH_SIN: return Dbl.get(sin(d)); case _MATH_COS: return Dbl.get(cos(d)); case _MATH_TAN: return Dbl.get(tan(d)); case _MATH_ASIN: return Dbl.get(asin(d)); case _MATH_ACOS: return Dbl.get(acos(d)); case _MATH_ATAN: return Dbl.get(atan(d)); case _MATH_EXP: return Dbl.get(exp(d)); case _MATH_EXP10: return Dbl.get(pow(10, d)); case _MATH_LOG: return Dbl.get(log(d)); case _MATH_LOG10: return Dbl.get(log10(d)); case _MATH_ATAN2: return Dbl.get(atan2(d, e)); case _MATH_POW: return Dbl.get(power(d, e)); // project-specific case _MATH_RANDOM: return Dbl.get(random()); case _MATH_SINH: return Dbl.get(sinh(d)); case _MATH_COSH: return Dbl.get(cosh(d)); case _MATH_TANH: return Dbl.get(tanh(d)); default: return super.item(ctx, ii); } } /** * Calculates the power. * @param b base * @param e exponent * @return power */ private static double power(final double b, final double e) { if(b == 1) return 1; if(b == -1) { if(Double.isNaN(e)) return b; if(Double.isInfinite(e)) return 1; } return pow(b, e); } @Override public boolean uses(final Use u) { // random() is non-deterministic; don't pre-evaluate return u == Use.X30 || u == Use.NDT && sig == Function._MATH_RANDOM || super.uses(u); } }