/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.sysds.parser;

import org.antlr.v4.runtime.ParserRuleContext;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.NotImplementedException;
import org.apache.sysds.common.Builtins;
import org.apache.sysds.common.Types.DataType;
import org.apache.sysds.common.Types.ValueType;
import org.apache.sysds.conf.ConfigurationManager;
import org.apache.sysds.parser.LanguageException.LanguageErrorCodes;
import org.apache.sysds.runtime.meta.MatrixCharacteristics;
import org.apache.sysds.runtime.util.DnnUtils;
import org.apache.sysds.runtime.util.UtilFunctions;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;

public class BuiltinFunctionExpression extends DataIdentifier 
{
	protected Expression[] _args = null;
	private Builtins _opcode;

	public BuiltinFunctionExpression(ParserRuleContext ctx, Builtins bifop, ArrayList<ParameterExpression> args, String fname) {
		_opcode = bifop;
		setCtxValuesAndFilename(ctx, fname);
		args = expandDnnArguments(args);
		_args = new Expression[args.size()];
		for(int i=0; i < args.size(); i++) {
			_args[i] = args.get(i).getExpr();
		}
	}

	public BuiltinFunctionExpression(Builtins bifop, Expression[] args, ParseInfo parseInfo) {
		_opcode = bifop;
		_args = new Expression[args.length];
		for (int i = 0; i < args.length; i++) {
			_args[i] = args[i];
		}
		setParseInfo(parseInfo);
	}

	public BuiltinFunctionExpression(ParserRuleContext ctx, Builtins bifop, Expression[] args, String fname) {
		_opcode = bifop;
		_args = new Expression[args.length];
		for(int i=0; i < args.length; i++) {
			_args[i] = args[i];
		}
		setCtxValuesAndFilename(ctx, fname);
	}

	@Override
	public Expression rewriteExpression(String prefix) {
		Expression[] newArgs = new Expression[_args.length];
		for (int i = 0; i < _args.length; i++) {
			newArgs[i] = _args[i].rewriteExpression(prefix);
		}
		BuiltinFunctionExpression retVal = new BuiltinFunctionExpression(this._opcode, newArgs, this);
		return retVal;
	}

	public Builtins getOpCode() {
		return _opcode;
	}

	public Expression getFirstExpr() {
		return (_args.length >= 1 ? _args[0] : null);
	}

	public Expression getSecondExpr() {
		return (_args.length >= 2 ? _args[1] : null);
	}

	public Expression getThirdExpr() {
		return (_args.length >= 3 ? _args[2] : null);
	}
	
	public Expression getFourthExpr() {
		return (_args.length >= 4 ? _args[3] : null);
	}
	
	public Expression getFifthExpr() {
		return (_args.length >= 5 ? _args[4] : null);
	}
	
	public Expression getSixthExpr() {
		return (_args.length >= 6 ? _args[5] : null);
	}
	
	public Expression getSeventhExpr() {
		return (_args.length >= 7 ? _args[6] : null);
	}

	public Expression getEighthExpr() {
		return (_args.length >= 8 ? _args[7] : null);
	}


	public Expression[] getAllExpr(){
		return _args;
	}
	
	public Expression getExpr(int i) {
		return (_args.length > i ? _args[i] : null);
	}
	
	@Override
	public void validateExpression(MultiAssignmentStatement stmt, HashMap<String, DataIdentifier> ids, HashMap<String, ConstIdentifier> constVars, boolean conditional)
	{
		if (this.getFirstExpr() instanceof FunctionCallIdentifier){
			raiseValidateError("UDF function call not supported as parameter to built-in function call", false);
		}
		
		this.getFirstExpr().validateExpression(ids, constVars, conditional);
		Expression [] expr = getAllExpr();
		if(expr != null && expr.length > 1) {
			for(int i = 1; i < expr.length; i++) {
				if (expr[i] instanceof FunctionCallIdentifier){
					raiseValidateError("UDF function call not supported as parameter to built-in function call", false);
				}
				expr[i].validateExpression(ids, constVars, conditional);
			}
		}
		_outputs = new Identifier[stmt.getTargetList().size()];
		int count = 0;
		for (DataIdentifier outParam: stmt.getTargetList()){
			DataIdentifier tmp = new DataIdentifier(outParam);
			tmp.setParseInfo(this);
			_outputs[count++] = tmp;
		}
		
		switch (_opcode) {
		case QR:
			checkNumParameters(1);
			checkMatrixParam(getFirstExpr());
			
			// setup output properties
			DataIdentifier qrOut1 = (DataIdentifier) getOutputs()[0];
			DataIdentifier qrOut2 = (DataIdentifier) getOutputs()[1];
			
			long rows = getFirstExpr().getOutput().getDim1();
			long cols = getFirstExpr().getOutput().getDim2();
			
			// Output1 - Q
			qrOut1.setDataType(DataType.MATRIX);
			qrOut1.setValueType(ValueType.FP64);
			qrOut1.setDimensions(rows, cols);
			qrOut1.setBlocksize(getFirstExpr().getOutput().getBlocksize());
			
			// Output2 - R
			qrOut2.setDataType(DataType.MATRIX);
			qrOut2.setValueType(ValueType.FP64);
			qrOut2.setDimensions(rows, cols);
			qrOut2.setBlocksize(getFirstExpr().getOutput().getBlocksize());
			
			break;

		case LU:
			checkNumParameters(1);
			checkMatrixParam(getFirstExpr());
			
			// setup output properties
			DataIdentifier luOut1 = (DataIdentifier) getOutputs()[0];
			DataIdentifier luOut2 = (DataIdentifier) getOutputs()[1];
			DataIdentifier luOut3 = (DataIdentifier) getOutputs()[2];
			
			long inrows = getFirstExpr().getOutput().getDim1();
			long incols = getFirstExpr().getOutput().getDim2();

			if (inrows != incols) {
				raiseValidateError("LU Decomposition requires a square matrix. Matrix " + getFirstExpr() + " is "
						+ inrows + "x" + incols + ".", conditional);
			}

			// Output1 - P
			luOut1.setDataType(DataType.MATRIX);
			luOut1.setValueType(ValueType.FP64);
			luOut1.setDimensions(inrows, inrows);
			luOut1.setBlocksize(getFirstExpr().getOutput().getBlocksize());
			
			// Output2 - L
			luOut2.setDataType(DataType.MATRIX);
			luOut2.setValueType(ValueType.FP64);
			luOut2.setDimensions(inrows, inrows);
			luOut2.setBlocksize(getFirstExpr().getOutput().getBlocksize());
			
			// Output3 - U
			luOut3.setDataType(DataType.MATRIX);
			luOut3.setValueType(ValueType.FP64);
			luOut3.setDimensions(inrows, inrows);
			luOut3.setBlocksize(getFirstExpr().getOutput().getBlocksize());
			
			break;

		case LSTM:
		{
			// X,  W, bias, out0, c0, return_sequences
			checkNumParameters(6);
			checkMatrixParam(getFirstExpr());
			checkMatrixParam(getSecondExpr());
			checkMatrixParam(getThirdExpr());
			checkMatrixParam(getFourthExpr());
			checkMatrixParam(getFifthExpr());
			
			// setup output properties
			if(getOutputs() == null || getOutputs().length != 2) {
				int numOutputs = getOutputs() == null ? 0 : getOutputs().length;
				raiseValidateError("The builtin function lstm has two outputs, but instead found: " + numOutputs, conditional);
			}
			DataIdentifier out = (DataIdentifier) getOutputs()[0];
			DataIdentifier cy = (DataIdentifier) getOutputs()[1];
			
			// Output1 - out: If `return_sequences` is True, outputs for all timesteps, else outputs for the final timestep.
			out.setDataType(DataType.MATRIX);
			out.setValueType(ValueType.FP64);
			out.setDimensions(-1, -1);
			out.setBlocksize(getFirstExpr().getOutput().getBlocksize());
			
			// Output2 - Cell state for final timestep.
			cy.setDataType(DataType.MATRIX);
			cy.setValueType(ValueType.FP64);
			cy.setDimensions(getExpr(4).getOutput().getDim1(), getExpr(4).getOutput().getDim2());
			cy.setBlocksize(getExpr(4).getOutput().getBlocksize());
			
			break;
		}
		case LSTM_BACKWARD:
		{
			// Input: X, W, b, out0, c0, return_sequences, dout, cy
			checkNumParameters(8);
			checkMatrixParam(getFirstExpr());
			checkMatrixParam(getSecondExpr());
			checkMatrixParam(getThirdExpr());
			checkMatrixParam(getFourthExpr());
			checkMatrixParam(getFifthExpr());
			checkMatrixParam(getSeventhExpr());
			checkMatrixParam(getEighthExpr());
			
			// Output: dx, dw, db, dout0, dc0
			// setup output properties
			if(getOutputs().length != 5)
				raiseValidateError("lstm_backward has 5 outputs", false);
			 
			DataIdentifier dx = (DataIdentifier) getOutputs()[0];
			DataIdentifier dw = (DataIdentifier) getOutputs()[1];
			DataIdentifier db = (DataIdentifier) getOutputs()[2];
			DataIdentifier dout0 = (DataIdentifier) getOutputs()[3];
			DataIdentifier dc0 = (DataIdentifier) getOutputs()[4];
			
			setDimensions(dx, getFirstExpr());
			setDimensions(dw, getSecondExpr());
			setDimensions(db, getThirdExpr());
			setDimensions(dout0, getFourthExpr());
			setDimensions(dc0, getFifthExpr());
			break;
		}
		case BATCH_NORM2D:
		{
			// Input: image, scale, bias, runningMean, runningVar, mode, epsilon, exponentialAverageFactor
			checkNumParameters(8);
			checkMatrixParam(getFirstExpr());
			checkMatrixParam(getSecondExpr());
			checkMatrixParam(getThirdExpr());
			checkMatrixParam(getFourthExpr());
			checkMatrixParam(getFifthExpr());
			
			// Output: ret, retRunningMean, retRunningVar, resultSaveMean, resultSaveInvVariance
			// setup output properties
			if(getOutputs().length != 5)
				raiseValidateError("batch_norm2d has 5 outputs", false);
			 
			DataIdentifier ret = (DataIdentifier) getOutputs()[0];
			DataIdentifier retRunningMean = (DataIdentifier) getOutputs()[1];
			DataIdentifier retRunningVar = (DataIdentifier) getOutputs()[2];
			DataIdentifier resultSaveMean = (DataIdentifier) getOutputs()[3];
			DataIdentifier resultSaveInvVariance = (DataIdentifier) getOutputs()[4];
			
			setDimensions(ret, getFirstExpr());
			setDimensions(retRunningMean, getFourthExpr());
			setDimensions(retRunningVar, getFourthExpr());
			setDimensions(resultSaveMean, getFourthExpr());
			setDimensions(resultSaveInvVariance, getFourthExpr());
			break;
		}
		case BATCH_NORM2D_BACKWARD:
		{
			// Input: image, dout, scale, epsilon, savedMean, savedInvVariance
			checkNumParameters(6);
			checkMatrixParam(getFirstExpr());
			checkMatrixParam(getSecondExpr());
			checkMatrixParam(getThirdExpr());
			checkMatrixParam(getFifthExpr());
			checkMatrixParam(getSixthExpr());
			
			// Output: dX, dScale, dBias 
			// setup output properties
			if(getOutputs().length != 3)
				raiseValidateError("batch_norm2d_backward has 3 outputs", false);
			
			DataIdentifier dX = (DataIdentifier) getOutputs()[0];
			DataIdentifier dScale = (DataIdentifier) getOutputs()[1];
			DataIdentifier dBias = (DataIdentifier) getOutputs()[2];
			
			setDimensions(dX, getFirstExpr());
			setDimensions(dScale, getThirdExpr());
			setDimensions(dBias, getThirdExpr());
			break;
		}
		case EIGEN: {
			checkNumParameters(1);
			checkMatrixParam(getFirstExpr());
			
			// setup output properties
			DataIdentifier eigenOut1 = (DataIdentifier) getOutputs()[0];
			DataIdentifier eigenOut2 = (DataIdentifier) getOutputs()[1];
			
			if ( getFirstExpr().getOutput().getDim1() != getFirstExpr().getOutput().getDim2() ) {
				raiseValidateError("Eigen Decomposition can only be done on a square matrix. Input matrix is rectangular (rows=" + getFirstExpr().getOutput().getDim1() + ", cols="+ getFirstExpr().getOutput().getDim2() +")", conditional);
			}
			
			// Output1 - Eigen Values
			eigenOut1.setDataType(DataType.MATRIX);
			eigenOut1.setValueType(ValueType.FP64);
			eigenOut1.setDimensions(getFirstExpr().getOutput().getDim1(), 1);
			eigenOut1.setBlocksize(getFirstExpr().getOutput().getBlocksize());
			
			// Output2 - Eigen Vectors
			eigenOut2.setDataType(DataType.MATRIX);
			eigenOut2.setValueType(ValueType.FP64);
			eigenOut2.setDimensions(getFirstExpr().getOutput().getDim1(), getFirstExpr().getOutput().getDim2());
			eigenOut2.setBlocksize(getFirstExpr().getOutput().getBlocksize());
			
			break;
		}
		case REMOVE: {
			checkNumParameters(2);
			checkListParam(getFirstExpr());
			
			// setup output properties
			DataIdentifier out1 = (DataIdentifier) getOutputs()[0];
			DataIdentifier out2 = (DataIdentifier) getOutputs()[1];
			
			// Output1 - Eigen Values
			out1.setDataType(DataType.LIST);
			out1.setValueType(getFirstExpr().getOutput().getValueType());
			out1.setDimensions(getFirstExpr().getOutput().getDim1()-1, 1);
			out1.setBlocksize(getFirstExpr().getOutput().getBlocksize());
			
			// Output2 - Eigen Vectors
			out2.setDataType(DataType.LIST);
			out2.setValueType(getFirstExpr().getOutput().getValueType());
			out2.setDimensions(1, 1);
			out2.setBlocksize(getFirstExpr().getOutput().getBlocksize());
			
			break;
		}
		case SVD:
			checkNumParameters(1);
			checkMatrixParam(getFirstExpr());
			
			long minMN = Math.min(getFirstExpr().getOutput().getDim1(), getFirstExpr().getOutput().getDim2());

			// setup output properties
			DataIdentifier svdOut1 = (DataIdentifier) getOutputs()[0];
			DataIdentifier svdOut2 = (DataIdentifier) getOutputs()[1];
			DataIdentifier svdOut3 = (DataIdentifier) getOutputs()[2];

			// Output 1
			svdOut1.setDataType(DataType.MATRIX);
			svdOut1.setValueType(ValueType.FP64);
			svdOut1.setDimensions(getFirstExpr().getOutput().getDim1(), minMN);
			svdOut1.setBlocksize(getFirstExpr().getOutput().getBlocksize());

			// Output 2
			svdOut2.setDataType(DataType.MATRIX);
			svdOut2.setValueType(ValueType.FP64);
			svdOut2.setDimensions(minMN, minMN);
			svdOut2.setBlocksize(getFirstExpr().getOutput().getBlocksize());

			// Output 3
			svdOut3.setDataType(DataType.MATRIX);
			svdOut3.setValueType(ValueType.FP64);
			svdOut3.setDimensions(getFirstExpr().getOutput().getDim2(), minMN);
			svdOut3.setBlocksize(getFirstExpr().getOutput().getBlocksize());

			break;
		
		default: //always unconditional
			raiseValidateError("Unknown Builtin Function opcode: " + _opcode, false);
		}
	}
	
