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

import expressiontree.ExpressionTreeElement;
import expressiontree.operands.Matrix;
import expressiontree.operators.UnaryOperator;
import expressiontree.operands.NumberType;
import expressiontree.operators.IncompatibleNumberFormatException;
import org.apfloat.Apfloat;
import org.apfloat.ApfloatMath;

/**
 * Az abszolutérték operátorok osztálya.
 * @author Esta
 */
public class AbsoluteValue extends UnaryOperator {

    @Override
    public ExpressionTreeElement getValue() throws IncompatibleNumberFormatException {
        ExpressionTreeElement op1 = this.operands.get(0).getValue();
        if (op1 instanceof NumberType) {
            //Ha csak számot talál, akkor abszolút értéket számol.
            NumberType n = (NumberType) op1;
            NumberType retValue = new NumberType(this.precision,false);
            retValue.setValue(ApfloatMath.abs(n.getNumericValue()));
            return retValue;
        } else if (op1 instanceof Matrix) {
            //Ha vektor, vagy mátrix, akkor norma lesz az abs helyett.
            Matrix m = (Matrix) op1;
            NumberType retValue = new NumberType(this.precision,false);
            retValue.setValue(new Apfloat(0.0, this.precision));
            if (m.getCols() == 1) { //ha oszlopvektor, akkor 2 norma
                for (int i = 0; i < m.getRows(); i++) {
                    retValue.setValue(retValue.getNumericValue().add(ApfloatMath.pow(m.getMatrixValues()[i][0], 2)));
                }
                retValue.setValue(ApfloatMath.sqrt(retValue.getNumericValue()));
                return retValue;
            } else if (m.getRows() == 1) { //ha sorvektor, akkor 2 norma
                for (int i = 0; i < m.getCols(); i++) {
                    retValue.setValue(retValue.getNumericValue().add(ApfloatMath.pow(m.getMatrixValues()[0][i], 2)));
                }
                retValue.setValue(ApfloatMath.sqrt(retValue.getNumericValue()));
                return retValue;
            } else { //ha mátrix, végtelen normát számolunk.
                for (int i = 0; i < m.getRows(); i++) {
                    Apfloat temp = new Apfloat(0.0, this.precision);
                    for (int j = 0; j < m.getCols(); j++) {
                        temp = temp.add(ApfloatMath.abs(m.getMatrixValues()[i][j]));
                    }
                    if (temp.compareTo(retValue.getNumericValue()) > 0) {
                        //ha temp > retValue, akkor lengthkell cserélni a retValue-t
                        retValue.setValue(temp);
                    }
                }
                return retValue;
            }
        } else { //Ez elvileg SOHA nem fordulhat elő.
            throw new IncompatibleNumberFormatException("ERROR_ABS");
        }
    }

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

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