Search in sources :

Example 36 with BinaryOp

use of org.apache.sysml.hops.BinaryOp in project incubator-systemml by apache.

the class TemplateUtils method isBinaryMatrixRowVector.

public static boolean isBinaryMatrixRowVector(Hop hop) {
    if (!(hop instanceof BinaryOp))
        return false;
    Hop left = hop.getInput().get(0);
    Hop right = hop.getInput().get(1);
    return left.dimsKnown() && right.dimsKnown() && left.getDataType().isMatrix() && right.getDataType().isMatrix() && left.getDim1() > right.getDim1();
}
Also used : Hop(org.apache.sysml.hops.Hop) AggBinaryOp(org.apache.sysml.hops.AggBinaryOp) BinaryOp(org.apache.sysml.hops.BinaryOp)

Example 37 with BinaryOp

use of org.apache.sysml.hops.BinaryOp in project incubator-systemml by apache.

the class DMLTranslator method processBuiltinFunctionExpression.

/**
 * Construct Hops from parse tree : Process BuiltinFunction Expression in an
 * assignment statement
 *
 * @param source built-in function expression
 * @param target data identifier
 * @param hops map of high-level operators
 * @return high-level operator
 */
private Hop processBuiltinFunctionExpression(BuiltinFunctionExpression source, DataIdentifier target, HashMap<String, Hop> hops) {
    Hop expr = processExpression(source.getFirstExpr(), null, hops);
    Hop expr2 = null;
    if (source.getSecondExpr() != null) {
        expr2 = processExpression(source.getSecondExpr(), null, hops);
    }
    Hop expr3 = null;
    if (source.getThirdExpr() != null) {
        expr3 = processExpression(source.getThirdExpr(), null, hops);
    }
    Hop currBuiltinOp = null;
    if (target == null) {
        target = createTarget(source);
    }
    // Construct the hop based on the type of Builtin function
    switch(source.getOpCode()) {
        case EVAL:
            currBuiltinOp = new NaryOp(target.getName(), target.getDataType(), target.getValueType(), OpOpN.EVAL, processAllExpressions(source.getAllExpr(), hops));
            break;
        case COLSUM:
            currBuiltinOp = new AggUnaryOp(target.getName(), target.getDataType(), target.getValueType(), AggOp.SUM, Direction.Col, expr);
            break;
        case COLMAX:
            currBuiltinOp = new AggUnaryOp(target.getName(), target.getDataType(), target.getValueType(), AggOp.MAX, Direction.Col, expr);
            break;
        case COLMIN:
            currBuiltinOp = new AggUnaryOp(target.getName(), target.getDataType(), target.getValueType(), AggOp.MIN, Direction.Col, expr);
            break;
        case COLMEAN:
            currBuiltinOp = new AggUnaryOp(target.getName(), target.getDataType(), target.getValueType(), AggOp.MEAN, Direction.Col, expr);
            break;
        case COLSD:
            // colStdDevs = sqrt(colVariances)
            currBuiltinOp = new AggUnaryOp(target.getName(), target.getDataType(), target.getValueType(), AggOp.VAR, Direction.Col, expr);
            currBuiltinOp = new UnaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp1.SQRT, currBuiltinOp);
            break;
        case COLVAR:
            currBuiltinOp = new AggUnaryOp(target.getName(), target.getDataType(), target.getValueType(), AggOp.VAR, Direction.Col, expr);
            break;
        case ROWSUM:
            currBuiltinOp = new AggUnaryOp(target.getName(), target.getDataType(), target.getValueType(), AggOp.SUM, Direction.Row, expr);
            break;
        case ROWMAX:
            currBuiltinOp = new AggUnaryOp(target.getName(), target.getDataType(), target.getValueType(), AggOp.MAX, Direction.Row, expr);
            break;
        case ROWINDEXMAX:
            currBuiltinOp = new AggUnaryOp(target.getName(), target.getDataType(), target.getValueType(), AggOp.MAXINDEX, Direction.Row, expr);
            break;
        case ROWINDEXMIN:
            currBuiltinOp = new AggUnaryOp(target.getName(), target.getDataType(), target.getValueType(), AggOp.MININDEX, Direction.Row, expr);
            break;
        case ROWMIN:
            currBuiltinOp = new AggUnaryOp(target.getName(), target.getDataType(), target.getValueType(), AggOp.MIN, Direction.Row, expr);
            break;
        case ROWMEAN:
            currBuiltinOp = new AggUnaryOp(target.getName(), target.getDataType(), target.getValueType(), AggOp.MEAN, Direction.Row, expr);
            break;
        case ROWSD:
            // rowStdDevs = sqrt(rowVariances)
            currBuiltinOp = new AggUnaryOp(target.getName(), target.getDataType(), target.getValueType(), AggOp.VAR, Direction.Row, expr);
            currBuiltinOp = new UnaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp1.SQRT, currBuiltinOp);
            break;
        case ROWVAR:
            currBuiltinOp = new AggUnaryOp(target.getName(), target.getDataType(), target.getValueType(), AggOp.VAR, Direction.Row, expr);
            break;
        case NROW:
            // If the dimensions are available at compile time, then create a LiteralOp (constant propagation)
            // Else create a UnaryOp so that a control program instruction is generated
            long nRows = expr.getDim1();
            if (nRows == -1) {
                currBuiltinOp = new UnaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp1.NROW, expr);
            } else {
                currBuiltinOp = new LiteralOp(nRows);
            }
            break;
        case NCOL:
            // If the dimensions are available at compile time, then create a LiteralOp (constant propagation)
            // Else create a UnaryOp so that a control program instruction is generated
            long nCols = expr.getDim2();
            if (nCols == -1) {
                currBuiltinOp = new UnaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp1.NCOL, expr);
            } else {
                currBuiltinOp = new LiteralOp(nCols);
            }
            break;
        case LENGTH:
            long nRows2 = expr.getDim1();
            long nCols2 = expr.getDim2();
            /* 
			 * If the dimensions are available at compile time, then create a LiteralOp (constant propagation)
			 * Else create a UnaryOp so that a control program instruction is generated
			 */
            if ((nCols2 == -1) || (nRows2 == -1)) {
                currBuiltinOp = new UnaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp1.LENGTH, expr);
            } else {
                long lval = (nCols2 * nRows2);
                currBuiltinOp = new LiteralOp(lval);
            }
            break;
        case SUM:
            currBuiltinOp = new AggUnaryOp(target.getName(), target.getDataType(), target.getValueType(), AggOp.SUM, Direction.RowCol, expr);
            break;
        case MEAN:
            if (expr2 == null) {
                // example: x = mean(Y);
                currBuiltinOp = new AggUnaryOp(target.getName(), target.getDataType(), target.getValueType(), AggOp.MEAN, Direction.RowCol, expr);
            } else {
                // example: x = mean(Y,W);
                // stable weighted mean is implemented by using centralMoment with order = 0
                Hop orderHop = new LiteralOp(0);
                currBuiltinOp = new TernaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp3.CENTRALMOMENT, expr, expr2, orderHop);
            }
            break;
        case SD:
            // stdDev = sqrt(variance)
            currBuiltinOp = new AggUnaryOp(target.getName(), target.getDataType(), target.getValueType(), AggOp.VAR, Direction.RowCol, expr);
            HopRewriteUtils.setOutputParametersForScalar(currBuiltinOp);
            currBuiltinOp = new UnaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp1.SQRT, currBuiltinOp);
            break;
        case VAR:
            currBuiltinOp = new AggUnaryOp(target.getName(), target.getDataType(), target.getValueType(), AggOp.VAR, Direction.RowCol, expr);
            break;
        case MIN:
            // construct AggUnary for min(X) but BinaryOp for min(X,Y)
            if (expr2 == null) {
                currBuiltinOp = new AggUnaryOp(target.getName(), target.getDataType(), target.getValueType(), AggOp.MIN, Direction.RowCol, expr);
            } else {
                currBuiltinOp = new BinaryOp(target.getName(), target.getDataType(), target.getValueType(), OpOp2.MIN, expr, expr2);
            }
            break;
        case MAX:
            // construct AggUnary for max(X) but BinaryOp for max(X,Y)
            if (expr2 == null) {
                currBuiltinOp = new AggUnaryOp(target.getName(), target.getDataType(), target.getValueType(), AggOp.MAX, Direction.RowCol, expr);
            } else {
                currBuiltinOp = new BinaryOp(target.getName(), target.getDataType(), target.getValueType(), OpOp2.MAX, expr, expr2);
            }
            break;
        case PPRED:
            String sop = ((StringIdentifier) source.getThirdExpr()).getValue();
            sop = sop.replace("\"", "");
            OpOp2 operation;
            if (sop.equalsIgnoreCase(">="))
                operation = OpOp2.GREATEREQUAL;
            else if (sop.equalsIgnoreCase(">"))
                operation = OpOp2.GREATER;
            else if (sop.equalsIgnoreCase("<="))
                operation = OpOp2.LESSEQUAL;
            else if (sop.equalsIgnoreCase("<"))
                operation = OpOp2.LESS;
            else if (sop.equalsIgnoreCase("=="))
                operation = OpOp2.EQUAL;
            else if (sop.equalsIgnoreCase("!="))
                operation = OpOp2.NOTEQUAL;
            else {
                LOG.error(source.printErrorLocation() + "Unknown argument (" + sop + ") for PPRED.");
                throw new ParseException(source.printErrorLocation() + "Unknown argument (" + sop + ") for PPRED.");
            }
            currBuiltinOp = new BinaryOp(target.getName(), target.getDataType(), target.getValueType(), operation, expr, expr2);
            break;
        case PROD:
            currBuiltinOp = new AggUnaryOp(target.getName(), target.getDataType(), target.getValueType(), AggOp.PROD, Direction.RowCol, expr);
            break;
        case TRACE:
            currBuiltinOp = new AggUnaryOp(target.getName(), target.getDataType(), target.getValueType(), AggOp.TRACE, Direction.RowCol, expr);
            break;
        case TRANS:
            currBuiltinOp = new ReorgOp(target.getName(), target.getDataType(), target.getValueType(), Hop.ReOrgOp.TRANSPOSE, expr);
            break;
        case REV:
            currBuiltinOp = new ReorgOp(target.getName(), target.getDataType(), target.getValueType(), Hop.ReOrgOp.REV, expr);
            break;
        case CBIND:
        case RBIND:
            OpOp2 appendOp1 = (source.getOpCode() == BuiltinFunctionOp.CBIND) ? OpOp2.CBIND : OpOp2.RBIND;
            OpOpN appendOp2 = (source.getOpCode() == BuiltinFunctionOp.CBIND) ? OpOpN.CBIND : OpOpN.RBIND;
            currBuiltinOp = (source.getAllExpr().length == 2) ? new BinaryOp(target.getName(), target.getDataType(), target.getValueType(), appendOp1, expr, expr2) : new NaryOp(target.getName(), target.getDataType(), target.getValueType(), appendOp2, processAllExpressions(source.getAllExpr(), hops));
            break;
        case DIAG:
            currBuiltinOp = new ReorgOp(target.getName(), target.getDataType(), target.getValueType(), Hop.ReOrgOp.DIAG, expr);
            break;
        case TABLE:
            // Always a TertiaryOp is created for table().
            // - create a hop for weights, if not provided in the function call.
            int numTableArgs = source._args.length;
            switch(numTableArgs) {
                case 2:
                case 4:
                    // example DML statement: F = ctable(A,B) or F = ctable(A,B,10,15)
                    // here, weight is interpreted as 1.0
                    Hop weightHop = new LiteralOp(1.0);
                    // set dimensions
                    weightHop.setDim1(0);
                    weightHop.setDim2(0);
                    weightHop.setNnz(-1);
                    weightHop.setRowsInBlock(0);
                    weightHop.setColsInBlock(0);
                    if (numTableArgs == 2)
                        currBuiltinOp = new TernaryOp(target.getName(), target.getDataType(), target.getValueType(), OpOp3.CTABLE, expr, expr2, weightHop);
                    else {
                        Hop outDim1 = processExpression(source._args[2], null, hops);
                        Hop outDim2 = processExpression(source._args[3], null, hops);
                        currBuiltinOp = new TernaryOp(target.getName(), target.getDataType(), target.getValueType(), OpOp3.CTABLE, expr, expr2, weightHop, outDim1, outDim2);
                    }
                    break;
                case 3:
                case 5:
                    // example DML statement: F = ctable(A,B,W) or F = ctable(A,B,W,10,15)
                    if (numTableArgs == 3)
                        currBuiltinOp = new TernaryOp(target.getName(), target.getDataType(), target.getValueType(), OpOp3.CTABLE, expr, expr2, expr3);
                    else {
                        Hop outDim1 = processExpression(source._args[3], null, hops);
                        Hop outDim2 = processExpression(source._args[4], null, hops);
                        currBuiltinOp = new TernaryOp(target.getName(), target.getDataType(), target.getValueType(), OpOp3.CTABLE, expr, expr2, expr3, outDim1, outDim2);
                    }
                    break;
                default:
                    throw new ParseException("Invalid number of arguments " + numTableArgs + " to table() function.");
            }
            break;
        // data type casts
        case CAST_AS_SCALAR:
            currBuiltinOp = new UnaryOp(target.getName(), DataType.SCALAR, target.getValueType(), Hop.OpOp1.CAST_AS_SCALAR, expr);
            break;
        case CAST_AS_MATRIX:
            currBuiltinOp = new UnaryOp(target.getName(), DataType.MATRIX, target.getValueType(), Hop.OpOp1.CAST_AS_MATRIX, expr);
            break;
        case CAST_AS_FRAME:
            currBuiltinOp = new UnaryOp(target.getName(), DataType.FRAME, target.getValueType(), Hop.OpOp1.CAST_AS_FRAME, expr);
            break;
        // value type casts
        case CAST_AS_DOUBLE:
            currBuiltinOp = new UnaryOp(target.getName(), target.getDataType(), ValueType.DOUBLE, Hop.OpOp1.CAST_AS_DOUBLE, expr);
            break;
        case CAST_AS_INT:
            currBuiltinOp = new UnaryOp(target.getName(), target.getDataType(), ValueType.INT, Hop.OpOp1.CAST_AS_INT, expr);
            break;
        case CAST_AS_BOOLEAN:
            currBuiltinOp = new UnaryOp(target.getName(), target.getDataType(), ValueType.BOOLEAN, Hop.OpOp1.CAST_AS_BOOLEAN, expr);
            break;
        // Boolean binary
        case XOR:
            currBuiltinOp = new BinaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp2.XOR, expr, expr2);
            break;
        case BITWAND:
            currBuiltinOp = new BinaryOp(target.getName(), target.getDataType(), target.getValueType(), OpOp2.BITWAND, expr, expr2);
            break;
        case BITWOR:
            currBuiltinOp = new BinaryOp(target.getName(), target.getDataType(), target.getValueType(), OpOp2.BITWOR, expr, expr2);
            break;
        case BITWXOR:
            currBuiltinOp = new BinaryOp(target.getName(), target.getDataType(), target.getValueType(), OpOp2.BITWXOR, expr, expr2);
            break;
        case BITWSHIFTL:
            currBuiltinOp = new BinaryOp(target.getName(), target.getDataType(), target.getValueType(), OpOp2.BITWSHIFTL, expr, expr2);
            break;
        case BITWSHIFTR:
            currBuiltinOp = new BinaryOp(target.getName(), target.getDataType(), target.getValueType(), OpOp2.BITWSHIFTR, expr, expr2);
            break;
        case ABS:
        case SIN:
        case COS:
        case TAN:
        case ASIN:
        case ACOS:
        case ATAN:
        case SINH:
        case COSH:
        case TANH:
        case SIGN:
        case SQRT:
        case EXP:
        case ROUND:
        case CEIL:
        case FLOOR:
        case CUMSUM:
        case CUMPROD:
        case CUMMIN:
        case CUMMAX:
            Hop.OpOp1 mathOp1;
            switch(source.getOpCode()) {
                case ABS:
                    mathOp1 = Hop.OpOp1.ABS;
                    break;
                case SIN:
                    mathOp1 = Hop.OpOp1.SIN;
                    break;
                case COS:
                    mathOp1 = Hop.OpOp1.COS;
                    break;
                case TAN:
                    mathOp1 = Hop.OpOp1.TAN;
                    break;
                case ASIN:
                    mathOp1 = Hop.OpOp1.ASIN;
                    break;
                case ACOS:
                    mathOp1 = Hop.OpOp1.ACOS;
                    break;
                case ATAN:
                    mathOp1 = Hop.OpOp1.ATAN;
                    break;
                case SINH:
                    mathOp1 = Hop.OpOp1.SINH;
                    break;
                case COSH:
                    mathOp1 = Hop.OpOp1.COSH;
                    break;
                case TANH:
                    mathOp1 = Hop.OpOp1.TANH;
                    break;
                case SIGN:
                    mathOp1 = Hop.OpOp1.SIGN;
                    break;
                case SQRT:
                    mathOp1 = Hop.OpOp1.SQRT;
                    break;
                case EXP:
                    mathOp1 = Hop.OpOp1.EXP;
                    break;
                case ROUND:
                    mathOp1 = Hop.OpOp1.ROUND;
                    break;
                case CEIL:
                    mathOp1 = Hop.OpOp1.CEIL;
                    break;
                case FLOOR:
                    mathOp1 = Hop.OpOp1.FLOOR;
                    break;
                case CUMSUM:
                    mathOp1 = Hop.OpOp1.CUMSUM;
                    break;
                case CUMPROD:
                    mathOp1 = Hop.OpOp1.CUMPROD;
                    break;
                case CUMMIN:
                    mathOp1 = Hop.OpOp1.CUMMIN;
                    break;
                case CUMMAX:
                    mathOp1 = Hop.OpOp1.CUMMAX;
                    break;
                default:
                    LOG.error(source.printErrorLocation() + "processBuiltinFunctionExpression():: Could not find Operation type for builtin function: " + source.getOpCode());
                    throw new ParseException(source.printErrorLocation() + "processBuiltinFunctionExpression():: Could not find Operation type for builtin function: " + source.getOpCode());
            }
            currBuiltinOp = new UnaryOp(target.getName(), target.getDataType(), target.getValueType(), mathOp1, expr);
            break;
        case LOG:
            if (expr2 == null) {
                Hop.OpOp1 mathOp2;
                switch(source.getOpCode()) {
                    case LOG:
                        mathOp2 = Hop.OpOp1.LOG;
                        break;
                    default:
                        LOG.error(source.printErrorLocation() + "processBuiltinFunctionExpression():: Could not find Operation type for builtin function: " + source.getOpCode());
                        throw new ParseException(source.printErrorLocation() + "processBuiltinFunctionExpression():: Could not find Operation type for builtin function: " + source.getOpCode());
                }
                currBuiltinOp = new UnaryOp(target.getName(), target.getDataType(), target.getValueType(), mathOp2, expr);
            } else {
                Hop.OpOp2 mathOp3;
                switch(source.getOpCode()) {
                    case LOG:
                        mathOp3 = Hop.OpOp2.LOG;
                        break;
                    default:
                        LOG.error(source.printErrorLocation() + "processBuiltinFunctionExpression():: Could not find Operation type for builtin function: " + source.getOpCode());
                        throw new ParseException(source.printErrorLocation() + "processBuiltinFunctionExpression():: Could not find Operation type for builtin function: " + source.getOpCode());
                }
                currBuiltinOp = new BinaryOp(target.getName(), target.getDataType(), target.getValueType(), mathOp3, expr, expr2);
            }
            break;
        case MOMENT:
            if (expr3 == null) {
                currBuiltinOp = new BinaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp2.CENTRALMOMENT, expr, expr2);
            } else {
                currBuiltinOp = new TernaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp3.CENTRALMOMENT, expr, expr2, expr3);
            }
            break;
        case COV:
            if (expr3 == null) {
                currBuiltinOp = new BinaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp2.COVARIANCE, expr, expr2);
            } else {
                currBuiltinOp = new TernaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp3.COVARIANCE, expr, expr2, expr3);
            }
            break;
        case QUANTILE:
            if (expr3 == null) {
                currBuiltinOp = new BinaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp2.QUANTILE, expr, expr2);
            } else {
                currBuiltinOp = new TernaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp3.QUANTILE, expr, expr2, expr3);
            }
            break;
        case INTERQUANTILE:
            if (expr3 == null) {
                currBuiltinOp = new BinaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp2.INTERQUANTILE, expr, expr2);
            } else {
                currBuiltinOp = new TernaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp3.INTERQUANTILE, expr, expr2, expr3);
            }
            break;
        case IQM:
            if (expr2 == null) {
                currBuiltinOp = new UnaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp1.IQM, expr);
            } else {
                currBuiltinOp = new BinaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp2.IQM, expr, expr2);
            }
            break;
        case MEDIAN:
            if (expr2 == null) {
                currBuiltinOp = new UnaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp1.MEDIAN, expr);
            } else {
                currBuiltinOp = new BinaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp2.MEDIAN, expr, expr2);
            }
            break;
        case IFELSE:
            currBuiltinOp = new TernaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp3.IFELSE, expr, expr2, expr3);
            break;
        case SEQ:
            HashMap<String, Hop> randParams = new HashMap<>();
            randParams.put(Statement.SEQ_FROM, expr);
            randParams.put(Statement.SEQ_TO, expr2);
            randParams.put(Statement.SEQ_INCR, (expr3 != null) ? expr3 : new LiteralOp(1));
            // note incr: default -1 (for from>to) handled during runtime
            currBuiltinOp = new DataGenOp(DataGenMethod.SEQ, target, randParams);
            break;
        case SAMPLE:
            {
                Expression[] in = source.getAllExpr();
                // arguments: range/size/replace/seed; defaults: replace=FALSE
                HashMap<String, Hop> tmpparams = new HashMap<>();
                // range
                tmpparams.put(DataExpression.RAND_MAX, expr);
                tmpparams.put(DataExpression.RAND_ROWS, expr2);
                tmpparams.put(DataExpression.RAND_COLS, new LiteralOp(1));
                if (in.length == 4) {
                    tmpparams.put(DataExpression.RAND_PDF, expr3);
                    Hop seed = processExpression(in[3], null, hops);
                    tmpparams.put(DataExpression.RAND_SEED, seed);
                } else if (in.length == 3) {
                    // check if the third argument is "replace" or "seed"
                    if (expr3.getValueType() == ValueType.BOOLEAN) {
                        tmpparams.put(DataExpression.RAND_PDF, expr3);
                        tmpparams.put(DataExpression.RAND_SEED, new LiteralOp(DataGenOp.UNSPECIFIED_SEED));
                    } else if (expr3.getValueType() == ValueType.INT) {
                        tmpparams.put(DataExpression.RAND_PDF, new LiteralOp(false));
                        tmpparams.put(DataExpression.RAND_SEED, expr3);
                    } else
                        throw new HopsException("Invalid input type " + expr3.getValueType() + " in sample().");
                } else if (in.length == 2) {
                    tmpparams.put(DataExpression.RAND_PDF, new LiteralOp(false));
                    tmpparams.put(DataExpression.RAND_SEED, new LiteralOp(DataGenOp.UNSPECIFIED_SEED));
                }
                currBuiltinOp = new DataGenOp(DataGenMethod.SAMPLE, target, tmpparams);
                break;
            }
        case SOLVE:
            currBuiltinOp = new BinaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp2.SOLVE, expr, expr2);
            break;
        case INVERSE:
            currBuiltinOp = new UnaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp1.INVERSE, expr);
            break;
        case CHOLESKY:
            currBuiltinOp = new UnaryOp(target.getName(), target.getDataType(), target.getValueType(), Hop.OpOp1.CHOLESKY, expr);
            break;
        case OUTER:
            if (!(expr3 instanceof LiteralOp))
                throw new HopsException("Operator for outer builtin function must be a constant: " + expr3);
            OpOp2 op = Hop.getOpOp2ForOuterVectorOperation(((LiteralOp) expr3).getStringValue());
            if (op == null)
                throw new HopsException("Unsupported outer vector binary operation: " + ((LiteralOp) expr3).getStringValue());
            currBuiltinOp = new BinaryOp(target.getName(), target.getDataType(), target.getValueType(), op, expr, expr2);
            // flag op as specific outer vector operation
            ((BinaryOp) currBuiltinOp).setOuterVectorOperation(true);
            // force size reevaluation according to 'outer' flag otherwise danger of incorrect dims
            currBuiltinOp.refreshSizeInformation();
            break;
        case CONV2D:
            {
                Hop image = expr;
                ArrayList<Hop> inHops1 = getALHopsForConvOp(image, source, 1, hops);
                currBuiltinOp = new ConvolutionOp(target.getName(), target.getDataType(), target.getValueType(), Hop.ConvOp.DIRECT_CONV2D, inHops1);
                setBlockSizeAndRefreshSizeInfo(image, currBuiltinOp);
                break;
            }
        case BIAS_ADD:
            {
                ArrayList<Hop> inHops1 = new ArrayList<>();
                inHops1.add(expr);
                inHops1.add(expr2);
                currBuiltinOp = new ConvolutionOp(target.getName(), target.getDataType(), target.getValueType(), Hop.ConvOp.BIAS_ADD, inHops1);
                setBlockSizeAndRefreshSizeInfo(expr, currBuiltinOp);
                break;
            }
        case BIAS_MULTIPLY:
            {
                ArrayList<Hop> inHops1 = new ArrayList<>();
                inHops1.add(expr);
                inHops1.add(expr2);
                currBuiltinOp = new ConvolutionOp(target.getName(), target.getDataType(), target.getValueType(), Hop.ConvOp.BIAS_MULTIPLY, inHops1);
                setBlockSizeAndRefreshSizeInfo(expr, currBuiltinOp);
                break;
            }
        case AVG_POOL:
        case MAX_POOL:
            {
                Hop image = expr;
                ArrayList<Hop> inHops1 = getALHopsForPoolingForwardIM2COL(image, source, 1, hops);
                if (source.getOpCode() == BuiltinFunctionOp.MAX_POOL)
                    currBuiltinOp = new ConvolutionOp(target.getName(), target.getDataType(), target.getValueType(), Hop.ConvOp.MAX_POOLING, inHops1);
                else
                    currBuiltinOp = new ConvolutionOp(target.getName(), target.getDataType(), target.getValueType(), Hop.ConvOp.AVG_POOLING, inHops1);
                setBlockSizeAndRefreshSizeInfo(image, currBuiltinOp);
                break;
            }
        case AVG_POOL_BACKWARD:
        case MAX_POOL_BACKWARD:
            {
                Hop image = expr;
                // process dout as well
                ArrayList<Hop> inHops1 = getALHopsForConvOpPoolingCOL2IM(image, source, 1, hops);
                if (source.getOpCode() == BuiltinFunctionOp.MAX_POOL_BACKWARD)
                    currBuiltinOp = new ConvolutionOp(target.getName(), target.getDataType(), target.getValueType(), Hop.ConvOp.MAX_POOLING_BACKWARD, inHops1);
                else
                    currBuiltinOp = new ConvolutionOp(target.getName(), target.getDataType(), target.getValueType(), Hop.ConvOp.AVG_POOLING_BACKWARD, inHops1);
                setBlockSizeAndRefreshSizeInfo(image, currBuiltinOp);
                break;
            }
        case CONV2D_BACKWARD_FILTER:
            {
                Hop image = expr;
                ArrayList<Hop> inHops1 = getALHopsForConvOp(image, source, 1, hops);
                currBuiltinOp = new ConvolutionOp(target.getName(), target.getDataType(), target.getValueType(), Hop.ConvOp.DIRECT_CONV2D_BACKWARD_FILTER, inHops1);
                setBlockSizeAndRefreshSizeInfo(image, currBuiltinOp);
                break;
            }
        case CONV2D_BACKWARD_DATA:
            {
                Hop image = expr;
                ArrayList<Hop> inHops1 = getALHopsForConvOp(image, source, 1, hops);
                currBuiltinOp = new ConvolutionOp(target.getName(), target.getDataType(), target.getValueType(), Hop.ConvOp.DIRECT_CONV2D_BACKWARD_DATA, inHops1);
                setBlockSizeAndRefreshSizeInfo(image, currBuiltinOp);
                break;
            }
        default:
            throw new ParseException("Unsupported builtin function type: " + source.getOpCode());
    }
    boolean isConvolution = source.getOpCode() == BuiltinFunctionOp.CONV2D || source.getOpCode() == BuiltinFunctionOp.CONV2D_BACKWARD_DATA || source.getOpCode() == BuiltinFunctionOp.CONV2D_BACKWARD_FILTER || source.getOpCode() == BuiltinFunctionOp.MAX_POOL || source.getOpCode() == BuiltinFunctionOp.MAX_POOL_BACKWARD || source.getOpCode() == BuiltinFunctionOp.AVG_POOL || source.getOpCode() == BuiltinFunctionOp.AVG_POOL_BACKWARD;
    if (!isConvolution) {
        // Since the dimension of output doesnot match that of input variable for these operations
        setIdentifierParams(currBuiltinOp, source.getOutput());
    }
    currBuiltinOp.setParseInfo(source);
    return currBuiltinOp;
}
Also used : OpOpN(org.apache.sysml.hops.Hop.OpOpN) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) OpOp2(org.apache.sysml.hops.Hop.OpOp2) DataGenOp(org.apache.sysml.hops.DataGenOp) ReorgOp(org.apache.sysml.hops.ReorgOp) LiteralOp(org.apache.sysml.hops.LiteralOp) AggBinaryOp(org.apache.sysml.hops.AggBinaryOp) BinaryOp(org.apache.sysml.hops.BinaryOp) AggUnaryOp(org.apache.sysml.hops.AggUnaryOp) UnaryOp(org.apache.sysml.hops.UnaryOp) Hop(org.apache.sysml.hops.Hop) HopsException(org.apache.sysml.hops.HopsException) TernaryOp(org.apache.sysml.hops.TernaryOp) AggUnaryOp(org.apache.sysml.hops.AggUnaryOp) ConvolutionOp(org.apache.sysml.hops.ConvolutionOp) NaryOp(org.apache.sysml.hops.NaryOp) OpOp2(org.apache.sysml.hops.Hop.OpOp2)

