/*
 * 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.runtime.matrix.data;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.sysds.common.Types.CorrectionLocationType;
import org.apache.sysds.common.Types.ValueType;
import org.apache.sysds.runtime.DMLRuntimeException;
import org.apache.sysds.runtime.compress.CompressedMatrixBlock;
import org.apache.sysds.runtime.controlprogram.caching.CacheBlock;
import org.apache.sysds.runtime.controlprogram.caching.MatrixObject.UpdateType;
import org.apache.sysds.runtime.functionobjects.Builtin;
import org.apache.sysds.runtime.instructions.spark.data.IndexedMatrixValue;
import org.apache.sysds.runtime.instructions.spark.utils.SparkUtils;
import org.apache.sysds.runtime.matrix.operators.AggregateBinaryOperator;
import org.apache.sysds.runtime.matrix.operators.AggregateOperator;
import org.apache.sysds.runtime.matrix.operators.AggregateUnaryOperator;
import org.apache.sysds.runtime.matrix.operators.BinaryOperator;
import org.apache.sysds.runtime.matrix.operators.Operator;
import org.apache.sysds.runtime.matrix.operators.ReorgOperator;
import org.apache.sysds.runtime.util.IndexRange;
import org.apache.sysds.runtime.util.UtilFunctions;


public class OperationsOnMatrixValues 
{
	public static void performReorg(MatrixIndexes indexesIn, MatrixValue valueIn, MatrixIndexes indexesOut, 
			MatrixValue valueOut, ReorgOperator op, int startRow, int startColumn, int length) {
		//operate on the value indexes first
		op.fn.execute(indexesIn, indexesOut);
		
		//operation on the cells inside the value
		valueIn.reorgOperations(op, valueOut, startRow, startColumn, length);
	}

	public static void performAppend(MatrixValue valueIn1, MatrixValue valueIn2,
			ArrayList<IndexedMatrixValue> outlist, int blen, boolean cbind, boolean m2IsLast, int nextNCol) {
		valueIn1.append(valueIn2, outlist, blen, cbind, m2IsLast, nextNCol);
	}
	
	public static void performZeroOut(MatrixIndexes indexesIn, MatrixValue valueIn, 
			MatrixIndexes indexesOut, MatrixValue valueOut, IndexRange range, boolean complementary) {
		valueIn.zeroOutOperations(valueOut, range, complementary);
		indexesOut.setIndexes(indexesIn);
	}
	
	// ------------- Ternary Operations -------------
	public static void performCtable(MatrixIndexes indexesIn1, MatrixValue valueIn1, MatrixIndexes indexesIn2, MatrixValue valueIn2, 
			MatrixIndexes indexesIn3, MatrixValue valueIn3, CTableMap resultMap, MatrixBlock resultBlock, Operator op ) {
		//operation on the cells inside the value
		valueIn1.ctableOperations(op, valueIn2, valueIn3, resultMap, resultBlock);
	}
	
	public static void performCtable(MatrixIndexes indexesIn1, MatrixValue valueIn1, MatrixIndexes indexesIn2, MatrixValue valueIn2, 
			double scalarIn3, CTableMap resultMap, MatrixBlock resultBlock, Operator op) {
		//operation on the cells inside the value
		valueIn1.ctableOperations(op, valueIn2, scalarIn3, false, resultMap, resultBlock);
	}
	
	public static void performCtable(MatrixIndexes indexesIn1, MatrixValue valueIn1, double scalarIn2, 
			double scalarIn3, CTableMap resultMap, MatrixBlock resultBlock, Operator op ) {
		//operation on the cells inside the value
		valueIn1.ctableOperations(op, scalarIn2, scalarIn3, resultMap, resultBlock);
	}
	
	public static void performCtable(MatrixIndexes indexesIn1, MatrixValue valueIn1, double scalarIn2, boolean left,
			int blen, CTableMap resultMap, MatrixBlock resultBlock, Operator op ) {
		//operation on the cells inside the value
		valueIn1.ctableOperations(op, indexesIn1, scalarIn2, left, blen, resultMap, resultBlock);
	}
	
	public static void performCtable(MatrixIndexes indexesIn1, MatrixValue valueIn1, double scalarIn2, 
			MatrixIndexes indexesIn3, MatrixValue valueIn3, CTableMap resultMap, MatrixBlock resultBlock, Operator op ) {
		//operation on the cells inside the value
		valueIn1.ctableOperations(op, scalarIn2, valueIn3, resultMap, resultBlock);
	}
	// -----------------------------------------------------
	
	//binary operations are those that the indexes of both cells have to be matched
	public static void performBinaryIgnoreIndexes(MatrixValue value1, MatrixValue value2, 
			MatrixValue valueOut, BinaryOperator op) {
		value1.binaryOperations(op, value2, valueOut);
	}

	public static void startAggregation(MatrixValue valueOut, MatrixValue correction, AggregateOperator op, 
			int rlen, int clen, boolean sparseHint, boolean embeddedCorrection) {
		int outRow=0, outCol=0, corRow=0, corCol=0;
		if(!embeddedCorrection || op.existsCorrection())
		{
			if( !embeddedCorrection ) {
				switch(op.correction)
				{
				case NONE:
					outRow=rlen;
					outCol=clen;
					corRow=rlen;
					corCol=clen;
					break;
				case LASTROW:
					outRow=rlen-1;
					outCol=clen;
					corRow=1;
					corCol=clen;
					break;
				case LASTCOLUMN:
					if(op.increOp.fn instanceof Builtin 
					   && ( ((Builtin)(op.increOp.fn)).bFunc == Builtin.BuiltinCode.MAXINDEX 
					        || ((Builtin)(op.increOp.fn)).bFunc == Builtin.BuiltinCode.MININDEX) )
					{
						outRow = rlen;
						outCol = 1;
						corRow = rlen;
						corCol = 1;
					}
					else{
						outRow=rlen;
						outCol=clen-1;
						corRow=rlen;
						corCol=1;
					}
					break;
				case LASTTWOROWS:
					outRow=rlen-2;
					outCol=clen;
					corRow=2;
					corCol=clen;
					break;
				case LASTTWOCOLUMNS:
					outRow=rlen;
					outCol=clen-2;
					corRow=rlen;
					corCol=2;
					break;
				case LASTFOURROWS:
					outRow=rlen-4;
					outCol=clen;
					corRow=4;
					corCol=clen;
					break;
				case LASTFOURCOLUMNS:
					outRow=rlen;
					outCol=clen-4;
					corRow=rlen;
					corCol=4;
					break;
				default:
						throw new DMLRuntimeException("unrecognized correctionLocation: "+op.correction);
				}
			}else
			{
				outRow=rlen;
				outCol=clen;
				corRow=rlen;
				corCol=clen;
			}
			
			//set initial values according to operator
			if(op.initialValue==0) {
				valueOut.reset(Math.max(outRow,0), Math.max(outCol,0), sparseHint);
				correction.reset(Math.max(corRow,0), Math.max(corCol,0), false);
			}
			else {
				valueOut.reset(Math.max(outRow, 0), Math.max(outCol,0), op.initialValue);
				correction.reset(Math.max(corRow,0), Math.max(corCol,0), op.initialValue);
			}
		}
		else {
			if(op.initialValue==0)
				valueOut.reset(rlen, clen, sparseHint);
			else
				valueOut.reset(rlen, clen, op.initialValue);
		}
	}
	
	public static void incrementalAggregation(MatrixValue valueAgg, MatrixValue correction, MatrixValue valueAdd, 
			AggregateOperator op, boolean embeddedCorrection) {
		incrementalAggregation(valueAgg, correction, valueAdd, op, embeddedCorrection, true);
	}
	
	
	public static void incrementalAggregation(MatrixValue valueAgg, MatrixValue correction, MatrixValue valueAdd, 
			AggregateOperator op, boolean embeddedCorrection, boolean deep)
	{
		if(!embeddedCorrection || op.existsCorrection()) {
			if( op.correction==CorrectionLocationType.NONE )
				valueAgg.incrementalAggregate(op, correction, valueAdd, deep);
			else
				valueAgg.incrementalAggregate(op, valueAdd);
		}
		else
			valueAgg.binaryOperationsInPlace(op.increOp, valueAdd);
	}
	
	public static void performAggregateUnary(MatrixIndexes indexesIn, MatrixValue valueIn, MatrixIndexes indexesOut, 
			MatrixValue valueOut, AggregateUnaryOperator op,int blen) {
		//operate on the value indexes first
		op.indexFn.execute(indexesIn, indexesOut);
		
		//perform on the value
		valueIn.aggregateUnaryOperations(op, valueOut, blen, indexesIn);
	}
	
	public static MatrixBlock matMult(MatrixIndexes indexes1, MatrixBlock value1, MatrixIndexes indexes2, MatrixBlock value2, 
			MatrixIndexes indexesOut, MatrixBlock valueOut, AggregateBinaryOperator op) {
		//compute output index
		indexesOut.setIndexes(indexes1.getRowIndex(), indexes2.getColumnIndex());
		//perform on the value
		if (value2 instanceof CompressedMatrixBlock)
			return value2.aggregateBinaryOperations(value1, value2, valueOut, op);
		else
			return value1.aggregateBinaryOperations(indexes1, value1, indexes2, value2, valueOut, op);
	}

	public static MatrixBlock matMult(MatrixBlock value1, MatrixBlock value2,
			MatrixBlock valueOut, AggregateBinaryOperator op) {
		//perform on the value
		if( value2 instanceof CompressedMatrixBlock )
			return value2.aggregateBinaryOperations(value1, value2, valueOut, op);
		else
			return value1.aggregateBinaryOperations(value1, value2, valueOut, op);
	}

	@SuppressWarnings("rawtypes")
	public static List performSlice(IndexRange ixrange, int blen, int iix, int jix, CacheBlock in) {
		if( in instanceof MatrixBlock )
			return performSlice(ixrange, blen, iix, jix, (MatrixBlock)in);
		else if( in instanceof FrameBlock )
			return performSlice(ixrange, blen, iix, jix, (FrameBlock)in);
		throw new DMLRuntimeException("Unsupported cache block type: "+in.getClass().getName());
	}
	
	@SuppressWarnings("rawtypes")
	public static List performSlice(IndexRange ixrange, int blen, int iix, int jix, MatrixBlock in) {
		IndexedMatrixValue imv = new IndexedMatrixValue(new MatrixIndexes(iix, jix), in);
		ArrayList<IndexedMatrixValue> outlist = new ArrayList<>();
		performSlice(imv, ixrange, blen, outlist);
		return SparkUtils.fromIndexedMatrixBlockToPair(outlist);
	}

	public static void performSlice(IndexedMatrixValue in, IndexRange ixrange, int blen, ArrayList<IndexedMatrixValue> outlist) {
		long cellIndexTopRow = UtilFunctions.computeCellIndex(in.getIndexes().getRowIndex(), blen, 0);
		long cellIndexBottomRow = UtilFunctions.computeCellIndex(in.getIndexes().getRowIndex(), blen, in.getValue().getNumRows()-1);
		long cellIndexLeftCol = UtilFunctions.computeCellIndex(in.getIndexes().getColumnIndex(), blen, 0);
		long cellIndexRightCol = UtilFunctions.computeCellIndex(in.getIndexes().getColumnIndex(), blen, in.getValue().getNumColumns()-1);
		
		long cellIndexOverlapTop = Math.max(cellIndexTopRow, ixrange.rowStart);
		long cellIndexOverlapBottom = Math.min(cellIndexBottomRow, ixrange.rowEnd);
		long cellIndexOverlapLeft = Math.max(cellIndexLeftCol, ixrange.colStart);
		long cellIndexOverlapRight = Math.min(cellIndexRightCol, ixrange.colEnd);
		
		//check if block is outside the indexing range
		if(cellIndexOverlapTop>cellIndexOverlapBottom || cellIndexOverlapLeft>cellIndexOverlapRight) {
			return;
		}
		
		IndexRange tmpRange = new IndexRange(
			UtilFunctions.computeCellInBlock(cellIndexOverlapTop, blen), 
			UtilFunctions.computeCellInBlock(cellIndexOverlapBottom, blen), 
			UtilFunctions.computeCellInBlock(cellIndexOverlapLeft, blen), 
			UtilFunctions.computeCellInBlock(cellIndexOverlapRight, blen));
		
		int rowCut=UtilFunctions.computeCellInBlock(ixrange.rowStart, blen);
		int colCut=UtilFunctions.computeCellInBlock(ixrange.colStart, blen);
		
		int rowsInLastBlock = (int)((ixrange.rowEnd-ixrange.rowStart+1)%blen);
		if(rowsInLastBlock==0) 
			rowsInLastBlock=blen;
		int colsInLastBlock = (int)((ixrange.colEnd-ixrange.colStart+1)%blen);
		if(colsInLastBlock==0) 
			colsInLastBlock=blen;
		
		long resultBlockIndexTop=UtilFunctions.computeBlockIndex(cellIndexOverlapTop-ixrange.rowStart+1, blen);
		long resultBlockIndexBottom=UtilFunctions.computeBlockIndex(cellIndexOverlapBottom-ixrange.rowStart+1, blen);
		long resultBlockIndexLeft=UtilFunctions.computeBlockIndex(cellIndexOverlapLeft-ixrange.colStart+1, blen);
		long resultBlockIndexRight=UtilFunctions.computeBlockIndex(cellIndexOverlapRight-ixrange.colStart+1, blen);
		
		int boundaryRlen = blen;
		int boundaryClen = blen;
		long finalBlockIndexBottom=UtilFunctions.computeBlockIndex(ixrange.rowEnd-ixrange.rowStart+1, blen);
		long finalBlockIndexRight=UtilFunctions.computeBlockIndex(ixrange.colEnd-ixrange.colStart+1, blen);
		if(resultBlockIndexBottom==finalBlockIndexBottom)
			boundaryRlen=rowsInLastBlock;
		if(resultBlockIndexRight==finalBlockIndexRight)
			boundaryClen=colsInLastBlock;
			
		//allocate space for the output value
		for(long r=resultBlockIndexTop; r<=resultBlockIndexBottom; r++)
			for(long c=resultBlockIndexLeft; c<=resultBlockIndexRight; c++)
			{
				IndexedMatrixValue out=new IndexedMatrixValue(new MatrixIndexes(), new MatrixBlock());
				out.getIndexes().setIndexes(r, c);
				outlist.add(out);
			}
		
		//execute actual slice operation
		in.getValue().slice(outlist, tmpRange, rowCut, colCut, blen, boundaryRlen, boundaryClen);
	}

	public static void performShift(IndexedMatrixValue in, IndexRange ixrange, int blen, long rlen, long clen, ArrayList<IndexedMatrixValue> outlist) {
		MatrixIndexes ix = in.getIndexes();
		MatrixBlock mb = (MatrixBlock)in.getValue();
		
		long start_lhs_globalRowIndex = ixrange.rowStart + (ix.getRowIndex()-1)*blen;
		long start_lhs_globalColIndex = ixrange.colStart + (ix.getColumnIndex()-1)*blen;
		long end_lhs_globalRowIndex = start_lhs_globalRowIndex + mb.getNumRows() - 1;
		long end_lhs_globalColIndex = start_lhs_globalColIndex + mb.getNumColumns() - 1;
		
		long start_lhs_rowIndex = UtilFunctions.computeBlockIndex(start_lhs_globalRowIndex, blen);
		long end_lhs_rowIndex = UtilFunctions.computeBlockIndex(end_lhs_globalRowIndex, blen);
		long start_lhs_colIndex = UtilFunctions.computeBlockIndex(start_lhs_globalColIndex, blen);
		long end_lhs_colIndex = UtilFunctions.computeBlockIndex(end_lhs_globalColIndex, blen);
		
		for(long leftRowIndex = start_lhs_rowIndex; leftRowIndex <= end_lhs_rowIndex; leftRowIndex++) {
			for(long leftColIndex = start_lhs_colIndex; leftColIndex <= end_lhs_colIndex; leftColIndex++) {
				
				// Calculate global index of right hand side block
				long lhs_rl = Math.max((leftRowIndex-1)*blen+1, start_lhs_globalRowIndex);
				long lhs_ru = Math.min(leftRowIndex*blen, end_lhs_globalRowIndex);
				long lhs_cl = Math.max((leftColIndex-1)*blen+1, start_lhs_globalColIndex);
				long lhs_cu = Math.min(leftColIndex*blen, end_lhs_globalColIndex);
				
				int lhs_lrl = UtilFunctions.computeCellInBlock(lhs_rl, blen);
				int lhs_lru = UtilFunctions.computeCellInBlock(lhs_ru, blen);
				int lhs_lcl = UtilFunctions.computeCellInBlock(lhs_cl, blen);
				int lhs_lcu = UtilFunctions.computeCellInBlock(lhs_cu, blen);
				
				long rhs_rl = lhs_rl - ixrange.rowStart + 1;
				long rhs_ru = rhs_rl + (lhs_ru - lhs_rl);
				long rhs_cl = lhs_cl - ixrange.colStart + 1;
				long rhs_cu = rhs_cl + (lhs_cu - lhs_cl);
				
				int rhs_lrl = UtilFunctions.computeCellInBlock(rhs_rl, blen);
				int rhs_lru = UtilFunctions.computeCellInBlock(rhs_ru, blen);
				int rhs_lcl = UtilFunctions.computeCellInBlock(rhs_cl, blen);
				int rhs_lcu = UtilFunctions.computeCellInBlock(rhs_cu, blen);
				
				MatrixBlock slicedRHSBlk = mb.slice(rhs_lrl, rhs_lru, rhs_lcl, rhs_lcu, new MatrixBlock());
				
				int lbrlen = UtilFunctions.computeBlockSize(rlen, leftRowIndex, blen);
				int lbclen = UtilFunctions.computeBlockSize(clen, leftColIndex, blen);
				MatrixBlock resultBlock = new MatrixBlock(lbrlen, lbclen, false);
				resultBlock = resultBlock.leftIndexingOperations(slicedRHSBlk, lhs_lrl, lhs_lru, lhs_lcl, lhs_lcu, null, UpdateType.COPY);
				outlist.add(new IndexedMatrixValue(new MatrixIndexes(leftRowIndex, leftColIndex), resultBlock));
			}
		}
	}

	public static void performMapGroupedAggregate( Operator op, IndexedMatrixValue inTarget, MatrixBlock groups, int ngroups, int blen, ArrayList<IndexedMatrixValue> outlist )
	{
		MatrixIndexes ix = inTarget.getIndexes();
		MatrixBlock target = (MatrixBlock)inTarget.getValue();
		
		//execute grouped aggregate operations
		MatrixBlock out = groups.groupedAggOperations(target, null, new MatrixBlock(), ngroups, op);
		
		if( out.getNumRows()<=blen && out.getNumColumns()<=blen )
		{
			//single output block
			outlist.add( new IndexedMatrixValue(new MatrixIndexes(1,ix.getColumnIndex()), out) );
		}
		else
		{
			//multiple output blocks (by op def, single column block )
			for(int blockRow = 0; blockRow < (int)Math.ceil(out.getNumRows()/(double)blen); blockRow++)
			{
				int maxRow = (blockRow*blen + blen < out.getNumRows()) ? blen : out.getNumRows() - blockRow*blen;
				int row_offset = blockRow*blen;

				//copy submatrix to block
				MatrixBlock tmp = out.slice(row_offset, row_offset+maxRow-1);
				
				//append block to result cache
				outlist.add(new IndexedMatrixValue(new MatrixIndexes(blockRow+1,ix.getColumnIndex()), tmp));
			}
		}
	}
	
	@SuppressWarnings("rawtypes")
	public static ArrayList performSlice(IndexRange ixrange, int blen, int iix, int jix, FrameBlock in) {
		Pair<Long, FrameBlock> lfp = new Pair<>(new Long(((iix-1)*blen)+1), in);
		ArrayList<Pair<Long, FrameBlock>> outlist = new ArrayList<>();
		performSlice(lfp, ixrange, blen, outlist);
	
		return outlist;
	}

	
	/**
	 * This function will get slice of the input frame block overlapping in overall slice(Range), slice has requested for.
	 * 
	 * @param in ?
	 * @param ixrange index range
	 * @param blen block length
	 * @param outlist list of pairs of frame blocks
	 */
	public static void performSlice(Pair<Long,FrameBlock> in, IndexRange ixrange, int blen, ArrayList<Pair<Long,FrameBlock>> outlist) {
		long index = in.getKey();
		FrameBlock block = in.getValue();
		
		// Get Block indexes (rows and columns boundaries)
		long cellIndexTopRow = index;
		long cellIndexBottomRow = index+block.getNumRows()-1;
		long cellIndexLeftCol = 1;
		long cellIndexRightCol = block.getNumColumns();
		
		// Calculate block boundaries with range of slice to be performed (Global index)
		long cellIndexOverlapTop = Math.max(cellIndexTopRow, ixrange.rowStart);
		long cellIndexOverlapBottom = Math.min(cellIndexBottomRow, ixrange.rowEnd);
		long cellIndexOverlapLeft = Math.max(cellIndexLeftCol, ixrange.colStart);
		long cellIndexOverlapRight = Math.min(cellIndexRightCol, ixrange.colEnd);
		
		//check if block is outside the indexing range
		if(cellIndexOverlapTop>cellIndexOverlapBottom || cellIndexOverlapLeft>cellIndexOverlapRight) {
			return;
		}
		
		// Create IndexRange for the slice to be performed on this block.
		IndexRange tmpRange = new IndexRange(
				cellIndexOverlapTop - index,
				cellIndexOverlapBottom - index,
				cellIndexOverlapLeft -1,
				cellIndexOverlapRight - 1);
		
		// Get Top Row and Left column cutting point. 
		int rowCut=(int)(ixrange.rowStart-index);
		
		// Get indices for result block
		long resultBlockIndexTop=UtilFunctions.computeBlockIndex(cellIndexOverlapTop, blen);
		long resultBlockIndexBottom=UtilFunctions.computeBlockIndex(cellIndexOverlapBottom, blen);
		
		//allocate space for the output value
		for(long r=resultBlockIndexTop; r<=resultBlockIndexBottom; r++)
		{
			ValueType[] schema = Arrays.copyOfRange(block.getSchema(), (int)tmpRange.colStart, (int)tmpRange.colEnd+1);
			long iResultIndex = Math.max(((r-1)*blen - ixrange.rowStart + 1), 0);
			Pair<Long,FrameBlock> out=new Pair<>(new Long(iResultIndex+1), new FrameBlock(schema));
			outlist.add(out);
		}
		
		//execute actual slice operation
		block.slice(outlist, tmpRange, rowCut);
	}

	public static void performShift(Pair<Long,FrameBlock> in, IndexRange ixrange, int blenLeft, long rlen, long clen, ArrayList<Pair<Long,FrameBlock>> outlist) {
		Long ix = in.getKey();
		FrameBlock fb = in.getValue();
		long start_lhs_globalRowIndex = ixrange.rowStart + (ix-1);
		long start_lhs_globalColIndex = ixrange.colStart;
		long end_lhs_globalRowIndex = start_lhs_globalRowIndex + fb.getNumRows() - 1;
		long end_lhs_globalColIndex = ixrange.colEnd;
		
		long start_lhs_rowIndex = UtilFunctions.computeBlockIndex(start_lhs_globalRowIndex, blenLeft);
		long end_lhs_rowIndex = UtilFunctions.computeBlockIndex(end_lhs_globalRowIndex, blenLeft);

		for(long leftRowIndex = start_lhs_rowIndex; leftRowIndex <= end_lhs_rowIndex; leftRowIndex++) {
				
			// Calculate global index of right hand side block
			long lhs_rl = Math.max((leftRowIndex-1)*blenLeft+1, start_lhs_globalRowIndex);
			long lhs_ru = Math.min(leftRowIndex*blenLeft, end_lhs_globalRowIndex);
			long lhs_cl = start_lhs_globalColIndex;
			long lhs_cu = end_lhs_globalColIndex;
			
			int lhs_lrl = UtilFunctions.computeCellInBlock(lhs_rl, blenLeft);
			int lhs_lru = UtilFunctions.computeCellInBlock(lhs_ru, blenLeft);
			int lhs_lcl = (int)lhs_cl-1;
			int lhs_lcu = (int)lhs_cu-1;
			
			long rhs_rl = lhs_rl - (ixrange.rowStart-1) - (ix-1);
			long rhs_ru = rhs_rl + (lhs_ru - lhs_rl);
			long rhs_cl = lhs_cl - ixrange.colStart + 1;
			long rhs_cu = rhs_cl + (lhs_cu - lhs_cl);
			
			// local indices are 0 (zero) based.
			int rhs_lrl = UtilFunctions.computeCellInBlock(rhs_rl, fb.getNumRows());
			int rhs_lru = UtilFunctions.computeCellInBlock(rhs_ru, fb.getNumRows());
			int rhs_lcl = (int)rhs_cl-1;
			int rhs_lcu = (int)rhs_cu-1;
			
			FrameBlock slicedRHSBlk = fb.slice(rhs_lrl, rhs_lru, rhs_lcl, rhs_lcu, new FrameBlock());
			
			int lblen = blenLeft;
			
			ValueType[] schemaPartialLeft = UtilFunctions.nCopies(lhs_lcl, ValueType.STRING);
			ValueType[] schemaRHS = Arrays.copyOfRange(fb.getSchema(), rhs_lcl, rhs_lcl-lhs_lcl+lhs_lcu+1);
			ValueType[] schema = UtilFunctions.copyOf(schemaPartialLeft, schemaRHS);
			ValueType[] schemaPartialRight = UtilFunctions.nCopies(lblen-schema.length, ValueType.STRING);
			schema = UtilFunctions.copyOf(schema, schemaPartialRight);
			FrameBlock resultBlock = new FrameBlock(schema);
			int iRHSRows = (int)(leftRowIndex<=rlen/blenLeft?blenLeft:rlen-(rlen/blenLeft)*blenLeft);
			resultBlock.ensureAllocatedColumns(iRHSRows);
			
			resultBlock = resultBlock.leftIndexingOperations(slicedRHSBlk, lhs_lrl, lhs_lru, lhs_lcl, lhs_lcu, new FrameBlock());
			outlist.add(new Pair<>((leftRowIndex-1)*blenLeft+1, resultBlock));
		}
	}
}