	private static void setDimensions(DataIdentifier out, Expression exp) {
		out.setDataType(DataType.MATRIX);
		out.setValueType(ValueType.FP64);
		out.setDimensions(exp.getOutput().getDim1(), exp.getOutput().getDim2());
		out.setBlocksize(exp.getOutput().getBlocksize());
	}
	
	private static ArrayList<ParameterExpression> orderDnnParams(ArrayList<ParameterExpression> paramExpression, int skip) {
		ArrayList<ParameterExpression> newParams = new ArrayList<>();

		for(int i = 0; i < skip; i++)
			newParams.add(paramExpression.get(i));

		String [] orderedParams = {
				"stride1", "stride2", "padding1", "padding2",  
				"input_shape1", "input_shape2", "input_shape3", "input_shape4", 
				"filter_shape1", "filter_shape2", "filter_shape3", "filter_shape4"	
		};
		for(int i = 0; i < orderedParams.length; i++) {
			boolean found = false;
			for(ParameterExpression param : paramExpression) {
				if(param.getName() != null &&  param.getName().equals(orderedParams[i])) {
					found = true;
					newParams.add(param);
				}
			}
			if(!found) {
				throw new LanguageException("Incorrect parameters. Expected " + orderedParams[i] + " to be expanded.");
			}
		}

		return newParams;
	}

	private static ArrayList<ParameterExpression> replaceListParams(ArrayList<ParameterExpression> paramExpression,
			String inputVarName, String outputVarName, int startIndex) {
		ArrayList<ParameterExpression> newParamExpression = new ArrayList<>();
		int i = startIndex;
		int j = 1; // Assumption: sequential ordering pool_size1, pool_size2 
		for (ParameterExpression expr : paramExpression) {
			if(expr.getName() != null && expr.getName().equals(inputVarName + j)) {
				newParamExpression.add(new ParameterExpression(outputVarName + i, expr.getExpr()));
				i++; j++;
			}
			else {
				newParamExpression.add(expr);
			}
		}
		return newParamExpression;
	}

	private static ArrayList<ParameterExpression> expandListParams(ArrayList<ParameterExpression> paramExpression, 
			HashSet<String> paramsToExpand) {
		ArrayList<ParameterExpression> newParamExpressions = new ArrayList<>();
		for(ParameterExpression expr : paramExpression) {
			if(paramsToExpand.contains(expr.getName())) {
				if(expr.getExpr() instanceof ExpressionList) {
					int i = 1;
					for(Expression e : ((ExpressionList)expr.getExpr()).getValue()) {
						newParamExpressions.add(new ParameterExpression(expr.getName() + i, e));
						i++;
					}
				}
			}
			else if(expr.getExpr() instanceof ExpressionList) {
				throw new LanguageException("The parameter " + expr.getName() + " cannot be list or is not supported for the given function");
			}
			else {
				newParamExpressions.add(expr);
			}
		}
		return newParamExpressions;
	}
	
	private ArrayList<ParameterExpression> expandDnnArguments(ArrayList<ParameterExpression> paramExpression) {
		try {
			if(_opcode == Builtins.CONV2D || _opcode == Builtins.CONV2D_BACKWARD_FILTER 
					|| _opcode == Builtins.CONV2D_BACKWARD_DATA) {
				HashSet<String> expand = new HashSet<>();
				expand.add("input_shape"); expand.add("filter_shape"); expand.add("stride"); expand.add("padding");
				paramExpression = expandListParams(paramExpression, expand);
				paramExpression = orderDnnParams(paramExpression, 2);
			}
			else if(_opcode == Builtins.MAX_POOL || _opcode == Builtins.AVG_POOL ||  
					_opcode == Builtins.MAX_POOL_BACKWARD || _opcode == Builtins.AVG_POOL_BACKWARD) {
				HashSet<String> expand = new HashSet<>();
				expand.add("input_shape"); expand.add("pool_size"); expand.add("stride"); expand.add("padding");
				paramExpression = expandListParams(paramExpression, expand);
				paramExpression.add(new ParameterExpression("filter_shape1", new IntIdentifier(1, this)));
				paramExpression.add(new ParameterExpression("filter_shape2", new IntIdentifier(1, this)));
				paramExpression = replaceListParams(paramExpression, "pool_size", "filter_shape", 3);
				if(_opcode == Builtins.MAX_POOL_BACKWARD || _opcode == Builtins.AVG_POOL_BACKWARD)
					paramExpression = orderDnnParams(paramExpression, 2);
				else
					paramExpression = orderDnnParams(paramExpression, 1);
			}
		}
		catch(LanguageException e) {
			throw new RuntimeException(e);
		}
		return paramExpression;
	}
	
