@BindExtension(implementation=AbsFunction.class)
public interface Abs<CALC> {
    
    public CALC abs(AbstractCalculator expression) ;
    
    public CALC abs(Object value) ;

    public CALC abs(String value, char decimalSeparator) ;

}
 public class AbsFunction implements Function {

    @Override
    public String getSymbol() {
        return "abs";
    }

    /**
     * ABS accept only one attribute abs(-1-)
     */
    @Override
    public int getFunctionAttributes() {
        return 1;
    }

    @Override
    public Num calc(AbstractCalculator calc, Num... values)  {
        return new Num(values[0].toBigDecimal().abs());
    }
    
    
} @BindExtension(implementation=AddOperator.class)
public interface Add<CALC> {
    public CALC add() ;

    public CALC add(Object value) ;

    public CALC add(String value, char decimalSeparator) ;

}
 public class AddOperator implements Operator {

    @Override
    public int getPriority() {
        return 5;
    }

    @Override
    public String getSymbol() {
        return "+";
    }

    @Override
    public Num calc(AbstractCalculator calc, Num value1, Num value2)  {
        BigDecimal value = value1.toBigDecimal().add(value2.toBigDecimal());
        Num result = new Num(value);
        return result;
    }

    @Override
    public String toString() {
        return getSymbol();
    }
} @BindExtension(implementation = ArcCosFunction.class)
public interface ArcCos<CALC> {

    public CALC acos(AbstractCalculator expression);

    public CALC acos(Object value);

    public CALC acos(String value, char decimalSeparator);
}
 public class ArcCosFunction implements Function {

    @Override
    public String getSymbol() {
        return "acos";
    }

    /**
     * ACOS accept only one attribute acos(-1-)
     */
    @Override
    public int getFunctionAttributes() {
        return 1;
    }

    @Override
    public Num calc(AbstractCalculator calc, Num... values)  {
        double acos = Math.acos(values[0].toBigDecimal().doubleValue());

        return new Num(acos);
    }

} @BindExtension(implementation = ArcSinFunction.class)
public interface ArcSin<CALC> {

    public CALC asin(AbstractCalculator expression);

    public CALC asin(Object value);

    public CALC asin(String value, char decimalSeparator);

}
 public class ArcSinFunction implements Function {

    @Override
    public String getSymbol() {
        return "asin";
    }

    /**
     * ASIN accept only one attribute asin(-1-)
     */
    @Override
    public int getFunctionAttributes() {
        return 1;
    }

    @Override
    public Num calc(AbstractCalculator calc, Num... values)  {
        double asin = Math.asin(values[0].toBigDecimal().doubleValue());

        return new Num(asin);
    }

} @BindExtension(implementation = ArcTanFunction.class)
public interface ArcTan<CALC> {

    public CALC atan(AbstractCalculator expression);

    public CALC atan(Object value);

    public CALC atan(String value, char decimalSeparator);

}
 public class ArcTanFunction implements Function {

    @Override
    public String getSymbol() {
        return "atan";
    }

    /**
     * ATAN accept only one attribute atan(-1-)
     */
    @Override
    public int getFunctionAttributes() {
        return 1;
    }

    @Override
    public Num calc(AbstractCalculator calc, Num... values)  {
        double atan = Math.atan(values[0].toBigDecimal().doubleValue());

        return new Num(atan);
    }

} @BindExtension(implementation = CosFunction.class)
public interface Cos<CALC> {

    public CALC cos(AbstractCalculator expression);

    public CALC cos(Object value);

    public CALC cos(String value, char decimalSeparator);

}
 public class CosFunction implements Function {

    @Override
    public String getSymbol() {
        return "cos";
    }

    /**
     * COS accept only one attribute cos(-1-)
     */
    @Override
    public int getFunctionAttributes() {
        return 1;
    }

    @Override
    public Num calc(AbstractCalculator calc, Num... values)  {
        double sin = Math.cos(values[0].toBigDecimal().doubleValue());
        
        return new Num(sin);
    }

} @BindExtension(implementation = CoshFunction.class)
public interface Cosh<CALC> {

    public CALC cosh(AbstractCalculator expression);

