{"action":"created","comment":{"url":"https://api.github.com/repos/apache/systemml/pulls/comments/171999838","pull_request_review_id":100953339,"id":171999838,"diff_hunk":"@@ -19,1749 +19,1718 @@\n \n package org.apache.sysml.parser;\n \n-import java.util.ArrayList;\n-import java.util.HashMap;\n-import java.util.HashSet;\n-\n import org.antlr.v4.runtime.ParserRuleContext;\n import org.apache.sysml.parser.LanguageException.LanguageErrorCodes;\n import org.apache.sysml.runtime.util.ConvolutionUtils;\n import org.apache.sysml.runtime.util.UtilFunctions;\n \n-public class BuiltinFunctionExpression extends DataIdentifier \n-{\n-\tprotected Expression[] \t  _args = null;\n-\tprivate BuiltinFunctionOp _opcode;\n-\n-\tpublic BuiltinFunctionExpression(ParserRuleContext ctx, BuiltinFunctionOp bifop, ArrayList<ParameterExpression> args, String fname) {\n-\t\t_opcode = bifop;\n-\t\tsetCtxValuesAndFilename(ctx, fname);\n-\t\targs = expandConvolutionArguments(args);\n-\t\t_args = new Expression[args.size()];\n-\t\tfor(int i=0; i < args.size(); i++) {\n-\t\t\t_args[i] = args.get(i).getExpr();\n-\t\t}\n-\t}\n-\n-\tpublic BuiltinFunctionExpression(BuiltinFunctionOp bifop, Expression[] args, ParseInfo parseInfo) {\n-\t\t_opcode = bifop;\n-\t\t_args = new Expression[args.length];\n-\t\tfor (int i = 0; i < args.length; i++) {\n-\t\t\t_args[i] = args[i];\n-\t\t}\n-\t\tsetParseInfo(parseInfo);\n-\t}\n-\n-\tpublic BuiltinFunctionExpression(ParserRuleContext ctx, BuiltinFunctionOp bifop, Expression[] args, String fname) {\n-\t\t_opcode = bifop;\n-\t\t_args = new Expression[args.length];\n-\t\tfor(int i=0; i < args.length; i++) {\n-\t\t\t_args[i] = args[i];\n-\t\t}\n-\t\tsetCtxValuesAndFilename(ctx, fname);\n-\t}\n-\n-\t@Override\n-\tpublic Expression rewriteExpression(String prefix) throws LanguageException {\n-\t\tExpression[] newArgs = new Expression[_args.length];\n-\t\tfor (int i = 0; i < _args.length; i++) {\n-\t\t\tnewArgs[i] = _args[i].rewriteExpression(prefix);\n-\t\t}\n-\t\tBuiltinFunctionExpression retVal = new BuiltinFunctionExpression(this._opcode, newArgs, this);\n-\t\treturn retVal;\n-\t}\n-\n-\tpublic BuiltinFunctionOp getOpCode() {\n-\t\treturn _opcode;\n-\t}\n-\n-\tpublic Expression getFirstExpr() {\n-\t\treturn (_args.length >= 1 ? _args[0] : null);\n-\t}\n-\n-\tpublic Expression getSecondExpr() {\n-\t\treturn (_args.length >= 2 ? _args[1] : null);\n-\t}\n-\n-\tpublic Expression getThirdExpr() {\n-\t\treturn (_args.length >= 3 ? _args[2] : null);\n-\t}\n-\n-\tpublic Expression[] getAllExpr(){\n-\t\treturn _args;\n-\t}\n-\t\n-\tpublic Expression getExpr(int i) {\n-\t\treturn (_args.length > i ? _args[i] : null);\t\n-\t}\n-\t\n-\t@Override\n-\tpublic void validateExpression(MultiAssignmentStatement stmt, HashMap<String, DataIdentifier> ids, HashMap<String, ConstIdentifier> constVars, boolean conditional)\n-\t\t\tthrows LanguageException \n-\t{\n-\t\tif (this.getFirstExpr() instanceof FunctionCallIdentifier){\n-\t\t\traiseValidateError(\"UDF function call not supported as parameter to built-in function call\", false);\n-\t\t}\n-\t\t\n-\t\tthis.getFirstExpr().validateExpression(ids, constVars, conditional);\n-\t\tif (getSecondExpr() != null){\n-\t\t\tif (this.getSecondExpr() instanceof FunctionCallIdentifier){\n-\t\t\t\traiseValidateError(\"UDF function call not supported as parameter to built-in function call\", false);\n-\t\t\t}\n-\t\t\tgetSecondExpr().validateExpression(ids, constVars, conditional);\n-\t\t}\n-\t\tif (getThirdExpr() != null) {\n-\t\t\tif (this.getThirdExpr() instanceof FunctionCallIdentifier){\n-\t\t\t\traiseValidateError(\"UDF function call not supported as parameter to built-in function call\", false);\n-\t\t\t}\n-\t\t\tgetThirdExpr().validateExpression(ids, constVars, conditional);\n-\t\t}\n-\t\t_outputs = new Identifier[stmt.getTargetList().size()];\n-\t\tint count = 0;\n-\t\tfor (DataIdentifier outParam: stmt.getTargetList()){\n-\t\t\tDataIdentifier tmp = new DataIdentifier(outParam);\n-\t\t\ttmp.setParseInfo(this);\n-\t\t\t_outputs[count++] = tmp;\n-\t\t}\n-\t\t\n-\t\tswitch (_opcode) {\n-\t\tcase QR:\n-\t\t\tcheckNumParameters(1);\n-\t\t\tcheckMatrixParam(getFirstExpr());\n-\t\t\t\n-\t\t\t// setup output properties\n-\t\t\tDataIdentifier qrOut1 = (DataIdentifier) getOutputs()[0];\n-\t\t\tDataIdentifier qrOut2 = (DataIdentifier) getOutputs()[1];\n-\t\t\t\n-\t\t\tlong rows = getFirstExpr().getOutput().getDim1();\n-\t\t\tlong cols = getFirstExpr().getOutput().getDim2();\n-\t\t\t\n-\t\t\t// Output1 - Q\n-\t\t\tqrOut1.setDataType(DataType.MATRIX);\n-\t\t\tqrOut1.setValueType(ValueType.DOUBLE);\n-\t\t\tqrOut1.setDimensions(rows, cols);\n-\t\t\tqrOut1.setBlockDimensions(getFirstExpr().getOutput().getRowsInBlock(), getFirstExpr().getOutput().getColumnsInBlock());\n-\t\t\t\n-\t\t\t// Output2 - R\n-\t\t\tqrOut2.setDataType(DataType.MATRIX);\n-\t\t\tqrOut2.setValueType(ValueType.DOUBLE);\n-\t\t\tqrOut2.setDimensions(rows, cols);\n-\t\t\tqrOut2.setBlockDimensions(getFirstExpr().getOutput().getRowsInBlock(), getFirstExpr().getOutput().getColumnsInBlock());\n-\t\t\t\n-\t\t\tbreak;\n-\n-\t\tcase LU:\n-\t\t\tcheckNumParameters(1);\n-\t\t\tcheckMatrixParam(getFirstExpr());\n-\t\t\t\n-\t\t\t// setup output properties\n-\t\t\tDataIdentifier luOut1 = (DataIdentifier) getOutputs()[0];\n-\t\t\tDataIdentifier luOut2 = (DataIdentifier) getOutputs()[1];\n-\t\t\tDataIdentifier luOut3 = (DataIdentifier) getOutputs()[2];\n-\t\t\t\n-\t\t\tlong inrows = getFirstExpr().getOutput().getDim1();\n-\t\t\tlong incols = getFirstExpr().getOutput().getDim2();\n-\n-\t\t\tif (inrows != incols) {\n-\t\t\t\traiseValidateError(\"LU Decomposition requires a square matrix. Matrix \" + getFirstExpr() + \" is \"\n-\t\t\t\t\t\t+ inrows + \"x\" + incols + \".\", conditional);\n-\t\t\t}\n-\n-\t\t\t// Output1 - P\n-\t\t\tluOut1.setDataType(DataType.MATRIX);\n-\t\t\tluOut1.setValueType(ValueType.DOUBLE);\n-\t\t\tluOut1.setDimensions(inrows, inrows);\n-\t\t\tluOut1.setBlockDimensions(getFirstExpr().getOutput().getRowsInBlock(), getFirstExpr().getOutput().getColumnsInBlock());\n-\t\t\t\n-\t\t\t// Output2 - L\n-\t\t\tluOut2.setDataType(DataType.MATRIX);\n-\t\t\tluOut2.setValueType(ValueType.DOUBLE);\n-\t\t\tluOut2.setDimensions(inrows, inrows);\n-\t\t\tluOut2.setBlockDimensions(getFirstExpr().getOutput().getRowsInBlock(), getFirstExpr().getOutput().getColumnsInBlock());\n-\t\t\t\n-\t\t\t// Output3 - U\n-\t\t\tluOut3.setDataType(DataType.MATRIX);\n-\t\t\tluOut3.setValueType(ValueType.DOUBLE);\n-\t\t\tluOut3.setDimensions(inrows, inrows);\n-\t\t\tluOut3.setBlockDimensions(getFirstExpr().getOutput().getRowsInBlock(), getFirstExpr().getOutput().getColumnsInBlock());\n-\t\t\t\n-\t\t\tbreak;\n-\n-\t\tcase EIGEN:\n-\t\t\tcheckNumParameters(1);\n-\t\t\tcheckMatrixParam(getFirstExpr());\n-\t\t\t\n-\t\t\t// setup output properties\n-\t\t\tDataIdentifier eigenOut1 = (DataIdentifier) getOutputs()[0];\n-\t\t\tDataIdentifier eigenOut2 = (DataIdentifier) getOutputs()[1];\n-\t\t\t\n-\t\t\tif ( getFirstExpr().getOutput().getDim1() != getFirstExpr().getOutput().getDim2() ) {\n-\t\t\t\traiseValidateError(\"Eigen Decomposition can only be done on a square matrix. Input matrix is rectangular (rows=\" + getFirstExpr().getOutput().getDim1() + \", cols=\"+ getFirstExpr().getOutput().getDim2() +\")\", conditional);\n-\t\t\t}\n-\t\t\t\n-\t\t\t// Output1 - Eigen Values\n-\t\t\teigenOut1.setDataType(DataType.MATRIX);\n-\t\t\teigenOut1.setValueType(ValueType.DOUBLE);\n-\t\t\teigenOut1.setDimensions(getFirstExpr().getOutput().getDim1(), 1);\n-\t\t\teigenOut1.setBlockDimensions(getFirstExpr().getOutput().getRowsInBlock(), getFirstExpr().getOutput().getColumnsInBlock());\n-\t\t\t\n-\t\t\t// Output2 - Eigen Vectors\n-\t\t\teigenOut2.setDataType(DataType.MATRIX);\n-\t\t\teigenOut2.setValueType(ValueType.DOUBLE);\n-\t\t\teigenOut2.setDimensions(getFirstExpr().getOutput().getDim1(), getFirstExpr().getOutput().getDim2());\n-\t\t\teigenOut2.setBlockDimensions(getFirstExpr().getOutput().getRowsInBlock(), getFirstExpr().getOutput().getColumnsInBlock());\n-\t\t\t\n-\t\t\tbreak;\n-\n-\t\tcase SVD:\n-\t\t\tcheckNumParameters(1);\n-\t\t\tcheckMatrixParam(getFirstExpr());\n-\t\t\t\n-\t\t\tlong minMN = Math.min(getFirstExpr().getOutput().getDim1(), getFirstExpr().getOutput().getDim2());\n-\n-\t\t\t// setup output properties\n-\t\t\tDataIdentifier svdOut1 = (DataIdentifier) getOutputs()[0];\n-\t\t\tDataIdentifier svdOut2 = (DataIdentifier) getOutputs()[1];\n-\t\t\tDataIdentifier svdOut3 = (DataIdentifier) getOutputs()[2];\n-\n-\t\t\t// Output 1\n-\t\t\tsvdOut1.setDataType(DataType.MATRIX);\n-\t\t\tsvdOut1.setValueType(ValueType.DOUBLE);\n-\t\t\tsvdOut1.setDimensions(getFirstExpr().getOutput().getDim1(), minMN);\n-\t\t\tsvdOut1.setBlockDimensions(getFirstExpr().getOutput().getRowsInBlock(), getFirstExpr().getOutput().getColumnsInBlock());\n-\n-\t\t\t// Output 2\n-\t\t\tsvdOut2.setDataType(DataType.MATRIX);\n-\t\t\tsvdOut2.setValueType(ValueType.DOUBLE);\n-\t\t\tsvdOut2.setDimensions(minMN, minMN);\n-\t\t\tsvdOut2.setBlockDimensions(getFirstExpr().getOutput().getRowsInBlock(), getFirstExpr().getOutput().getColumnsInBlock());\n-\n-\t\t\t// Output 3\n-\t\t\tsvdOut3.setDataType(DataType.MATRIX);\n-\t\t\tsvdOut3.setValueType(ValueType.DOUBLE);\n-\t\t\tsvdOut3.setDimensions(getFirstExpr().getOutput().getDim2(), minMN);\n-\t\t\tsvdOut3.setBlockDimensions(getFirstExpr().getOutput().getRowsInBlock(), getFirstExpr().getOutput().getColumnsInBlock());\n-\n-\t\t\tbreak;\n-\t\t\n-\t\tdefault: //always unconditional\n-\t\t\traiseValidateError(\"Unknown Builtin Function opcode: \" + _opcode, false);\n-\t\t}\n-\t}\n-\t\n-\tprivate static ArrayList<ParameterExpression> orderConvolutionParams(ArrayList<ParameterExpression> paramExpression, \n-\t\t\tint skip) throws LanguageException {\n-\t\tArrayList<ParameterExpression> newParams = new ArrayList<>();\n-\n-\t\tfor(int i = 0; i < skip; i++)\n-\t\t\tnewParams.add(paramExpression.get(i));\n-\n-\t\tString [] orderedParams = {\n-\t\t\t\t\"stride1\", \"stride2\", \"padding1\", \"padding2\",  \n-\t\t\t\t\"input_shape1\", \"input_shape2\", \"input_shape3\", \"input_shape4\", \n-\t\t\t\t\"filter_shape1\", \"filter_shape2\", \"filter_shape3\", \"filter_shape4\"\t\n-\t\t};\n-\t\tfor(int i = 0; i < orderedParams.length; i++) {\n-\t\t\tboolean found = false;\n-\t\t\tfor(ParameterExpression param : paramExpression) {\n-\t\t\t\tif(param.getName() != null &&  param.getName().equals(orderedParams[i])) {\n-\t\t\t\t\tfound = true;\n-\t\t\t\t\tnewParams.add(param);\n-\t\t\t\t}\n-\t\t\t}\n-\t\t\tif(!found) {\n-\t\t\t\tthrow new LanguageException(\"Incorrect parameters. Expected \" + orderedParams[i] + \" to be expanded.\");\n-\t\t\t}\n-\t\t}\n-\n-\t\treturn newParams;\n-\t}\n-\n-\tprivate static ArrayList<ParameterExpression> replaceListParams(ArrayList<ParameterExpression> paramExpression,\n-\t\t\tString inputVarName, String outputVarName, int startIndex) throws LanguageException {\n-\t\tArrayList<ParameterExpression> newParamExpression = new ArrayList<>();\n-\t\tint i = startIndex;\n-\t\tint j = 1; // Assumption: sequential ordering pool_size1, pool_size2 \n-\t\tfor (ParameterExpression expr : paramExpression) {\n-\t\t\tif(expr.getName() != null && expr.getName().equals(inputVarName + j)) {\n-\t\t\t\tnewParamExpression.add(new ParameterExpression(outputVarName + i, expr.getExpr()));\n-\t\t\t\ti++; j++;\n-\t\t\t}\n-\t\t\telse {\n-\t\t\t\tnewParamExpression.add(expr);\n-\t\t\t}\n-\t\t}\n-\t\treturn newParamExpression;\n-\t}\n-\n-\tprivate static ArrayList<ParameterExpression> expandListParams(ArrayList<ParameterExpression> paramExpression, \n-\t\t\tHashSet<String> paramsToExpand) throws LanguageException {\n-\t\tArrayList<ParameterExpression> newParamExpressions = new ArrayList<>();\n-\t\tfor(ParameterExpression expr : paramExpression) {\n-\t\t\tif(paramsToExpand.contains(expr.getName())) {\n-\t\t\t\tif(expr.getExpr() instanceof ExpressionList) {\n-\t\t\t\t\tint i = 1;\n-\t\t\t\t\tfor(Expression e : ((ExpressionList)expr.getExpr()).getValue()) {\n-\t\t\t\t\t\tnewParamExpressions.add(new ParameterExpression(expr.getName() + i, e));\n-\t\t\t\t\t\ti++;\n-\t\t\t\t\t}\n-\t\t\t\t}\n-\t\t\t}\n-\t\t\telse if(expr.getExpr() instanceof ExpressionList) {\n-\t\t\t\tthrow new LanguageException(\"The parameter \" + expr.getName() + \" cannot be list or is not supported for the given function\");\n-\t\t\t}\n-\t\t\telse {\n-\t\t\t\tnewParamExpressions.add(expr);\n-\t\t\t}\n-\t\t}\n-\t\treturn newParamExpressions;\n-\t}\n-\t\n-\tprivate ArrayList<ParameterExpression> expandConvolutionArguments(ArrayList<ParameterExpression> paramExpression) {\n-\t\ttry {\n-\t\t\tif(_opcode == BuiltinFunctionOp.CONV2D || _opcode == BuiltinFunctionOp.CONV2D_BACKWARD_FILTER \n-\t\t\t\t\t|| _opcode == BuiltinFunctionOp.CONV2D_BACKWARD_DATA) {\n-\t\t\t\tHashSet<String> expand = new HashSet<>();\n-\t\t\t\texpand.add(\"input_shape\"); expand.add(\"filter_shape\"); expand.add(\"stride\"); expand.add(\"padding\");\n-\t\t\t\tparamExpression = expandListParams(paramExpression, expand);\n-\t\t\t\tparamExpression = orderConvolutionParams(paramExpression, 2);\n-\t\t\t}\n-\t\t\telse if(_opcode == BuiltinFunctionOp.MAX_POOL || \n-\t\t\t\t\t_opcode == BuiltinFunctionOp.MAX_POOL_BACKWARD) {\n-\t\t\t\tHashSet<String> expand = new HashSet<>();\n-\t\t\t\texpand.add(\"input_shape\"); expand.add(\"pool_size\"); expand.add(\"stride\"); expand.add(\"padding\");\n-\t\t\t\tparamExpression = expandListParams(paramExpression, expand);\n-\t\t\t\tparamExpression.add(new ParameterExpression(\"filter_shape1\", new IntIdentifier(1, this)));\n-\t\t\t\tparamExpression.add(new ParameterExpression(\"filter_shape2\", new IntIdentifier(1, this)));\n-\t\t\t\tparamExpression = replaceListParams(paramExpression, \"pool_size\", \"filter_shape\", 3);\n-\t\t\t\tif(_opcode == BuiltinFunctionOp.MAX_POOL_BACKWARD)\n-\t\t\t\t\tparamExpression = orderConvolutionParams(paramExpression, 2);\n-\t\t\t\telse\n-\t\t\t\t\tparamExpression = orderConvolutionParams(paramExpression, 1);\n-\t\t\t}\n-\t\t}\n-\t\tcatch(LanguageException e) {\n-\t\t\tthrow new RuntimeException(e);\n-\t\t}\n-\t\treturn paramExpression;\n-\t}\n-\n-\t/**\n-\t * Validate parse tree : Process BuiltinFunction Expression in an assignment\n-\t * statement\n-\t * \n-\t * @throws LanguageException if LanguageException occurs\n-\t */\n-\t@Override\n-\tpublic void validateExpression(HashMap<String, DataIdentifier> ids, HashMap<String, ConstIdentifier> constVars, boolean conditional)\n-\t\t\tthrows LanguageException {\n-\t\t\n-\t\tfor(int i=0; i < _args.length; i++ ) {\n-\t\t\t\n-\t\t\tif (_args[i] instanceof FunctionCallIdentifier){\n-\t\t\t\traiseValidateError(\"UDF function call not supported as parameter to built-in function call\", false);\n-\t\t\t}\n-\t\t\t\n-\t\t\t_args[i].validateExpression(ids, constVars, conditional);\n-\t\t}\n-\t\t\n-\t\t// checkIdentifierParams();\n-\t\tString outputName = getTempName();\n-\t\tDataIdentifier output = new DataIdentifier(outputName);\n-\t\toutput.setParseInfo(this);\n-\t\t\n-\t\tif (this.getFirstExpr() == null) {\n-\t\t\traiseValidateError(\"Function \" + this + \" has no arguments.\", false);\n-\t\t}\n-\t\tIdentifier id = this.getFirstExpr().getOutput();\n-\t\toutput.setProperties(this.getFirstExpr().getOutput());\n-\t\toutput.setNnz(-1); //conservatively, cannot use input nnz!\n-\t\tthis.setOutput(output);\n-\t\t\n-\t\tswitch (this.getOpCode()) {\n-\t\tcase COLSUM:\n-\t\tcase COLMAX:\n-\t\tcase COLMIN:\n-\t\tcase COLMEAN:\n-\t\tcase COLSD:\n-\t\tcase COLVAR:\n-\t\t\t// colSums(X);\n-\t\t\tcheckNumParameters(1);\n-\t\t\tcheckMatrixParam(getFirstExpr());\n-\t\t\toutput.setDataType(DataType.MATRIX);\n-\t\t\toutput.setDimensions(1, id.getDim2());\n-\t\t\toutput.setBlockDimensions (id.getRowsInBlock(), id.getColumnsInBlock());\n-\t\t\toutput.setValueType(id.getValueType());\n-\t\t\tbreak;\n-\t\tcase ROWSUM:\n-\t\tcase ROWMAX:\n-\t\tcase ROWINDEXMAX:\n-\t\tcase ROWMIN:\n-\t\tcase ROWINDEXMIN:\n-\t\tcase ROWMEAN:\n-\t\tcase ROWSD:\n-\t\tcase ROWVAR:\n-\t\t\t//rowSums(X);\n-\t\t\tcheckNumParameters(1);\n-\t\t\tcheckMatrixParam(getFirstExpr());\n-\t\t\toutput.setDataType(DataType.MATRIX);\n-\t\t\toutput.setDimensions(id.getDim1(), 1);\n-\t\t\toutput.setBlockDimensions (id.getRowsInBlock(), id.getColumnsInBlock());\n-\t\t\toutput.setValueType(id.getValueType());\n-\t\t\tbreak;\n-\t\tcase SUM:\n-\t\tcase PROD:\n-\t\tcase TRACE:\n-\t\tcase SD:\n-\t\tcase VAR:\n-\t\t\t// sum(X);\n-\t\t\tcheckNumParameters(1);\n-\t\t\tcheckMatrixParam(getFirstExpr());\n-\t\t\t\n-\t\t\toutput.setDataType(DataType.SCALAR);\n-\t\t\toutput.setDimensions(0, 0);\n-\t\t\toutput.setBlockDimensions (0, 0);\n-\t\t\toutput.setValueType(id.getValueType());\n-\t\t\t\n-\t\t\tbreak;\n-\t\t\n-\t\tcase MEAN:\n-\t\t\t//checkNumParameters(2, false); // mean(Y) or mean(Y,W)\n-            if (getSecondExpr() != null) {\n-            \tcheckNumParameters (2);\n+import java.util.ArrayList;\n+import java.util.HashMap;\n+import java.util.HashSet;\n+\n+public class BuiltinFunctionExpression extends DataIdentifier {\n+    protected Expression[] _args = null;\n+    private BuiltinFunctionOp _opcode;\n+\n+    public BuiltinFunctionExpression(ParserRuleContext ctx, BuiltinFunctionOp bifop, ArrayList<ParameterExpression> args, String fname) {\n+        _opcode = bifop;\n+        setCtxValuesAndFilename(ctx, fname);\n+        args = expandConvolutionArguments(args);\n+        _args = new Expression[args.size()];\n+        for (int i = 0; i < args.size(); i++) {\n+            _args[i] = args.get(i).getExpr();\n+        }\n+    }\n+\n+    public BuiltinFunctionExpression(BuiltinFunctionOp bifop, Expression[] args, ParseInfo parseInfo) {\n+        _opcode = bifop;\n+        _args = new Expression[args.length];\n+        for (int i = 0; i < args.length; i++) {\n+            _args[i] = args[i];\n+        }\n+        setParseInfo(parseInfo);\n+    }\n+\n+    public BuiltinFunctionExpression(ParserRuleContext ctx, BuiltinFunctionOp bifop, Expression[] args, String fname) {\n+        _opcode = bifop;\n+        _args = new Expression[args.length];\n+        for (int i = 0; i < args.length; i++) {\n+            _args[i] = args[i];\n+        }\n+        setCtxValuesAndFilename(ctx, fname);\n+    }\n+\n+    @Override\n+    public Expression rewriteExpression(String prefix) throws LanguageException {\n+        Expression[] newArgs = new Expression[_args.length];\n+        for (int i = 0; i < _args.length; i++) {\n+            newArgs[i] = _args[i].rewriteExpression(prefix);\n+        }\n+        BuiltinFunctionExpression retVal = new BuiltinFunctionExpression(this._opcode, newArgs, this);\n+        return retVal;\n+    }\n+\n+    public BuiltinFunctionOp getOpCode() {\n+        return _opcode;\n+    }\n+\n+    public Expression getFirstExpr() {\n+        return (_args.length >= 1 ? _args[0] : null);\n+    }\n+\n+    public Expression getSecondExpr() {\n+        return (_args.length >= 2 ? _args[1] : null);\n+    }\n+\n+    public Expression getThirdExpr() {\n+        return (_args.length >= 3 ? _args[2] : null);\n+    }\n+\n+    public Expression[] getAllExpr() {\n+        return _args;\n+    }\n+\n+    public Expression getExpr(int i) {\n+        return (_args.length > i ? _args[i] : null);\n+    }\n+\n+    @Override\n+    public void validateExpression(MultiAssignmentStatement stmt, HashMap<String, DataIdentifier> ids, HashMap<String, ConstIdentifier> constVars, boolean conditional)\n+            throws LanguageException {\n+        if (this.getFirstExpr() instanceof FunctionCallIdentifier) {\n+            raiseValidateError(\"UDF function call not supported as parameter to built-in function call\", false);\n+        }\n+\n+        this.getFirstExpr().validateExpression(ids, constVars, conditional);\n+        if (getSecondExpr() != null) {\n+            if (this.getSecondExpr() instanceof FunctionCallIdentifier) {\n+                raiseValidateError(\"UDF function call not supported as parameter to built-in function call\", false);\n+            }\n+            getSecondExpr().validateExpression(ids, constVars, conditional);\n+        }\n+        if (getThirdExpr() != null) {\n+            if (this.getThirdExpr() instanceof FunctionCallIdentifier) {\n+                raiseValidateError(\"UDF function call not supported as parameter to built-in function call\", false);\n+            }\n+            getThirdExpr().validateExpression(ids, constVars, conditional);\n+        }\n+        _outputs = new Identifier[stmt.getTargetList().size()];\n+        int count = 0;\n+        for (DataIdentifier outParam : stmt.getTargetList()) {\n+            DataIdentifier tmp = new DataIdentifier(outParam);\n+            tmp.setParseInfo(this);\n+            _outputs[count++] = tmp;\n+        }\n+\n+        switch (_opcode) {\n+            case QR:\n+                checkNumParameters(1);\n+                checkMatrixParam(getFirstExpr());\n+\n+                // setup output properties\n+                DataIdentifier qrOut1 = (DataIdentifier) getOutputs()[0];\n+                DataIdentifier qrOut2 = (DataIdentifier) getOutputs()[1];\n+\n+                long rows = getFirstExpr().getOutput().getDim1();\n+                long cols = getFirstExpr().getOutput().getDim2();\n+\n+                // Output1 - Q\n+                qrOut1.setDataType(DataType.MATRIX);\n+                qrOut1.setValueType(ValueType.DOUBLE);\n+                qrOut1.setDimensions(rows, cols);\n+                qrOut1.setBlockDimensions(getFirstExpr().getOutput().getRowsInBlock(), getFirstExpr().getOutput().getColumnsInBlock());\n+\n+                // Output2 - R\n+                qrOut2.setDataType(DataType.MATRIX);\n+                qrOut2.setValueType(ValueType.DOUBLE);\n+                qrOut2.setDimensions(rows, cols);\n+                qrOut2.setBlockDimensions(getFirstExpr().getOutput().getRowsInBlock(), getFirstExpr().getOutput().getColumnsInBlock());\n+\n+                break;\n+\n+            case LU:\n+                checkNumParameters(1);\n+                checkMatrixParam(getFirstExpr());\n+\n+                // setup output properties\n+                DataIdentifier luOut1 = (DataIdentifier) getOutputs()[0];\n+                DataIdentifier luOut2 = (DataIdentifier) getOutputs()[1];\n+                DataIdentifier luOut3 = (DataIdentifier) getOutputs()[2];\n+\n+                long inrows = getFirstExpr().getOutput().getDim1();\n+                long incols = getFirstExpr().getOutput().getDim2();\n+\n+                if (inrows != incols) {\n+                    raiseValidateError(\"LU Decomposition requires a square matrix. Matrix \" + getFirstExpr() + \" is \"\n+                            + inrows + \"x\" + incols + \".\", conditional);\n+                }\n+\n+                // Output1 - P\n+                luOut1.setDataType(DataType.MATRIX);\n+                luOut1.setValueType(ValueType.DOUBLE);\n+                luOut1.setDimensions(inrows, inrows);\n+                luOut1.setBlockDimensions(getFirstExpr().getOutput().getRowsInBlock(), getFirstExpr().getOutput().getColumnsInBlock());\n+\n+                // Output2 - L\n+                luOut2.setDataType(DataType.MATRIX);\n+                luOut2.setValueType(ValueType.DOUBLE);\n+                luOut2.setDimensions(inrows, inrows);\n+                luOut2.setBlockDimensions(getFirstExpr().getOutput().getRowsInBlock(), getFirstExpr().getOutput().getColumnsInBlock());\n+\n+                // Output3 - U\n+                luOut3.setDataType(DataType.MATRIX);\n+                luOut3.setValueType(ValueType.DOUBLE);\n+                luOut3.setDimensions(inrows, inrows);\n+                luOut3.setBlockDimensions(getFirstExpr().getOutput().getRowsInBlock(), getFirstExpr().getOutput().getColumnsInBlock());\n+\n+                break;\n+\n+            case EIGEN:\n+                checkNumParameters(1);\n+                checkMatrixParam(getFirstExpr());\n+\n+                // setup output properties\n+                DataIdentifier eigenOut1 = (DataIdentifier) getOutputs()[0];\n+                DataIdentifier eigenOut2 = (DataIdentifier) getOutputs()[1];\n+\n+                if (getFirstExpr().getOutput().getDim1() != getFirstExpr().getOutput().getDim2()) {\n+                    raiseValidateError(\"Eigen Decomposition can only be done on a square matrix. Input matrix is rectangular (rows=\" + getFirstExpr().getOutput().getDim1() + \", cols=\" + getFirstExpr().getOutput().getDim2() + \")\", conditional);\n+                }\n+\n+                // Output1 - Eigen Values\n+                eigenOut1.setDataType(DataType.MATRIX);\n+                eigenOut1.setValueType(ValueType.DOUBLE);\n+                eigenOut1.setDimensions(getFirstExpr().getOutput().getDim1(), 1);\n+                eigenOut1.setBlockDimensions(getFirstExpr().getOutput().getRowsInBlock(), getFirstExpr().getOutput().getColumnsInBlock());\n+\n+                // Output2 - Eigen Vectors\n+                eigenOut2.setDataType(DataType.MATRIX);\n+                eigenOut2.setValueType(ValueType.DOUBLE);\n+                eigenOut2.setDimensions(getFirstExpr().getOutput().getDim1(), getFirstExpr().getOutput().getDim2());\n+                eigenOut2.setBlockDimensions(getFirstExpr().getOutput().getRowsInBlock(), getFirstExpr().getOutput().getColumnsInBlock());\n+\n+                break;\n+\n+            case SVD:\n+                checkNumParameters(1);\n+                checkMatrixParam(getFirstExpr());\n+\n+                long minMN = Math.min(getFirstExpr().getOutput().getDim1(), getFirstExpr().getOutput().getDim2());\n+\n+                // setup output properties\n+                DataIdentifier svdOut1 = (DataIdentifier) getOutputs()[0];\n+                DataIdentifier svdOut2 = (DataIdentifier) getOutputs()[1];\n+                DataIdentifier svdOut3 = (DataIdentifier) getOutputs()[2];\n+\n+                // Output 1\n+                svdOut1.setDataType(DataType.MATRIX);\n+                svdOut1.setValueType(ValueType.DOUBLE);\n+                svdOut1.setDimensions(getFirstExpr().getOutput().getDim1(), minMN);\n+                svdOut1.setBlockDimensions(getFirstExpr().getOutput().getRowsInBlock(), getFirstExpr().getOutput().getColumnsInBlock());\n+\n+                // Output 2\n+                svdOut2.setDataType(DataType.MATRIX);\n+                svdOut2.setValueType(ValueType.DOUBLE);\n+                svdOut2.setDimensions(minMN, minMN);\n+                svdOut2.setBlockDimensions(getFirstExpr().getOutput().getRowsInBlock(), getFirstExpr().getOutput().getColumnsInBlock());\n+\n+                // Output 3\n+                svdOut3.setDataType(DataType.MATRIX);\n+                svdOut3.setValueType(ValueType.DOUBLE);\n+                svdOut3.setDimensions(getFirstExpr().getOutput().getDim2(), minMN);\n+                svdOut3.setBlockDimensions(getFirstExpr().getOutput().getRowsInBlock(), getFirstExpr().getOutput().getColumnsInBlock());\n+\n+                break;\n+\n+            default: //always unconditional\n+                raiseValidateError(\"Unknown Builtin Function opcode: \" + _opcode, false);\n+        }\n+    }\n+\n+    private static ArrayList<ParameterExpression> orderConvolutionParams(ArrayList<ParameterExpression> paramExpression,\n+                                                                         int skip) throws LanguageException {\n+        ArrayList<ParameterExpression> newParams = new ArrayList<>();\n+\n+        for (int i = 0; i < skip; i++)\n+            newParams.add(paramExpression.get(i));\n+\n+        String[] orderedParams = {\n+                \"stride1\", \"stride2\", \"padding1\", \"padding2\",\n+                \"input_shape1\", \"input_shape2\", \"input_shape3\", \"input_shape4\",\n+                \"filter_shape1\", \"filter_shape2\", \"filter_shape3\", \"filter_shape4\"\n+        };\n+        for (int i = 0; i < orderedParams.length; i++) {\n+            boolean found = false;\n+            for (ParameterExpression param : paramExpression) {\n+                if (param.getName() != null && param.getName().equals(orderedParams[i])) {\n+                    found = true;\n+                    newParams.add(param);\n+                }\n+            }\n+            if (!found) {\n+                throw new LanguageException(\"Incorrect parameters. Expected \" + orderedParams[i] + \" to be expanded.\");\n+            }\n+        }\n+\n+        return newParams;\n+    }\n+\n+    private static ArrayList<ParameterExpression> replaceListParams(ArrayList<ParameterExpression> paramExpression,\n+                                                                    String inputVarName, String outputVarName, int startIndex) throws LanguageException {\n+        ArrayList<ParameterExpression> newParamExpression = new ArrayList<>();\n+        int i = startIndex;\n+        int j = 1; // Assumption: sequential ordering pool_size1, pool_size2\n+        for (ParameterExpression expr : paramExpression) {\n+            if (expr.getName() != null && expr.getName().equals(inputVarName + j)) {\n+                newParamExpression.add(new ParameterExpression(outputVarName + i, expr.getExpr()));\n+                i++;\n+                j++;\n+            } else {\n+                newParamExpression.add(expr);\n+            }\n+        }\n+        return newParamExpression;\n+    }\n+\n+    private static ArrayList<ParameterExpression> expandListParams(ArrayList<ParameterExpression> paramExpression,\n+                                                                   HashSet<String> paramsToExpand) throws LanguageException {\n+        ArrayList<ParameterExpression> newParamExpressions = new ArrayList<>();\n+        for (ParameterExpression expr : paramExpression) {\n+            if (paramsToExpand.contains(expr.getName())) {\n+                if (expr.getExpr() instanceof ExpressionList) {\n+                    int i = 1;\n+                    for (Expression e : ((ExpressionList) expr.getExpr()).getValue()) {\n+                        newParamExpressions.add(new ParameterExpression(expr.getName() + i, e));\n+                        i++;\n+                    }\n+                }\n+            } else if (expr.getExpr() instanceof ExpressionList) {\n+                throw new LanguageException(\"The parameter \" + expr.getName() + \" cannot be list or is not supported for the given function\");\n+            } else {\n+                newParamExpressions.add(expr);\n             }\n-            else {\n-            \tcheckNumParameters (1);\n+        }\n+        return newParamExpressions;\n+    }\n+\n+    private ArrayList<ParameterExpression> expandConvolutionArguments(ArrayList<ParameterExpression> paramExpression) {\n+        try {\n+            if (_opcode == BuiltinFunctionOp.CONV2D || _opcode == BuiltinFunctionOp.CONV2D_BACKWARD_FILTER\n+                    || _opcode == BuiltinFunctionOp.CONV2D_BACKWARD_DATA) {\n+                HashSet<String> expand = new HashSet<>();\n+                expand.add(\"input_shape\");\n+                expand.add(\"filter_shape\");\n+                expand.add(\"stride\");\n+                expand.add(\"padding\");\n+                paramExpression = expandListParams(paramExpression, expand);\n+                paramExpression = orderConvolutionParams(paramExpression, 2);\n+            } else if (_opcode == BuiltinFunctionOp.MAX_POOL ||\n+                    _opcode == BuiltinFunctionOp.MAX_POOL_BACKWARD) {\n+                HashSet<String> expand = new HashSet<>();\n+                expand.add(\"input_shape\");\n+                expand.add(\"pool_size\");\n+                expand.add(\"stride\");\n+                expand.add(\"padding\");\n+                paramExpression = expandListParams(paramExpression, expand);\n+                paramExpression.add(new ParameterExpression(\"filter_shape1\", new IntIdentifier(1, this)));\n+                paramExpression.add(new ParameterExpression(\"filter_shape2\", new IntIdentifier(1, this)));\n+                paramExpression = replaceListParams(paramExpression, \"pool_size\", \"filter_shape\", 3);\n+                if (_opcode == BuiltinFunctionOp.MAX_POOL_BACKWARD)\n+                    paramExpression = orderConvolutionParams(paramExpression, 2);\n+                else\n+                    paramExpression = orderConvolutionParams(paramExpression, 1);\n             }\n-\t\t\t\n-\t\t\tcheckMatrixParam(getFirstExpr());\n-\t\t\tif ( getSecondExpr() != null ) {\n-\t\t\t\t// x = mean(Y,W);\n-\t\t\t\tcheckMatchingDimensions(getFirstExpr(), getSecondExpr());\n-\t\t\t}\n-\t\t\t\n-\t\t\toutput.setDataType(DataType.SCALAR);\n-\t\t\toutput.setDimensions(0, 0);\n-\t\t\toutput.setBlockDimensions (0, 0);\n-\t\t\toutput.setValueType(id.getValueType());\n-\t\t\tbreak;\n-\t\t\t\n-\t\tcase MIN:\n-\t\tcase MAX:\n-\t\t\t//min(X), min(X,s), min(s,X), min(s,r), min(X,Y)\n-\t\t\t\n-\t\t\t//unary aggregate\n-\t\t\tif (getSecondExpr() == null) {\n-\t\t\t\tcheckNumParameters(1);\n-\t\t\t\tcheckMatrixParam(getFirstExpr());\n-\t\t\t\toutput.setDataType(DataType.SCALAR);\n-\t\t\t\toutput.setValueType(id.getValueType());\n-\t\t\t\toutput.setDimensions(0, 0);\n-\t\t\t\toutput.setBlockDimensions (0, 0);\n-\t\t\t}\n-\t\t\t//binary operation\n-\t\t\telse {\n-\t\t\t\tcheckNumParameters(2);\n-\t\t\t\tsetBinaryOutputProperties(output);\n-\t\t\t}\n-\t\t\t\n-\t\t\tbreak;\n-\t\t\n-\t\tcase CUMSUM:\n-\t\tcase CUMPROD:\n-\t\tcase CUMMIN:\n-\t\tcase CUMMAX:\n-\t\t\t// cumsum(X);\n-\t\t\tcheckNumParameters(1);\n-\t\t\tcheckMatrixParam(getFirstExpr());\n-\t\t\t\n-\t\t\toutput.setDataType(DataType.MATRIX);\n-\t\t\toutput.setDimensions(id.getDim1(), id.getDim2());\n-\t\t\toutput.setBlockDimensions (id.getRowsInBlock(), id.getColumnsInBlock());\n-\t\t\toutput.setValueType(id.getValueType());\n-\t\t\t\n-\t\t\tbreak;\n-\t\t\t\n-\t\tcase CAST_AS_SCALAR:\n-\t\t\tcheckNumParameters(1);\n-\t\t\tcheckMatrixFrameParam(getFirstExpr());\n-\t\t\tif (( getFirstExpr().getOutput().getDim1() != -1 && getFirstExpr().getOutput().getDim1() !=1) || ( getFirstExpr().getOutput().getDim2() != -1 && getFirstExpr().getOutput().getDim2() !=1)) {\n-\t\t\t\traiseValidateError(\"dimension mismatch while casting matrix to scalar: dim1: \" + getFirstExpr().getOutput().getDim1() +  \" dim2 \" + getFirstExpr().getOutput().getDim2(), \n-\t\t\t\t          conditional, LanguageErrorCodes.INVALID_PARAMETERS);\n-\t\t\t}\n-\t\t\toutput.setDataType(DataType.SCALAR);\n-\t\t\toutput.setDimensions(0, 0);\n-\t\t\toutput.setBlockDimensions (0, 0);\n-\t\t\toutput.setValueType(id.getValueType());\n-\t\t\tbreak;\n-\t\tcase CAST_AS_MATRIX:\n-\t\t\tcheckNumParameters(1);\n-\t\t\tcheckScalarFrameParam(getFirstExpr());\n-\t\t\toutput.setDataType(DataType.MATRIX);\n-\t\t\toutput.setDimensions(id.getDim1(), id.getDim2());\n-\t\t\tif( getFirstExpr().getOutput().getDataType()==DataType.SCALAR )\n-\t\t\t\toutput.setDimensions(1, 1); //correction scalars\n-\t\t\toutput.setBlockDimensions(id.getRowsInBlock(), id.getColumnsInBlock());\n-\t\t\toutput.setValueType(ValueType.DOUBLE); //matrices always in double\n-\t\t\tbreak;\n-\t\tcase CAST_AS_FRAME:\n-\t\t\tcheckNumParameters(1);\n-\t\t\tcheckMatrixScalarParam(getFirstExpr());\n-\t\t\toutput.setDataType(DataType.FRAME);\n-\t\t\toutput.setDimensions(id.getDim1(), id.getDim2());\n-\t\t\tif( getFirstExpr().getOutput().getDataType()==DataType.SCALAR )\n-\t\t\t\toutput.setDimensions(1, 1); //correction scalars\n-\t\t\toutput.setBlockDimensions(id.getRowsInBlock(), id.getColumnsInBlock());\n-\t\t\toutput.setValueType(id.getValueType());\n-\t\t\tbreak;\n-\t\tcase CAST_AS_DOUBLE:\n-\t\t\tcheckNumParameters(1);\n-\t\t\tcheckScalarParam(getFirstExpr());\n-\t\t\toutput.setDataType(DataType.SCALAR);\n-\t\t\t//output.setDataType(id.getDataType()); //TODO whenever we support multiple matrix value types, currently noop.\n-\t\t\toutput.setDimensions(0, 0);\n-\t\t\toutput.setBlockDimensions (0, 0);\n-\t\t\toutput.setValueType(ValueType.DOUBLE);\n-\t\t\tbreak;\n-\t\tcase CAST_AS_INT:\n-\t\t\tcheckNumParameters(1);\n-\t\t\tcheckScalarParam(getFirstExpr());\n-\t\t\toutput.setDataType(DataType.SCALAR);\n-\t\t\t//output.setDataType(id.getDataType()); //TODO whenever we support multiple matrix value types, currently noop.\n-\t\t\toutput.setDimensions(0, 0);\n-\t\t\toutput.setBlockDimensions (0, 0);\n-\t\t\toutput.setValueType(ValueType.INT);\n-\t\t\tbreak;\n-\t\tcase CAST_AS_BOOLEAN:\n-\t\t\tcheckNumParameters(1);\n-\t\t\tcheckScalarParam(getFirstExpr());\n-\t\t\toutput.setDataType(DataType.SCALAR);\n-\t\t\t//output.setDataType(id.getDataType()); //TODO whenever we support multiple matrix value types, currently noop.\n-\t\t\toutput.setDimensions(0, 0);\n-\t\t\toutput.setBlockDimensions (0, 0);\n-\t\t\toutput.setValueType(ValueType.BOOLEAN);\n-\t\t\tbreak;\n-\t\t\t\n-\t\tcase CBIND:\n-\t\tcase RBIND:\n-\t\t\t//scalar string append (string concatenation with \\n)\n-\t\t\tif( getFirstExpr().getOutput().getDataType()==DataType.SCALAR ) {\n-\t\t\t\tcheckNumParameters(2);\n-\t\t\t\tcheckScalarParam(getFirstExpr());\n-\t\t\t\tcheckScalarParam(getSecondExpr());\n-\t\t\t\tcheckValueTypeParam(getFirstExpr(), ValueType.STRING);\n-\t\t\t\tcheckValueTypeParam(getSecondExpr(), ValueType.STRING);\n-\t\t\t}\n-\t\t\t//matrix append (rbind/cbind)\n-\t\t\telse {\n-\t\t\t\tif( getAllExpr().length < 2 )\n-\t\t\t\t\traiseValidateError(\"Invalid number of arguments for \"+getOpCode(), conditional);\n-\t\t\t\tfor(int i=0; i<getAllExpr().length; i++)\n-\t\t\t\t\tcheckMatrixFrameParam(getExpr(i));\n-\t\t\t}\n-\t\t\t\n-\t\t\toutput.setDataType(id.getDataType());\n-\t\t\toutput.setValueType(id.getValueType());\n-\t\t\t\n-\t\t\t// set output dimensions and validate consistency\n-\t\t\tlong m1rlen = getFirstExpr().getOutput().getDim1();\n-\t\t\tlong m1clen = getFirstExpr().getOutput().getDim2();\n-\t\t\tlong appendDim1 = m1rlen, appendDim2 = m1clen;\n-\t\t\t\n-\t\t\tfor(int i=1; i<getAllExpr().length; i++) {\n-\t\t\t\tlong m2rlen = getExpr(i).getOutput().getDim1();\n-\t\t\t\tlong m2clen = getExpr(i).getOutput().getDim2();\n-\t\t\t\t\n-\t\t\t\tif( getOpCode() == BuiltinFunctionOp.CBIND ) {\n-\t\t\t\t\tif (m1rlen > 0 && m2rlen > 0 && m1rlen!=m2rlen) {\n-\t\t\t\t\t\traiseValidateError(\"inputs to cbind must have same number of rows: input 1 rows: \" + \n-\t\t\t\t\t\t\tm1rlen+\", input 2 rows: \"+m2rlen, conditional, LanguageErrorCodes.INVALID_PARAMETERS);\n-\t\t\t\t\t}\n-\t\t\t\t\tappendDim1 = (m2rlen>0) ? m2rlen : appendDim1;\n-\t\t\t\t\tappendDim2 = (appendDim2>0 && m2clen>0) ? appendDim2 + m2clen : -1;\n-\t\t\t\t}\n-\t\t\t\telse if( getOpCode() == BuiltinFunctionOp.RBIND ) {\n-\t\t\t\t\tif (m1clen > 0 && m2clen > 0 && m1clen!=m2clen) {\n-\t\t\t\t\t\traiseValidateError(\"inputs to rbind must have same number of columns: input 1 columns: \" + \n-\t\t\t\t\t\t\tm1clen+\", input 2 columns: \"+m2clen, conditional, LanguageErrorCodes.INVALID_PARAMETERS);\n-\t\t\t\t\t}\n-\t\t\t\t\tappendDim1 = (appendDim1>0 && m2rlen>0)? appendDim1 + m2rlen : -1;\n-\t\t\t\t\tappendDim2 = (m2clen>0) ? m2clen : appendDim2;\n-\t\t\t\t}\n-\t\t\t}\n-\t\t\toutput.setDimensions(appendDim1, appendDim2);\n-\t\t\toutput.setBlockDimensions (id.getRowsInBlock(), id.getColumnsInBlock());\n-\t\t\t\n-\t\t\tbreak;\n-\t\t\t\n-\t\tcase PPRED:\n-\t\t\t// TODO: remove this when ppred has been removed from DML\n-\t\t\traiseValidateError(\"ppred() has been deprecated. Please use the operator directly.\", true);\n-\n-\t\t\t// ppred (X,Y, \"<\"); ppred (X,y, \"<\"); ppred (y,X, \"<\");\n-\t\t\tcheckNumParameters(3);\n-\t\t\t\n-\t\t\tDataType dt1 = getFirstExpr().getOutput().getDataType();\n-\t\t\tDataType dt2 = getSecondExpr().getOutput().getDataType();\n-\t\t\t\n-\t\t\t//check input data types\n-\t\t\tif( dt1 == DataType.SCALAR && dt2 == DataType.SCALAR ) {\n-\t\t\t\traiseValidateError(\"ppred() requires at least one matrix input.\", conditional, LanguageErrorCodes.INVALID_PARAMETERS);\n-\t\t\t}\t\t\t\n-\t\t\tif( dt1 == DataType.MATRIX )\n-\t\t\t\tcheckMatrixParam(getFirstExpr());\n-\t\t\tif( dt2 == DataType.MATRIX )\n-\t\t\t\tcheckMatrixParam(getSecondExpr());\n-\t\t\t\n-\t\t\t//check operator\n-\t\t\tif (getThirdExpr().getOutput().getDataType() != DataType.SCALAR || \n-\t\t\t\tgetThirdExpr().getOutput().getValueType() != ValueType.STRING) \n-\t\t\t{\t\n-\t\t\t\traiseValidateError(\"Third argument in ppred() is not an operator \", conditional, LanguageErrorCodes.INVALID_PARAMETERS);\n-\t\t\t}\n-\t\t\t\n-\t\t\tsetBinaryOutputProperties(output);\n-\t\t\tbreak;\n-\n-\t\tcase TRANS:\n-\t\t\tcheckNumParameters(1);\n-\t\t\tcheckMatrixParam(getFirstExpr());\n-\t\t\toutput.setDataType(DataType.MATRIX);\n-\t\t\toutput.setDimensions(id.getDim2(), id.getDim1());\n-\t\t\toutput.setBlockDimensions (id.getColumnsInBlock(), id.getRowsInBlock());\n-\t\t\toutput.setValueType(id.getValueType());\n-\t\t\tbreak;\n-\t\t\n-\t\tcase REV:\n-\t\t\tcheckNumParameters(1);\n-\t\t\tcheckMatrixParam(getFirstExpr());\n-\t\t\toutput.setDataType(DataType.MATRIX);\n-\t\t\toutput.setDimensions(id.getDim1(), id.getDim2());\n-\t\t\toutput.setBlockDimensions (id.getColumnsInBlock(), id.getRowsInBlock());\n-\t\t\toutput.setValueType(id.getValueType());\n-\t\t\tbreak;\t\n-\t\t\t\n-\t\tcase DIAG:\n-\t\t\tcheckNumParameters(1);\n-\t\t\tcheckMatrixParam(getFirstExpr());\n-\t\t\toutput.setDataType(DataType.MATRIX);\n-\t\t\tif( id.getDim2() != -1 ) { //type known\n-\t\t\t\tif ( id.getDim2() == 1 ) \n-\t\t\t\t{\n-\t\t\t\t\t//diag V2M\n-\t\t\t\t\toutput.setDimensions(id.getDim1(), id.getDim1());\n-\t\t\t\t} \n-\t\t\t\telse \n-\t\t\t\t{\n-\t\t\t\t\tif (id.getDim1() != id.getDim2()) {\n-\t\t\t\t\t\traiseValidateError(\"diag can either: (1) create diagonal matrix from (n x 1) matrix, or (2) take diagonal from a square matrix. \"\n-\t\t\t\t\t\t\t\t+ \"Error invoking diag on matrix with dimensions (\"\n-\t\t\t\t\t\t\t\t+ id.getDim1() + \",\" + id.getDim2()\n-\t\t\t\t\t\t\t\t+ \") in \" + this.toString(), conditional, LanguageErrorCodes.INVALID_PARAMETERS);\n-\t\t\t\t\t}\n-\t\t\t\t\t//diag M2V\n-\t\t\t\t\toutput.setDimensions(id.getDim1(), 1);\n-\t\t\t\t}\n-\t\t\t}\n-\t\t\toutput.setBlockDimensions (id.getRowsInBlock(), id.getColumnsInBlock());\n-\t\t\toutput.setValueType(id.getValueType());\n-\t\t\tbreak;\n-\t\tcase NROW:\n-\t\tcase NCOL:\n-\t\tcase LENGTH:\n-\t\t\tcheckNumParameters(1);\n-\t\t\tcheckMatrixFrameParam(getFirstExpr());\n-\t\t\toutput.setDataType(DataType.SCALAR);\n-\t\t\toutput.setDimensions(0, 0);\n-\t\t\toutput.setBlockDimensions (0, 0);\n-\t\t\toutput.setValueType(ValueType.INT);\n-\t\t\tbreak;\n-\n-\t\t// Contingency tables\n-\t\tcase TABLE:\n-\t\t\t\n+        } catch (LanguageException e) {\n+            throw new RuntimeException(e);\n+        }\n+        return paramExpression;\n+    }\n+\n+    /**\n+     * Validate parse tree : Process BuiltinFunction Expression in an assignment\n+     * statement\n+     *\n+     * @throws LanguageException if LanguageException occurs\n+     */\n+    @Override\n+    public void validateExpression(HashMap<String, DataIdentifier> ids, HashMap<String, ConstIdentifier> constVars, boolean conditional)\n+            throws LanguageException {\n+\n+        for (int i = 0; i < _args.length; i++) {\n+\n+            if (_args[i] instanceof FunctionCallIdentifier) {\n+                raiseValidateError(\"UDF function call not supported as parameter to built-in function call\", false);\n+            }\n+\n+            _args[i].validateExpression(ids, constVars, conditional);\n+        }\n+\n+        // checkIdentifierParams();\n+        String outputName = getTempName();\n+        DataIdentifier output = new DataIdentifier(outputName);\n+        output.setParseInfo(this);\n+\n+        if (this.getFirstExpr() == null) {\n+            raiseValidateError(\"Function \" + this + \" has no arguments.\", false);\n+        }\n+        Identifier id = this.getFirstExpr().getOutput();\n+        output.setProperties(this.getFirstExpr().getOutput());\n+        output.setNnz(-1); //conservatively, cannot use input nnz!\n+        this.setOutput(output);\n+\n+        switch (this.getOpCode()) {\n+            case EVAL:\n+                checkNumParameters(Integer.MAX_VALUE);\n+                output.setDataType(DataType.MATRIX);\n+                output.setValueType(ValueType.DOUBLE);\n+                output.setDimensions(1, 1);","path":"src/main/java/org/apache/sysml/parser/BuiltinFunctionExpression.java","position":1022,"original_position":1022,"commit_id":"e64d037f0a01b65cf5194fd4a92efe2e59c3b64b","original_commit_id":"e64d037f0a01b65cf5194fd4a92efe2e59c3b64b","user":{"login":"mboehm7","id":13721609,"avatar_url":"https://avatars0.githubusercontent.com/u/13721609?v=4","gravatar_id":"","url":"https://api.github.com/users/mboehm7","html_url":"https://github.com/mboehm7","followers_url":"https://api.github.com/users/mboehm7/followers","following_url":"https://api.github.com/users/mboehm7/following{/other_user}","gists_url":"https://api.github.com/users/mboehm7/gists{/gist_id}","starred_url":"https://api.github.com/users/mboehm7/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mboehm7/subscriptions","organizations_url":"https://api.github.com/users/mboehm7/orgs","repos_url":"https://api.github.com/users/mboehm7/repos","events_url":"https://api.github.com/users/mboehm7/events{/privacy}","received_events_url":"https://api.github.com/users/mboehm7/received_events","type":"User","site_admin":false},"body":"If you fix the output dimensions to 1x1 this could lead to incorrect results if subsequent rewrites exploit this \"known\" size information. Please, use -1 to indicate unknowns instead.","created_at":"2018-03-03T01:21:00Z","updated_at":"2018-03-03T01:49:09Z","html_url":"https://github.com/apache/systemml/pull/736#discussion_r171999838","pull_request_url":"https://api.github.com/repos/apache/systemml/pulls/736","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/apache/systemml/pulls/comments/171999838"},"html":{"href":"https://github.com/apache/systemml/pull/736#discussion_r171999838"},"pull_request":{"href":"https://api.github.com/repos/apache/systemml/pulls/736"}}},"pull_request":{"url":"https://api.github.com/repos/apache/systemml/pulls/736","id":172548450,"html_url":"https://github.com/apache/systemml/pull/736","diff_url":"https://github.com/apache/systemml/pull/736.diff","patch_url":"https://github.com/apache/systemml/pull/736.patch","issue_url":"https://api.github.com/repos/apache/systemml/issues/736","number":736,"state":"open","locked":false,"title":"[SYSTEMML-2077] Add eval built-in function","user":{"login":"EdgarLGB","id":15153347,"avatar_url":"https://avatars0.githubusercontent.com/u/15153347?v=4","gravatar_id":"","url":"https://api.github.com/users/EdgarLGB","html_url":"https://github.com/EdgarLGB","followers_url":"https://api.github.com/users/EdgarLGB/followers","following_url":"https://api.github.com/users/EdgarLGB/following{/other_user}","gists_url":"https://api.github.com/users/EdgarLGB/gists{/gist_id}","starred_url":"https://api.github.com/users/EdgarLGB/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/EdgarLGB/subscriptions","organizations_url":"https://api.github.com/users/EdgarLGB/orgs","repos_url":"https://api.github.com/users/EdgarLGB/repos","events_url":"https://api.github.com/users/EdgarLGB/events{/privacy}","received_events_url":"https://api.github.com/users/EdgarLGB/received_events","type":"User","site_admin":false},"body":"Hi, I have added an eval built-in function and a test for it. Thanks!","created_at":"2018-03-02T16:39:14Z","updated_at":"2018-03-03T01:49:09Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d7654db0c3754170110c5a425a1c4fae936650e7","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/apache/systemml/pulls/736/commits","review_comments_url":"https://api.github.com/repos/apache/systemml/pulls/736/comments","review_comment_url":"https://api.github.com/repos/apache/systemml/pulls/comments{/number}","comments_url":"https://api.github.com/repos/apache/systemml/issues/736/comments","statuses_url":"https://api.github.com/repos/apache/systemml/statuses/e64d037f0a01b65cf5194fd4a92efe2e59c3b64b","head":{"label":"EdgarLGB:branch-1.0.0","ref":"branch-1.0.0","sha":"e64d037f0a01b65cf5194fd4a92efe2e59c3b64b","user":{"login":"EdgarLGB","id":15153347,"avatar_url":"https://avatars0.githubusercontent.com/u/15153347?v=4","gravatar_id":"","url":"https://api.github.com/users/EdgarLGB","html_url":"https://github.com/EdgarLGB","followers_url":"https://api.github.com/users/EdgarLGB/followers","following_url":"https://api.github.com/users/EdgarLGB/following{/other_user}","gists_url":"https://api.github.com/users/EdgarLGB/gists{/gist_id}","starred_url":"https://api.github.com/users/EdgarLGB/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/EdgarLGB/subscriptions","organizations_url":"https://api.github.com/users/EdgarLGB/orgs","repos_url":"https://api.github.com/users/EdgarLGB/repos","events_url":"https://api.github.com/users/EdgarLGB/events{/privacy}","received_events_url":"https://api.github.com/users/EdgarLGB/received_events","type":"User","site_admin":false},"repo":{"id":123602502,"name":"systemml","full_name":"EdgarLGB/systemml","owner":{"login":"EdgarLGB","id":15153347,"avatar_url":"https://avatars0.githubusercontent.com/u/15153347?v=4","gravatar_id":"","url":"https://api.github.com/users/EdgarLGB","html_url":"https://github.com/EdgarLGB","followers_url":"https://api.github.com/users/EdgarLGB/followers","following_url":"https://api.github.com/users/EdgarLGB/following{/other_user}","gists_url":"https://api.github.com/users/EdgarLGB/gists{/gist_id}","starred_url":"https://api.github.com/users/EdgarLGB/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/EdgarLGB/subscriptions","organizations_url":"https://api.github.com/users/EdgarLGB/orgs","repos_url":"https://api.github.com/users/EdgarLGB/repos","events_url":"https://api.github.com/users/EdgarLGB/events{/privacy}","received_events_url":"https://api.github.com/users/EdgarLGB/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/EdgarLGB/systemml","description":"Mirror of Apache SystemML","fork":true,"url":"https://api.github.com/repos/EdgarLGB/systemml","forks_url":"https://api.github.com/repos/EdgarLGB/systemml/forks","keys_url":"https://api.github.com/repos/EdgarLGB/systemml/keys{/key_id}","collaborators_url":"https://api.github.com/repos/EdgarLGB/systemml/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/EdgarLGB/systemml/teams","hooks_url":"https://api.github.com/repos/EdgarLGB/systemml/hooks","issue_events_url":"https://api.github.com/repos/EdgarLGB/systemml/issues/events{/number}","events_url":"https://api.github.com/repos/EdgarLGB/systemml/events","assignees_url":"https://api.github.com/repos/EdgarLGB/systemml/assignees{/user}","branches_url":"https://api.github.com/repos/EdgarLGB/systemml/branches{/branch}","tags_url":"https://api.github.com/repos/EdgarLGB/systemml/tags","blobs_url":"https://api.github.com/repos/EdgarLGB/systemml/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/EdgarLGB/systemml/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/EdgarLGB/systemml/git/refs{/sha}","trees_url":"https://api.github.com/repos/EdgarLGB/systemml/git/trees{/sha}","statuses_url":"https://api.github.com/repos/EdgarLGB/systemml/statuses/{sha}","languages_url":"https://api.github.com/repos/EdgarLGB/systemml/languages","stargazers_url":"https://api.github.com/repos/EdgarLGB/systemml/stargazers","contributors_url":"https://api.github.com/repos/EdgarLGB/systemml/contributors","subscribers_url":"https://api.github.com/repos/EdgarLGB/systemml/subscribers","subscription_url":"https://api.github.com/repos/EdgarLGB/systemml/subscription","commits_url":"https://api.github.com/repos/EdgarLGB/systemml/commits{/sha}","git_commits_url":"https://api.github.com/repos/EdgarLGB/systemml/git/commits{/sha}","comments_url":"https://api.github.com/repos/EdgarLGB/systemml/comments{/number}","issue_comment_url":"https://api.github.com/repos/EdgarLGB/systemml/issues/comments{/number}","contents_url":"https://api.github.com/repos/EdgarLGB/systemml/contents/{+path}","compare_url":"https://api.github.com/repos/EdgarLGB/systemml/compare/{base}...{head}","merges_url":"https://api.github.com/repos/EdgarLGB/systemml/merges","archive_url":"https://api.github.com/repos/EdgarLGB/systemml/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/EdgarLGB/systemml/downloads","issues_url":"https://api.github.com/repos/EdgarLGB/systemml/issues{/number}","pulls_url":"https://api.github.com/repos/EdgarLGB/systemml/pulls{/number}","milestones_url":"https://api.github.com/repos/EdgarLGB/systemml/milestones{/number}","notifications_url":"https://api.github.com/repos/EdgarLGB/systemml/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/EdgarLGB/systemml/labels{/name}","releases_url":"https://api.github.com/repos/EdgarLGB/systemml/releases{/id}","deployments_url":"https://api.github.com/repos/EdgarLGB/systemml/deployments","created_at":"2018-03-02T16:23:19Z","updated_at":"2018-03-02T16:23:30Z","pushed_at":"2018-03-02T16:27:28Z","git_url":"git://github.com/EdgarLGB/systemml.git","ssh_url":"git@github.com:EdgarLGB/systemml.git","clone_url":"https://github.com/EdgarLGB/systemml.git","svn_url":"https://github.com/EdgarLGB/systemml","homepage":"","size":205793,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"apache:branch-1.0.0","ref":"branch-1.0.0","sha":"6519f3383f8fd43af93ecba8742ae4b2b28d4b35","user":{"login":"apache","id":47359,"avatar_url":"https://avatars0.githubusercontent.com/u/47359?v=4","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"repo":{"id":45896813,"name":"systemml","full_name":"apache/systemml","owner":{"login":"apache","id":47359,"avatar_url":"https://avatars0.githubusercontent.com/u/47359?v=4","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/apache/systemml","description":"Mirror of Apache SystemML","fork":false,"url":"https://api.github.com/repos/apache/systemml","forks_url":"https://api.github.com/repos/apache/systemml/forks","keys_url":"https://api.github.com/repos/apache/systemml/keys{/key_id}","collaborators_url":"https://api.github.com/repos/apache/systemml/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/apache/systemml/teams","hooks_url":"https://api.github.com/repos/apache/systemml/hooks","issue_events_url":"https://api.github.com/repos/apache/systemml/issues/events{/number}","events_url":"https://api.github.com/repos/apache/systemml/events","assignees_url":"https://api.github.com/repos/apache/systemml/assignees{/user}","branches_url":"https://api.github.com/repos/apache/systemml/branches{/branch}","tags_url":"https://api.github.com/repos/apache/systemml/tags","blobs_url":"https://api.github.com/repos/apache/systemml/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/apache/systemml/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/apache/systemml/git/refs{/sha}","trees_url":"https://api.github.com/repos/apache/systemml/git/trees{/sha}","statuses_url":"https://api.github.com/repos/apache/systemml/statuses/{sha}","languages_url":"https://api.github.com/repos/apache/systemml/languages","stargazers_url":"https://api.github.com/repos/apache/systemml/stargazers","contributors_url":"https://api.github.com/repos/apache/systemml/contributors","subscribers_url":"https://api.github.com/repos/apache/systemml/subscribers","subscription_url":"https://api.github.com/repos/apache/systemml/subscription","commits_url":"https://api.github.com/repos/apache/systemml/commits{/sha}","git_commits_url":"https://api.github.com/repos/apache/systemml/git/commits{/sha}","comments_url":"https://api.github.com/repos/apache/systemml/comments{/number}","issue_comment_url":"https://api.github.com/repos/apache/systemml/issues/comments{/number}","contents_url":"https://api.github.com/repos/apache/systemml/contents/{+path}","compare_url":"https://api.github.com/repos/apache/systemml/compare/{base}...{head}","merges_url":"https://api.github.com/repos/apache/systemml/merges","archive_url":"https://api.github.com/repos/apache/systemml/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/apache/systemml/downloads","issues_url":"https://api.github.com/repos/apache/systemml/issues{/number}","pulls_url":"https://api.github.com/repos/apache/systemml/pulls{/number}","milestones_url":"https://api.github.com/repos/apache/systemml/milestones{/number}","notifications_url":"https://api.github.com/repos/apache/systemml/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/apache/systemml/labels{/name}","releases_url":"https://api.github.com/repos/apache/systemml/releases{/id}","deployments_url":"https://api.github.com/repos/apache/systemml/deployments","created_at":"2015-11-10T08:00:06Z","updated_at":"2018-03-01T19:13:52Z","pushed_at":"2018-03-02T16:39:16Z","git_url":"git://github.com/apache/systemml.git","ssh_url":"git@github.com:apache/systemml.git","clone_url":"https://github.com/apache/systemml.git","svn_url":"https://github.com/apache/systemml","homepage":"","size":205765,"stargazers_count":620,"watchers_count":620,"language":"Java","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":226,"mirror_url":null,"archived":false,"open_issues_count":22,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":226,"open_issues":22,"watchers":620,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/apache/systemml/pulls/736"},"html":{"href":"https://github.com/apache/systemml/pull/736"},"issue":{"href":"https://api.github.com/repos/apache/systemml/issues/736"},"comments":{"href":"https://api.github.com/repos/apache/systemml/issues/736/comments"},"review_comments":{"href":"https://api.github.com/repos/apache/systemml/pulls/736/comments"},"review_comment":{"href":"https://api.github.com/repos/apache/systemml/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/apache/systemml/pulls/736/commits"},"statuses":{"href":"https://api.github.com/repos/apache/systemml/statuses/e64d037f0a01b65cf5194fd4a92efe2e59c3b64b"}},"author_association":"NONE"}}
{"actor":{"display_login":"mboehm7"}}