com.bc.jexp.impl.DefaultNamespace.java Source code

Java tutorial

Introduction

Here is the source code for com.bc.jexp.impl.DefaultNamespace.java

Source

/*
 * Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de)
 *
 * 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 3 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, see http://www.gnu.org/licenses/
 */

package com.bc.jexp.impl;

import com.bc.jexp.EvalEnv;
import com.bc.jexp.EvalException;
import com.bc.jexp.Namespace;
import com.bc.jexp.Term;
import org.apache.commons.math3.util.FastMath;

/**
 * A default namespace which includes the constants PI, E and NaN as well as most of the functions from
 * Java {@link Math}, e.g.
 * sin(x),
 * cos(x),
 * tan(x),
 * asin(x),
 * acos(x),
 * atan(x),
 * atan2(x,y),
 * log(x),
 * exp(x),
 * pow(x,y),
 * sqrt(x,y),
 * abs(x),
 * min(x,y),
 * max(x,y),
 * floor(x),
 * rad(x) ({@link Math#toRadians(double)}),
 * deg(x,y) ({@link Math#toDegrees(double)}).
 * inf(x,y) ({@link Double#isInfinite(double)}),
 * nan(x,y) ({@link Double#isNaN(double)}).
 * <p>The following functions are not taken from Java Java {@link Math}:
 * log10(x),
 * exp10(x),
 * sign(x).
 * <p>It also provides the fuzzy comparision functions
 * feq(x, y),
 * fneq(x).
 *
 * @author Norman Fomferra (norman.fomferra@brockmann-consult.de)
 * @version $Revision$ $Date$
 */
public final class DefaultNamespace extends NamespaceImpl {

    private static final double EPS = 1e-6;

    public DefaultNamespace() {
        this(null);
    }

    public DefaultNamespace(Namespace parent) {
        super(parent);
        registerDefaultSymbols();
        registerDefaultFunctions();
    }

    private void registerDefaultSymbols() {
        registerSymbol(SymbolFactory.createConstant("PI", Math.PI));
        registerSymbol(SymbolFactory.createConstant("E", Math.E));
        registerSymbol(SymbolFactory.createConstant("NaN", Double.NaN));
    }

