You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@systemml.apache.org by mb...@apache.org on 2017/07/22 20:52:26 UTC

[2/5] systemml git commit: [SYSTEMML-1787] Column range indexing in codegen rowwise operators

[SYSTEMML-1787] Column range indexing in codegen rowwise operators

This patch extends the code generator row-wise template (compiler/
runtime) by column range indexing, where for each row we lookup a row
vector from a side input. This is useful to support expressions as the
following (which is part of the inner loop of Mlogreg with multiple
classes):

Q = P[,1:K] * (X %*% ssX_V);
R = t(X) %*% (Q - P[,1:K] * rowSums(Q));

Fusing P[,1:K] into the surrounding row-wise template avoids an
additional intermediate in nrow(X) x #classes.


Project: http://git-wip-us.apache.org/repos/asf/systemml/repo
Commit: http://git-wip-us.apache.org/repos/asf/systemml/commit/d7e4c5a5
Tree: http://git-wip-us.apache.org/repos/asf/systemml/tree/d7e4c5a5
Diff: http://git-wip-us.apache.org/repos/asf/systemml/diff/d7e4c5a5

Branch: refs/heads/master
Commit: d7e4c5a56b392b218235f82e2fbbe57626db2710
Parents: c6679b7
Author: Matthias Boehm <mb...@gmail.com>
Authored: Fri Jul 21 15:57:07 2017 -0700
Committer: Matthias Boehm <mb...@gmail.com>
Committed: Sat Jul 22 13:53:15 2017 -0700

----------------------------------------------------------------------
 .../org/apache/sysml/hops/LeftIndexingOp.java   |  4 +-
 .../sysml/hops/codegen/SpoofCompiler.java       |  5 ++-
 .../sysml/hops/codegen/cplan/CNodeTernary.java  | 21 ++++++++--
 .../hops/codegen/template/TemplateRow.java      |  9 +++--
 .../hops/codegen/template/TemplateUtils.java    | 15 ++++++--
 .../sysml/hops/rewrite/HopRewriteUtils.java     | 40 ++++++++++----------
 .../rewrite/RewriteForLoopVectorization.java    |  8 ++--
 .../rewrite/RewriteIndexingVectorization.java   |  8 ++--
 .../runtime/codegen/LibSpoofPrimitives.java     |  4 +-
 .../sysml/runtime/codegen/SpoofOperator.java    | 13 +++++++
 .../functions/codegen/RowAggTmplTest.java       |  3 +-
 11 files changed, 83 insertions(+), 47 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/systemml/blob/d7e4c5a5/src/main/java/org/apache/sysml/hops/LeftIndexingOp.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/LeftIndexingOp.java b/src/main/java/org/apache/sysml/hops/LeftIndexingOp.java
index 601cb6f..a641622 100644
--- a/src/main/java/org/apache/sysml/hops/LeftIndexingOp.java
+++ b/src/main/java/org/apache/sysml/hops/LeftIndexingOp.java
@@ -82,11 +82,11 @@ public class LeftIndexingOp  extends Hop
 		HopsException.check(_input.size() == 6, this, "should have 6 inputs but has %d inputs", 6);
 	}
 
