/*
 * 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 java.util.ArrayList;
import java.util.HashMap;

import org.apache.sysds.runtime.util.UtilFunctions;

public class IndexedIdentifier extends DataIdentifier 
{
	
	// stores the expressions containing the ranges for the 
	private Expression 	_rowLowerBound = null, _rowUpperBound = null, _colLowerBound = null, _colUpperBound = null;
	
	// stores whether row / col indices have same value (thus selecting either (1 X n) row-vector OR (n X 1) col-vector)
	private boolean _rowLowerEqualsUpper = false, _colLowerEqualsUpper = false;
	
	// 	for IndexedIdentifier, dim1 and dim2 will ultimately be the dimensions of the indexed region and NOT the dims of what is being indexed
	// 	E.g., for A[1:10,1:10], where A = Rand (rows = 20, cols = 20), dim1 = 10, dim2 = 10, origDim1 = 20, origDim2 = 20
	
	// stores the dimensions of Identifier prior to indexing 
	private long _origDim1, _origDim2;
	
	public boolean getRowLowerEqualsUpper(){
		return _rowLowerEqualsUpper;
	}
	
	public boolean getColLowerEqualsUpper() {
		return _colLowerEqualsUpper;
	}
	
	public void setRowLowerEqualsUpper(boolean passed){
		_rowLowerEqualsUpper  = passed;
	}
	
	public void setColLowerEqualsUpper(boolean passed) {
		_colLowerEqualsUpper = passed;
	}
	
	public IndexedIdentifier(String name, boolean passedRows, boolean passedCols){
		super(name);
		_rowLowerBound = null; 
   		_rowUpperBound = null; 
   		_colLowerBound = null; 
   		_colUpperBound = null;
   		
   		_rowLowerEqualsUpper = passedRows;
   		_colLowerEqualsUpper = passedCols;
   		
   		_origDim1 = -1L;
   		_origDim2 = -1L;
	}
	
	public IndexPair calculateIndexedDimensions(HashMap<String,DataIdentifier> ids, HashMap<String, ConstIdentifier> currConstVars, boolean conditional) 
	{
		// stores the updated row / col dimension info
		long updatedRowDim = -1, updatedColDim = -1;
		
		boolean isConst_rowLowerBound = false;
		boolean isConst_rowUpperBound = false;
		boolean isConst_colLowerBound = false;
		boolean isConst_colUpperBound = false;
		
		//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// STEP 1 : perform constant propagation for index boundaries
		//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		
		//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// PROCESS ROW LOWER BOUND
		//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		
		// process row lower bound
		if (_rowLowerBound instanceof ConstIdentifier && ( _rowLowerBound instanceof IntIdentifier || _rowLowerBound instanceof DoubleIdentifier )){
			
			Long rowLB_1_1 = -1L;
			if (_rowLowerBound instanceof IntIdentifier) 
				rowLB_1_1 = ((IntIdentifier)_rowLowerBound).getValue();
			else 
				rowLB_1_1 = UtilFunctions.toLong(((DoubleIdentifier)_rowLowerBound).getValue());
				
			if (rowLB_1_1 < 1){
				raiseValidateError("lower-bound row index " + rowLB_1_1 + " initialized to out of bounds value. Value must be >= 1", conditional);
			}
			if ((this.getOrigDim1() >= 0)  && (rowLB_1_1 > this.getOrigDim1())) {
				raiseValidateError("lower-bound row index " + rowLB_1_1 + " initialized to out of bounds value.  Rows in " + this.getName() + ": " + this.getOrigDim1(), conditional);
			}
			// valid lower row bound value
			isConst_rowLowerBound = true;
		}
		else if (_rowLowerBound instanceof ConstIdentifier && !getDataType().isList() ) {
			raiseValidateError("assign lower-bound row index for Indexed Identifier " + this.toString() + " the non-numeric value " + _rowLowerBound.toString(), conditional);
		}
	
		// perform constant propogation for row lower bound
		else if (_rowLowerBound != null && _rowLowerBound instanceof DataIdentifier && !(_rowLowerBound instanceof IndexedIdentifier)) {
			String identifierName = ((DataIdentifier)_rowLowerBound).getName();
			
			// CASE: rowLowerBound is a constant DataIdentifier
			if (currConstVars.containsKey(identifierName) && !conditional){
				ConstIdentifier constValue = currConstVars.get(identifierName);
				
				if (!(constValue instanceof IntIdentifier || constValue instanceof DoubleIdentifier ))
					LOG.info(this.printInfoLocation() + "attempted to assign lower row bound for " + this.toString() + "the non-numeric value " + constValue.getOutput().toString() + " assigned to " + identifierName + ". May cause runtime exception ");
	
				else {
					
					// test constant propogation			
					long tempRowLB = -1L;
					boolean validRowLB = true;
					if (constValue instanceof IntIdentifier) 
						tempRowLB = ((IntIdentifier)constValue).getValue();
					else
						tempRowLB = UtilFunctions.toLong(((DoubleIdentifier)constValue).getValue());
							
					if (tempRowLB < 1){
						LOG.info(this.printInfoLocation() + "lower-bound row index " + identifierName + " initialized to "  + tempRowLB + " May cause runtime exception (runtime value must be >= 1)");	
						validRowLB = false;
					}
					if (this.getOrigDim1() >= 0  && tempRowLB > this.getOrigDim1()){ 
						LOG.info(this.printInfoLocation() + "lower-bound row index " + identifierName 
								+ " initialized to " + tempRowLB + " May cause runtime exception (Rows in " 
								+ this.getName() + ": " + this.getOrigDim1() +")");
						validRowLB = false;
					}	
					
					if (validRowLB) {
						if (constValue instanceof IntIdentifier) {
							_rowLowerBound = new IntIdentifier((IntIdentifier) constValue, constValue);
						} else {
							_rowLowerBound = new DoubleIdentifier((DoubleIdentifier) constValue, constValue);
						}
						isConst_rowLowerBound = true;
					}
				} // end else -- if (!(constValue instanceof IntIdentifier || constValue instanceof DoubleIdentifier ))				
			} // end if (currConstVars.containsKey(identifierName))		
		} // end constant propogation for row LB
		
		// check 1 < indexed row lower-bound < rows in IndexedIdentifier 
		// (assuming row dims available for upper bound)
		Long rowLB_1 = -1L;
		if (isConst_rowLowerBound) {
				
			if (_rowLowerBound instanceof IntIdentifier) 
				rowLB_1 = ((IntIdentifier)_rowLowerBound).getValue();
			else
				rowLB_1 = UtilFunctions.toLong(((DoubleIdentifier)_rowLowerBound).getValue());
		}
			
		
		
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// PROCESS ROW UPPER BOUND
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		
		if (_rowUpperBound instanceof ConstIdentifier && ( _rowUpperBound instanceof IntIdentifier || _rowUpperBound instanceof DoubleIdentifier )){
			
			Long rowUB_1_1 = -1L;
			if (_rowUpperBound instanceof IntIdentifier) 
				rowUB_1_1 = ((IntIdentifier)_rowUpperBound).getValue();
			else 
				rowUB_1_1 = UtilFunctions.toLong(((DoubleIdentifier)_rowUpperBound).getValue());
				
			if (rowUB_1_1 < 1){
				raiseValidateError("upper-bound row index " + rowUB_1_1 + " out of bounds value. Value must be >= 1", conditional);
			}
			if ((this.getOrigDim1() >= 0)  && (rowUB_1_1 > this.getOrigDim1())) {
				raiseValidateError("upper-bound row index " + rowUB_1_1 + " out of bounds value.  Rows in " + this.getName() + ": " + this.getOrigDim1(), conditional);
			}
			if (isConst_rowLowerBound && rowUB_1_1 < rowLB_1){
				raiseValidateError("upper-bound row index " + rowUB_1_1 + " greater than lower-bound row index " + rowLB_1, conditional);
			}
			isConst_rowUpperBound = true;
		}	
		else if (_rowUpperBound instanceof ConstIdentifier && !getDataType().isList()){
			raiseValidateError("assign upper-bound row index for " + this.toString() + " the non-numeric value " + _rowUpperBound.toString(), conditional);
		}
		
		// perform constant propogation for upper row index
		else if (_rowUpperBound != null && _rowUpperBound instanceof DataIdentifier && !(_rowUpperBound instanceof IndexedIdentifier)) {
			String identifierName = ((DataIdentifier)_rowUpperBound).getName();
			
			if (currConstVars.containsKey(identifierName) && !conditional){
				ConstIdentifier constValue = currConstVars.get(identifierName);
				
				if (!(constValue instanceof IntIdentifier || constValue instanceof DoubleIdentifier ))
					LOG.info(this.printInfoLocation() + "attempted to assign upper row bound for " + this.toString() + "the non-numeric value " + constValue.getOutput().toString() + " assigned to " + identifierName + ". May cause runtime exception ");
	
				else {						
					// test constant propogation			
					long tempRowUB = -1L;
					boolean validRowUB = true;
					if (constValue instanceof IntIdentifier) 
						tempRowUB = ((IntIdentifier)constValue).getValue();
					else
						tempRowUB = UtilFunctions.toLong(((DoubleIdentifier)constValue).getValue());
							
					if (tempRowUB < 1){
						LOG.info(this.printInfoLocation() + "upper-bound row index " + identifierName + " initialized to "  + tempRowUB + " May cause runtime exception (runtime value must be >= 1)");	
						validRowUB = false;
					}
					if (this.getOrigDim1() >= 0  && tempRowUB > this.getOrigDim1()){ 
						LOG.info(this.printInfoLocation() + "upper-bound row index " + identifierName + " initialized to "  + tempRowUB + " May cause runtime exception (Rows in " + this.getName() + ": " + this.getOrigDim1() +")");
						validRowUB = false;
					}	
					if (isConst_rowLowerBound && tempRowUB < rowLB_1){
						LOG.info(this.printInfoLocation() + "upper-bound row index " 
								+ identifierName + " initialized to " +  tempRowUB 
								+ ", which is greater than lower-bound row index value " 
								+ rowLB_1 + " May cause runtime exception");
						validRowUB = false;
					}

					if (validRowUB) {
						if (constValue instanceof IntIdentifier) {
							_rowUpperBound = new IntIdentifier((IntIdentifier) constValue, constValue);
						} else {
							_rowUpperBound = new DoubleIdentifier((DoubleIdentifier) constValue, constValue);
						}
						isConst_rowUpperBound = true;
					}
				} // end else -- if (!(constValue instanceof IntIdentifier || constValue instanceof DoubleIdentifier ))
			} // end if (currConstVars.containsKey(identifierName)){
			
		} // end constant propagation for row UB	
		
		
		//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// PROCESS COLUMN LOWER BOUND
		//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		
		// process column lower bound
		if (_colLowerBound instanceof ConstIdentifier && ( _colLowerBound instanceof IntIdentifier || _colLowerBound instanceof DoubleIdentifier )){
			
			Long colLB_1_1 = -1L;
			if (_colLowerBound instanceof IntIdentifier) 
				colLB_1_1 = ((IntIdentifier)_colLowerBound).getValue();
			else 
				colLB_1_1 = UtilFunctions.toLong(((DoubleIdentifier)_colLowerBound).getValue());
				
			if (colLB_1_1 < 1){
				raiseValidateError("lower-bound column index " + colLB_1_1 + " initialized to out of bounds value. Value must be >= 1", conditional);
			}
			if ((this.getOrigDim2() >= 0)  && (colLB_1_1 > this.getOrigDim2())){ 
				raiseValidateError("lower-bound column index " + colLB_1_1 + " initialized to out of bounds value.  Columns in " + this.getName() + ": " + this.getOrigDim2(), conditional);
			}
			// valid lower row bound value
			isConst_colLowerBound = true;
		}
			
		else if (_colLowerBound instanceof ConstIdentifier && !getDataType().isList()) {
			raiseValidateError("assign lower-bound column index for Indexed Identifier " + this.toString() + " the non-numeric value " + _colLowerBound.toString(), conditional);
		}
		
		// perform constant propogation for column lower bound
		else if (_colLowerBound != null && _colLowerBound instanceof DataIdentifier && !(_colLowerBound instanceof IndexedIdentifier)) {
			String identifierName = ((DataIdentifier)_colLowerBound).getName();
			if (currConstVars.containsKey(identifierName) && !conditional){
				ConstIdentifier constValue = currConstVars.get(identifierName);
				
				if (!(constValue instanceof IntIdentifier || constValue instanceof DoubleIdentifier ))
					LOG.info(this.printInfoLocation() + "attempted to assign lower column bound for " + this.toString() + "the non-numeric value " + constValue.getOutput().toString() + " assigned to " + identifierName + ". May cause runtime exception ");
	
				else {
					
					// test constant propogation			
					long tempColLB = -1L;
					boolean validColLB = true;
					if (constValue instanceof IntIdentifier) 
						tempColLB = ((IntIdentifier)constValue).getValue();
					else
						tempColLB = UtilFunctions.toLong(((DoubleIdentifier)constValue).getValue());
							
					if (tempColLB < 1){
						LOG.info(this.printInfoLocation() + "lower-bound column index " + identifierName + " initialized to "  + tempColLB + " May cause runtime exception (runtime value must be >= 1)");	
						validColLB = false;
					}
					if (this.getOrigDim2() >= 0  && tempColLB > this.getOrigDim2()){ 
						LOG.info(this.printInfoLocation() + "lower-bound column index " 
								+ identifierName + " initialized to " + tempColLB 
								+ " May cause runtime exception (Columns in " + this.getName() 
								+ ": " + this.getOrigDim2() +")");
						validColLB = false;
					}	

					if (validColLB) {
						if (constValue instanceof IntIdentifier) {
							_colLowerBound = new IntIdentifier((IntIdentifier) constValue, constValue);
						} else {
							_colLowerBound = new DoubleIdentifier((DoubleIdentifier) constValue, constValue);
						}
						isConst_colLowerBound = true;
					}
				} // end else -- if (!(constValue instanceof IntIdentifier || constValue instanceof DoubleIdentifier ))
			} 	
		} // end constant propogation for column LB
		
		// check 1 < indexed column lower-bound < columns in IndexedIdentifier 
		// (assuming column dims available for upper bound)
		Long colLB_1 = -1L;
		if (isConst_colLowerBound) {
				
			if (_colLowerBound instanceof IntIdentifier) 
				colLB_1 = ((IntIdentifier)_colLowerBound).getValue();
			else
				colLB_1 = UtilFunctions.toLong(((DoubleIdentifier)_colLowerBound).getValue());
		}
			
		
		
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// PROCESS ROW UPPER BOUND
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		
		if (_colUpperBound instanceof ConstIdentifier && ( _colUpperBound instanceof IntIdentifier || _colUpperBound instanceof DoubleIdentifier )){
			
			Long colUB_1_1 = -1L;
			if (_colUpperBound instanceof IntIdentifier) 
				colUB_1_1 = ((IntIdentifier)_colUpperBound).getValue();
			else 
				colUB_1_1 = UtilFunctions.toLong(((DoubleIdentifier)_colUpperBound).getValue());
				
			if (colUB_1_1 < 1){
				raiseValidateError("upper-bound column index " + colUB_1_1 + " out of bounds value. Value must be >= 1", conditional);
			}
			if ((this.getOrigDim2() >= 0)  && (colUB_1_1 > this.getOrigDim2())) {
				raiseValidateError("upper-bound column index " + colUB_1_1 + " out of bounds value.  Columns in " + this.getName() + ": " + this.getOrigDim2(), conditional);
			}
			if (isConst_rowLowerBound && colUB_1_1 < colLB_1) {
				raiseValidateError("upper-bound column index " + colUB_1_1 + " greater than lower-bound row index " + colLB_1, conditional);
			}
		    	
			isConst_colUpperBound = true;
		}	
		else if (_colUpperBound instanceof ConstIdentifier && !getDataType().isList()){	
			raiseValidateError("assign upper-bound column index for " + this.toString() + " the non-numeric value " + _colUpperBound.toString(), conditional);
		}
		
		// perform constant propogation for upper row index
		else if (_colUpperBound != null && _colUpperBound instanceof DataIdentifier 
				&& !(_colUpperBound instanceof IndexedIdentifier)) {
			String identifierName = ((DataIdentifier)_colUpperBound).getName();
			
			
			if (currConstVars.containsKey(identifierName) && !conditional){
				ConstIdentifier constValue = currConstVars.get(identifierName);
				
				if (!(constValue instanceof IntIdentifier || constValue instanceof DoubleIdentifier ))
					LOG.info(this.printInfoLocation() + "attempted to assign upper column bound for " 
							+ this.toString() + "the non-numeric value " + constValue.getOutput().toString() 
							+ " assigned to " + identifierName + ". May cause runtime exception ");
	
				else {						
					// test constant propogation			
					long tempColUB = -1L;
					boolean validColUB = true;
					if (constValue instanceof IntIdentifier) 
						tempColUB = ((IntIdentifier)constValue).getValue();
					else
						tempColUB = UtilFunctions.toLong(((DoubleIdentifier)constValue).getValue());
							
					if (tempColUB < 1){
						LOG.info(this.printInfoLocation() + "upper-bound column index " 
								+ identifierName + " initialized to "  + tempColUB 
								+ " May cause runtime exception (runtime value must be >= 1)");	
						validColUB = false;
					}
					if (this.getOrigDim2() >= 0  && tempColUB > this.getOrigDim2()){ 
						LOG.info(this.printInfoLocation() + "upper-bound column index " 
								+ identifierName + " initialized to "  + tempColUB 
								+ " May cause runtime exception (Columns in " + this.getName() 
								+ ": " + this.getOrigDim2() + ")");
						validColUB = false;
					}	
					if (isConst_colLowerBound && tempColUB < colLB_1){
						LOG.info(this.printInfoLocation() + "upper-bound column index " 
					+ identifierName + " initialized to " +  tempColUB 
					+ ", which is greater than lower-bound column index value " + colLB_1 
					+ " May cause runtime exception");
						validColUB = false;
					}

					if (validColUB) {
						if (constValue instanceof IntIdentifier) {
							_colUpperBound = new IntIdentifier((IntIdentifier) constValue, constValue);
						} else {
							_colUpperBound = new DoubleIdentifier((DoubleIdentifier) constValue, constValue);
						}
						isConst_colUpperBound = true;
					}
				} // end else -- if (!(constValue instanceof IntIdentifier || constValue instanceof DoubleIdentifier ))
			}	
		} // end constant propagation for column UB	
		
		///////////////////////////////////////////////////////////////////////
		// STEP 2: update row dimensions
		///////////////////////////////////////////////////////////////////////
			
		// CASE:  lower == upper --> updated row dim = 1
		if (_rowLowerEqualsUpper) 
			updatedRowDim = 1;
		
		// CASE: (lower == null && upper == null) --> updated row dim = (rows of input)
		else if (_rowLowerBound == null && _rowUpperBound == null){
			updatedRowDim = this.getOrigDim1(); 
		}
		
		// CASE: (lower == null) && (upper == constant) --> updated row dim = (constant)
		else if (_rowLowerBound == null && isConst_rowUpperBound) {
			if (_rowUpperBound instanceof IntIdentifier)
				updatedRowDim = ((IntIdentifier)_rowUpperBound).getValue();
			else if (_rowUpperBound instanceof DoubleIdentifier)
				updatedRowDim = UtilFunctions.toLong(((DoubleIdentifier)_rowUpperBound).getValue());
		}
			
		// CASE: (lower == constant) && (upper == null) && (dimIndex > 0) --> rowCount - lower bound + 1
		else if (isConst_rowLowerBound && _rowUpperBound == null && this.getOrigDim1() >= 0) {
			long rowCount = this.getOrigDim1();
			if (_rowLowerBound instanceof IntIdentifier)
				updatedRowDim = rowCount - ((IntIdentifier)_rowLowerBound).getValue() + 1;
			else if (_rowLowerBound instanceof DoubleIdentifier)
				updatedRowDim = UtilFunctions.toLong(rowCount - ((DoubleIdentifier)_rowLowerBound).getValue() + 1);
		}
		// CASE: (lower == constant) && (upper == constant) --> upper bound - lower bound + 1
		else if (isConst_rowLowerBound && isConst_rowUpperBound) {
			if (_rowLowerBound instanceof IntIdentifier && _rowUpperBound instanceof IntIdentifier)
				updatedRowDim = ((IntIdentifier)_rowUpperBound).getValue() - ((IntIdentifier)_rowLowerBound).getValue() + 1;
			
			else if (_rowLowerBound instanceof DoubleIdentifier && _rowUpperBound instanceof DoubleIdentifier)
				updatedRowDim = UtilFunctions.toLong( ((DoubleIdentifier)_rowUpperBound).getValue() - ((DoubleIdentifier)_rowLowerBound).getValue() + 1);
			
			else if (_rowLowerBound instanceof IntIdentifier && _rowUpperBound instanceof DoubleIdentifier)
				updatedRowDim = UtilFunctions.toLong( ((DoubleIdentifier)_rowUpperBound).getValue() - ((IntIdentifier)_rowLowerBound).getValue() + 1);
			
			else if (_rowLowerBound instanceof DoubleIdentifier && _rowUpperBound instanceof IntIdentifier)
				updatedRowDim = UtilFunctions.toLong( ((IntIdentifier)_rowUpperBound).getValue() - ((DoubleIdentifier)_rowLowerBound).getValue() + 1);
			
		}
		
		// CASE: row dimension is unknown --> assign -1
		else{ 
			updatedRowDim = -1;
		}
		
		
		//////////////////////////////////////////////////////////////////////
		// STEP 3: update column dimensions
		///////////////////////////////////////////////////////////////////////
			
		// CASE:  lower == upper --> updated col dim = 1
		if (_colLowerEqualsUpper) 
			updatedColDim = 1;
		
		// CASE: (lower == null && upper == null) --> updated col dim = (cols of input)
		else if (_colLowerBound == null && _colUpperBound == null){
			updatedColDim = this.getOrigDim2(); 
		}
		// CASE: (lower == null) && (upper == constant) --> updated col dim = (constant)
		else if (_colLowerBound == null && isConst_colUpperBound) {
			if (_colUpperBound instanceof IntIdentifier)
				updatedColDim = ((IntIdentifier)_colUpperBound).getValue();
			else if (_colUpperBound instanceof DoubleIdentifier)
				updatedColDim = UtilFunctions.toLong(((DoubleIdentifier)_colUpperBound).getValue());
		}
			
		// CASE: (lower == constant) && (upper == null) && (dimIndex > 0) --> colCount - lower bound + 1
		else if (isConst_colLowerBound && _colUpperBound == null && this.getOrigDim2() >= 0) {
			long colCount = this.getOrigDim2();
			if (_colLowerBound instanceof IntIdentifier)
				updatedColDim = colCount - ((IntIdentifier)_colLowerBound).getValue() + 1;
			else if (_colLowerBound instanceof DoubleIdentifier)
				updatedColDim = UtilFunctions.toLong(colCount - ((DoubleIdentifier)_colLowerBound).getValue() + 1);
		}
		
		// CASE: (lower == constant) && (upper == constant) --> upper bound - lower bound + 1
		else if (isConst_colLowerBound && isConst_colUpperBound) {
			if (_colLowerBound instanceof IntIdentifier && _colUpperBound instanceof IntIdentifier)
				updatedColDim = ((IntIdentifier)_colUpperBound).getValue() - ((IntIdentifier)_colLowerBound).getValue() + 1;
			
			else if (_colLowerBound instanceof DoubleIdentifier && _colUpperBound instanceof DoubleIdentifier)
				updatedColDim = UtilFunctions.toLong( ((DoubleIdentifier)_colUpperBound).getValue() - ((DoubleIdentifier)_colLowerBound).getValue() + 1);
			
			else if (_colLowerBound instanceof IntIdentifier && _colUpperBound instanceof DoubleIdentifier)
				updatedColDim = UtilFunctions.toLong( ((DoubleIdentifier)_colUpperBound).getValue() - ((IntIdentifier)_colLowerBound).getValue() + 1);
			
			else if (_colLowerBound instanceof DoubleIdentifier && _colUpperBound instanceof IntIdentifier)
				updatedColDim = UtilFunctions.toLong( ((IntIdentifier)_colUpperBound).getValue() - ((DoubleIdentifier)_colLowerBound).getValue() + 1);
			
		}
		
		// CASE: column dimension is unknown --> assign -1
		else{ 
			updatedColDim = -1;
		}
		
		return new IndexPair(updatedRowDim, updatedColDim);
		
	}
	
	public void setOriginalDimensions(long passedDim1, long passedDim2){
		this._origDim1 = passedDim1;
		this._origDim2 = passedDim2;
	}
	
	public long getOrigDim1() { return this._origDim1; }
	public long getOrigDim2() { return this._origDim2; }
	
	
	@Override
	public Expression rewriteExpression(String prefix) {
		IndexedIdentifier newIndexedIdentifier = new IndexedIdentifier(this.getName(), this._rowLowerEqualsUpper, this._colLowerEqualsUpper);
		newIndexedIdentifier.setParseInfo(this);
		
		// set dimensionality information and other Identifier specific properties for new IndexedIdentifier
		newIndexedIdentifier.setProperties(this);
		newIndexedIdentifier.setOriginalDimensions(this._origDim1, this._origDim2);
		
		// set remaining properties (specific to DataIdentifier)
		newIndexedIdentifier._name = prefix + this._name;
		newIndexedIdentifier._valueTypeString = this.getValueType().toString();	
		
		// creates rewritten expression (deep copy)
		newIndexedIdentifier._rowLowerBound = (_rowLowerBound == null) ? null : _rowLowerBound.rewriteExpression(prefix);
		newIndexedIdentifier._rowUpperBound = (_rowUpperBound == null) ? null : _rowUpperBound.rewriteExpression(prefix);
		newIndexedIdentifier._colLowerBound = (_colLowerBound == null) ? null : _colLowerBound.rewriteExpression(prefix);
		newIndexedIdentifier._colUpperBound = (_colUpperBound == null) ? null : _colUpperBound.rewriteExpression(prefix);
		
		return newIndexedIdentifier;
	}
		
	public void setIndices(ArrayList<ArrayList<Expression>> passed) {
		if (passed.size() != 2)
			raiseValidateError("matrix indices must be specified for 2 dimensions");
		
		ArrayList<Expression> rowIndices = passed.get(0);
		ArrayList<Expression> colIndices = passed.get(1);
	
		// case: both upper and lower are defined
		if (rowIndices.size() == 2){			
			_rowLowerBound = rowIndices.get(0);
			_rowUpperBound = rowIndices.get(1);
		}
		// case: only one index is defined --> thus lower = upper
		else if (rowIndices.size() == 1){
			_rowLowerBound = rowIndices.get(0);
			_rowUpperBound = rowIndices.get(0);
			_rowLowerEqualsUpper = true;
		}
		else {
			raiseValidateError("row indices are length " + rowIndices.size() + " -- should be either 1 or 2");
		}
		
		// case: both upper and lower are defined
		if (colIndices.size() == 2){			
			_colLowerBound = colIndices.get(0);
			_colUpperBound = colIndices.get(1);
		}
		// case: only one index is defined --> thus lower = upper
		else if (colIndices.size() == 1){
			_colLowerBound = colIndices.get(0);
			_colUpperBound = colIndices.get(0);
			_colLowerEqualsUpper = true;
		}
		else {
			raiseValidateError("column indices are length " + + colIndices.size() + " -- should be either 1 or 2");
		}
		
		if (_rowLowerBound instanceof FunctionCallIdentifier || _rowUpperBound instanceof FunctionCallIdentifier
				|| _colLowerBound instanceof FunctionCallIdentifier || _colUpperBound instanceof FunctionCallIdentifier){
			raiseValidateError("UDF functions not supported for row or column indices");
		}
		
	}
	
	public Expression getRowLowerBound(){ return this._rowLowerBound; }
	public Expression getRowUpperBound(){ return this._rowUpperBound; }
	public Expression getColLowerBound(){ return this._colLowerBound; }
	public Expression getColUpperBound(){ return this._colUpperBound; }
	
	public void setRowLowerBound(Expression passed){ this._rowLowerBound = passed; }
	public void setRowUpperBound(Expression passed){ this._rowUpperBound = passed; }
	public void setColLowerBound(Expression passed){ this._colLowerBound = passed; }
	public void setColUpperBound(Expression passed){ this._colUpperBound = passed; }
	
	@Override	
	public String toString() {
		String retVal = getName();
		if (_rowLowerBound != null || _rowUpperBound != null || _colLowerBound != null || _colUpperBound != null) {
			retVal += "[";
			
			if (_rowLowerBound != null && _rowUpperBound != null){
				if (_rowLowerBound.toString().equals(_rowUpperBound.toString()))
					retVal += _rowLowerBound.toString();
				else 
					retVal += _rowLowerBound.toString() + ":" + _rowUpperBound.toString();
			}
			else {
				if (_rowLowerBound != null || _rowUpperBound != null){
					if (_rowLowerBound != null)
						retVal += _rowLowerBound.toString();
					
					retVal += ":";
					
					if (_rowUpperBound != null)
						retVal += _rowUpperBound.toString();
				}
			}
				
			retVal += ",";
			
			if (_colLowerBound != null && _colUpperBound != null){
				if (_colLowerBound.toString().equals(_colUpperBound.toString()))
					retVal += _colLowerBound.toString();
				else
					retVal += _colLowerBound.toString() + ":" + _colUpperBound.toString();
			}
			else {
				if (_colLowerBound != null || _colUpperBound != null) {
					
					if (_colLowerBound != null)
						retVal += _colLowerBound.toString();
					
					retVal += ":";
					
					if (_colUpperBound != null)
						retVal += _colUpperBound.toString();
				}
			}
			
			
			retVal += "]";
		}
		return retVal;
	}

	@Override
	// handles case when IndexedIdentifier is on RHS for assignment 
	public VariableSet variablesRead() {
		VariableSet result = new VariableSet();
		
		// add variable being indexed to read set
		result.addVariable(this.getName(), this);
		
		// add variables for indexing expressions
		if (_rowLowerBound != null)
			result.addVariables(_rowLowerBound.variablesRead());
		if (_rowUpperBound != null)
			result.addVariables(_rowUpperBound.variablesRead());
		if (_colLowerBound != null)
			result.addVariables(_colLowerBound.variablesRead());
		if (_colUpperBound != null)
			result.addVariables(_colUpperBound.variablesRead());
		
		return result;
	}
	
	@Override
	public void setProperties(Identifier i){
		_dataType = i.getDataType();
		_valueType = i.getValueType();
		_dim1 = i.getDim1();
		_dim2 = i.getDim2();
		_blocksize = i.getBlocksize();
		_nnz = i.getNnz();
		_format = i.getFileFormat();
		
		if (i instanceof IndexedIdentifier){
			_origDim1 = ((IndexedIdentifier)i).getOrigDim1();
			_origDim2 = ((IndexedIdentifier)i).getOrigDim2();
		}
		else{
			_origDim1 = i.getDim1();
			_origDim2 = i.getDim2();
		}
	}
	
	@Override
	public boolean multipleReturns() {
		return false;
	}
	
} // end class
	
class IndexPair {
	
	public long _row, _col;
	
	public IndexPair (long row, long col){
		_row = row;
		_col = col;
	}
} // end class