	private boolean isValidNoArgumentFunction() {
		return getOpCode() == Builtins.TIME
			|| getOpCode() == Builtins.LIST;
	}

	/**
	 * Validate parse tree : Process BuiltinFunction Expression in an assignment
	 * statement
	 */
	@Override
	public void validateExpression(HashMap<String, DataIdentifier> ids, HashMap<String, ConstIdentifier> constVars, boolean conditional) 
	{
		for(int i=0; i < _args.length; i++ ) {
			if (_args[i] instanceof FunctionCallIdentifier){
				raiseValidateError("UDF function call not supported as parameter to built-in function call", false);
			}
			_args[i].validateExpression(ids, constVars, conditional);
		}
		
		// checkIdentifierParams();
		String outputName = getTempName();
		DataIdentifier output = new DataIdentifier(outputName);
		output.setParseInfo(this);
		
		if (getFirstExpr() == null && !isValidNoArgumentFunction()) { // time has no arguments 
			raiseValidateError("Function " + this + " has no arguments.", false);
		}
		Identifier id = (_args.length != 0) ?
			getFirstExpr().getOutput() : null;
		if (_args.length != 0)
			output.setProperties(this.getFirstExpr().getOutput());
		output.setNnz(-1); //conservatively, cannot use input nnz!
		setOutput(output);
		
		switch (getOpCode()) {
		case EVAL:
			if (_args.length == 0)
				raiseValidateError("Function eval should provide at least one argument, i.e., the function name.", false);
			checkValueTypeParam(_args[0], ValueType.STRING);
			output.setDataType(DataType.MATRIX);
			output.setValueType(ValueType.FP64);
			output.setDimensions(-1, -1);
			output.setBlocksize(ConfigurationManager.getBlocksize());
			break;
		case COLSUM:
		case COLMAX:
		case COLMIN:
		case COLMEAN:
		case COLPROD:
		case COLSD:
		case COLVAR:
			// colSums(X);
			checkNumParameters(1);
			checkMatrixParam(getFirstExpr());
			output.setDataType(DataType.MATRIX);
			output.setDimensions(1, id.getDim2());
			output.setBlocksize (id.getBlocksize());
			output.setValueType(id.getValueType());
			break;
		case ROWSUM:
		case ROWMAX:
		case ROWINDEXMAX:
		case ROWMIN:
		case ROWINDEXMIN:
		case ROWMEAN:
		case ROWPROD:
		case ROWSD:
		case ROWVAR:
			//rowSums(X);
			checkNumParameters(1);
			checkMatrixParam(getFirstExpr());
			output.setDataType(DataType.MATRIX);
			output.setDimensions(id.getDim1(), 1);
			output.setBlocksize (id.getBlocksize());
			output.setValueType(id.getValueType());
			break;
		case SUM:
		case PROD:
		case TRACE:
		case SD:
		case VAR:
			// sum(X);
			checkNumParameters(1);
			checkMatrixTensorParam(getFirstExpr());
			output.setDataType(DataType.SCALAR);
			output.setDimensions(0, 0);
			output.setBlocksize(0);
			switch (id.getValueType()) {
				case STRING: // TODO think about what we want to get when we sum tensor of strings
				case FP64:
				case FP32:
					output.setValueType(ValueType.FP64);
					break;
				case INT64:
				case INT32:
				case UINT8:
				case BOOLEAN:
					output.setValueType(ValueType.INT64);
					break;
				case UNKNOWN:
					throw new NotImplementedException();
			}
			break;
		
		case MEAN:
			//checkNumParameters(2, false); // mean(Y) or mean(Y,W)
			if (getSecondExpr() != null) {
				checkNumParameters (2);
			}
			else {
				checkNumParameters (1);
			}
			
			checkMatrixParam(getFirstExpr());
			if ( getSecondExpr() != null ) {
				// x = mean(Y,W);
				checkMatchingDimensions(getFirstExpr(), getSecondExpr());
			}
			
			output.setDataType(DataType.SCALAR);
			output.setDimensions(0, 0);
			output.setBlocksize(0);
			output.setValueType(id.getValueType());
			break;
		
		case XOR:
		case BITWAND:
		case BITWOR:
		case BITWXOR:
		case BITWSHIFTL:
		case BITWSHIFTR:
			checkNumParameters(2);
			setBinaryOutputProperties(output);
			break;
		
		case MIN:
		case MAX:
			//min(X), min(X,s), min(s,X), min(s,r), min(X,Y)
			if (getSecondExpr() == null) { //unary
				checkNumParameters(1);
				checkMatrixParam(getFirstExpr());
				output.setDataType(DataType.SCALAR);
				output.setValueType(id.getValueType());
				output.setDimensions(0, 0);
				output.setBlocksize(0);
			}
			else if( getAllExpr().length == 2 ) { //binary
				checkNumParameters(2);
				setBinaryOutputProperties(output);
			}
			else { //nary
				for( Expression e : getAllExpr() )
					checkMatrixScalarParam(e);
				setNaryOutputProperties(output);
			}
			break;
		
		case CUMSUM:
		case CUMPROD:
		case CUMSUMPROD:
		case CUMMIN:
		case CUMMAX:
			// cumsum(X);
			checkNumParameters(1);
			checkMatrixParam(getFirstExpr());
			if( getOpCode() == Builtins.CUMSUMPROD && id.getDim2() > 2 )
				raiseValidateError("Cumsumprod only supported over two-column matrices", conditional);
			
			output.setDataType(DataType.MATRIX);
			output.setDimensions(id.getDim1(), id.getDim2());
			output.setBlocksize (id.getBlocksize());
			output.setValueType(id.getValueType());
			
			break;
		case CAST_AS_SCALAR:
			checkNumParameters(1);
			checkDataTypeParam(getFirstExpr(),
				DataType.MATRIX, DataType.FRAME, DataType.LIST);
			if (( getFirstExpr().getOutput().getDim1() != -1 && getFirstExpr().getOutput().getDim1() !=1)
				|| ( getFirstExpr().getOutput().getDim2() != -1 && getFirstExpr().getOutput().getDim2() !=1)) {
				raiseValidateError("dimension mismatch while casting matrix to scalar: dim1: " + getFirstExpr().getOutput().getDim1() 
					+  " dim2 " + getFirstExpr().getOutput().getDim2(), conditional, LanguageErrorCodes.INVALID_PARAMETERS);
			}
			output.setDataType(DataType.SCALAR);
			output.setDimensions(0, 0);
			output.setBlocksize(0);
			output.setValueType((id.getValueType()!=ValueType.UNKNOWN 
				|| id.getDataType()==DataType.LIST) ? id.getValueType() : ValueType.FP64);
			break;
		case CAST_AS_MATRIX:
			checkNumParameters(1);
			checkDataTypeParam(getFirstExpr(),
				DataType.SCALAR, DataType.FRAME, DataType.LIST);
			output.setDataType(DataType.MATRIX);
			output.setDimensions(id.getDim1(), id.getDim2());
			if( getFirstExpr().getOutput().getDataType()==DataType.SCALAR )
				output.setDimensions(1, 1); //correction scalars
			if( getFirstExpr().getOutput().getDataType()==DataType.LIST )
				output.setDimensions(-1, -1); //correction list: arbitrary object
			output.setBlocksize(id.getBlocksize());
			output.setValueType(ValueType.FP64); //matrices always in double
			break;
		case TYPEOF:
		case DETECTSCHEMA:
		case COLNAMES:
			checkNumParameters(1);
			checkMatrixFrameParam(getFirstExpr());
			output.setDataType(DataType.FRAME);
			output.setDimensions(1, id.getDim2());
			output.setBlocksize (id.getBlocksize());
			output.setValueType(ValueType.STRING);
			break;
		case CAST_AS_FRAME:
			checkNumParameters(1);
			checkDataTypeParam(getFirstExpr(),
			DataType.SCALAR, DataType.MATRIX, DataType.LIST);
			output.setDataType(DataType.FRAME);
			output.setDimensions(id.getDim1(), id.getDim2());
			if( getFirstExpr().getOutput().getDataType()==DataType.SCALAR )
				output.setDimensions(1, 1); //correction scalars
			if( getFirstExpr().getOutput().getDataType()==DataType.LIST )
				output.setDimensions(-1, -1); //correction list: arbitrary object
			output.setBlocksize(id.getBlocksize());
			output.setValueType(id.getValueType());
			break;
		case CAST_AS_DOUBLE:
			checkNumParameters(1);
			checkScalarParam(getFirstExpr());
			output.setDataType(DataType.SCALAR);
			//output.setDataType(id.getDataType()); //TODO whenever we support multiple matrix value types, currently noop.
			output.setDimensions(0, 0);
			output.setBlocksize(0);
			output.setValueType(ValueType.FP64);
			break;
		case CAST_AS_INT:
			checkNumParameters(1);
			checkScalarParam(getFirstExpr());
			output.setDataType(DataType.SCALAR);
			//output.setDataType(id.getDataType()); //TODO whenever we support multiple matrix value types, currently noop.
			output.setDimensions(0, 0);
			output.setBlocksize(0);
			output.setValueType(ValueType.INT64);
			break;
		case CAST_AS_BOOLEAN:
			checkNumParameters(1);
			checkScalarParam(getFirstExpr());
			output.setDataType(DataType.SCALAR);
			//output.setDataType(id.getDataType()); //TODO whenever we support multiple matrix value types, currently noop.
			output.setDimensions(0, 0);
			output.setBlocksize(0);
			output.setValueType(ValueType.BOOLEAN);
			break;
			
		case IFELSE:
			checkNumParameters(3);
			setTernaryOutputProperties(output, conditional);
			break;
			
		case CBIND:
		case RBIND:
			//scalar string append (string concatenation with \n)
			if( getFirstExpr().getOutput().getDataType()==DataType.SCALAR ) {
				checkNumParameters(2);
				checkScalarParam(getFirstExpr());
				checkScalarParam(getSecondExpr());
				checkValueTypeParam(getFirstExpr(), ValueType.STRING);
				checkValueTypeParam(getSecondExpr(), ValueType.STRING);
			}
			// append (rbind/cbind) all the elements of a list
			else if( getAllExpr().length == 1 ) {
				checkDataTypeParam(getFirstExpr(), DataType.LIST);
			}
			else {
				if( getAllExpr().length < 2 )
					raiseValidateError("Invalid number of arguments for "+getOpCode(), conditional);
				//list append
				if(getFirstExpr().getOutput().getDataType().isList() )
					for(int i=1; i<getAllExpr().length; i++)
						checkDataTypeParam(getExpr(i), DataType.SCALAR, DataType.MATRIX, DataType.FRAME, DataType.LIST);
				//matrix append (rbind/cbind)
				else
					for(int i=0; i<getAllExpr().length; i++)
						checkMatrixFrameParam(getExpr(i));
			}
			
			output.setDataType(id.getDataType());
			output.setValueType(id.getValueType());
			if( id.getDataType() == DataType.LIST && getAllExpr().length == 1) {
				output.setDataType(DataType.MATRIX);
				output.setValueType(ValueType.FP64);
			}
			
			// set output dimensions and validate consistency
			long m1rlen = getFirstExpr().getOutput().getDim1();
			long m1clen = getFirstExpr().getOutput().getDim2();
			long appendDim1 = m1rlen, appendDim2 = m1clen;
			
			for(int i=1; i<getAllExpr().length; i++) {
				long m2rlen = getExpr(i).getOutput().getDim1();
				long m2clen = getExpr(i).getOutput().getDim2();
				
				if( getOpCode() == Builtins.CBIND ) {
					if (m1rlen >= 0 && m2rlen >= 0 && m1rlen!=m2rlen) {
						raiseValidateError("inputs to cbind must have same number of rows: input 1 rows: " + 
							m1rlen+", input 2 rows: "+m2rlen, conditional, LanguageErrorCodes.INVALID_PARAMETERS);
					}
					appendDim1 = (m2rlen>=0) ? m2rlen : appendDim1;
					appendDim2 = (appendDim2>=0 && m2clen>=0) ? appendDim2 + m2clen : -1;
				}
				else if( getOpCode() == Builtins.RBIND ) {
					if (m1clen >= 0 && m2clen >= 0 && m1clen!=m2clen) {
						raiseValidateError("inputs to rbind must have same number of columns: input 1 columns: " + 
							m1clen+", input 2 columns: "+m2clen, conditional, LanguageErrorCodes.INVALID_PARAMETERS);
					}
					appendDim1 = (appendDim1>=0 && m2rlen>=0)? appendDim1 + m2rlen : -1;
					appendDim2 = (m2clen>=0) ? m2clen : appendDim2;
				}
			}
			
			if( id.getDataType() == DataType.LIST ) {
				appendDim1 = -1;
				appendDim2 = -1;
			}

			output.setDimensions(appendDim1, appendDim2);
			output.setBlocksize (id.getBlocksize());
			
			break;
			
		case PPRED:
			// TODO: remove this when ppred has been removed from DML
			raiseValidateError("ppred() has been deprecated. Please use the operator directly.", true);

			// ppred (X,Y, "<"); ppred (X,y, "<"); ppred (y,X, "<");
			checkNumParameters(3);
			
			DataType dt1 = getFirstExpr().getOutput().getDataType();
			DataType dt2 = getSecondExpr().getOutput().getDataType();
			
			//check input data types
			if( dt1 == DataType.SCALAR && dt2 == DataType.SCALAR ) {
				raiseValidateError("ppred() requires at least one matrix input.", conditional, LanguageErrorCodes.INVALID_PARAMETERS);
			}			
			if( dt1 == DataType.MATRIX )
				checkMatrixParam(getFirstExpr());
			if( dt2 == DataType.MATRIX )
				checkMatrixParam(getSecondExpr());
			
			//check operator
			if (getThirdExpr().getOutput().getDataType() != DataType.SCALAR || 
				getThirdExpr().getOutput().getValueType() != ValueType.STRING) 
			{	
				raiseValidateError("Third argument in ppred() is not an operator ", conditional, LanguageErrorCodes.INVALID_PARAMETERS);
			}
			
			setBinaryOutputProperties(output);
			break;

		case TRANS:
			checkNumParameters(1);
			checkMatrixParam(getFirstExpr());
			output.setDataType(DataType.MATRIX);
			output.setDimensions(id.getDim2(), id.getDim1());
			output.setBlocksize (id.getBlocksize());
			output.setValueType(id.getValueType());
			break;
		
		case REV:
			checkNumParameters(1);
			checkMatrixParam(getFirstExpr());
			output.setDataType(DataType.MATRIX);
			output.setDimensions(id.getDim1(), id.getDim2());
			output.setBlocksize (id.getBlocksize());
			output.setValueType(id.getValueType());
			break;
			
		case DIAG:
			checkNumParameters(1);
			checkMatrixParam(getFirstExpr());
			output.setDataType(DataType.MATRIX);
			if( id.getDim2() != -1 ) { //type known
				if ( id.getDim2() == 1 ) 
				{
					//diag V2M
					output.setDimensions(id.getDim1(), id.getDim1());
				} 
				else 
				{
					if (id.getDim1() != id.getDim2()) {
						raiseValidateError("diag can either: (1) create diagonal matrix from (n x 1) matrix, or (2) take diagonal from a square matrix. "
								+ "Error invoking diag on matrix with dimensions ("
								+ id.getDim1() + "," + id.getDim2()
								+ ") in " + this.toString(), conditional, LanguageErrorCodes.INVALID_PARAMETERS);
					}
					//diag M2V
					output.setDimensions(id.getDim1(), 1);
				}
			}
			output.setBlocksize(id.getBlocksize());
			output.setValueType(id.getValueType());
			break;
		case NROW:
		case NCOL:
		case LENGTH:
			checkNumParameters(1);
			checkDataTypeParam(getFirstExpr(), 
				DataType.FRAME, DataType.LIST, DataType.MATRIX);
			output.setDataType(DataType.SCALAR);
			output.setDimensions(0, 0);
			output.setBlocksize(0);
			output.setValueType(ValueType.INT64);
			break;
		case COUNT_DISTINCT:
		case COUNT_DISTINCT_APPROX:
			checkNumParameters(1);
			checkDataTypeParam(getFirstExpr(), DataType.MATRIX);
			output.setDataType(DataType.SCALAR);
			output.setDimensions(0, 0);
			output.setBlocksize(0);
			output.setValueType(ValueType.INT64);
			break;
		
		case LINEAGE:
			checkNumParameters(1);
			checkDataTypeParam(getFirstExpr(),
				DataType.MATRIX, DataType.FRAME, DataType.LIST);
			output.setDataType(DataType.SCALAR);
			output.setDimensions(0, 0);
			output.setBlocksize(0);
			output.setValueType(ValueType.STRING);
			break;
			
		case LIST:
			output.setDataType(DataType.LIST);
			output.setValueType(ValueType.UNKNOWN);
			output.setDimensions(getAllExpr().length, 1);
			output.setBlocksize(-1);
			break;
		
		case EXISTS:
			checkNumParameters(1);
			checkStringOrDataIdentifier(getFirstExpr());
			output.setDataType(DataType.SCALAR);
			output.setDimensions(0, 0);
			output.setBlocksize(0);
			output.setValueType(ValueType.BOOLEAN);
			break;
		
		// Contingency tables
		case TABLE:
			
			/*
			 * Allowed #of arguments: 2,3,4,5
			 * table(A,B)
			 * table(A,B,W)
			 * table(A,B,1)
			 * table(A,B,dim1,dim2)
			 * table(A,B,W,dim1,dim2)
			 * table(A,B,1,dim1,dim2)
			 */
			
			// Check for validity of input arguments, and setup output dimensions
			
			// First input: is always of type MATRIX
			checkMatrixParam(getFirstExpr());

			if (getSecondExpr() == null)
				raiseValidateError(
						"Invalid number of arguments to table(). The table() function requires 2, 3, 4, or 5 arguments.",
						conditional);

			// Second input: can be MATRIX or SCALAR
			// cases: table(A,B) or table(A,1)
			if ( getSecondExpr().getOutput().getDataType() == DataType.MATRIX)
				checkMatchingDimensions(getFirstExpr(),getSecondExpr());
			
			long outputDim1=-1, outputDim2=-1;
			
			switch(_args.length) {
			case 2:
				// nothing to do
				break;
				
			case 3:
				// case - table w/ weights
				//        - weights specified as a matrix: table(A,B,W) or table(A,1,W)
				//        - weights specified as a scalar: table(A,B,1) or table(A,1,1)
				if ( getThirdExpr().getOutput().getDataType() == DataType.MATRIX)
					checkMatchingDimensions(getFirstExpr(),getThirdExpr());
				break;
				
			case 4:
				// case - table w/ output dimensions: table(A,B,dim1,dim2) or table(A,1,dim1,dim2)
				// third and fourth arguments must be scalars
				if ( getThirdExpr().getOutput().getDataType() != DataType.SCALAR || _args[3].getOutput().getDataType() != DataType.SCALAR ) {
					raiseValidateError("Invalid argument types to table(): output dimensions must be of type scalar: " 
							+ this.toString(), conditional, LanguageErrorCodes.INVALID_PARAMETERS);
				}
				else {
					// constant propagation
					if( getThirdExpr() instanceof DataIdentifier && constVars.containsKey(((DataIdentifier)getThirdExpr()).getName()) && !conditional )
						_args[2] = constVars.get(((DataIdentifier)getThirdExpr()).getName());
					if( _args[3] instanceof DataIdentifier && constVars.containsKey(((DataIdentifier)_args[3]).getName()) && !conditional )
						_args[3] = constVars.get(((DataIdentifier)_args[3]).getName());
					
					if ( getThirdExpr().getOutput() instanceof ConstIdentifier ) 
						outputDim1 = ((ConstIdentifier) getThirdExpr().getOutput()).getLongValue();
					if ( _args[3].getOutput() instanceof ConstIdentifier ) 
						outputDim2 = ((ConstIdentifier) _args[3].getOutput()).getLongValue();
				}
				break;
				
			case 5:
				// case - table w/ weights and output dimensions: 
				//        - table(A,B,W,dim1,dim2) or table(A,1,W,dim1,dim2)
				//        - table(A,B,1,dim1,dim2) or table(A,1,1,dim1,dim2)
				
				if ( getThirdExpr().getOutput().getDataType() == DataType.MATRIX)
					checkMatchingDimensions(getFirstExpr(),getThirdExpr());
				
				// fourth and fifth arguments must be scalars
				if ( _args[3].getOutput().getDataType() != DataType.SCALAR || _args[4].getOutput().getDataType() != DataType.SCALAR ) {
					raiseValidateError("Invalid argument types to table(): output dimensions must be of type scalar: " 
							+ this.toString(), conditional, LanguageErrorCodes.INVALID_PARAMETERS);
				}
				else {
					// constant propagation
					if( _args[3] instanceof DataIdentifier && constVars.containsKey(((DataIdentifier)_args[3]).getName())  && !conditional )
						_args[3] = constVars.get(((DataIdentifier)_args[3]).getName());
					if( _args[4] instanceof DataIdentifier && constVars.containsKey(((DataIdentifier)_args[4]).getName())  && !conditional )
						_args[4] = constVars.get(((DataIdentifier)_args[4]).getName());
					
					if ( _args[3].getOutput() instanceof ConstIdentifier ) 
						outputDim1 = ((ConstIdentifier) _args[3].getOutput()).getLongValue();
					if ( _args[4].getOutput() instanceof ConstIdentifier ) 
						outputDim2 = ((ConstIdentifier) _args[4].getOutput()).getLongValue();
				}
				break;

			default:
				raiseValidateError("Invalid number of arguments to table(): " 
						+ this.toString(), conditional, LanguageErrorCodes.INVALID_PARAMETERS);
			}
			// The dimensions for the output matrix will be known only at the
			// run time
			output.setDimensions(outputDim1, outputDim2);
			output.setBlocksize (-1);
			output.setDataType(DataType.MATRIX);
			output.setValueType(ValueType.FP64);
			break;

		case MOMENT:
			checkMatrixParam(getFirstExpr());
			if (getThirdExpr() != null) {
				checkNumParameters(3);
				checkMatrixParam(getSecondExpr());
				checkMatchingDimensions(getFirstExpr(),getSecondExpr());
				checkScalarParam(getThirdExpr());
			}
			else {
				checkNumParameters(2);
				checkScalarParam(getSecondExpr());
			}

			// output is a scalar
			output.setDataType(DataType.SCALAR);
			output.setValueType(ValueType.FP64);
			output.setDimensions(0, 0);
			output.setBlocksize(0);
			break;

		case COV:
			/*
			 * x = cov(V1,V2) or xw = cov(V1,V2,W)
			 */
			if (getThirdExpr() != null) {
				checkNumParameters(3);
			}
			else {
				checkNumParameters(2);
			}
			checkMatrixParam(getFirstExpr());
			checkMatrixParam(getSecondExpr());
			checkMatchingDimensions(getFirstExpr(),getSecondExpr());
			
			if (getThirdExpr() != null) {
				checkMatrixParam(getThirdExpr());
			 checkMatchingDimensions(getFirstExpr(), getThirdExpr());
			}

			// output is a scalar
			output.setDataType(DataType.SCALAR);
			output.setValueType(ValueType.FP64);
			output.setDimensions(0, 0);
			output.setBlocksize(0);
			break;

		case QUANTILE:
			/*
			 * q = quantile(V1,0.5) computes median in V1 
			 * or Q = quantile(V1,P) computes the vector of quantiles as specified by P
			 * or qw = quantile(V1,W,0.5) computes median when weights (W) are given
			 * or QW = quantile(V1,W,P) computes the vector of quantiles as specified by P, when weights (W) are given
			 */
			if(getThirdExpr() != null) {
				checkNumParameters(3);
			}
			else {
				checkNumParameters(2);
			}
			
			// first parameter must always be a 1D matrix 
			check1DMatrixParam(getFirstExpr());
			
			// check for matching dimensions for other matrix parameters
			if (getThirdExpr() != null) {
				checkMatrixParam(getSecondExpr());
				checkMatchingDimensions(getFirstExpr(), getSecondExpr());
			}
			
			// set the properties for _output expression
			// output dimensions = dimensions of second, if third is null
			//                   = dimensions of the third, otherwise.

			if (getThirdExpr() != null) {
				output.setDimensions(getThirdExpr().getOutput().getDim1(), getThirdExpr().getOutput().getDim2());
				output.setBlocksize(getThirdExpr().getOutput().getBlocksize());
				output.setDataType(getThirdExpr().getOutput().getDataType());
			} else {
				output.setDimensions(getSecondExpr().getOutput().getDim1(), getSecondExpr().getOutput().getDim2());
				output.setBlocksize(getSecondExpr().getOutput().getBlocksize());
				output.setDataType(getSecondExpr().getOutput().getDataType());
			}
			break;

		case INTERQUANTILE:
			if (getThirdExpr() != null) {
			    checkNumParameters(3);
			}
			else {
				checkNumParameters(2);
			}
			checkMatrixParam(getFirstExpr());
			if (getThirdExpr() != null) {
				// i.e., second input is weight vector
				checkMatrixParam(getSecondExpr());
				checkMatchingDimensionsQuantile();
			}

			if ((getThirdExpr() == null && getSecondExpr().getOutput().getDataType() != DataType.SCALAR)
					&& (getThirdExpr() != null && getThirdExpr().getOutput().getDataType() != DataType.SCALAR)) {
				
				raiseValidateError("Invalid parameters to "+ this.getOpCode(), conditional, LanguageErrorCodes.INVALID_PARAMETERS);
			}

			output.setValueType(id.getValueType());
			// output dimensions are unknown
			output.setDimensions(-1, -1);
			output.setBlocksize(-1);
			output.setDataType(DataType.MATRIX);
			break;

		case IQM:
			/*
			 * Usage: iqm = InterQuartileMean(A,W); iqm = InterQuartileMean(A);
			 */
			if (getSecondExpr() != null){
			    checkNumParameters(2);
		    }
			else {
				checkNumParameters(1);
			}
			checkMatrixParam(getFirstExpr());

			if (getSecondExpr() != null) {
				// i.e., second input is weight vector
				checkMatrixParam(getSecondExpr());
				checkMatchingDimensions(getFirstExpr(), getSecondExpr());
			}

			// Output is a scalar
			output.setValueType(id.getValueType());
			output.setDimensions(0, 0);
			output.setBlocksize(0);
			output.setDataType(DataType.SCALAR);

			break;
		
		case ISNA:
		case ISNAN:
		case ISINF:
			checkNumParameters(1);
			checkMatrixScalarParam(getFirstExpr());
			output.setDataType(id.getDataType());
			output.setDimensions(id.getDim1(), id.getDim2());
			output.setBlocksize (id.getBlocksize());
			//TODO set output type to boolean when supported
			output.setValueType(id.getValueType());
			break;
			
		case MEDIAN:
			checkNumParameters((getSecondExpr()!=null) ? 2 : 1);
			checkMatrixParam(getFirstExpr());

			if (getSecondExpr() != null) {
				// i.e., second input is weight vector
				checkMatrixParam(getSecondExpr());
				checkMatchingDimensions(getFirstExpr(), getSecondExpr());
			}

			// Output is a scalar
			output.setValueType(id.getValueType());
			output.setDimensions(0, 0);
			output.setBlocksize(0);
			output.setDataType(DataType.SCALAR);

			break;
			
		case SAMPLE:
		{
			Expression[] in = getAllExpr(); 
			
			for(Expression e : in)
				checkScalarParam(e);
			
			if (in[0].getOutput().getValueType() != ValueType.FP64 && in[0].getOutput().getValueType() != ValueType.INT64) 
				throw new LanguageException("First argument to sample() must be a number.");
			if (in[1].getOutput().getValueType() != ValueType.FP64 && in[1].getOutput().getValueType() != ValueType.INT64) 
				throw new LanguageException("Second argument to sample() must be a number.");
			
			boolean check = false;
			if ( isConstant(in[0]) && isConstant(in[1]) )
			{
				long range = ((ConstIdentifier)in[0]).getLongValue();
				long size = ((ConstIdentifier)in[1]).getLongValue();
				if ( range < size )
					check = true;
			}
			
			if(in.length == 4 )
			{
				checkNumParameters(4);
				if (in[3].getOutput().getValueType() != ValueType.INT64) 
					throw new LanguageException("Fourth arugment, seed, to sample() must be an integer value.");
				if (in[2].getOutput().getValueType() != ValueType.BOOLEAN ) 
					throw new LanguageException("Third arugment to sample() must either denote replacement policy (boolean) or seed (integer).");
			}
			else if(in.length == 3) 
			{
				checkNumParameters(3);
				if (in[2].getOutput().getValueType() != ValueType.BOOLEAN 
						&& in[2].getOutput().getValueType() != ValueType.INT64 ) 
					throw new LanguageException("Third arugment to sample() must either denote replacement policy (boolean) or seed (integer).");
			}
			
			if ( check && in.length >= 3 
					&& isConstant(in[2]) 
					&& in[2].getOutput().getValueType() == ValueType.BOOLEAN  
					&& !((BooleanIdentifier)in[2]).getValue() )
				throw new LanguageException("Sample (size=" + ((ConstIdentifier)in[0]).getLongValue() 
						+ ") larger than population (size=" + ((ConstIdentifier)in[1]).getLongValue() 
						+ ") can only be generated with replacement.");
			
			// Output is a column vector
			output.setDataType(DataType.MATRIX);
			output.setValueType(ValueType.FP64);
			
			if ( isConstant(in[1]) )
	 			output.setDimensions(((ConstIdentifier)in[1]).getLongValue(), 1);
			else
				output.setDimensions(-1, 1);
 			setBlocksize(id.getBlocksize());
 			
			break;
		}
		case SEQ:
			
			//basic parameter validation
			checkScalarParam(getFirstExpr());
			checkScalarParam(getSecondExpr());
			if ( getThirdExpr() != null ) {
				checkNumParameters(3);
				checkScalarParam(getThirdExpr());
			}
			else
				checkNumParameters(2);
			
			// constant propagation (from, to, incr)
			if( !conditional ) {
				if( getFirstExpr() instanceof DataIdentifier && constVars.containsKey(((DataIdentifier)getFirstExpr()).getName()) )
					_args[0] = constVars.get(((DataIdentifier)getFirstExpr()).getName());
				if( getSecondExpr() instanceof DataIdentifier && constVars.containsKey(((DataIdentifier)getSecondExpr()).getName()) )
					_args[1] = constVars.get(((DataIdentifier)getSecondExpr()).getName());
				if( getThirdExpr()!=null && getThirdExpr() instanceof DataIdentifier && constVars.containsKey(((DataIdentifier)getThirdExpr()).getName()) )
					_args[2] = constVars.get(((DataIdentifier)getThirdExpr()).getName());
			}
			
			// check if dimensions can be inferred
			long dim1=-1, dim2=1;
			if ( isConstant(getFirstExpr()) && isConstant(getSecondExpr()) && (getThirdExpr() != null ? isConstant(getThirdExpr()) : true) ) {
				double from, to, incr;
				try {
					from = getDoubleValue(getFirstExpr());
					to = getDoubleValue(getSecondExpr());
					
					// Setup the value of increment
					// default value: 1 if from <= to; -1 if from > to
					if(getThirdExpr() == null) {
						expandArguments();
						_args[2] = new DoubleIdentifier(((from > to) ? -1.0 : 1.0), this);
					}
					incr = getDoubleValue(getThirdExpr()); 
					
				}
				catch (LanguageException e) {
					throw new LanguageException("Arguments for seq() must be numeric.");
				}

				if( (from > to) && (incr >= 0) )
					throw new LanguageException("Wrong sign for the increment in a call to seq()");
				
				// Both end points of the range must included i.e., [from,to] both inclusive.
				// Note that, "to" is included only if (to-from) is perfectly divisible by incr
				// For example, seq(0,1,0.5) produces (0.0 0.5 1.0) whereas seq(0,1,0.6) produces only (0.0 0.6) but not (0.0 0.6 1.0)
				dim1 = UtilFunctions.getSeqLength(from, to, incr);
			}
			output.setDataType(DataType.MATRIX);
			output.setValueType(ValueType.FP64);
			output.setDimensions(dim1, dim2);
			output.setBlocksize(0);
			break;

		case SOLVE:
			checkNumParameters(2);
			checkMatrixParam(getFirstExpr());
			checkMatrixParam(getSecondExpr());
			
			if ( getSecondExpr().getOutput().dimsKnown() && !is1DMatrix(getSecondExpr()) )
				raiseValidateError("Second input to solve() must be a vector", conditional);
			
			if ( getFirstExpr().getOutput().dimsKnown() && getSecondExpr().getOutput().dimsKnown() && 
					getFirstExpr().getOutput().getDim1() != getSecondExpr().getOutput().getDim1() &&
					getFirstExpr().getOutput().getDim1() != getFirstExpr().getOutput().getDim2())
				raiseValidateError("Dimension mismatch in a call to solve()", conditional);
			
			output.setDataType(DataType.MATRIX);
			output.setValueType(ValueType.FP64);
			output.setDimensions(getFirstExpr().getOutput().getDim2(), 1);
			output.setBlocksize(0);
			break;
		
		case INVERSE:
			checkNumParameters(1);
			checkMatrixParam(getFirstExpr());
			
			output.setDataType(DataType.MATRIX);
			output.setValueType(ValueType.FP64);
			
			Identifier in = getFirstExpr().getOutput();
			if(in.dimsKnown() && in.getDim1() != in.getDim2()) 
				raiseValidateError("Input to inv() must be square matrix -- given: a " + in.getDim1() + "x" + in.getDim2() + " matrix.", conditional);
			
			output.setDimensions(in.getDim1(), in.getDim2());
			output.setBlocksize(in.getBlocksize());
			break;
		
		case CHOLESKY:
		{
			// A = L%*%t(L) where L is the lower triangular matrix
			checkNumParameters(1);
			checkMatrixParam(getFirstExpr());

			output.setDataType(DataType.MATRIX);
			output.setValueType(ValueType.FP64);
			
			Identifier inA = getFirstExpr().getOutput();
			if(inA.dimsKnown() && inA.getDim1() != inA.getDim2()) 
				raiseValidateError("Input to cholesky() must be square matrix -- given: a " + inA.getDim1() + "x" + inA.getDim2() + " matrix.", conditional);
			
			output.setDimensions(inA.getDim1(), inA.getDim2());
			output.setBlocksize(inA.getBlocksize());
			break;
		}

		case OUTER:
			Identifier id2 = this.getSecondExpr().getOutput();
			
			//check input types and characteristics
			checkNumParameters(3);
			checkMatrixParam(getFirstExpr());
			checkMatrixParam(getSecondExpr());
			checkScalarParam(getThirdExpr());
			checkValueTypeParam(getThirdExpr(), ValueType.STRING);
			if( id.getDim2() > 1 || id2.getDim1()>1 ) {
				raiseValidateError("Outer vector operations require a common dimension of one: " +
					id.getDim1()+"x"+id.getDim2()+" o "+id2.getDim1()+"x"+id2.getDim2()+".", false);
			}
			
			//set output characteristics
			output.setDataType(id.getDataType());
			output.setDimensions(id.getDim1(), id2.getDim2());
			output.setBlocksize(id.getBlocksize());
			break;
		
		case BIASADD:
		case BIASMULT:
		{
			Expression input = _args[0];
			Expression bias = _args[1];
			output.setDataType(DataType.MATRIX);
			output.setValueType(ValueType.FP64);
			output.setDimensions(input.getOutput().getDim1(), input.getOutput().getDim2());
			output.setBlocksize(input.getOutput().getBlocksize());
			checkMatrixParam(input);
			checkMatrixParam(bias);
			break;
		}
		case CONV2D:
		case CONV2D_BACKWARD_FILTER:
		case CONV2D_BACKWARD_DATA:
		case MAX_POOL:
		case AVG_POOL:
		case MAX_POOL_BACKWARD:
		case AVG_POOL_BACKWARD:
		{
			// At DML level:
			// output = conv2d(input, filter, input_shape=[1, 3, 2, 2], filter_shape=[1, 3, 2, 2], 
			// strides=[1, 1], padding=[1,1])
			// 
			// Converted to following in constructor (only supported NCHW):
			// output = conv2d(input, filter, stride1, stride2, padding1,padding2,  
			// input_shape1, input_shape2, input_shape3, input_shape4, 
			// filter_shape1, filter_shape2, filter_shape3, filter_shape4)
			//
			// Similarly,
			// conv2d_backward_filter and conv2d_backward_data
			Expression input = _args[0]; // For conv2d_backward_filter, this is input and for conv2d_backward_data, this is filter
			
			Expression input2 = null;
			if(!(this.getOpCode() == Builtins.MAX_POOL || this.getOpCode() == Builtins.AVG_POOL)) {
				input2 = _args[1];			// For conv2d_backward functions, this is dout
				checkMatrixParam(input2);
			}
			output.setDataType(DataType.MATRIX);
			output.setValueType(ValueType.FP64);
			output.setBlocksize(input.getOutput().getBlocksize());
			
			if(this.getOpCode() == Builtins.MAX_POOL_BACKWARD || this.getOpCode() == Builtins.AVG_POOL_BACKWARD) {
				output.setDimensions(input.getOutput().getDim1(), input.getOutput().getDim2());
			}
			else {
				// stride1, stride2, padding1, padding2, numImg, numChannels, imgSize, imgSize, 
	 			// filter_shape1=1, filter_shape2=1, filterSize/poolSize1, filterSize/poolSize1
				try {
					int start = 2;
					if(!(this.getOpCode() == Builtins.MAX_POOL || this.getOpCode() == Builtins.AVG_POOL)) {
						start = 1;
					}
					long stride_h = (long) getDoubleValue(_args[start++]);
					long stride_w = (long) getDoubleValue(_args[start++]);
					long pad_h = (long) getDoubleValue(_args[start++]);
					long pad_w = (long) getDoubleValue(_args[start++]); 
					long N = (long) getDoubleValue(_args[start++]);
					long C = (long) getDoubleValue(_args[start++]);
					long H = (long) getDoubleValue(_args[start++]);
					long W = (long) getDoubleValue(_args[start++]);
					long K = -1;
					if(!(this.getOpCode() == Builtins.MAX_POOL || this.getOpCode() == Builtins.AVG_POOL)) {
						K = (long) getDoubleValue(_args[start]);
					}
					start++; start++; // Increment index for K and C
					long R = (long) getDoubleValue(_args[start++]);
					long S = (long) getDoubleValue(_args[start++]);
					
					if(this.getOpCode() == Builtins.CONV2D_BACKWARD_FILTER) {
						output.setDimensions(K, C*R*S);
					}
					else if(this.getOpCode() == Builtins.CONV2D_BACKWARD_DATA) {
						output.setDimensions(N, C*H*W);
					}
					else if(H > 0 && W > 0 && stride_h > 0 && stride_w > 0 && pad_h >= 0 && pad_w >= 0 && R > 0 && S > 0) {
						long P = DnnUtils.getP(H, R, stride_h, pad_h);
						long Q = DnnUtils.getQ(W, S, stride_w, pad_w);
						
						// Try to set both rows and columns
						if(this.getOpCode() == Builtins.CONV2D) 
							output.setDimensions(N, K*P*Q);
						else if(this.getOpCode() == Builtins.MAX_POOL || this.getOpCode() == Builtins.AVG_POOL)
							output.setDimensions(N, C*P*Q);
						else
							throw new LanguageException("");
					}
					else {
						// Since columns cannot be computed, set only rows
						if(this.getOpCode() == Builtins.CONV2D) 
							output.setDimensions(input.getOutput().getDim1(), -1);
						else if(this.getOpCode() == Builtins.MAX_POOL || this.getOpCode() == Builtins.AVG_POOL)
							output.setDimensions(input.getOutput().getDim1(), -1);
						else
							throw new LanguageException("");
					}
				}
				catch(Exception e) {
					output.setDimensions(-1, -1); // To make sure that output dimensions are not incorrect even if getDoubleValue doesnot return value
				}
			}
			checkMatrixParam(input);
			if(input2 != null)
				checkMatrixParam(input2);
			break;
		}
		case TIME: 
			checkNumParameters(0);
			// Output of TIME() is scalar and long
			output.setDataType(DataType.SCALAR);
			output.setValueType(ValueType.INT64);
			output.setDimensions(0, 0);
			output.setBlocksize(0);
			break;

		case DROP_INVALID_TYPE:
			checkNumParameters(2);
			checkMatrixFrameParam(getFirstExpr());
			checkMatrixFrameParam(getSecondExpr());
			output.setDataType(DataType.FRAME);
			output.setDimensions(id.getDim1(), id.getDim2());
			output.setBlocksize (id.getBlocksize());
			output.setValueType(ValueType.STRING);
			break;

		case DROP_INVALID_LENGTH:
			checkNumParameters(2);
			checkMatrixFrameParam(getFirstExpr());
			checkMatrixFrameParam(getSecondExpr());
			output.setDataType(DataType.FRAME);
			output.setDimensions(id.getDim1(), id.getDim2());
			output.setBlocksize (id.getBlocksize());
			output.setValueType(id.getValueType());
			break;

		case MAP:
			checkNumParameters(2);
			checkMatrixFrameParam(getFirstExpr());
			checkScalarParam(getSecondExpr());
			output.setDataType(DataType.FRAME);
			output.setDimensions(id.getDim1(), 1);
			output.setBlocksize (id.getBlocksize());
			output.setValueType(ValueType.STRING);
			break;

		default:
			if( isMathFunction() ) {
				checkMathFunctionParam();
				//unary operations
				if( getSecondExpr() == null ) {
					output.setDataType(id.getDataType());
					output.setValueType((output.getDataType()==DataType.SCALAR
						&& getOpCode()==Builtins.ABS)?id.getValueType():ValueType.FP64 );
					output.setDimensions(id.getDim1(), id.getDim2());
					output.setBlocksize(id.getBlocksize()); 
				}
				//binary operations
				else {
					setBinaryOutputProperties(output);
					// override computed value type for special cases
					if( getOpCode() == Builtins.LOG )
						output.setValueType(ValueType.FP64);
				}
			} 
			else {
				// always unconditional (because unsupported operation)
				Builtins op = getOpCode();
				if( op==Builtins.EIGEN || op==Builtins.LU || op==Builtins.QR || op==Builtins.SVD 
						|| op==Builtins.LSTM || op==Builtins.LSTM_BACKWARD
						|| op==Builtins.BATCH_NORM2D || op==Builtins.BATCH_NORM2D_BACKWARD)
					raiseValidateError("Function "+op+" needs to be called with multi-return assignment.", false, LanguageErrorCodes.INVALID_PARAMETERS);
				else
					raiseValidateError("Unsupported function "+op, false, LanguageErrorCodes.INVALID_PARAMETERS);
			}
		}
	}
	
