/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package expressiontree.operators.binary;

import expressiontree.ExpressionTreeElement;
import expressiontree.operands.NumberType;
import expressiontree.operators.BinaryOperator;
import expressiontree.operators.IncompatibleNumberFormatException;
import org.apfloat.Apint;
import org.apfloat.ApintMath;

/**
 * Az n alatt a k típusú operátorok osztálya.
 * @author Esta
 */
public class BinomialCoefficient extends BinaryOperator {

    @Override
    public ExpressionTreeElement getValue() throws IncompatibleNumberFormatException {
        ExpressionTreeElement op1 = this.operands.get(0).getValue();
        ExpressionTreeElement op2 = this.operands.get(1).getValue();
        if (op1 instanceof NumberType && op2 instanceof NumberType) {
            //csak akkor lehet számolni, ha számot találtunk
            NumberType a = (NumberType) op1;
            NumberType b = (NumberType) op2;
            if (!a.isLongValue() || !b.isLongValue()) {
                //ha nem hosszú egészeket kaptunk, akkor nem számolunk semmit.
                throw new IncompatibleNumberFormatException("ERROR_BINOM");
            }
            NumberType retValue = new NumberType(this.precision, false);
            long n = a.getNumericValue().longValue();
            long k = b.getNumericValue().longValue();
            if (n < 0 || k < 0) {
                //negatív n-return ill k-ra nem értelmes a faktoriális
                throw new IncompatibleNumberFormatException("ERROR_BINOM");
            }
            if (n < k) {
                //ha n<k akkor nem értelmes n alatt a k
                throw new IncompatibleNumberFormatException("ERROR_BINOM_NK");
            }
            //kiszámoljuk a nevezőt
            Apint nevezo = ApintMath.factorial(k).multiply(ApintMath.factorial(n - k));
            //kiszámítjuk a számlálót, és elosztjuk a nevezővel.
            retValue.setValue(ApintMath.factorial(n).precision(this.precision).divide(nevezo).precision(this.precision));
            return retValue;
        } else { //mátrix >> exception
            throw new IncompatibleNumberFormatException("ERROR_BINOM");
        }
    }

    @Override
    public String toText(boolean b) {
        if (b) {
            return "() bic ()";
        } else {
            return "bic ";
        }
    }

    @Override
    public String getLocalizedName() {
        return java.util.ResourceBundle.getBundle("languages/operators").getString("BINOMIAL_COEFFICIENT");
    }
}