    public CALC cosh(Object value);

    public CALC cosh(String value, char decimalSeparator);

}
 public class CoshFunction implements Function {

    @Override
    public String getSymbol() {
        return "cosh";
    }

    /**
     * COSH accept only one attribute cosh(-1-)
     */
    @Override
    public int getFunctionAttributes() {
        return 1;
    }

    @Override
    public Num calc(AbstractCalculator calc, Num... values)  {
        double cosh = Math.cosh(values[0].toBigDecimal().doubleValue());
        
        return new Num(cosh);
    }

} @BindExtension(implementation = DivOperator.class)
public interface Div<CALC> {

    public CALC div();

    public CALC div(Object value);

    public CALC div(String value, char decimalSeparator);

}
 public class DivOperator implements Operator {

    @Override
    public int getPriority() {
        return 10;
    }

    @Override
    public String getSymbol() {
        return "/";
    }

    @Override
    public Num calc(AbstractCalculator calc, Num value1, Num value2)  {
        int scale = Properties.getInheritedScale(calc, value2);
        Rounding roundingMode = Properties.getInheritedRoundingMode(calc, value2);

        return calc(calc, value1, value2, scale, roundingMode);
    }

    public Num calc(AbstractCalculator calc, Num value1, Num value2, Integer scale, Rounding roundingMode)  {
        BigDecimal value = value1.toBigDecimal().divide(value2.toBigDecimal(), scale, roundingMode.getBigDecimalRound());
        Num result = new Num(value);
        return result;
    }

    @Override
    public String toString() {
        return getSymbol();
    }
} @BindExtension(implementation = LogFunction.class)
public interface Log<CALC> {

    public CALC log(AbstractCalculator expression);

    public CALC log(Object value);

    public CALC log(String value, char decimalSeparator);

}
 public class LogFunction implements Function {

    @Override
    public String getSymbol() {
        return "log";
    }

    /**
     * ABS accept only one attribute abs(-1-)
     */
    @Override
    public int getFunctionAttributes() {
        return 1;
    }

    @Override
    public Num calc(AbstractCalculator calc, Num... values) {
        return new Num(Math.log(values[0].doubleValue()));
    }
    
    
} @BindExtension(implementation = ModOperator.class)
public interface Mod<CALC> {

	public CALC mod();

	public CALC mod(Object value);

	public CALC mod(String value, char decimalSeparator);

}
 public class ModOperator implements Operator {

    @Override
    public int getPriority() {
        return 10;
    }

    @Override
    public String getSymbol() {
        return "%";
    }

    @Override
    public Num calc(AbstractCalculator calc, Num value1, Num value2)  {
        int scale = Properties.getInheritedScale(calc, value2);
        Rounding roundingMode = Properties.getInheritedRoundingMode(calc, value2);

        return calc(value1, value2, scale, roundingMode);
    }

    public Num calc(Num value1, Num value2, Integer scale, Rounding roundingMode)  {
        MathContext mc = new MathContext(scale, roundingMode.getRoundingMode());
        BigDecimal value = value1.toBigDecimal().remainder(value2.toBigDecimal(), mc);
        Num result = new Num(value);
        return result;
    }

    @Override
    public String toString() {
        return getSymbol();
    }
} @BindExtension(implementation = MulOperator.class)
public interface Mul<CALC> {
	public CALC mul();

	public CALC mul(Object value);

	public CALC mul(String value, char decimalSeparator);

}
 public class MulOperator implements Operator {

    @Override
    public int getPriority() {
        return 10;
    }

    @Override
    public String getSymbol() {
        return "*";
    }


    @Override
    public Num calc(AbstractCalculator calc, Num value1, Num value2)  {
        BigDecimal value = value1.toBigDecimal().multiply(value2.toBigDecimal());
        Num result = new Num(value);
        return result;
    }
    
    @Override
    public String toString() {
        return getSymbol();
    }
} @BindExtension(implementation = PowOperator.class)
public interface Pow<CALC> {

	public CALC pow();

	public CALC pow(Object value);