	private void setBinaryOutputProperties(DataIdentifier output) {
		DataType dt1 = getFirstExpr().getOutput().getDataType();
		DataType dt2 = getSecondExpr().getOutput().getDataType();
		DataType dtOut = (dt1==DataType.MATRIX || dt2==DataType.MATRIX) ?
			DataType.MATRIX : DataType.SCALAR;
		if( dt1==DataType.MATRIX && dt2==DataType.MATRIX )
			checkMatchingDimensions(getFirstExpr(), getSecondExpr(), true);
		MatrixCharacteristics dims = getBinaryMatrixCharacteristics(getFirstExpr(), getSecondExpr());
		output.setDataType(dtOut);
		output.setValueType(dtOut==DataType.MATRIX ? ValueType.FP64 :
			computeValueType(getFirstExpr(), getSecondExpr(), true));
		output.setDimensions(dims.getRows(), dims.getCols());
		output.setBlocksize (dims.getBlocksize());
	}
	
	private void setTernaryOutputProperties(DataIdentifier output, boolean conditional) {
		DataType dt1 = getFirstExpr().getOutput().getDataType();
		DataType dt2 = getSecondExpr().getOutput().getDataType();
		DataType dt3 = getThirdExpr().getOutput().getDataType();
		DataType dtOut = (dt1.isMatrix() || dt2.isMatrix() || dt3.isMatrix()) ?
			DataType.MATRIX : DataType.SCALAR;
		if( dt1==DataType.MATRIX && dt2==DataType.MATRIX )
			checkMatchingDimensions(getFirstExpr(), getSecondExpr(), false, conditional);
		if( dt1==DataType.MATRIX && dt3==DataType.MATRIX )
			checkMatchingDimensions(getFirstExpr(), getThirdExpr(), false, conditional);
		if( dt2==DataType.MATRIX && dt3==DataType.MATRIX )
			checkMatchingDimensions(getSecondExpr(), getThirdExpr(), false, conditional);
		MatrixCharacteristics dims1 = getBinaryMatrixCharacteristics(getFirstExpr(), getSecondExpr());
		MatrixCharacteristics dims2 = getBinaryMatrixCharacteristics(getSecondExpr(), getThirdExpr());
		output.setDataType(dtOut);
		output.setValueType(dtOut==DataType.MATRIX ? ValueType.FP64 :
			computeValueType(getSecondExpr(), getThirdExpr(), true));
		output.setDimensions(Math.max(dims1.getRows(), dims2.getRows()), Math.max(dims1.getCols(), dims2.getCols()));
		output.setBlocksize(Math.max(dims1.getBlocksize(), dims2.getBlocksize()));
	}
	