Example 38 with BinaryOp

use of org.apache.sysml.hops.BinaryOp in project incubator-systemml by apache.

the class RewriteElementwiseMultChainOptimization method rule_RewriteEMult.

private static Hop rule_RewriteEMult(final Hop root) {
    if (root.isVisited())
        return root;
    root.setVisited();
    // 1. Find immediate subtree of EMults. Check dimsKnown.
    if (isBinaryMult(root) && root.dimsKnown()) {
        final Hop left = root.getInput().get(0), right = root.getInput().get(1);
        // The set of BinaryOp element-wise multiply hops in the emult chain.
        final Set<BinaryOp> emults = new HashSet<>();
        // The multiset of multiplicands in the emult chain.
        // poor man's HashMultiset
        final Map<Hop, Integer> leaves = new HashMap<>();
        findEMultsAndLeaves((BinaryOp) root, emults, leaves);
        // Only optimize a subtree of emults if there are at least two emults (meaning, at least 3 multiplicands).
        if (emults.size() >= 2) {
            // 3. Check for foreign parents.
            // A foreign parent is a parent of some EMult that is not in the set.
            // Foreign parents destroy correctness of this rewrite.
            final boolean okay = (!isBinaryMult(left) || checkForeignParent(emults, (BinaryOp) left)) && (!isBinaryMult(right) || checkForeignParent(emults, (BinaryOp) right));
            if (okay) {
                // 4. Construct replacement EMults for the leaves
                final Hop replacement = constructReplacement(emults, leaves);
                if (LOG.isDebugEnabled())
                    LOG.debug(String.format("Element-wise multiply chain rewrite of %d e-mults at sub-dag %d to new sub-dag %d", emults.size(), root.getHopID(), replacement.getHopID()));
                // 5. Replace root with replacement
                final Hop newRoot = HopRewriteUtils.rewireAllParentChildReferences(root, replacement);
                // 6. Recurse at leaves (no need to repeat the interior emults)
                for (final Hop leaf : leaves.keySet()) {
                    recurseInputs(leaf);
                }
                return newRoot;
            }
        }
    }
    // This rewrite is not applicable to the current root.
    // Try the root's children.
    recurseInputs(root);
    return root;
}
Also used : HashMap(java.util.HashMap) Hop(org.apache.sysml.hops.Hop) BinaryOp(org.apache.sysml.hops.BinaryOp) HashSet(java.util.HashSet)