	public CALC pow(String value, char decimalSeparator);

}
 public class PowOperator implements Operator {

    @Override
    public int getPriority() {
        return 15;
    }

    @Override
    public String getSymbol() {
        return "^";
    }

    @Override
    public Num calc(AbstractCalculator calc, Num value1, Num exponent)  {
        int scale = Properties.getInheritedScale(calc, exponent);
        Rounding roundingMode = Properties.getInheritedRoundingMode(calc, exponent);

        return calc(calc, value1, exponent, scale, roundingMode);
    }

    public Num calc(AbstractCalculator calc, Num value1, Num exponent, Integer scale, Rounding roundingMode)  {
        if (exponent.hasRemainder()) {
            double result = Math.pow(value1.doubleValue(), exponent.doubleValue());
            return new Num(result);
        } else {
            int ex = exponent.intValue();
            
            if (ex == 0)
                return value1;
            else if (ex < 0) {
                BigDecimal one = BigDecimal.ONE;
                BigDecimal value = value1.toBigDecimal().pow(ex * -1);
                value = one.divide(value, scale, roundingMode.getBigDecimalRound());
                
                Num result = new Num(value);
                return result;
            } else {
                BigDecimal value = value1.toBigDecimal().pow(exponent.toBigDecimal().intValue());
                Num result = new Num(value);
                return result;
            }
        }
        
    }

    @Override
    public String toString() {
        return getSymbol();
    }
} @BindExtension(implementation = SinFunction.class)
public interface Sin<CALC> {

	public CALC sin(AbstractCalculator expression);

	public CALC sin(Object value);

	public CALC sin(String value, char decimalSeparator);

}
 public class SinFunction implements Function {

    @Override
    public String getSymbol() {
        return "sin";
    }

    /**
     * SIN accept only one attribute SIN(-1-)
     */
    @Override
    public int getFunctionAttributes() {
        return 1;
    }

    @Override
    public Num calc(AbstractCalculator calc, Num... values)  {
        double sin = Math.sin(values[0].toBigDecimal().doubleValue());
        
        return new Num(sin);
    }

} @BindExtension(implementation = SinhFunction.class)
public interface Sinh<CALC> {

	public CALC sinh(AbstractCalculator expression);

	public CALC sinh(Object value);

	public CALC sinh(String value, char decimalSeparator);

}
 public class SinhFunction implements Function {

    @Override
    public String getSymbol() {
        return "sinh";
    }

    /**
     * SINH accept only one attribute sinh(-1-)
     */
    @Override
    public int getFunctionAttributes() {
        return 1;
    }

    @Override
    public Num calc(AbstractCalculator calc, Num... values)  {
        double sinh = Math.sinh(values[0].toBigDecimal().doubleValue());
        
        return new Num(sinh);
    }

} @BindExtension(implementation = SqrtFunction.class)
public interface Sqrt<CALC> {

	public CALC sqrt(AbstractCalculator expression);

	public CALC sqrt(Object value);

	public CALC sqrt(String value, char decimalSeparator);

}
 public class SqrtFunction implements Function {

    @Override
    public String getSymbol() {
        return "sqrt";
    }

    @Override
    public int getFunctionAttributes() {
        return 2;
    }

    @Override
    public Num calc(AbstractCalculator calc, Num... values) {
        if (values.length == 1) {
            Num toSqrt = new Num();         
            toSqrt.set(Math.sqrt(values[0].toBigDecimal().doubleValue()));
            
            return toSqrt;
        }
        else {
            throw new IllegalArgumentException();
        }
    }




} @BindExtension(implementation = SubOperator.class)
public interface Sub<CALC> {

	public CALC sub();

	public CALC sub(Object value);

	public CALC sub(String value, char decimalSeparator);

}
 public class SubOperator implements Operator {

    @Override
    public int getPriority() {
        return 5;
    }

    @Override
    public String getSymbol() {
        return "-";
    }

    @Override
    public Num calc(AbstractCalculator calc, Num value1, Num value2)  {
        BigDecimal value = value1.toBigDecimal().subtract(value2.toBigDecimal());
        Num result = new Num(value);
        return result;
    }

    @Override
    public String toString() {
        return getSymbol();
    }
} @BindExtension(implementation = TanFunction.class)
public interface Tan<CALC> {