	private void setNaryOutputProperties(DataIdentifier output) {
		DataType dt = Arrays.stream(getAllExpr()).allMatch(
			e -> e.getOutput().getDataType().isScalar()) ? DataType.SCALAR : DataType.MATRIX;
		Expression firstM = dt.isMatrix() ? Arrays.stream(getAllExpr()).filter(
			e -> e.getOutput().getDataType().isMatrix()).findFirst().get() : null;
		ValueType vt = dt.isMatrix() ? ValueType.FP64 : ValueType.INT64;
		for( Expression e : getAllExpr() ) {
			vt = computeValueType(e, e.getOutput().getValueType(), vt, true);
			if( e.getOutput().getDataType().isMatrix() )
				checkMatchingDimensions(firstM, e, true);
		}
		output.setDataType(dt);
		output.setValueType(vt);
		output.setDimensions(dt.isMatrix() ? firstM.getOutput().getDim1() : 0,
			dt.isMatrix() ? firstM.getOutput().getDim2() : 0);
		output.setBlocksize (dt.isMatrix() ? firstM.getOutput().getBlocksize() : 0);
	}
	
	private void expandArguments() {
	
		if ( _args == null ) {
			_args = new Expression[1];
			return;
		}
		Expression [] temp = _args.clone();
		_args = new Expression[_args.length + 1];
		System.arraycopy(temp, 0, _args, 0, temp.length);
	}
	