Example 39 with BinaryOp

use of org.apache.sysml.hops.BinaryOp in project incubator-systemml by apache.

the class RewriteForLoopVectorization method vectorizeScalarAggregate.

private static StatementBlock vectorizeScalarAggregate(StatementBlock sb, StatementBlock csb, Hop from, Hop to, Hop increment, String itervar) {
    StatementBlock ret = sb;
    // check missing and supported increment values
    if (!(increment != null && increment instanceof LiteralOp && ((LiteralOp) increment).getDoubleValue() == 1.0)) {
        return ret;
    }
    // check for applicability
    boolean leftScalar = false;
    boolean rightScalar = false;
    // row or col
    boolean rowIx = false;
    if (csb.getHops() != null && csb.getHops().size() == 1) {
        Hop root = csb.getHops().get(0);
        if (root.getDataType() == DataType.SCALAR && root.getInput().get(0) instanceof BinaryOp) {
            BinaryOp bop = (BinaryOp) root.getInput().get(0);
            Hop left = bop.getInput().get(0);
            Hop right = bop.getInput().get(1);
            // check for left scalar plus
            if (HopRewriteUtils.isValidOp(bop.getOp(), MAP_SCALAR_AGGREGATE_SOURCE_OPS) && left instanceof DataOp && left.getDataType() == DataType.SCALAR && root.getName().equals(left.getName()) && right instanceof UnaryOp && ((UnaryOp) right).getOp() == OpOp1.CAST_AS_SCALAR && right.getInput().get(0) instanceof IndexingOp) {
                IndexingOp ix = (IndexingOp) right.getInput().get(0);
                if (ix.isRowLowerEqualsUpper() && ix.getInput().get(1) instanceof DataOp && ix.getInput().get(1).getName().equals(itervar)) {
                    leftScalar = true;
                    rowIx = true;
                } else if (ix.isColLowerEqualsUpper() && ix.getInput().get(3) instanceof DataOp && ix.getInput().get(3).getName().equals(itervar)) {
                    leftScalar = true;
                    rowIx = false;
                }
            } else // check for right scalar plus
            if (HopRewriteUtils.isValidOp(bop.getOp(), MAP_SCALAR_AGGREGATE_SOURCE_OPS) && right instanceof DataOp && right.getDataType() == DataType.SCALAR && root.getName().equals(right.getName()) && left instanceof UnaryOp && ((UnaryOp) left).getOp() == OpOp1.CAST_AS_SCALAR && left.getInput().get(0) instanceof IndexingOp) {
                IndexingOp ix = (IndexingOp) left.getInput().get(0);
                if (ix.isRowLowerEqualsUpper() && ix.getInput().get(1) instanceof DataOp && ix.getInput().get(1).getName().equals(itervar)) {
                    rightScalar = true;
                    rowIx = true;
                } else if (ix.isColLowerEqualsUpper() && ix.getInput().get(3) instanceof DataOp && ix.getInput().get(3).getName().equals(itervar)) {
                    rightScalar = true;
                    rowIx = false;
                }
            }
        }
    }
    // apply rewrite if possible
    if (leftScalar || rightScalar) {
        Hop root = csb.getHops().get(0);
        BinaryOp bop = (BinaryOp) root.getInput().get(0);
        Hop cast = bop.getInput().get(leftScalar ? 1 : 0);
        Hop ix = cast.getInput().get(0);
        int aggOpPos = HopRewriteUtils.getValidOpPos(bop.getOp(), MAP_SCALAR_AGGREGATE_SOURCE_OPS);
        AggOp aggOp = MAP_SCALAR_AGGREGATE_TARGET_OPS[aggOpPos];
        // replace cast with sum
        AggUnaryOp newSum = HopRewriteUtils.createAggUnaryOp(ix, aggOp, Direction.RowCol);
        HopRewriteUtils.removeChildReference(cast, ix);
        HopRewriteUtils.removeChildReference(bop, cast);
        HopRewriteUtils.addChildReference(bop, newSum, leftScalar ? 1 : 0);
        // modify indexing expression according to loop predicate from-to
        // NOTE: any redundant index operations are removed via dynamic algebraic simplification rewrites
        int index1 = rowIx ? 1 : 3;
        int index2 = rowIx ? 2 : 4;
        HopRewriteUtils.replaceChildReference(ix, ix.getInput().get(index1), from, index1);
        HopRewriteUtils.replaceChildReference(ix, ix.getInput().get(index2), to, index2);
        // update indexing size information
        if (rowIx)
            ((IndexingOp) ix).setRowLowerEqualsUpper(false);
        else
            ((IndexingOp) ix).setColLowerEqualsUpper(false);
        ix.refreshSizeInformation();
        ret = csb;
        LOG.debug("Applied vectorizeScalarSumForLoop.");
    }
    return ret;
}
Also used : AggUnaryOp(org.apache.sysml.hops.AggUnaryOp) UnaryOp(org.apache.sysml.hops.UnaryOp) IndexingOp(org.apache.sysml.hops.IndexingOp) LeftIndexingOp(org.apache.sysml.hops.LeftIndexingOp) AggUnaryOp(org.apache.sysml.hops.AggUnaryOp) AggOp(org.apache.sysml.hops.Hop.AggOp) Hop(org.apache.sysml.hops.Hop) LiteralOp(org.apache.sysml.hops.LiteralOp) DataOp(org.apache.sysml.hops.DataOp) IfStatementBlock(org.apache.sysml.parser.IfStatementBlock) WhileStatementBlock(org.apache.sysml.parser.WhileStatementBlock) ForStatementBlock(org.apache.sysml.parser.ForStatementBlock) StatementBlock(org.apache.sysml.parser.StatementBlock) BinaryOp(org.apache.sysml.hops.BinaryOp)