    private void registerDefaultFunctions() {
        registerFunction(new AbstractFunction.D("sin", 1) {

            public double evalD(final EvalEnv env, final Term[] args) {
                return FastMath.sin(args[0].evalD(env));
            }
        });
        registerFunction(new AbstractFunction.D("cos", 1) {

            public double evalD(final EvalEnv env, final Term[] args) {
                return FastMath.cos(args[0].evalD(env));
            }
        });
        registerFunction(new AbstractFunction.D("tan", 1) {

            public double evalD(final EvalEnv env, final Term[] args) {
                return FastMath.tan(args[0].evalD(env));
            }
        });
        registerFunction(new AbstractFunction.D("asin", 1) {

            public double evalD(final EvalEnv env, final Term[] args) {
                return FastMath.asin(args[0].evalD(env));
            }
        });
        registerFunction(new AbstractFunction.D("acos", 1) {

            public double evalD(final EvalEnv env, final Term[] args) {
                return FastMath.acos(args[0].evalD(env));
            }
        });
        registerFunction(new AbstractFunction.D("atan", 1) {

            public double evalD(final EvalEnv env, final Term[] args) {
                return FastMath.atan(args[0].evalD(env));
            }
        });
        registerFunction(new AbstractFunction.D("atan2", 2) {

            public double evalD(final EvalEnv env, final Term[] args) {
                return Math.atan2(args[0].evalD(env), args[1].evalD(env));
            }
        });
        registerFunction(new AbstractFunction.D("log", 1) {

            public double evalD(final EvalEnv env, final Term[] args) {
                return Math.log(args[0].evalD(env));
            }
        });

        registerFunction(new AbstractFunction.D("log10", 1) {
            public double evalD(EvalEnv env, Term[] args) throws EvalException {
                return Math.log10(args[0].evalD(env));
            }
        });

        registerFunction(new AbstractFunction.D("exp", 1) {

            public double evalD(final EvalEnv env, final Term[] args) {
                return FastMath.exp(args[0].evalD(env));
            }
        });

        registerFunction(new AbstractFunction.D("exp10", 1) {

            public double evalD(EvalEnv env, Term[] args) throws EvalException {
                return FastMath.pow(10.0, args[0].evalD(env));
            }
        });

        registerFunction(new AbstractFunction.D("sqr", 1) {

            public double evalD(final EvalEnv env, final Term[] args) {
                double v = args[0].evalD(env);
                return v * v;
            }
        });

        registerFunction(new AbstractFunction.D("sqrt", 1) {

            public double evalD(final EvalEnv env, final Term[] args) {
                return Math.sqrt(args[0].evalD(env));
            }
        });

        registerFunction(new AbstractFunction.D("pow", 2) {

            public double evalD(final EvalEnv env, final Term[] args) {
                return FastMath.pow(args[0].evalD(env), args[1].evalD(env));
            }
        });

        registerFunction(new AbstractFunction.I("min", 2) {

            public int evalI(final EvalEnv env, final Term[] args) {
                return Math.min(args[0].evalI(env), args[1].evalI(env));
            }
        });

        registerFunction(new AbstractFunction.D("min", 2) {

            public double evalD(final EvalEnv env, final Term[] args) {
                return Math.min(args[0].evalD(env), args[1].evalD(env));
            }
        });

        registerFunction(new AbstractFunction.I("max", 2) {

            public int evalI(final EvalEnv env, final Term[] args) {
                return Math.max(args[0].evalI(env), args[1].evalI(env));
            }
        });

        registerFunction(new AbstractFunction.D("max", 2) {

            public double evalD(final EvalEnv env, final Term[] args) {
                return Math.max(args[0].evalD(env), args[1].evalD(env));
            }
        });

        registerFunction(new AbstractFunction.D("floor", 1) {
            public double evalD(EvalEnv env, Term[] args) throws EvalException {
                return Math.floor(args[0].evalD(env));
            }
        });

        registerFunction(new AbstractFunction.D("round", 1) {
            public double evalD(EvalEnv env, Term[] args) throws EvalException {
                return Math.round(args[0].evalD(env));
            }
        });

        registerFunction(new AbstractFunction.D("ceil", 1) {
            public double evalD(EvalEnv env, Term[] args) throws EvalException {
                return Math.ceil(args[0].evalD(env));
            }
        });

        registerFunction(new AbstractFunction.D("rint", 1) {
            public double evalD(EvalEnv env, Term[] args) throws EvalException {
                return Math.rint(args[0].evalD(env));
            }
        });

        registerFunction(new AbstractFunction.I("sign", 1) {

            public int evalI(final EvalEnv env, final Term[] args) {
                return ExtMath.sign(args[0].evalI(env));
            }
        });

        registerFunction(new AbstractFunction.D("sign", 1) {

            public double evalD(final EvalEnv env, final Term[] args) {
                return ExtMath.sign(args[0].evalD(env));
            }
        });

        registerFunction(new AbstractFunction.I("abs", 1) {

            public int evalI(final EvalEnv env, final Term[] args) {
                return Math.abs(args[0].evalI(env));
            }
        });

        registerFunction(new AbstractFunction.D("abs", 1) {

            public double evalD(final EvalEnv env, final Term[] args) {
                return Math.abs(args[0].evalD(env));
            }
        });

        registerFunction(new AbstractFunction.D("deg", 1) {

            public double evalD(final EvalEnv env, final Term[] args) {
                return Math.toDegrees(args[0].evalD(env));
            }
        });

        registerFunction(new AbstractFunction.D("rad", 1) {

            public double evalD(final EvalEnv env, final Term[] args) {
                return Math.toRadians(args[0].evalD(env));
            }
        });

        registerFunction(new AbstractFunction.D("ampl", 2) {

            public double evalD(final EvalEnv env, final Term[] args) {
                final double a = args[0].evalD(env);
                final double b = args[1].evalD(env);
                return Math.sqrt(a * a + b * b);
            }
        });

        registerFunction(new AbstractFunction.D("phase", 2) {

            public double evalD(final EvalEnv env, final Term[] args) {
                final double a = args[0].evalD(env);
                final double b = args[1].evalD(env);
                return Math.atan2(b, a);
            }
        });

        registerFunction(new AbstractFunction.B("feq", 2) {
            public boolean evalB(EvalEnv env, Term[] args) throws EvalException {
                final double x1 = args[0].evalD(env);
                final double x2 = args[1].evalD(env);
                return ExtMath.feq(x1, x2, EPS);
            }
        });

        registerFunction(new AbstractFunction.B("feq", 3) {
            public boolean evalB(EvalEnv env, Term[] args) throws EvalException {
                final double x1 = args[0].evalD(env);
                final double x2 = args[1].evalD(env);
                final double eps = args[2].evalD(env);
                return ExtMath.feq(x1, x2, eps);
            }
        });

        registerFunction(new AbstractFunction.B("fneq", 2) {
            public boolean evalB(EvalEnv env, Term[] args) throws EvalException {
                final double x1 = args[0].evalD(env);
                final double x2 = args[1].evalD(env);
                return ExtMath.fneq(x1, x2, EPS);
            }
        });

        registerFunction(new AbstractFunction.B("fneq", 3) {
            public boolean evalB(EvalEnv env, Term[] args) throws EvalException {
                final double x1 = args[0].evalD(env);
                final double x2 = args[1].evalD(env);
                final double eps = args[2].evalD(env);
                return ExtMath.fneq(x1, x2, eps);
            }
        });

        registerFunction(new AbstractFunction.B("inf", 1) {
            public boolean evalB(EvalEnv env, Term[] args) throws EvalException {
                return Double.isInfinite(args[0].evalD(env));
            }
        });

        registerFunction(new AbstractFunction.B("nan", 1) {
            public boolean evalB(EvalEnv env, Term[] args) throws EvalException {
                return Double.isNaN(args[0].evalD(env));
            }
        });

        registerFunction(new AbstractFunction.D("distance", -1) {

            public double evalD(final EvalEnv env, final Term[] args) {
                double sqrSum = 0.0;
                final int n = args.length / 2;
                for (int i = 0; i < n; i++) {
                    final double v = args[i + n].evalD(env) - args[i].evalD(env);
                    sqrSum += v * v;
                }
                return Math.sqrt(sqrSum);
            }
        });

        registerFunction(new AbstractFunction.D("distance_deriv", -1) {

            public double evalD(final EvalEnv env, final Term[] args) {
                double sqrSum = 0.0;
                final int n = args.length / 2;
                for (int i = 0; i < n - 1; i++) {
                    final double v1 = args[i + 1].evalD(env) - args[i].evalD(env);
                    final double v2 = args[i + n + 1].evalD(env) - args[i + n].evalD(env);
                    sqrSum += (v1 - v2) * (v1 - v2);
                }
                return Math.sqrt(sqrSum);
            }
        });

        registerFunction(new AbstractFunction.D("distance_integ", -1) {

            public double evalD(final EvalEnv env, final Term[] args) {
                double sqrSum = 0.0;
                double v1Sum = 0.0;
                double v2Sum = 0.0;
                final int n = args.length / 2;
                for (int i = 0; i < n; i++) {
                    v1Sum += args[i].evalD(env);
                    v2Sum += args[i + n].evalD(env);
                    sqrSum += (v2Sum - v1Sum) * (v2Sum - v1Sum);
                }
                return Math.sqrt(sqrSum);
            }
        });

        registerFunction(new AbstractFunction.B("inrange", -1) {

            public boolean evalB(final EvalEnv env, final Term[] args) {
                final int n1 = args.length / 3;
                final int n2 = n1 + args.length / 3;
                for (int i = 0; i < n1; i++) {
                    final double v = args[i].evalD(env);
                    final double v1 = args[i + n1].evalD(env);
                    final double v2 = args[i + n2].evalD(env);
                    if (v < v1 || v > v2) {
                        return false;
                    }
                }
                return true;
            }
        });

        registerFunction(new AbstractFunction.B("inrange_deriv", -1) {

            public boolean evalB(final EvalEnv env, final Term[] args) {
                final int n1 = args.length / 3;
                final int n2 = 2 * n1;
                for (int i = 0; i < n1 - 1; i++) {
                    final double v = args[i + 1].evalD(env) - args[i].evalD(env);
                    final double v1 = args[i + n1 + 1].evalD(env) - args[i + n1].evalD(env);
                    final double v2 = args[i + n2 + 1].evalD(env) - args[i + n2].evalD(env);
                    if (v < v1 || v > v2) {
                        return false;
                    }
                }
                return true;
            }
        });

        registerFunction(new AbstractFunction.B("inrange_integ", -1) {

            public boolean evalB(final EvalEnv env, final Term[] args) {
                final int n1 = args.length / 3;
                final int n2 = 2 * n1;
                double vSum = 0.0;
                double v1Sum = 0.0;
                double v2Sum = 0.0;
                for (int i = 0; i < n1; i++) {
                    vSum += args[i].evalD(env);
                    v1Sum += args[i + n1].evalD(env);
                    v2Sum += args[i + n2].evalD(env);
                    if (vSum < v1Sum || vSum > v2Sum) {
                        return false;
                    }
                }
                return true;
            }
        });

    }

}