	@Override
	public boolean multipleReturns() {
		return _opcode.isMultiReturn();
	}

	private static boolean isConstant(Expression expr) {
		return ( expr != null && expr instanceof ConstIdentifier );
	}
	
	private static double getDoubleValue(Expression expr) {
		if ( expr instanceof DoubleIdentifier )
			return ((DoubleIdentifier)expr).getValue();
		else if ( expr instanceof IntIdentifier)
			return ((IntIdentifier)expr).getValue();
		else
			throw new LanguageException("Expecting a numeric value.");
	}
	
	private boolean isMathFunction() {
		switch (this.getOpCode()) {
		case COS:
		case SIN:
		case TAN:
		case ACOS:
		case ASIN:
		case ATAN:
		case COSH:
		case SINH:
		case TANH:
		case SIGN:
		case SQRT:
		case ABS:
		case LOG:
		case EXP:
		case ROUND:
		case CEIL:
		case FLOOR:
		case MEDIAN:
		case XOR:
		case BITWAND:
		case BITWOR:
		case BITWXOR:
		case BITWSHIFTL:
		case BITWSHIFTR:
			return true;
		default:
			return false;
		}
	}

	private void checkMathFunctionParam() {
		switch (this.getOpCode()) {
		case COS:
		case SIN:
		case TAN:
		case ACOS:
		case ASIN:
		case ATAN:
		case COSH:
		case SINH:
		case TANH:
		case SIGN:	
		case SQRT:
		case ABS:
		case EXP:
		case ROUND:
		case CEIL:
		case FLOOR:
		case MEDIAN:
			checkNumParameters(1);
			break;
		case LOG:
			if (getSecondExpr() != null) {
			  checkNumParameters(2);
			}
			else {
			  checkNumParameters(1);
			}
			break;
		default:
			//always unconditional
			raiseValidateError("Unknown math function "+ this.getOpCode(), false);
		}
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder(_opcode.toString() + "(");
		if (_args != null) {
			for (int i = 0; i < _args.length; i++) {
				if (i > 0) {
					sb.append(",");
				}
				sb.append(_args[i].toString());
			}
		}
		sb.append(")");
		return sb.toString();
	}