-	public boolean getRowLowerEqualsUpper(){
+	public boolean isRowLowerEqualsUpper(){
 		return _rowLowerEqualsUpper;
 	}
 	
-	public boolean getColLowerEqualsUpper() {
+	public boolean isColLowerEqualsUpper() {
 		return _colLowerEqualsUpper;
 	}
 	

http://git-wip-us.apache.org/repos/asf/systemml/blob/d7e4c5a5/src/main/java/org/apache/sysml/hops/codegen/SpoofCompiler.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/codegen/SpoofCompiler.java b/src/main/java/org/apache/sysml/hops/codegen/SpoofCompiler.java
index 87ed1a0..4a59d1b 100644
--- a/src/main/java/org/apache/sysml/hops/codegen/SpoofCompiler.java
+++ b/src/main/java/org/apache/sysml/hops/codegen/SpoofCompiler.java
@@ -688,7 +688,7 @@ public class SpoofCompiler
 			cplans2.put(e.getKey(), new Pair<Hop[],CNodeTpl>(inHops, tpl));
 			
 			//remove invalid plans with column indexing on main input
-			if( tpl instanceof CNodeCell ) {
+			if( tpl instanceof CNodeCell || tpl instanceof CNodeRow ) {
 				CNodeData in1 = (CNodeData)tpl.getInput().get(0);
 				if( rHasLookupRC1(tpl.getOutput(), in1) || isLookupRC1(tpl.getOutput(), in1) ) {
 					cplans2.remove(e.getKey());
@@ -776,7 +776,8 @@ public class SpoofCompiler
 	}
 	
 	private static boolean isLookupRC1(CNode node, CNodeData mainInput) {
-		return (node instanceof CNodeTernary && ((CNodeTernary)node).getType()==TernaryType.LOOKUP_RC1 
+		return (node instanceof CNodeTernary && (((CNodeTernary)node).getType()==TernaryType.LOOKUP_RC1 
+				|| ((CNodeTernary)node).getType()==TernaryType.LOOKUP_RVECT1 )
 				&& node.getInput().get(0) instanceof CNodeData
 				&& ((CNodeData)node.getInput().get(0)).getHopID() == mainInput.getHopID());
 	}

http://git-wip-us.apache.org/repos/asf/systemml/blob/d7e4c5a5/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeTernary.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeTernary.java b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeTernary.java
index 9a4b103..e9bb472 100644
--- a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeTernary.java
+++ b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeTernary.java
@@ -28,7 +28,8 @@ public class CNodeTernary extends CNode
 	public enum TernaryType {
 		PLUS_MULT, MINUS_MULT,
 		REPLACE, REPLACE_NAN,
-		LOOKUP_RC1;
+		LOOKUP_RC1, LOOKUP_RVECT1;
+		
 		
 		public static boolean contains(String value) {
 			for( TernaryType tt : values()  )
@@ -53,14 +54,19 @@ public class CNodeTernary extends CNode
 					return "    double %TMP% = Double.isNaN(%IN1%) ? %IN3% : %IN1%;\n";
 					
 				case LOOKUP_RC1:
-					return sparse ?
-							"    double %TMP% = getValue(%IN1v%, %IN2%, rowIndex, %IN3%-1);\n" :	
-							"    double %TMP% = getValue(%IN1%, %IN2%, rowIndex, %IN3%-1);\n";	
+					return "    double %TMP% = getValue(%IN1%, %IN2%, rowIndex, %IN3%-1);\n";
+					
+				case LOOKUP_RVECT1:
+					return "    double[] %TMP% = getVector(%IN1%, %IN2%, rowIndex, %IN3%-1);\n";
 					
 				default: 
 					throw new RuntimeException("Invalid ternary type: "+this.toString());
 			}
 		}
+		
+		public boolean isVectorPrimitive() {
+			return (this == LOOKUP_RVECT1);
+		}
 	}
 	
 	private final TernaryType _type;
@@ -116,6 +122,8 @@ public class CNodeTernary extends CNode
 			case REPLACE: 
 			case REPLACE_NAN: return "t(rplc)";
 			case LOOKUP_RC1: return "u(ixrc1)";
+			case LOOKUP_RVECT1: return "u(ixrv1)";
+			
 			default:
 				return super.toString();	
 		}
@@ -133,6 +141,11 @@ public class CNodeTernary extends CNode
 				_cols = 0;
 				_dataType= DataType.SCALAR;
 				break;
+			case LOOKUP_RVECT1:
+				_rows = 1;
+				_cols = _inputs.get(0)._cols;
+				_dataType= DataType.MATRIX;
+				break;
 		}
 	}
 	

http://git-wip-us.apache.org/repos/asf/systemml/blob/d7e4c5a5/src/main/java/org/apache/sysml/hops/codegen/template/TemplateRow.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/codegen/template/TemplateRow.java b/src/main/java/org/apache/sysml/hops/codegen/template/TemplateRow.java
index 8445aeb..659b528 100644
--- a/src/main/java/org/apache/sysml/hops/codegen/template/TemplateRow.java
+++ b/src/main/java/org/apache/sysml/hops/codegen/template/TemplateRow.java
@@ -88,7 +88,8 @@ public class TemplateRow extends TemplateBase
 				&& isFuseSkinnyMatrixMult(hop.getParent().get(0)))
 			|| (hop instanceof AggUnaryOp && ((AggUnaryOp)hop).getDirection()!=Direction.RowCol 
 				&& hop.getInput().get(0).getDim1()>1 && hop.getInput().get(0).getDim2()>1
-				&& HopRewriteUtils.isAggUnaryOp(hop, SUPPORTED_ROW_AGG));
+				&& HopRewriteUtils.isAggUnaryOp(hop, SUPPORTED_ROW_AGG))
+			|| (hop instanceof IndexingOp && HopRewriteUtils.isColumnRangeIndexing((IndexingOp)hop));
 	}
 
 	@Override