Example 40 with BinaryOp

use of org.apache.sysml.hops.BinaryOp in project incubator-systemml by apache.

the class HopRewriteUtils method createBinary.

public static BinaryOp createBinary(Hop input1, Hop input2, OpOp2 op, boolean outer) {
    Hop mainInput = input1.getDataType().isMatrix() ? input1 : input2.getDataType().isMatrix() ? input2 : input1;
    BinaryOp bop = new BinaryOp(mainInput.getName(), mainInput.getDataType(), mainInput.getValueType(), op, input1, input2);
    // cleanup value type for relational operations
    if (bop.isPPredOperation() && bop.getDataType().isScalar())
        bop.setValueType(ValueType.BOOLEAN);
    bop.setOuterVectorOperation(outer);
    bop.setOutputBlocksizes(mainInput.getRowsInBlock(), mainInput.getColsInBlock());
    copyLineNumbers(mainInput, bop);
    bop.refreshSizeInformation();
    return bop;
}
Also used : Hop(org.apache.sysml.hops.Hop) AggBinaryOp(org.apache.sysml.hops.AggBinaryOp) BinaryOp(org.apache.sysml.hops.BinaryOp)

Aggregations

BinaryOp (org.apache.sysml.hops.BinaryOp)58 Hop (org.apache.sysml.hops.Hop)57 AggBinaryOp (org.apache.sysml.hops.AggBinaryOp)50 LiteralOp (org.apache.sysml.hops.LiteralOp)27 AggUnaryOp (org.apache.sysml.hops.AggUnaryOp)23 UnaryOp (org.apache.sysml.hops.UnaryOp)18 OpOp2 (org.apache.sysml.hops.Hop.OpOp2)9 IndexingOp (org.apache.sysml.hops.IndexingOp)6 ReorgOp (org.apache.sysml.hops.ReorgOp)6 TernaryOp (org.apache.sysml.hops.TernaryOp)6 ArrayList (java.util.ArrayList)5 DataOp (org.apache.sysml.hops.DataOp)5 ParameterizedBuiltinOp (org.apache.sysml.hops.ParameterizedBuiltinOp)5 QuaternaryOp (org.apache.sysml.hops.QuaternaryOp)5 DataGenOp (org.apache.sysml.hops.DataGenOp)4 HashMap (java.util.HashMap)3 LeftIndexingOp (org.apache.sysml.hops.LeftIndexingOp)3 CNode (org.apache.sysml.hops.codegen.cplan.CNode)3 CNodeBinary (org.apache.sysml.hops.codegen.cplan.CNodeBinary)3 CNodeData (org.apache.sysml.hops.codegen.cplan.CNodeData)3