	@Override
	// third part of expression IS NOT a variable -- it is the OP to be applied
	public VariableSet variablesRead() {
		VariableSet result = new VariableSet();
		
		for(int i=0; i<_args.length; i++) {
			result.addVariables(_args[i].variablesRead());
		}
		
		return result;
	}

	@Override
	public VariableSet variablesUpdated() {
		VariableSet result = new VariableSet();
		// result.addVariables(_first.variablesUpdated());
		return result;
	}

	protected void checkNumParameters(int count) { //always unconditional
		if (getFirstExpr() == null && _args.length > 0) {
			raiseValidateError("Missing argument for function " + this.getOpCode(), false,
				LanguageErrorCodes.INVALID_PARAMETERS);
		}
		
		// Not sure the rationale for the first two if loops, but will keep them for backward compatibility
		if (((count == 1) && (getSecondExpr() != null || getThirdExpr() != null))
				|| ((count == 2) && (getThirdExpr() != null))) {
			raiseValidateError("Invalid number of arguments for function " + this.getOpCode().toString().toLowerCase()
					+ "(). This function only takes 1 or 2 arguments.", false);
		} else if (((count == 2) && (getSecondExpr() == null))
				|| ((count == 3) && (getSecondExpr() == null || getThirdExpr() == null))) {
			raiseValidateError("Missing argument for function " + this.getOpCode(), false,
					LanguageErrorCodes.INVALID_PARAMETERS);
		} else if(count > 0 && (_args == null || _args.length < count)) {
			raiseValidateError("Missing argument for function " + this.getOpCode(), false,
					LanguageErrorCodes.INVALID_PARAMETERS);
		} else if (count == 0 && (_args.length > 0
				|| getSecondExpr() != null || getThirdExpr() != null)) {
			raiseValidateError("Missing argument for function " + this.getOpCode()
				+ "(). This function doesn't take any arguments.", false);
		}
	}