@@ -398,9 +399,9 @@ public class TemplateRow extends TemplateBase
 		{
 			CNode cdata1 = tmp.get(hop.getInput().get(0).getHopID());
 			out = new CNodeTernary(cdata1, 
-					TemplateUtils.createCNodeData(new LiteralOp(hop.getInput().get(0).getDim2()), true), 
-					TemplateUtils.createCNodeData(hop.getInput().get(4), true),
-					TernaryType.LOOKUP_RC1);
+				TemplateUtils.createCNodeData(new LiteralOp(hop.getInput().get(0).getDim2()), true), 
+				TemplateUtils.createCNodeData(hop.getInput().get(4), true),
+				(!hop.dimsKnown()||hop.getDim2()>1) ? TernaryType.LOOKUP_RVECT1 : TernaryType.LOOKUP_RC1);
 		}
 		
 		if( out == null ) {

http://git-wip-us.apache.org/repos/asf/systemml/blob/d7e4c5a5/src/main/java/org/apache/sysml/hops/codegen/template/TemplateUtils.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/codegen/template/TemplateUtils.java b/src/main/java/org/apache/sysml/hops/codegen/template/TemplateUtils.java
index 4bd5bf1..647c9d3 100644
--- a/src/main/java/org/apache/sysml/hops/codegen/template/TemplateUtils.java
+++ b/src/main/java/org/apache/sysml/hops/codegen/template/TemplateUtils.java
@@ -32,6 +32,7 @@ import org.apache.sysml.hops.TernaryOp;
 import org.apache.sysml.hops.Hop.AggOp;
 import org.apache.sysml.hops.Hop.Direction;
 import org.apache.sysml.hops.Hop.OpOp2;
+import org.apache.sysml.hops.IndexingOp;
 import org.apache.sysml.hops.UnaryOp;
 import org.apache.sysml.hops.codegen.cplan.CNode;
 import org.apache.sysml.hops.codegen.cplan.CNodeBinary;
@@ -174,9 +175,10 @@ public class TemplateUtils
 	public static RowType getRowType(Hop output, Hop... inputs) {
 		Hop X = inputs[0];
 		Hop B1 = (inputs.length>1) ? inputs[1] : null;
-		if( HopRewriteUtils.isEqualSize(output, X) )
+		if( X!=null && HopRewriteUtils.isEqualSize(output, X) )
 			return RowType.NO_AGG;
-		else if( B1 != null && output.getDim1()==X.getDim1() && output.getDim2()==B1.getDim2() )
+		else if( (B1 != null && output.getDim1()==X.getDim1() && output.getDim2()==B1.getDim2())
+			|| (output instanceof IndexingOp && HopRewriteUtils.isColumnRangeIndexing((IndexingOp)output)))
 			return RowType.NO_AGG_B1;
 		else if( output.getDim1()==X.getDim1() && (output.getDim2()==1 
 				|| HopRewriteUtils.isBinary(output, OpOp2.CBIND)) 
@@ -325,6 +327,8 @@ public class TemplateUtils
 		int max = 0;
 		for( CNode input : node.getInput() )
 			max = Math.max(max, getMaxVectorIntermediates(input));
+		max = Math.max(max, (node instanceof CNodeTernary
+			&& ((CNodeTernary)node).getType().isVectorPrimitive()) ? 1 : 0);
 		max = Math.max(max, (node instanceof CNodeBinary)? 
 			(((CNodeBinary)node).getType().isVectorVectorPrimitive() ? 3 :
 			((CNodeBinary)node).getType().isVectorScalarPrimitive() ? 2 :
@@ -345,10 +349,13 @@ public class TemplateUtils
 			ret += countVectorIntermediates(c);
 		//compute vector requirements of current node
 		int cntBin = (node instanceof CNodeBinary 
-			&& ((CNodeBinary)node).getType().isVectorPrimitive()) ? 1 : 0;
+			&& ((CNodeBinary)node).getType().isVectorPrimitive()
+			&& !((CNodeBinary)node).getType().name().endsWith("_ADD")) ? 1 : 0;
 		int cntUn = (node instanceof CNodeUnary
 				&& ((CNodeUnary)node).getType().isVectorScalarPrimitive()) ? 1 : 0;
-		return ret + cntBin + cntUn;
+		int cntTn = (node instanceof CNodeTernary
+				&& ((CNodeTernary)node).getType().isVectorPrimitive()) ? 1 : 0;
+		return ret + cntBin + cntUn + cntTn;
 	}
 
 	public static boolean isType(TemplateType type, TemplateType... validTypes) {

http://git-wip-us.apache.org/repos/asf/systemml/blob/d7e4c5a5/src/main/java/org/apache/sysml/hops/rewrite/HopRewriteUtils.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/rewrite/HopRewriteUtils.java b/src/main/java/org/apache/sysml/hops/rewrite/HopRewriteUtils.java
index 14bcc1e..bc6d22c 100644
--- a/src/main/java/org/apache/sysml/hops/rewrite/HopRewriteUtils.java
+++ b/src/main/java/org/apache/sysml/hops/rewrite/HopRewriteUtils.java
@@ -904,26 +904,26 @@ public class HopRewriteUtils
 		return true;
 	}
 	
-	public static boolean isFullColumnIndexing(LeftIndexingOp hop)
-	{
-		boolean colPred = hop.getColLowerEqualsUpper();  //single col
-		
-		Hop rl = hop.getInput().get(2);
-		Hop ru = hop.getInput().get(3);
-		
-		return colPred && rl instanceof LiteralOp && getDoubleValueSafe((LiteralOp)rl)==1
-				&& ru instanceof LiteralOp && getDoubleValueSafe((LiteralOp)ru)==hop.getDim1();
-	}
-	
-	public static boolean isFullRowIndexing(LeftIndexingOp hop)
-	{
-		boolean rowPred = hop.getRowLowerEqualsUpper();  //single row
-		
-		Hop cl = hop.getInput().get(4);
-		Hop cu = hop.getInput().get(5);
-		
-		return rowPred && cl instanceof LiteralOp && getDoubleValueSafe((LiteralOp)cl)==1
-				&& cu instanceof LiteralOp && getDoubleValueSafe((LiteralOp)cu)==hop.getDim2();
+	public static boolean isFullColumnIndexing(LeftIndexingOp hop) {
+		return hop.isColLowerEqualsUpper()
+			&& ((isLiteralOfValue(hop.getInput().get(2), 1)
+			&& isLiteralOfValue(hop.getInput().get(3), hop.getDim1()))
+			|| hop.getDim1() == hop.getInput().get(0).getDim1());
+	}
+	
+	public static boolean isFullRowIndexing(LeftIndexingOp hop) {
+		return hop.isRowLowerEqualsUpper()
+			&& ((isLiteralOfValue(hop.getInput().get(4), 1)
+			&& isLiteralOfValue(hop.getInput().get(5), hop.getDim2()))
+			|| hop.getDim2() == hop.getInput().get(0).getDim2());
+	}
+	
+	public static boolean isColumnRangeIndexing(IndexingOp hop) {
+		return ((isLiteralOfValue(hop.getInput().get(1), 1)
+			&& isLiteralOfValue(hop.getInput().get(2), hop.getDim1()))
+			|| hop.getDim1() == hop.getInput().get(0).getDim1())
+			&& isLiteralOfValue(hop.getInput().get(3), 1)
+			&& hop.getInput().get(4) instanceof LiteralOp;
 	}
 	
 	public static boolean isScalarMatrixBinaryMult( Hop hop ) {

http://git-wip-us.apache.org/repos/asf/systemml/blob/d7e4c5a5/src/main/java/org/apache/sysml/hops/rewrite/RewriteForLoopVectorization.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/rewrite/RewriteForLoopVectorization.java b/src/main/java/org/apache/sysml/hops/rewrite/RewriteForLoopVectorization.java
index e3e55fe..7154b36 100644
--- a/src/main/java/org/apache/sysml/hops/rewrite/RewriteForLoopVectorization.java
+++ b/src/main/java/org/apache/sysml/hops/rewrite/RewriteForLoopVectorization.java
@@ -236,7 +236,7 @@ public class RewriteForLoopVectorization extends StatementBlockRewriteRule
 					IndexingOp rix1 = (IndexingOp) lixrhs.getInput().get(1);
 					
 					//check for rowwise
-					if(    lix.getRowLowerEqualsUpper() && rix0.isRowLowerEqualsUpper() && rix1.isRowLowerEqualsUpper() 
+					if(    lix.isRowLowerEqualsUpper() && rix0.isRowLowerEqualsUpper() && rix1.isRowLowerEqualsUpper() 
 						&& lix.getInput().get(2).getName().equals(itervar)
 						&& rix0.getInput().get(1).getName().equals(itervar)
 						&& rix1.getInput().get(1).getName().equals(itervar))
@@ -245,7 +245,7 @@ public class RewriteForLoopVectorization extends StatementBlockRewriteRule
 						rowIx = true;
 					}
 					//check for colwise
-					if(    lix.getColLowerEqualsUpper() && rix0.isColLowerEqualsUpper() && rix1.isColLowerEqualsUpper() 
+					if(    lix.isColLowerEqualsUpper() && rix0.isColLowerEqualsUpper() && rix1.isColLowerEqualsUpper() 
 						&& lix.getInput().get(4).getName().equals(itervar)
 						&& rix0.getInput().get(3).getName().equals(itervar)
 						&& rix1.getInput().get(3).getName().equals(itervar))
@@ -406,14 +406,14 @@ public class RewriteForLoopVectorization extends StatementBlockRewriteRule
 		boolean[] ret = new boolean[2]; //apply, rowIx
 		
 		//check for rowwise
-		if(    lix.getRowLowerEqualsUpper() && rix.isRowLowerEqualsUpper() 
+		if(    lix.isRowLowerEqualsUpper() && rix.isRowLowerEqualsUpper() 
 			&& lix.getInput().get(2).getName().equals(itervar)
 			&& rix.getInput().get(1).getName().equals(itervar) ) {
 			ret[0] = true;
 			ret[1] = true;
 		}
 		//check for colwise
-		if(    lix.getColLowerEqualsUpper() && rix.isColLowerEqualsUpper() 
+		if(    lix.isColLowerEqualsUpper() && rix.isColLowerEqualsUpper() 
 			&& lix.getInput().get(4).getName().equals(itervar)
 			&& rix.getInput().get(3).getName().equals(itervar) ) {
 			ret[0] = true;

http://git-wip-us.apache.org/repos/asf/systemml/blob/d7e4c5a5/src/main/java/org/apache/sysml/hops/rewrite/RewriteIndexingVectorization.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/rewrite/RewriteIndexingVectorization.java b/src/main/java/org/apache/sysml/hops/rewrite/RewriteIndexingVectorization.java
index b797e00..0724612 100644
--- a/src/main/java/org/apache/sysml/hops/rewrite/RewriteIndexingVectorization.java
+++ b/src/main/java/org/apache/sysml/hops/rewrite/RewriteIndexingVectorization.java
@@ -197,8 +197,8 @@ public class RewriteIndexingVectorization extends HopRewriteRule
 		if( hop instanceof LeftIndexingOp ) //left indexing
 		{
 			LeftIndexingOp ihop0 = (LeftIndexingOp) hop;
-			boolean isSingleRow = ihop0.getRowLowerEqualsUpper();
-			boolean isSingleCol = ihop0.getColLowerEqualsUpper();
+			boolean isSingleRow = ihop0.isRowLowerEqualsUpper();
+			boolean isSingleCol = ihop0.isColLowerEqualsUpper();
 			boolean appliedRow = false;
 			
 			if( isSingleRow && isSingleCol )
@@ -210,7 +210,7 @@ public class RewriteIndexingVectorization extends HopRewriteRule
 				while( current.getInput().get(0) instanceof LeftIndexingOp ) {
 					LeftIndexingOp tmp = (LeftIndexingOp) current.getInput().get(0);
 					if(    tmp.getParent().size()>1  //multiple consumers, i.e., not a simple chain
-						|| !((LeftIndexingOp) tmp).getRowLowerEqualsUpper() //row merge not applicable
+						|| !((LeftIndexingOp) tmp).isRowLowerEqualsUpper() //row merge not applicable
 						|| tmp.getInput().get(2) != ihop0.getInput().get(2) //not the same row
 						|| tmp.getInput().get(0).getDim2() <= 1 ) //target is single column or unknown 
 					{
@@ -289,7 +289,7 @@ public class RewriteIndexingVectorization extends HopRewriteRule
 				while( current.getInput().get(0) instanceof LeftIndexingOp ) {
 					LeftIndexingOp tmp = (LeftIndexingOp) current.getInput().get(0);
 					if(    tmp.getParent().size()>1  //multiple consumers, i.e., not a simple chain
-						|| !((LeftIndexingOp) tmp).getColLowerEqualsUpper() //row merge not applicable
+						|| !((LeftIndexingOp) tmp).isColLowerEqualsUpper() //row merge not applicable
 						|| tmp.getInput().get(4) != ihop0.getInput().get(4)  //not the same col
 						|| tmp.getInput().get(0).getDim1() <= 1 )  //target is single row or unknown
 					{

http://git-wip-us.apache.org/repos/asf/systemml/blob/d7e4c5a5/src/main/java/org/apache/sysml/runtime/codegen/LibSpoofPrimitives.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/codegen/LibSpoofPrimitives.java b/src/main/java/org/apache/sysml/runtime/codegen/LibSpoofPrimitives.java
index 1c59ee0..5b3b193 100644
--- a/src/main/java/org/apache/sysml/runtime/codegen/LibSpoofPrimitives.java
+++ b/src/main/java/org/apache/sysml/runtime/codegen/LibSpoofPrimitives.java
@@ -1451,11 +1451,11 @@ public class LibSpoofPrimitives
 		memPool.remove();
 	}
 	
-	private static double[] allocVector(int len, boolean reset) {
+	protected static double[] allocVector(int len, boolean reset) {
 		return allocVector(len, reset, 0);
 	}
 	
-	private static double[] allocVector(int len, boolean reset, double resetVal) {
+	protected static double[] allocVector(int len, boolean reset, double resetVal) {
 		LinkedList<double[]> list = memPool.get(); 
 		
 		//find and remove vector with matching len 

http://git-wip-us.apache.org/repos/asf/systemml/blob/d7e4c5a5/src/main/java/org/apache/sysml/runtime/codegen/SpoofOperator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/codegen/SpoofOperator.java b/src/main/java/org/apache/sysml/runtime/codegen/SpoofOperator.java
index 9561fcb..e302012 100644
--- a/src/main/java/org/apache/sysml/runtime/codegen/SpoofOperator.java
+++ b/src/main/java/org/apache/sysml/runtime/codegen/SpoofOperator.java
@@ -168,6 +168,19 @@ public abstract class SpoofOperator implements Serializable
 			(data.mdat!=null) ? data.mdat.quickGetValue(rowIndex, colIndex) : 0;
 	}
 	
+	protected static double[] getVector(SideInput data, int n, double rowIndex, double colIndex) {
+		int irowIndex = UtilFunctions.toInt(rowIndex);
+		int icolIndex = UtilFunctions.toInt(colIndex);
+		return getVector(data, n, irowIndex, icolIndex);
+	}
+	
+	protected static double[] getVector(SideInput data, int n, int rowIndex, int colIndex) {
+		//note: wrapper sideinput guaranteed to be in dense format
+		double[] c = LibSpoofPrimitives.allocVector(colIndex+1, false);
+		System.arraycopy(data.ddat, rowIndex*n, c, 0, colIndex+1);
+		return c;
+	}
+	
 	public static class SideInput {
 		public final double[] ddat;
 		public final MatrixBlock mdat;

http://git-wip-us.apache.org/repos/asf/systemml/blob/d7e4c5a5/src/test/java/org/apache/sysml/test/integration/functions/codegen/RowAggTmplTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/sysml/test/integration/functions/codegen/RowAggTmplTest.java b/src/test/java/org/apache/sysml/test/integration/functions/codegen/RowAggTmplTest.java
index 59c3ab4..2092f22 100644
--- a/src/test/java/org/apache/sysml/test/integration/functions/codegen/RowAggTmplTest.java
+++ b/src/test/java/org/apache/sysml/test/integration/functions/codegen/RowAggTmplTest.java
@@ -578,7 +578,8 @@ public class RowAggTmplTest extends AutomatedTestBase
 				Assert.assertTrue(!heavyHittersContainsSubString("spoofRA", 2)
 					&& !heavyHittersContainsSubString("sp_spoofRA", 2));
 			if( testname.equals(TEST_NAME30) )
-				Assert.assertTrue(!heavyHittersContainsSubString("spoofRA", 2));
+				Assert.assertTrue(!heavyHittersContainsSubString("spoofRA", 2)
+					&& !heavyHittersContainsSubString("rangeReIndex"));
 		}
 		finally {
 			rtplatform = platformOld;