public Expression()

in gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Expression.java [648:1041]


    public Expression(String expression) {
        this.expression = expression;

        addOperator(new Assignment("=", 5) {
            @Override
            public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
                return v2;
            }
        });
        addOperator(new Assignment("+=", 5) {
            @Override
            public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
                return v1.add(v2, mc);
            }

            @Override
            public Object eval(String v1, String v2) {
                return v1 + v2;
            }
        });
        addOperator(new Assignment("-=", 5) {
            @Override
            public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
                return v1.subtract(v2, mc);
            }
        });
        addOperator(new Assignment("*=", 5) {
            @Override
            public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
                return v1.multiply(v2, mc);
            }
        });
        addOperator(new Assignment("/=", 5) {
            @Override
            public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
                return v1.divide(v2, mc);
            }
        });
        addOperator(new Assignment("%=", 5) {
            @Override
            public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
                return v1.remainder(v2, mc);
            }
        });
        addOperator(new Assignment("|=", 5) {
            @Override
            public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
                return new BigDecimal(v1.toBigInteger().or(v2.toBigInteger()), mc);
            }
        });
        addOperator(new Assignment("&=", 5) {
            @Override
            public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
                return new BigDecimal(v1.toBigInteger().and(v2.toBigInteger()), mc);
            }
        });
        addOperator(new Assignment("^=", 5) {
            @Override
            public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
                return new BigDecimal(v1.toBigInteger().xor(v2.toBigInteger()), mc);
            }
        });
        addOperator(new Assignment("<<=", 5) {
            @Override
            public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
                return new BigDecimal(v1.toBigInteger().shiftLeft(v2.intValue()), mc);
            }
        });
        addOperator(new Assignment(">>=", 5) {
            @Override
            public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
                return new BigDecimal(v1.toBigInteger().shiftRight(v2.intValue()), mc);
            }
        });

        addOperator(new Operator("<<", 10, true) {
            @Override
            public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
                return new BigDecimal(v1.toBigInteger().shiftLeft(v2.intValue()), mc);
            }
        });
        addOperator(new Operator(">>", 10, true) {
            @Override
            public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
                return new BigDecimal(v1.toBigInteger().shiftRight(v2.intValue()), mc);
            }
        });
        addOperator(new Operator("|", 15, true) {
            @Override
            public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
                return new BigDecimal(v1.toBigInteger().or(v2.toBigInteger()), mc);
            }
        });
        addOperator(new Operator("&", 15, true) {
            @Override
            public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
                return new BigDecimal(v1.toBigInteger().and(v2.toBigInteger()), mc);
            }
        });
        addOperator(new Operator("^", 15, true) {
            @Override
            public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
                return new BigDecimal(v1.toBigInteger().xor(v2.toBigInteger()), mc);
            }
        });
        addOperator(new Operator("+", 20, true) {
            @Override
            public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
                return v1.add(v2, mc);
            }
            @Override
            public Object eval(String v1, String v2) {
                return v1 + v2;
            }
        });
        addOperator(new Operator("-", 20, true) {
            @Override
            public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
                return v1.subtract(v2, mc);
            }
        });
        addOperator(new Operator("*", 30, true) {
            @Override
            public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
                return v1.multiply(v2, mc);
            }
        });
        addOperator(new Operator("/", 30, true) {
            @Override
            public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
                return v1.divide(v2, mc);
            }
        });
        addOperator(new Operator("%", 30, true) {
            @Override
            public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
                return v1.remainder(v2, mc);
            }
        });
        addOperator(new Operator("**", 40, false) {
            @Override
            public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
                /*-
                * Thanks to Gene Marin:
                * http://stackoverflow.com/questions/3579779/how-to-do-a-fractional-power-on-bigdecimal-in-java
                */
                int signOf2 = v2.signum();
                double dn1 = v1.doubleValue();
                v2 = v2.multiply(new BigDecimal(signOf2)); // n2 is now positive
                BigDecimal remainderOf2 = v2.remainder(BigDecimal.ONE);
                BigDecimal n2IntPart = v2.subtract(remainderOf2);
                BigDecimal intPow = v1.pow(n2IntPart.intValueExact(), mc);
                BigDecimal doublePow = new BigDecimal(Math.pow(dn1,
                        remainderOf2.doubleValue()));

                BigDecimal result = intPow.multiply(doublePow, mc);
                if (signOf2 == -1) {
                    result = BigDecimal.ONE.divide(result, mc.getPrecision(),
                            RoundingMode.HALF_UP);
                }
                return result;
            }
        });
        addOperator(new Operator("&&", 4, false) {
            @Override
            public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
                boolean b1 = !v1.equals(BigDecimal.ZERO);
                boolean b2 = !v2.equals(BigDecimal.ZERO);
                return b1 && b2 ? BigDecimal.ONE : BigDecimal.ZERO;
            }
        });

        addOperator(new Operator("||", 2, false) {
            @Override
            public BigDecimal eval(BigDecimal v1, BigDecimal v2) {
                boolean b1 = !v1.equals(BigDecimal.ZERO);
                boolean b2 = !v2.equals(BigDecimal.ZERO);
                return b1 || b2 ? BigDecimal.ONE : BigDecimal.ZERO;
            }
        });

        addOperator(new Comparator(">", 10) {
            @Override @SuppressWarnings({ "unchecked", "rawtypes" })
            public boolean compare(Comparable v1, Comparable v2) {
                return v1.compareTo(v2) > 0;
            }
        });

        addOperator(new Comparator(">=", 10) {
            @Override @SuppressWarnings({ "unchecked", "rawtypes" })
            public boolean compare(Comparable v1, Comparable v2) {
                return v1.compareTo(v2) >= 0;
            }
        });

        addOperator(new Comparator("<", 10) {
            @Override @SuppressWarnings({ "unchecked", "rawtypes" })
            public boolean compare(Comparable v1, Comparable v2) {
                return v1.compareTo(v2) < 0;
            }
        });

        addOperator(new Comparator("<=", 10) {
            @Override @SuppressWarnings({ "unchecked", "rawtypes" })
            public boolean compare(Comparable v1, Comparable v2) {
                return v1.compareTo(v2) <= 0;
            }
        });

        addOperator(new Comparator("==", 7) {
            @Override @SuppressWarnings({ "unchecked", "rawtypes" })
            public boolean compare(Comparable v1, Comparable v2) {
                return v1.compareTo(v2) == 0;
            }
        });

        addOperator(new Comparator("!=", 7) {
            @Override @SuppressWarnings({ "unchecked", "rawtypes" })
            public boolean compare(Comparable v1, Comparable v2) {
                return v1.compareTo(v2) != 0;
            }
        });

        addFunction(new Function("NOT", 1) {
            @Override
            public BigDecimal eval(List<BigDecimal> parameters) {
                boolean zero = parameters.get(0).compareTo(BigDecimal.ZERO) == 0;
                return zero ? BigDecimal.ONE : BigDecimal.ZERO;
            }
        });

        addFunction(new Function("IF", 3) {
            @Override
            public BigDecimal eval(List<BigDecimal> parameters) {
                boolean isTrue = !parameters.get(0).equals(BigDecimal.ZERO);
                return isTrue ? parameters.get(1) : parameters.get(2);
            }
        });

        addFunction(new Function("RANDOM", 0) {
            @Override
            public BigDecimal eval(List<BigDecimal> parameters) {
                double d = Math.random();
                return new BigDecimal(d, mc);
            }
        });
        addFunction(new Function("SIN", 1) {
            @Override
            public BigDecimal eval(List<BigDecimal> parameters) {
                double d = Math.sin(Math.toRadians(parameters.get(0)
                        .doubleValue()));
                return new BigDecimal(d, mc);
            }
        });
        addFunction(new Function("COS", 1) {
            @Override
            public BigDecimal eval(List<BigDecimal> parameters) {
                double d = Math.cos(Math.toRadians(parameters.get(0)
                        .doubleValue()));
                return new BigDecimal(d, mc);
            }
        });
        addFunction(new Function("TAN", 1) {
            @Override
            public BigDecimal eval(List<BigDecimal> parameters) {
                double d = Math.tan(Math.toRadians(parameters.get(0)
                        .doubleValue()));
                return new BigDecimal(d, mc);
            }
        });
        addFunction(new Function("SINH", 1) {
            @Override
            public BigDecimal eval(List<BigDecimal> parameters) {
                double d = Math.sinh(parameters.get(0).doubleValue());
                return new BigDecimal(d, mc);
            }
        });
        addFunction(new Function("COSH", 1) {
            @Override
            public BigDecimal eval(List<BigDecimal> parameters) {
                double d = Math.cosh(parameters.get(0).doubleValue());
                return new BigDecimal(d, mc);
            }
        });
        addFunction(new Function("TANH", 1) {
            @Override
            public BigDecimal eval(List<BigDecimal> parameters) {
                double d = Math.tanh(parameters.get(0).doubleValue());
                return new BigDecimal(d, mc);
            }
        });
        addFunction(new Function("RAD", 1) {
            @Override
            public BigDecimal eval(List<BigDecimal> parameters) {
                double d = Math.toRadians(parameters.get(0).doubleValue());
                return new BigDecimal(d, mc);
            }
        });
        addFunction(new Function("DEG", 1) {
            @Override
            public BigDecimal eval(List<BigDecimal> parameters) {
                double d = Math.toDegrees(parameters.get(0).doubleValue());
                return new BigDecimal(d, mc);
            }
        });
        addFunction(new Function("MAX", 2) {
            @Override
            public BigDecimal eval(List<BigDecimal> parameters) {
                BigDecimal v1 = parameters.get(0);
                BigDecimal v2 = parameters.get(1);
                return v1.compareTo(v2) > 0 ? v1 : v2;
            }
        });
        addFunction(new Function("MIN", 2) {
            @Override
            public BigDecimal eval(List<BigDecimal> parameters) {
                BigDecimal v1 = parameters.get(0);
                BigDecimal v2 = parameters.get(1);
                return v1.compareTo(v2) < 0 ? v1 : v2;
            }
        });
        addFunction(new Function("ABS", 1) {
            @Override
            public BigDecimal eval(List<BigDecimal> parameters) {
                return parameters.get(0).abs(mc);
            }
        });
        addFunction(new Function("LOG", 1) {
            @Override
            public BigDecimal eval(List<BigDecimal> parameters) {
                double d = Math.log(parameters.get(0).doubleValue());
                return new BigDecimal(d, mc);
            }
        });
        addFunction(new Function("ROUND", 2) {
            @Override
            public BigDecimal eval(List<BigDecimal> parameters) {
                BigDecimal toRound = parameters.get(0);
                int precision = parameters.get(1).intValue();
                return toRound.setScale(precision, mc.getRoundingMode());
            }
        });
        addFunction(new Function("FLOOR", 1) {
            @Override
            public BigDecimal eval(List<BigDecimal> parameters) {
                BigDecimal toRound = parameters.get(0);
                return toRound.setScale(0, RoundingMode.FLOOR);
            }
        });
        addFunction(new Function("CEILING", 1) {
            @Override
            public BigDecimal eval(List<BigDecimal> parameters) {
                BigDecimal toRound = parameters.get(0);
                return toRound.setScale(0, RoundingMode.CEILING);
            }
        });
        addFunction(new Function("SQRT", 1) {
            @Override
            public BigDecimal eval(List<BigDecimal> parameters) {
                /*
                * From The Java Programmers Guide To numerical Computing
                * (Ronald Mak, 2003)
                */
                BigDecimal x = parameters.get(0);
                if (x.compareTo(BigDecimal.ZERO) == 0) {
                    return new BigDecimal(0);
                }
                if (x.signum() < 0) {
                    throw new ExpressionException(
                            "Argument to SQRT() function must not be negative");
                }
                BigInteger n = x.movePointRight(mc.getPrecision() << 1)
                        .toBigInteger();

                int bits = (n.bitLength() + 1) >> 1;
                BigInteger ix = n.shiftRight(bits);
                BigInteger ixPrev;

                do {
                    ixPrev = ix;
                    ix = ix.add(n.divide(ix)).shiftRight(1);
                    // Give other threads a chance to work;
                    Thread.yield();
                } while (ix.compareTo(ixPrev) != 0);

                return new BigDecimal(ix, mc.getPrecision());
            }
        });

        constants.put("PI", PI);
        constants.put("TRUE", Boolean.TRUE);
        constants.put("FALSE", Boolean.FALSE);

    }