	public CALC tan(AbstractCalculator expression);

	public CALC tan(Object value);

	public CALC tan(String value, char decimalSeparator);

}
 public class TanFunction implements Function {

    @Override
    public String getSymbol() {
        return "tan";
    }

    /**
     * TAN accept only one attribute tan(-1-)
     */
    @Override
    public int getFunctionAttributes() {
        return 1;
    }

    @Override
    public Num calc(AbstractCalculator calc, Num... values)  {
        double tan = Math.tan(values[0].toBigDecimal().doubleValue());

        return new Num(tan);
    }

} @BindExtension(implementation = TanhFunction.class)
public interface Tanh<CALC> {

	public CALC tanh(AbstractCalculator expression);

	public CALC tanh(Object value);

	public CALC tanh(String value);

	public CALC tanh(String value, char decimalSeparator);

}
 public class TanhFunction implements Function {

    @Override
    public String getSymbol() {
        return "tanh";
    }

    /**
     * TANH accept only one attribute tanh(-1-)
     */
    @Override
    public int getFunctionAttributes() {
        return 1;
    }

    @Override
    public Num calc(AbstractCalculator calc, Num... values)  {
        double tanh = Math.tanh(values[0].toBigDecimal().doubleValue());

        return new Num(tanh);
    }

}
import java.text.ParseException;
import org.jdice.calc.extension.Abs;
import org.jdice.calc.extension.AbsFunction;
import org.jdice.calc.extension.Add;
import org.jdice.calc.extension.AddOperator;
import org.jdice.calc.extension.ArcCos;
import org.jdice.calc.extension.ArcCosFunction;
import org.jdice.calc.extension.ArcSin;
import org.jdice.calc.extension.ArcSinFunction;
import org.jdice.calc.extension.ArcTan;
import org.jdice.calc.extension.ArcTanFunction;
import org.jdice.calc.extension.Cos;
import org.jdice.calc.extension.CosFunction;
import org.jdice.calc.extension.Cosh;
import org.jdice.calc.extension.CoshFunction;
import org.jdice.calc.extension.Div;
import org.jdice.calc.extension.DivOperator;
import org.jdice.calc.extension.Log;
import org.jdice.calc.extension.LogFunction;
import org.jdice.calc.extension.Mod;
import org.jdice.calc.extension.ModOperator;
import org.jdice.calc.extension.Mul;
import org.jdice.calc.extension.MulOperator;
import org.jdice.calc.extension.Pow;
import org.jdice.calc.extension.PowOperator;
import org.jdice.calc.extension.Sin;
import org.jdice.calc.extension.SinFunction;
import org.jdice.calc.extension.Sinh;
import org.jdice.calc.extension.SinhFunction;
import org.jdice.calc.extension.Sqrt;
import org.jdice.calc.extension.SqrtFunction;
import org.jdice.calc.extension.Sub;
import org.jdice.calc.extension.SubOperator;
import org.jdice.calc.extension.Tan;
import org.jdice.calc.extension.TanFunction;
import org.jdice.calc.extension.Tanh;
import org.jdice.calc.extension.TanhFunction;

/*
 * Copyright 2014 Davor Sauer
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jdice.calc;



/**
 * Calculator implementation with trigonometric functions.
 * Support extensions: Sin, Cos, Tan, ArcSin, ArcCos, ArcTan, Sinh, Cosh, Tanh, Add, Sub, Div, Mul, Mod, Pow, Abs, Sqrt, Log
 * 
 * @author Davor Sauer <davor.sauer@gmail.com>
 * 
 */
public final class TrigCalculator extends AbstractCalculator<TrigCalculator> implements
        Sin<TrigCalculator>, Cos<TrigCalculator>, Tan<TrigCalculator>, ArcSin<TrigCalculator>,
        ArcCos<TrigCalculator>, ArcTan<TrigCalculator>, Sinh<TrigCalculator>, Cosh<TrigCalculator>,

        Tanh<TrigCalculator>, Add<TrigCalculator>, Sub<TrigCalculator>, Div<TrigCalculator>,