	protected void checkMatrixParam(Expression e) {
		if (e.getOutput().getDataType() != DataType.MATRIX) {
			raiseValidateError("Expected " + e.getText() + " to be a matrix argument for function " +
					this.getOpCode().toString().toLowerCase() + "().", false);
		}
	}
	
	protected void checkMatrixTensorParam(Expression e) {
		if (e.getOutput().getDataType() != DataType.MATRIX) {
			// Param is not a matrix
			// TODO get supported Operations form builtins
			if (e.getOutput().getDataType() != DataType.TENSOR || getOpCode() != Builtins.SUM) {
				// Param is also not a tensor, or the operation is not supported on tensor
				raiseValidateError("Expected " + e.getText() + " to be a matrix or tensor argument for function "
						+ this.getOpCode().toString().toLowerCase() + "().", false);
			}
		}
	}

	protected void checkDataTypeParam(Expression e, DataType... dt) { //always unconditional
		if( !ArrayUtils.contains(dt, e.getOutput().getDataType()) )
			raiseValidateError("Non-matching expected data type for function "+ getOpCode(), false, LanguageErrorCodes.UNSUPPORTED_PARAMETERS);
	}
	
	protected void checkMatrixFrameParam(Expression e) { //always unconditional
		if (e.getOutput().getDataType() != DataType.MATRIX && e.getOutput().getDataType() != DataType.FRAME) {
			raiseValidateError("Expecting matrix or frame parameter for function "+ getOpCode(), false, LanguageErrorCodes.UNSUPPORTED_PARAMETERS);
		}
	}
	
	protected void checkMatrixScalarParam(Expression e) { //always unconditional
		if (e.getOutput().getDataType() != DataType.MATRIX && e.getOutput().getDataType() != DataType.SCALAR) {
			raiseValidateError("Expecting matrix or scalar parameter for function "+ getOpCode(), false, LanguageErrorCodes.UNSUPPORTED_PARAMETERS);
		}
	}
	
	private void checkScalarParam(Expression e) { //always unconditional
		if (e.getOutput().getDataType() != DataType.SCALAR) {
			raiseValidateError("Expecting scalar parameter for function " + getOpCode(), false, LanguageErrorCodes.UNSUPPORTED_PARAMETERS);
		}
	}
	
	private void checkListParam(Expression e) { //always unconditional
		if (e.getOutput().getDataType() != DataType.LIST) {
			raiseValidateError("Expecting scalar parameter for function " + getOpCode(), false, LanguageErrorCodes.UNSUPPORTED_PARAMETERS);
		}
	}
	
	@SuppressWarnings("unused")
	private void checkScalarFrameParam(Expression e) { //always unconditional
		if (e.getOutput().getDataType() != DataType.SCALAR && e.getOutput().getDataType() != DataType.FRAME) {
			raiseValidateError("Expecting scalar parameter for function " + getOpCode(), false, LanguageErrorCodes.UNSUPPORTED_PARAMETERS);
		}
	}

	private void checkValueTypeParam(Expression e, ValueType vt) { //always unconditional
		if (e.getOutput().getValueType() != vt) {
			raiseValidateError("Expecting parameter of different value type " + this.getOpCode(), false, LanguageErrorCodes.UNSUPPORTED_PARAMETERS);
		}
	}
	
	protected void checkStringOrDataIdentifier(Expression e) { //always unconditional
		if( !(e.getOutput().getDataType().isScalar() && e.getOutput().getValueType()==ValueType.STRING)
			&& !(e instanceof DataIdentifier && !(e instanceof IndexedIdentifier)) ) {
			raiseValidateError("Expecting variable name or data identifier "+ getOpCode(), false, LanguageErrorCodes.UNSUPPORTED_PARAMETERS);
		}
	}
	
	private static boolean is1DMatrix(Expression e) {
		return (e.getOutput().getDim1() == 1 || e.getOutput().getDim2() == 1 );
	}
	
	private static boolean dimsKnown(Expression e) {
		return (e.getOutput().getDim1() != -1 && e.getOutput().getDim2() != -1);
	}
	
	private void check1DMatrixParam(Expression e) { //always unconditional
		checkMatrixParam(e);
		
		// throw an exception, when e's output is NOT a one-dimensional matrix 
		// the check must be performed only when the dimensions are known at compilation time
		if ( dimsKnown(e) && !is1DMatrix(e)) {
			raiseValidateError("Expecting one-dimensional matrix parameter for function "
					          + this.getOpCode(), false, LanguageErrorCodes.UNSUPPORTED_PARAMETERS);
		}
	}

	private void checkMatchingDimensions(Expression expr1, Expression expr2) {
		checkMatchingDimensions(expr1, expr2, false);
	}
	
	private void checkMatchingDimensions(Expression expr1, Expression expr2, boolean allowsMV) {
		checkMatchingDimensions(expr1, expr2, allowsMV, false);
	}
	
	private void checkMatchingDimensions(Expression expr1, Expression expr2, boolean allowsMV, boolean conditional) 
	{
		if (expr1 != null && expr2 != null) {
			
			// if any matrix has unknown dimensions, simply return
			if(  expr1.getOutput().getDim1() == -1 || expr2.getOutput().getDim1() == -1 
			   ||expr1.getOutput().getDim2() == -1 || expr2.getOutput().getDim2() == -1 ) 
			{
				return;
			}
			else if( (!allowsMV && expr1.getOutput().getDim1() != expr2.getOutput().getDim1())
				  || (allowsMV && expr1.getOutput().getDim1() != expr2.getOutput().getDim1() && expr2.getOutput().getDim1() != 1)
				  || (!allowsMV && expr1.getOutput().getDim2() != expr2.getOutput().getDim2()) 
				  || (allowsMV && expr1.getOutput().getDim2() != expr2.getOutput().getDim2() && expr2.getOutput().getDim2() != 1) ) 
			{
				raiseValidateError("Mismatch in matrix dimensions of parameters for function "
						+ this.getOpCode(), conditional, LanguageErrorCodes.INVALID_PARAMETERS);
			}
		}
	}
	
	private void checkMatchingDimensionsQuantile() 
	{
		if (getFirstExpr().getOutput().getDim1() != getSecondExpr().getOutput().getDim1()) {
			raiseValidateError("Mismatch in matrix dimensions for "
					+ this.getOpCode(), false, LanguageErrorCodes.INVALID_PARAMETERS);
		}
	}

	public static BuiltinFunctionExpression getBuiltinFunctionExpression(ParserRuleContext ctx, 
		String functionName, ArrayList<ParameterExpression> paramExprsPassed, String filename) {
		
		if (functionName == null || paramExprsPassed == null)
			return null;
		
		// check if the function name is built-in function
		//	(assign built-in function op if function is built-in
		
				
		return (Builtins.contains(functionName, false, false) 
			&& (paramExprsPassed.stream().anyMatch(p -> p.getName()==null) //at least one unnamed
				|| paramExprsPassed.size() == 0)) ? 
			new BuiltinFunctionExpression(ctx, Builtins.get(functionName), paramExprsPassed, filename) : null;
	}
	
	/**
	 * Convert a value type (double, int, or boolean) to a built-in function operator.
	 * 
	 * @param vt Value type ({@code ValueType.DOUBLE}, {@code ValueType.INT}, or {@code ValueType.BOOLEAN}).
	 * @return Built-in function operator ({@code Builtins.AS_DOUBLE},
	 * {@code Builtins.AS_INT}, or {@code Builtins.AS_BOOLEAN}).
	 */
	public static Builtins getValueTypeCastOperator( ValueType vt ) {
		switch( vt )
		{
			case FP64:
				return Builtins.CAST_AS_DOUBLE;
			case INT64:
				return Builtins.CAST_AS_INT;
			case BOOLEAN:
				return Builtins.CAST_AS_BOOLEAN;
			default:
				throw new LanguageException("No cast for value type "+vt);
		}
	}
}
