[SYSTEMML-1365] Extended code generator (celltmpl n-ary matrix inputs)

This patch generalizes the existing SpoofCellwise templates from one
input matrix with arbitrary sideways vectors to one input matrix with
arbitrary sideways dense matrices. It applies to both binary and ternary
HOPs. In detail, we now have special LOOKUP_R and LOOKUP_RC nodes that
retrieve the relevant information for the current cell of the main input
matrix. 

Furthermore, this change also simplifies the signature of all code
templates and adds new tests for sum-product chains.


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

Branch: refs/heads/master
Commit: d65c7b5bba81387d250a762f6bf75973cf90f466
Parents: 6946ff0
Author: Matthias Boehm <[email protected]>
Authored: Sat Mar 4 17:14:10 2017 -0800
Committer: Matthias Boehm <[email protected]>
Committed: Sat Mar 4 17:14:10 2017 -0800

----------------------------------------------------------------------
 .../sysml/hops/codegen/SpoofCompiler.java       |  23 ++-
 .../sysml/hops/codegen/cplan/CNodeBinary.java   |   4 +-
 .../sysml/hops/codegen/cplan/CNodeCell.java     |   4 +-
 .../hops/codegen/cplan/CNodeOuterProduct.java   |  16 +-
 .../hops/codegen/cplan/CNodeRowAggVector.java   |  12 +-
 .../sysml/hops/codegen/cplan/CNodeTpl.java      |  28 ++--
 .../sysml/hops/codegen/cplan/CNodeUnary.java    |  23 ++-
 .../sysml/hops/codegen/template/CellTpl.java    |  66 +++++---
 .../hops/codegen/template/CplanRegister.java    |   5 +-
 .../hops/codegen/template/OuterProductTpl.java  |   4 +-
 .../sysml/hops/codegen/template/RowAggTpl.java  |   7 +-
 .../hops/codegen/template/TemplateUtils.java    |   6 +
 .../sysml/hops/rewrite/HopRewriteUtils.java     |  10 +-
 .../sysml/runtime/codegen/SpoofCellwise.java    |   2 +-
 .../sysml/runtime/codegen/SpoofOperator.java    |  19 ++-
 .../functions/codegen/SumProductChainTest.java  | 153 +++++++++++++++++++
 .../functions/codegen/SumAdditionChain.R        |  32 ++++
 .../functions/codegen/SumAdditionChain.dml      |  29 ++++
 .../scripts/functions/codegen/SumProductChain.R |  32 ++++
 .../functions/codegen/SumProductChain.dml       |  29 ++++
 .../functions/codegen/ZPackageSuite.java        |   1 +
 21 files changed, 437 insertions(+), 68 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/d65c7b5b/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 26a0b58..760eff0 100644
--- a/src/main/java/org/apache/sysml/hops/codegen/SpoofCompiler.java
+++ b/src/main/java/org/apache/sysml/hops/codegen/SpoofCompiler.java
@@ -37,6 +37,7 @@ import org.apache.sysml.hops.codegen.cplan.CNodeData;
 import org.apache.sysml.hops.codegen.cplan.CNodeOuterProduct;
 import org.apache.sysml.hops.codegen.cplan.CNodeTpl;
 import org.apache.sysml.hops.codegen.cplan.CNodeUnary;
+import org.apache.sysml.hops.codegen.cplan.CNodeUnary.UnaryType;
 import org.apache.sysml.hops.codegen.template.BaseTpl;
 import org.apache.sysml.hops.codegen.template.CellTpl;
 import org.apache.sysml.hops.codegen.template.CplanRegister;
@@ -205,7 +206,7 @@ public class SpoofCompiler
                        HashMap<Long, Pair<Hop[],CNodeTpl>>  cplans = 
constructCPlans(roots, compileLiterals);
                        
                        //cleanup codegen plans (remove unnecessary inputs, fix 
hop-cnodedata mapping,
-                       //remove empty templates with single cnodedata input)
+                       //remove empty templates with single cnodedata input, 
remove spurious lookups)
                        cplans = cleanupCPlans(cplans);
                                        
                        //explain before modification
@@ -386,6 +387,12 @@ public class SpoofCompiler
                                                tmp.toArray(new Hop[0]),tpl));
                        }
                        
+                       //remove spurious lookups on main input of cell template
+                       if( tpl instanceof CNodeCell || tpl instanceof 
CNodeOuterProduct ) {
+                               CNode in1 = tpl.getInput().get(0);
+                               rFindAndRemoveLookup(tpl.getOutput(), 
in1.getVarname());
+                       }
+                       
                        //remove cplan w/ single op and w/o agg
                        if( tpl instanceof CNodeCell && 
((CNodeCell)tpl).getCellType()==CellType.NO_AGG
                                && tpl.getOutput() instanceof CNodeUnary && 
tpl.getOutput().getInput().get(0) instanceof CNodeData) 
@@ -408,4 +415,18 @@ public class SpoofCompiler
                for( CNode c : node.getInput() )
                        rCollectLeafIDs(c, leafs);
        }
+       
+       private static void rFindAndRemoveLookup(CNode node, String nodeName) {
+               for( int i=0; i<node.getInput().size(); i++ ) {
+                       CNode tmp = node.getInput().get(i);
+                       if( tmp instanceof CNodeUnary && 
(((CNodeUnary)tmp).getType()==UnaryType.LOOKUP_R 
+                                       || 
((CNodeUnary)tmp).getType()==UnaryType.LOOKUP_RC)
+                               && 
tmp.getInput().get(0).getVarname().equals(nodeName) )
+                       {
+                               node.getInput().set(i, tmp.getInput().get(0));
+                       }
+                       else
+                               rFindAndRemoveLookup(tmp, nodeName);
+               }
+       }
 }

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/d65c7b5b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeBinary.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeBinary.java 
b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeBinary.java
index d11d0ac..fcd2d16 100644
--- a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeBinary.java
+++ b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeBinary.java
@@ -160,8 +160,8 @@ public class CNodeBinary extends CNode
                        else
                                tmp = tmp.replaceAll("%IN"+j+"%", varj );
                        
-                       if(varj.startsWith("_b")  ) //i.e. b.get(index)
-                               tmp = tmp.replaceAll("%POS"+j+"%", "_bi");
+                       if(varj.startsWith("b")  ) //i.e. b.get(index)
+                               tmp = tmp.replaceAll("%POS"+j+"%", "bi");
                        else
                                tmp = tmp.replaceAll("%POS"+j+"%", varj+"i");
                }

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/d65c7b5b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeCell.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeCell.java 
b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeCell.java
index a9408ca..9fdaa62 100644
--- a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeCell.java
+++ b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeCell.java
@@ -41,7 +41,7 @@ public class CNodeCell extends CNodeTpl
                        + "  public %TMP%() {\n"
                        + "    _type = CellType.%TYPE%;\n"
                        + "  }\n"
-                       + "  protected double genexecDense( double _a, 
double[][] _b, double[] _scalars, int _n, int _m, int _rowIndex, int _colIndex) 
{ \n"
+                       + "  protected double genexecDense( double a, 
double[][] b, double[] scalars, int n, int m, int rowIndex, int colIndex) { \n"
                        + "%BODY_dense%"
                        + "    return %OUT%;\n"
                        + "  } \n"
@@ -76,7 +76,7 @@ public class CNodeCell extends CNodeTpl
                String tmp = TEMPLATE;
                
                //rename inputs
-               rReplaceDataNode(_output, _inputs.get(0), "_a");
+               rReplaceDataNode(_output, _inputs.get(0), "a");
                renameInputs(_inputs, 1);
                
                //generate dense/sparse bodies

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/d65c7b5b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeOuterProduct.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeOuterProduct.java 
b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeOuterProduct.java
index 6867d00..6a543cc 100644
--- a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeOuterProduct.java
+++ b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeOuterProduct.java
@@ -41,10 +41,10 @@ public class CNodeOuterProduct extends CNodeTpl
                        + "  public %TMP%() {\n"
                        + "    _outerProductType = OutProdType.%TYPE%;\n"
                        + "  }\n"
-                       + "  protected void genexecDense( double _a, double[] 
_a1, int _a1i, double[] _a2, int _a2i, double[][] _b, double[] _scalars, 
double[] _c, int _ci, int _n, int _m, int _k, int _rowIndex, int _colIndex) { 
\n"
+                       + "  protected void genexecDense( double a, double[] 
a1, int a1i, double[] a2, int a2i, double[][] b, double[] scalars, double[] c, 
int ci, int n, int m, int k, int rowIndex, int colIndex) { \n"
                        + "%BODY_dense%"
                        + "  } \n"
-                       + "  protected double genexecCellwise( double _a, 
double[] _a1, int _a1i, double[] _a2, int _a2i, double[][] _b, double[] 
_scalars, int _n, int _m, int _k, int _rowIndex, int _colIndex) { \n"
+                       + "  protected double genexecCellwise( double a, 
double[] a1, int a1i, double[] a2, int a2i, double[][] b, double[] scalars, int 
n, int m, int k, int rowIndex, int colIndex) { \n"
                        + "%BODY_cellwise%"
                        + "    return %OUT_cellwise%;\n"
                        + "  } \n"
@@ -64,9 +64,9 @@ public class CNodeOuterProduct extends CNodeTpl
                String tmp = TEMPLATE;
                
                //rename inputs
-               rReplaceDataNode(_output, _inputs.get(0), "_a");
-               rReplaceDataNode(_output, _inputs.get(1), "_a1"); // u
-               rReplaceDataNode(_output, _inputs.get(2), "_a2"); // v
+               rReplaceDataNode(_output, _inputs.get(0), "a");
+               rReplaceDataNode(_output, _inputs.get(1), "a1"); // u
+               rReplaceDataNode(_output, _inputs.get(2), "a2"); // v
                renameInputs(_inputs, 3);
 
                //generate dense/sparse bodies
@@ -77,7 +77,7 @@ public class CNodeOuterProduct extends CNodeTpl
 
                if(_type == OutProdType.LEFT_OUTER_PRODUCT || _type == 
OutProdType.RIGHT_OUTER_PRODUCT) {
                        tmp = tmp.replaceAll("%BODY_dense%", tmpDense);
-                       tmp = tmp.replaceAll("%OUT%", "_c");
+                       tmp = tmp.replaceAll("%OUT%", "c");
                        tmp = tmp.replaceAll("%BODY_cellwise%", "");
                        tmp = tmp.replaceAll("%OUT_cellwise%", "0");
                }
@@ -87,9 +87,9 @@ public class CNodeOuterProduct extends CNodeTpl
                        tmp = tmp.replaceAll("%OUT_cellwise%", 
getCurrentVarName());
                }
                //replace size information
-               tmp = tmp.replaceAll("%LEN%", "_k");
+               tmp = tmp.replaceAll("%LEN%", "k");
                
-               tmp = tmp.replaceAll("%POSOUT%", "_ci");
+               tmp = tmp.replaceAll("%POSOUT%", "ci");
                
                tmp = tmp.replaceAll("%TYPE%", _type.toString());
 

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/d65c7b5b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeRowAggVector.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeRowAggVector.java 
b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeRowAggVector.java
index 147615f..09967aa 100644
--- a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeRowAggVector.java
+++ b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeRowAggVector.java
@@ -36,10 +36,10 @@ public class CNodeRowAggVector extends CNodeTpl
                        + "  public %TMP%() {\n"
                        + "    _colVector = %FLAG%;\n"
                        + "  }\n"
-                       + "  protected void genexecRowDense( double[] _a, int 
_ai, double[][] _b, double[] _scalars, double[] _c, int _len, int _rowIndex ) { 
\n"
+                       + "  protected void genexecRowDense( double[] a, int 
ai, double[][] b, double[] scalars, double[] c, int len, int rowIndex ) { \n"
                        + "%BODY_dense%"
                        + "  } \n"
-                       + "  protected void genexecRowSparse( double[] _avals, 
int[] _aix, int _ai, double[][] _b, double[] _scalars, double[] _c, int _len, 
int _rowIndex ) { \n"
+                       + "  protected void genexecRowSparse( double[] avals, 
int[] aix, int ai, double[][] b, double[] scalars, double[] c, int len, int 
rowIndex ) { \n"
                        + "%BODY_sparse%"
                        + "  } \n"                      
                        + "}\n";
@@ -55,7 +55,7 @@ public class CNodeRowAggVector extends CNodeTpl
                String tmp = TEMPLATE;
                
                //rename inputs
-               rReplaceDataNode(_output, _inputs.get(0), "_a"); // input matrix
+               rReplaceDataNode(_output, _inputs.get(0), "a"); // input matrix
                renameInputs(_inputs, 1);
                
                //generate dense/sparse bodies
@@ -67,15 +67,15 @@ public class CNodeRowAggVector extends CNodeTpl
                tmp = tmp.replaceAll("%BODY_sparse%", tmpSparse);
                
                //replace outputs 
-               tmp = tmp.replaceAll("%OUT%", "_c");
+               tmp = tmp.replaceAll("%OUT%", "c");
                tmp = tmp.replaceAll("%POSOUT%", "0");
                
                //replace size information
-               tmp = tmp.replaceAll("%LEN%", "_len");
+               tmp = tmp.replaceAll("%LEN%", "len");
                
                //replace colvector information and start position
                tmp = tmp.replaceAll("%FLAG%", 
String.valueOf(_output._cols==1));
-               tmp = tmp.replaceAll("_bi", "0");
+               tmp = tmp.replaceAll("bi", "0");
                
                return tmp;
        }

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/d65c7b5b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeTpl.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeTpl.java 
b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeTpl.java
index 719770b..343aba4 100644
--- a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeTpl.java
+++ b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeTpl.java
@@ -25,6 +25,7 @@ import java.util.HashSet;
 
 import org.apache.sysml.hops.codegen.SpoofFusedOp.SpoofOutputDimsType;
 import org.apache.sysml.hops.codegen.cplan.CNodeUnary.UnaryType;
+import org.apache.sysml.hops.codegen.template.TemplateUtils;
 import org.apache.sysml.parser.Expression.DataType;
 
 public abstract class CNodeTpl extends CNode implements Cloneable
@@ -67,13 +68,13 @@ public abstract class CNodeTpl extends CNode implements 
Cloneable
                HashMap<Long, CNode> nodes = new HashMap<Long, CNode>();
                for(int i=startIndex, sPos=0, mPos=0; i < inputs.size(); i++) {
                        CNode cnode = inputs.get(i);
-                       if( !(cnode instanceof CNodeData) || 
((CNodeData)cnode).isLiteral())
+                       if( cnode instanceof CNodeData && 
((CNodeData)cnode).isLiteral() )
                                continue;
                        CNodeData cdata = (CNodeData)cnode;
                        if( cdata.getDataType() == DataType.SCALAR  || ( 
cdata.getNumCols() == 0 && cdata.getNumRows() == 0) ) 
-                               nodes.put(cdata.getHopID(), new 
CNodeData(cdata, "_scalars["+ mPos++ +"]"));
+                               nodes.put(cdata.getHopID(), new 
CNodeData(cdata, "scalars["+ mPos++ +"]"));
                        else
-                               nodes.put(cdata.getHopID(), new 
CNodeData(cdata, "_b["+ sPos++ +"]"));
+                               nodes.put(cdata.getHopID(), new 
CNodeData(cdata, "b["+ sPos++ +"]"));
                }
                
                //single pass to replace all names
@@ -112,9 +113,10 @@ public abstract class CNodeTpl extends CNode implements 
Cloneable
                                        node._inputs.set(i, 
dnodes.get(tmp.getHopID()));
                        }
                        
-                       //replace lookup on top of leaf data node
+                       //replace lookup on top of leaf data node (for CSE only)
                        if( node._inputs.get(i) instanceof CNodeUnary
-                               && 
((CNodeUnary)node._inputs.get(i)).getType()==UnaryType.LOOKUP) {
+                               && 
(((CNodeUnary)node._inputs.get(i)).getType()==UnaryType.LOOKUP_R
+                               || 
((CNodeUnary)node._inputs.get(i)).getType()==UnaryType.LOOKUP_RC)) {
                                CNodeData tmp = 
(CNodeData)node._inputs.get(i)._inputs.get(0);
                                if( !lnodes.containsKey(tmp.getHopID()) )
                                        lnodes.put(tmp.getHopID(), 
node._inputs.get(i));
@@ -138,17 +140,18 @@ public abstract class CNodeTpl extends CNode implements 
Cloneable
                        
                        //remove unnecessary lookups
                        if( node._inputs.get(i) instanceof CNodeUnary 
-                               && 
((CNodeUnary)node._inputs.get(i)).getType()==UnaryType.LOOKUP 
+                               && 
(((CNodeUnary)node._inputs.get(i)).getType()==UnaryType.LOOKUP_R
+                               || 
((CNodeUnary)node._inputs.get(i)).getType()==UnaryType.LOOKUP_RC)
                                && 
node._inputs.get(i)._inputs.get(0).getDataType()==DataType.SCALAR)
                                node._inputs.set(i, 
node._inputs.get(i)._inputs.get(0));
                }
        }
        
-       public void rInsertLookupNode( CNode node, long hopID, HashMap<Long, 
CNode> memo ) 
+       public void rInsertLookupNode( CNode node, long hopID, HashMap<Long, 
CNode> memo, UnaryType lookupType ) 
        {
                for( int i=0; i<node._inputs.size(); i++ ) {
                        //recursively process children
-                       rInsertLookupNode(node._inputs.get(i), hopID, memo);
+                       rInsertLookupNode(node._inputs.get(i), hopID, memo, 
lookupType);
                        
                        //replace leaf node
                        if( node._inputs.get(i) instanceof CNodeData ) {
@@ -156,11 +159,14 @@ public abstract class CNodeTpl extends CNode implements 
Cloneable
                                if( tmp.getHopID() == hopID ) {
                                        //use memo structure to retain DAG 
structure
                                        CNode lookup = memo.get(hopID);
-                                       if( lookup == null ) {
-                                               lookup = new CNodeUnary(tmp, 
UnaryType.LOOKUP);
+                                       if( lookup == null && 
!TemplateUtils.isLookup(node) ) {
+                                               lookup = new CNodeUnary(tmp, 
lookupType);
                                                memo.put(hopID, lookup);
                                        }
-                                       node._inputs.set(i, lookup);
+                                       else if( TemplateUtils.isLookup(node) )
+                                               
((CNodeUnary)node).setType(lookupType);
+                                       else
+                                               node._inputs.set(i, lookup);
                                }
                        }
                }

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/d65c7b5b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeUnary.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeUnary.java 
b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeUnary.java
index dd8431b..f491609 100644
--- a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeUnary.java
+++ b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeUnary.java
@@ -27,7 +27,7 @@ import org.apache.sysml.parser.Expression.DataType;
 public class CNodeUnary extends CNode
 {
        public enum UnaryType {
-               ROW_SUMS, LOOKUP, LOOKUP0, //codegen specific
+               ROW_SUMS, LOOKUP_R, LOOKUP_RC, LOOKUP0, //codegen specific
                EXP, POW2, MULT2, SQRT, LOG,
                ABS, ROUND, CEIL, FLOOR, SIGN, 
                SIN, COS, TAN, ASIN, ACOS, ATAN,
@@ -47,8 +47,10 @@ public class CNodeUnary extends CNode
                                                                        "    
double %TMP% = LibSpoofPrimitives.vectSum( %IN1%, %POS1%,  %LEN%);\n"; 
                                case EXP:
                                        return "    double %TMP% = 
FastMath.exp(%IN1%);\n";
-                           case LOOKUP:
-                                       return "    double %TMP% = 
%IN1%[_rowIndex];\n" ;
+                           case LOOKUP_R:
+                                       return "    double %TMP% = 
%IN1%[rowIndex];\n";
+                           case LOOKUP_RC:
+                                       return "    double %TMP% = 
%IN1%[rowIndex*n+colIndex];\n";      
                                case LOOKUP0:
                                        return "    double %TMP% = %IN1%[0];\n" 
;
                                case POW2:
@@ -96,7 +98,7 @@ public class CNodeUnary extends CNode
                }
        }
        
-       private final UnaryType _type;
+       private UnaryType _type;
        
        public CNodeUnary( CNode in1, UnaryType type ) {
                _inputs.add(in1);
@@ -107,6 +109,10 @@ public class CNodeUnary extends CNode
        public UnaryType getType() {
                return _type;
        }
+       
+       public void setType(UnaryType type) {
+               _type = type;
+       }
 
        @Override
        public String codegen(boolean sparse) {
@@ -131,10 +137,10 @@ public class CNodeUnary extends CNode
                else
                        tmp = tmp.replaceAll("%IN1%", varj );
                
-               if(varj.startsWith("_b")  ) //i.e. b.get(index)
+               if(varj.startsWith("b")  ) //i.e. b.get(index)
                {
-                       tmp = tmp.replaceAll("%POS1%", "_bi");
-                       tmp = tmp.replaceAll("%POS2%", "_bi");
+                       tmp = tmp.replaceAll("%POS1%", "bi");
+                       tmp = tmp.replaceAll("%POS2%", "bi");
                }
                tmp = tmp.replaceAll("%POS1%", varj+"i");
                tmp = tmp.replaceAll("%POS2%", varj+"i");
@@ -161,7 +167,8 @@ public class CNodeUnary extends CNode
                switch(_type) {
                        case ROW_SUMS:
                        case EXP:
-                       case LOOKUP:
+                       case LOOKUP_R:
+                       case LOOKUP_RC:
                        case LOOKUP0:   
                        case POW2:
                        case MULT2:     

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/d65c7b5b/src/main/java/org/apache/sysml/hops/codegen/template/CellTpl.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/codegen/template/CellTpl.java 
b/src/main/java/org/apache/sysml/hops/codegen/template/CellTpl.java
index 4d95686..6b5930c 100644
--- a/src/main/java/org/apache/sysml/hops/codegen/template/CellTpl.java
+++ b/src/main/java/org/apache/sysml/hops/codegen/template/CellTpl.java
@@ -198,11 +198,15 @@ public class CellTpl extends BaseTpl
                                        
                                        //cdata1 is vector
                                        if( TemplateUtils.isColVector(cdata1) )
-                                               cdata1 = new CNodeUnary(cdata1, 
UnaryType.LOOKUP);
+                                               cdata1 = new CNodeUnary(cdata1, 
UnaryType.LOOKUP_R);
+                                       else if( cdata1 instanceof CNodeData && 
hop.getInput().get(0).getDataType().isMatrix() )
+                                               cdata1 = new CNodeUnary(cdata1, 
UnaryType.LOOKUP_RC);
                                        
                                        //cdata2 is vector
                                        if( TemplateUtils.isColVector(cdata2) )
-                                               cdata2 = new CNodeUnary(cdata2, 
UnaryType.LOOKUP);
+                                               cdata2 = new CNodeUnary(cdata2, 
UnaryType.LOOKUP_R);
+                                       else if( cdata2 instanceof CNodeData && 
hop.getInput().get(1).getDataType().isMatrix() )
+                                               cdata2 = new CNodeUnary(cdata2, 
UnaryType.LOOKUP_RC);
                                        
                                        if( bop.getOp()==OpOp2.POW && 
cdata2.isLiteral() && cdata2.getVarname().equals("2") )
                                                out = new CNodeUnary(cdata1, 
UnaryType.POW2);
@@ -220,10 +224,15 @@ public class CellTpl extends BaseTpl
                                        
                                        //cdata1 is vector
                                        if( TemplateUtils.isColVector(cdata1) )
-                                               cdata1 = new CNodeUnary(cdata1, 
UnaryType.LOOKUP);
+                                               cdata1 = new CNodeUnary(cdata1, 
UnaryType.LOOKUP_R);
+                                       else if( cdata1 instanceof CNodeData && 
hop.getInput().get(0).getDataType().isMatrix() )
+                                               cdata1 = new CNodeUnary(cdata1, 
UnaryType.LOOKUP_RC);
+                                       
                                        //cdata3 is vector
                                        if( TemplateUtils.isColVector(cdata3) )
-                                               cdata3 = new CNodeUnary(cdata3, 
UnaryType.LOOKUP);
+                                               cdata3 = new CNodeUnary(cdata3, 
UnaryType.LOOKUP_R);
+                                       else if( cdata3 instanceof CNodeData && 
hop.getInput().get(2).getDataType().isMatrix() )
+                                               cdata3 = new CNodeUnary(cdata3, 
UnaryType.LOOKUP_RC);
                                        
                                        //construct ternary cnode, primitive 
operation derived from OpOp3
                                        out = new CNodeTernary(cdata1, cdata2, 
cdata3, 
@@ -297,19 +306,42 @@ public class CellTpl extends BaseTpl
                }
        }
 
-       private boolean isValidOperation(Hop hop) {
-               boolean isBinaryMatrixScalar = hop instanceof BinaryOp && 
hop.getDataType()==DataType.MATRIX &&
-                       (hop.getInput().get(0).getDataType()==DataType.SCALAR 
|| hop.getInput().get(1).getDataType()==DataType.SCALAR); 
-               boolean isBinaryMatrixVector = hop instanceof BinaryOp && 
hop.dimsKnown() &&
-                       ((hop.getInput().get(0).getDataType() == DataType.MATRIX
-                               && 
TemplateUtils.isVectorOrScalar(hop.getInput().get(1)) && 
!TemplateUtils.isBinaryMatrixRowVector(hop)) 
-                       ||(TemplateUtils.isVectorOrScalar( 
hop.getInput().get(0))  
-                               && hop.getInput().get(1).getDataType() == 
DataType.MATRIX && !TemplateUtils.isBinaryMatrixRowVector(hop)) );
-               boolean isTernaryVectorScalarVector = hop instanceof TernaryOp 
&& hop.getInput().size()==3 && hop.dimsKnown()
-                               && HopRewriteUtils.checkInputDataTypes(hop, 
DataType.MATRIX, DataType.SCALAR, DataType.MATRIX)
-                               && 
TemplateUtils.isVector(hop.getInput().get(0)) && 
TemplateUtils.isVector(hop.getInput().get(2));
+       private boolean isValidOperation(Hop hop) 
+       {       
+               //prepare indicators for binary operations
+               boolean isBinaryMatrixScalar = false;
+               boolean isBinaryMatrixVector = false;
+               boolean isBinaryMatrixMatrixDense = false;
+               if( hop instanceof BinaryOp && hop.getDataType().isMatrix() ) {
+                       Hop left = hop.getInput().get(0);
+                       Hop right = hop.getInput().get(1);
+                       DataType ldt = left.getDataType();
+                       DataType rdt = right.getDataType();
+                       
+                       isBinaryMatrixScalar = (ldt.isScalar() || 
rdt.isScalar());      
+                       isBinaryMatrixVector = hop.dimsKnown() 
+                               && ((ldt.isMatrix() && 
TemplateUtils.isVectorOrScalar(right) && 
!TemplateUtils.isBinaryMatrixRowVector(hop)) 
+                               || (rdt.isMatrix() && 
TemplateUtils.isVectorOrScalar(left) && 
!TemplateUtils.isBinaryMatrixRowVector(hop)) );
+                       isBinaryMatrixMatrixDense = hop.dimsKnown() && 
HopRewriteUtils.isEqualSize(left, right)
+                               && ldt.isMatrix() && rdt.isMatrix() && 
!HopRewriteUtils.isSparse(left) && !HopRewriteUtils.isSparse(right);
+               }
+                               
+               //prepare indicators for ternary operations
+               boolean isTernaryVectorScalarVector = false;
+               boolean isTernaryMatrixScalarMatrixDense = false;
+               if( hop instanceof TernaryOp && hop.getInput().size()==3 && 
hop.dimsKnown() 
+                       && HopRewriteUtils.checkInputDataTypes(hop, 
DataType.MATRIX, DataType.SCALAR, DataType.MATRIX)) {
+                       Hop left = hop.getInput().get(0);
+                       Hop right = hop.getInput().get(2);
+                       
+                       isTernaryVectorScalarVector = 
TemplateUtils.isVector(left) && TemplateUtils.isVector(right);
+                       isTernaryMatrixScalarMatrixDense = 
HopRewriteUtils.isEqualSize(left, right) 
+                               && !HopRewriteUtils.isSparse(left) && 
!HopRewriteUtils.isSparse(right);
+               }
                
-               return hop.getDataType() == DataType.MATRIX && 
TemplateUtils.isOperationSupported(hop)
-                       && (hop instanceof UnaryOp || isBinaryMatrixScalar || 
isBinaryMatrixVector || isTernaryVectorScalarVector);     
+               //check supported unary, binary, ternary operations
+               return hop.getDataType() == DataType.MATRIX && 
TemplateUtils.isOperationSupported(hop) && (hop instanceof UnaryOp 
+                               || isBinaryMatrixScalar || isBinaryMatrixVector 
|| isBinaryMatrixMatrixDense 
+                               || isTernaryVectorScalarVector || 
isTernaryMatrixScalarMatrixDense);    
        }
 }

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/d65c7b5b/src/main/java/org/apache/sysml/hops/codegen/template/CplanRegister.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/hops/codegen/template/CplanRegister.java 
b/src/main/java/org/apache/sysml/hops/codegen/template/CplanRegister.java
index a4bcffe..f14981d 100644
--- a/src/main/java/org/apache/sysml/hops/codegen/template/CplanRegister.java
+++ b/src/main/java/org/apache/sysml/hops/codegen/template/CplanRegister.java
@@ -32,6 +32,7 @@ import org.apache.sysml.hops.codegen.cplan.CNodeCell;
 import org.apache.sysml.hops.codegen.cplan.CNodeData;
 import org.apache.sysml.hops.codegen.cplan.CNodeRowAggVector;
 import org.apache.sysml.hops.codegen.cplan.CNodeTpl;
+import org.apache.sysml.hops.codegen.cplan.CNodeUnary.UnaryType;
 import org.apache.sysml.hops.codegen.template.BaseTpl.TemplateType;
 import org.apache.sysml.parser.Expression.DataType;
 import org.apache.sysml.runtime.matrix.data.Pair;
@@ -149,8 +150,8 @@ public class CplanRegister {
                                        CNodeCell celltpl = 
(CNodeCell)ret.get(inhopID).getValue();
                                        
celltpl.getInput().get(0).setDataType(DataType.MATRIX);
                                        
rowaggtpl.rReplaceDataNode(rowaggtpl.getOutput(), inhopID, celltpl.getOutput());
-                                       
rowaggtpl.rInsertLookupNode(rowaggtpl.getOutput(), 
-                                               
((CNodeData)celltpl.getInput().get(0)).getHopID(), new HashMap<Long, CNode>());
+                                       
rowaggtpl.rInsertLookupNode(rowaggtpl.getOutput(), 
((CNodeData)celltpl.getInput().get(0)).getHopID(), 
+                                                       new HashMap<Long, 
CNode>(), UnaryType.LOOKUP_R);
                                        for( CNode input : celltpl.getInput() )
                                                rowaggtpl.addInput(input);
                                        HashSet<Long> inputIDs = 
TemplateUtils.rGetInputHopIDs(rowaggtpl.getOutput(), new HashSet<Long>());

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/d65c7b5b/src/main/java/org/apache/sysml/hops/codegen/template/OuterProductTpl.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/hops/codegen/template/OuterProductTpl.java 
b/src/main/java/org/apache/sysml/hops/codegen/template/OuterProductTpl.java
index c202d3c..bc6ef5b 100644
--- a/src/main/java/org/apache/sysml/hops/codegen/template/OuterProductTpl.java
+++ b/src/main/java/org/apache/sysml/hops/codegen/template/OuterProductTpl.java
@@ -341,7 +341,7 @@ public class OuterProductTpl extends BaseTpl {
                                        if( (cdata1.getNumRows() > 1 && 
cdata1.getNumCols() == 1) || (cdata1.getNumRows() == 1 && cdata1.getNumCols() > 
1) )
                                        {
                                                //second argument is always the 
vector
-                                               cdata1 = new CNodeUnary(cdata1, 
UnaryType.LOOKUP);
+                                               cdata1 = new CNodeUnary(cdata1, 
UnaryType.LOOKUP_R);
                                                //out = new CNodeBinary(tmp, 
cdata2, BinType.valueOf(primitiveOpName));
                                        }
                                        //cdata1 is a matrix 
@@ -356,7 +356,7 @@ public class OuterProductTpl extends BaseTpl {
                                        //else if( cdata2 instanceof CNodeData 
&& (((CNodeData)cdata2).getNumRows() > 1 && ((CNodeData)cdata2).getNumCols() == 
1) || ( ((CNodeData)cdata2).getNumRows() == 1 && 
((CNodeData)cdata2).getNumCols() > 1  ))
                                        if( (cdata2.getNumRows() > 1 && 
cdata2.getNumCols() == 1) || (cdata2.getNumRows() == 1 && cdata2.getNumCols() > 
1) )
                                        {
-                                               cdata2 = new CNodeUnary(cdata2, 
UnaryType.LOOKUP);
+                                               cdata2 = new CNodeUnary(cdata2, 
UnaryType.LOOKUP_R);
                                                //out = new CNodeBinary(cdata1, 
tmp, BinType.valueOf(primitiveOpName));
                                        }
                                        //cdata2 is a matrix 

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/d65c7b5b/src/main/java/org/apache/sysml/hops/codegen/template/RowAggTpl.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/hops/codegen/template/RowAggTpl.java 
b/src/main/java/org/apache/sysml/hops/codegen/template/RowAggTpl.java
index 0aff9ae..367cca3 100644
--- a/src/main/java/org/apache/sysml/hops/codegen/template/RowAggTpl.java
+++ b/src/main/java/org/apache/sysml/hops/codegen/template/RowAggTpl.java
@@ -186,7 +186,7 @@ public class RowAggTpl extends BaseTpl {
                                        if(  ((AggUnaryOp)hop).getDirection() 
== Direction.Row && ((AggUnaryOp)hop).getOp() == AggOp.SUM  ) //RowSums 
                                        {
                                                
if(hop.getInput().get(0).getDim2()==1)
-                                                       out = 
(cdata1.getDataType()==DataType.SCALAR) ? cdata1 : new 
CNodeUnary(cdata1,UnaryType.LOOKUP);
+                                                       out = 
(cdata1.getDataType()==DataType.SCALAR) ? cdata1 : new 
CNodeUnary(cdata1,UnaryType.LOOKUP_R);
                                                else
                                                        out = new 
CNodeUnary(cdata1, UnaryType.ROW_SUMS);
                                        }
@@ -245,14 +245,13 @@ public class RowAggTpl extends BaseTpl {
                                                if( (cdata1.getNumRows() > 1 && 
cdata1.getNumCols() == 1) || (cdata1.getNumRows() == 1 && cdata1.getNumCols() > 
1) )
                                                {
                                                        //second argument is 
always the vector
-                                                       cdata1 = new 
CNodeUnary(cdata1, UnaryType.LOOKUP);
-                                                       //out = new 
CNodeBinary(tmp, cdata2, BinType.valueOf(primitiveOpName));
+                                                       cdata1 = new 
CNodeUnary(cdata1, UnaryType.LOOKUP_R);
                                                }
                                                //cdata2 is vector
                                                //else if( cdata2 instanceof 
CNodeData && (((CNodeData)cdata2).getNumRows() > 1 && 
((CNodeData)cdata2).getNumCols() == 1) || ( ((CNodeData)cdata2).getNumRows() == 
1 && ((CNodeData)cdata2).getNumCols() > 1  ))
                                                if( (cdata2.getNumRows() > 1 && 
cdata2.getNumCols() == 1) || (cdata2.getNumRows() == 1 && cdata2.getNumCols() > 
1) )
                                                {
-                                                       cdata2 = new 
CNodeUnary(cdata2, UnaryType.LOOKUP);
+                                                       cdata2 = new 
CNodeUnary(cdata2, UnaryType.LOOKUP_R);
                                                        //out = new 
CNodeBinary(cdata1, tmp, BinType.valueOf(primitiveOpName));
                                                }
                                                out = new CNodeBinary(cdata1, 
cdata2, BinType.valueOf(primitiveOpName));        

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/d65c7b5b/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 32a4d80..6934e02 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
@@ -313,4 +313,10 @@ public class TemplateUtils
                        ((((AggUnaryOp) hop).getDirection() == 
Direction.RowCol) ? 
                        CellType.FULL_AGG : CellType.ROW_AGG) : CellType.NO_AGG;
        }
+       
+       public static boolean isLookup(CNode node) {
+               return (node instanceof CNodeUnary 
+                               && 
(((CNodeUnary)node).getType()==UnaryType.LOOKUP_R 
+                               || 
((CNodeUnary)node).getType()==UnaryType.LOOKUP_RC));
+       }
 }

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/d65c7b5b/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 e69ecbf..c21e9e3 100644
--- a/src/main/java/org/apache/sysml/hops/rewrite/HopRewriteUtils.java
+++ b/src/main/java/org/apache/sysml/hops/rewrite/HopRewriteUtils.java
@@ -642,13 +642,19 @@ public class HopRewriteUtils
                return ( hop.getNnz()==0 );
        }
        
-       public static boolean isEqualSize( Hop hop1, Hop hop2 )
-       {
+       public static boolean isEqualSize( Hop hop1, Hop hop2 ) {
                return (hop1.dimsKnown() && hop2.dimsKnown()
                                && hop1.getDim1() == hop2.getDim1()
                                && hop1.getDim2() == hop2.getDim2());
        }
        
+       public static boolean isEqualSize( Hop hop1, Hop... hops ) {
+               boolean ret = hop1.dimsKnown();
+               for( int i=0; i<hops.length && ret; i++ )
+                       ret &= isEqualSize(hop1, hops[i]);
+               return ret;     
+       }
+       
        public static boolean isSingleBlock( Hop hop ) {
                return isSingleBlock(hop, true)
                        && isSingleBlock(hop, false);

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/d65c7b5b/src/main/java/org/apache/sysml/runtime/codegen/SpoofCellwise.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/codegen/SpoofCellwise.java 
b/src/main/java/org/apache/sysml/runtime/codegen/SpoofCellwise.java
index 51c5164..005b3ca 100644
--- a/src/main/java/org/apache/sysml/runtime/codegen/SpoofCellwise.java
+++ b/src/main/java/org/apache/sysml/runtime/codegen/SpoofCellwise.java
@@ -208,7 +208,7 @@ public abstract class SpoofCellwise extends SpoofOperator 
implements Serializabl
                return kbuff._sum;
        }
        
-       private long executeDense(double[] a, double[][] b,double[] scalars, 
double[] c, int n, int m, int rl, int ru) 
+       private long executeDense(double[] a, double[][] b, double[] scalars, 
double[] c, int n, int m, int rl, int ru) 
        {
                long lnnz = 0;
                

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/d65c7b5b/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 ddbf96d..f4ee915 100644
--- a/src/main/java/org/apache/sysml/runtime/codegen/SpoofOperator.java
+++ b/src/main/java/org/apache/sysml/runtime/codegen/SpoofOperator.java
@@ -22,14 +22,18 @@ package org.apache.sysml.runtime.codegen;
 import java.io.Serializable;
 import java.util.ArrayList;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.sysml.runtime.DMLRuntimeException;
 import org.apache.sysml.runtime.instructions.cp.ScalarObject;
 import org.apache.sysml.runtime.matrix.data.MatrixBlock;
+import org.apache.sysml.runtime.util.DataConverter;
 
 public abstract class SpoofOperator implements Serializable
 {
        private static final long serialVersionUID = 3834006998853573319L;
-
+       private static final Log LOG = 
LogFactory.getLog(SpoofOperator.class.getName());
+       
        public abstract void execute(ArrayList<MatrixBlock> inputs, 
ArrayList<ScalarObject> scalars, MatrixBlock out) 
                throws DMLRuntimeException;
        
@@ -58,9 +62,20 @@ public abstract class SpoofOperator implements Serializable
        protected double[][] prepInputMatrices(ArrayList<MatrixBlock> inputs, 
int offset) {
                double[][] b = new double[inputs.size()-offset][]; 
                for(int i=offset; i < inputs.size(); i++) {
+                       //allocate dense block in place for empty blocks
                        if( inputs.get(i).isEmptyBlock(false) && 
!inputs.get(i).isAllocated() )
                                inputs.get(i).allocateDenseBlock(); 
-                       b[i-offset] = inputs.get(i).getDenseBlock();
+                       //convert sparse to dense temporary block
+                       if( inputs.get(i).isInSparseFormat() ) {
+                               MatrixBlock tmp = inputs.get(i);
+                               b[i-offset] = 
DataConverter.convertToDoubleVector(tmp);
+                               LOG.warn("Converted 
"+tmp.getNumRows()+"x"+tmp.getNumColumns() + 
+                                               " sideways input matrix from 
sparse to dense.");
+                       }
+                       //use existing dense block
+                       else {
+                               b[i-offset] = inputs.get(i).getDenseBlock();
+                       }
                }
                return b;
        }

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/d65c7b5b/src/test/java/org/apache/sysml/test/integration/functions/codegen/SumProductChainTest.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/sysml/test/integration/functions/codegen/SumProductChainTest.java
 
b/src/test/java/org/apache/sysml/test/integration/functions/codegen/SumProductChainTest.java
new file mode 100644
index 0000000..2ba9ffa
--- /dev/null
+++ 
b/src/test/java/org/apache/sysml/test/integration/functions/codegen/SumProductChainTest.java
@@ -0,0 +1,153 @@
+/*
+ * 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.sysml.test.integration.functions.codegen;
+
+import java.util.HashMap;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.sysml.api.DMLScript;
+import org.apache.sysml.api.DMLScript.RUNTIME_PLATFORM;
+import org.apache.sysml.hops.OptimizerUtils;
+import org.apache.sysml.lops.LopProperties.ExecType;
+import org.apache.sysml.runtime.matrix.data.MatrixValue.CellIndex;
+import org.apache.sysml.test.integration.AutomatedTestBase;
+import org.apache.sysml.test.integration.TestConfiguration;
+import org.apache.sysml.test.utils.TestUtils;
+
+public class SumProductChainTest extends AutomatedTestBase 
+{      
+       private static final String TEST_NAME1 = "SumProductChain";
+       private static final String TEST_NAME2 = "SumAdditionChain";
+       private static final String TEST_DIR = "functions/codegen/";
+       private static final String TEST_CLASS_DIR = TEST_DIR + 
SumProductChainTest.class.getSimpleName() + "/";
+       private final static String TEST_CONF = "SystemML-config-codegen.xml";
+       
+       private static final int rows = 1191;
+       private static final int cols1 = 1;
+       private static final int cols2 = 31;
+       private static final double sparsity1 = 0.9;
+       private static final double sparsity2 = 0.09;
+       private static final double eps = Math.pow(10, -10);
+       
+       @Override
+       public void setUp() {
+               TestUtils.clearAssertionInformation();
+               addTestConfiguration( TEST_NAME1, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME1, new String[] { "R" }) );
+               addTestConfiguration( TEST_NAME2, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME2, new String[] { "R" }) );
+       }
+               
+       @Test
+       public void testSumProductVectorsDense() {
+               testSumProductChain( TEST_NAME1, true, false, false, 
ExecType.CP );
+       }
+       
+       @Test
+       public void testSumProductVectorsSparse() {
+               testSumProductChain( TEST_NAME1, true, true, false, ExecType.CP 
);
+       }
+       
+       @Test
+       public void testSumProductMatrixDense() {
+               testSumProductChain( TEST_NAME1, false, false, false, 
ExecType.CP );
+       }
+       
+       @Test
+       public void testSumProductMatrixSparse() {
+               testSumProductChain( TEST_NAME1, false, true, false, 
ExecType.CP );
+       }
+       
+       @Test
+       public void testSumAdditionVectorsDense() {
+               testSumProductChain( TEST_NAME2, true, false, false, 
ExecType.CP );
+       }
+       
+       @Test
+       public void testSumAdditionVectorsSparse() {
+               testSumProductChain( TEST_NAME2, true, true, false, ExecType.CP 
);
+       }
+       
+       @Test
+       public void testSumAdditionMatrixDense() {
+               testSumProductChain( TEST_NAME2, false, false, false, 
ExecType.CP );
+       }
+       
+       @Test
+       public void testSumAdditionMatrixSparse() {
+               testSumProductChain( TEST_NAME2, false, true, false, 
ExecType.CP );
+       }
+       
+       
+       private void testSumProductChain(String testname, boolean vectors, 
boolean sparse, boolean rewrites, ExecType instType)
+       {       
+               RUNTIME_PLATFORM oldPlatform = rtplatform;
+               boolean oldRewrites = 
OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION;
+               
+               switch( instType ){
+                       case MR: rtplatform = RUNTIME_PLATFORM.HADOOP; break;
+                       case SPARK: rtplatform = RUNTIME_PLATFORM.SPARK; break;
+                       default: rtplatform = RUNTIME_PLATFORM.HYBRID; break;
+               }
+               boolean oldSparkConfig = DMLScript.USE_LOCAL_SPARK_CONFIG;
+               if( rtplatform == RUNTIME_PLATFORM.SPARK || rtplatform == 
RUNTIME_PLATFORM.HYBRID_SPARK )
+                       DMLScript.USE_LOCAL_SPARK_CONFIG = true;
+               
+               try
+               {
+                       OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION = 
rewrites;
+                       
+                       TestConfiguration config = 
getTestConfiguration(testname);
+                       loadTestConfiguration(config);
+                       
+                       String HOME = SCRIPT_DIR + TEST_DIR;
+                       fullDMLScriptName = HOME + testname + ".dml";
+                       programArgs = new String[]{"-explain", "-stats", 
+                                       "-config=" + HOME + TEST_CONF, "-args", 
input("X"), output("R") };
+                       
+                       fullRScriptName = HOME + testname + ".R";
+                       rCmd = getRCmd(inputDir(), expectedDir());              
        
+
+                       //generate input data
+                       int cols = vectors ? cols1 : cols2;
+                       double sparsity = sparse ? sparsity2 : sparsity1;
+                       double[][] X = getRandomMatrix(rows, cols, -1, 1, 
sparsity, 7);
+                       writeInputMatrixWithMTD("X", X, true);
+                       
+                       //run tests
+                       runTest(true, false, null, -1); 
+                       runRScript(true); 
+                       
+                       //compare matrices 
+                       HashMap<CellIndex, Double> dmlfile = 
readDMLMatrixFromHDFS("R");
+                       HashMap<CellIndex, Double> rfile  = 
readRMatrixFromFS("R");     
+                       TestUtils.compareMatrices(dmlfile, rfile, eps, 
"Stat-DML", "Stat-R");
+                       if( vectors || !sparse  )
+                               
Assert.assertTrue(heavyHittersContainsSubString("spoof") 
+                                               || 
heavyHittersContainsSubString("sp_spoof"));
+               }
+               finally {
+                       rtplatform = oldPlatform;
+                       DMLScript.USE_LOCAL_SPARK_CONFIG = oldSparkConfig;
+                       OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION = 
oldRewrites;
+                       OptimizerUtils.ALLOW_AUTO_VECTORIZATION = true;
+                       OptimizerUtils.ALLOW_OPERATOR_FUSION = true;
+               }
+       }       
+}

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/d65c7b5b/src/test/scripts/functions/codegen/SumAdditionChain.R
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/codegen/SumAdditionChain.R 
b/src/test/scripts/functions/codegen/SumAdditionChain.R
new file mode 100644
index 0000000..ff9fe21
--- /dev/null
+++ b/src/test/scripts/functions/codegen/SumAdditionChain.R
@@ -0,0 +1,32 @@
+#-------------------------------------------------------------
+#
+# 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.
+#
+#-------------------------------------------------------------
+
+args <- commandArgs(TRUE)
+library("Matrix")
+library("matrixStats")
+
+X = readMM(paste(args[1], "X.mtx", sep=""));
+Y = X + 2;
+Z = X + 3;
+
+R = as.matrix(sum(X+Y+Z));
+
+writeMM(as(R,"CsparseMatrix"), paste(args[2], "R", sep=""));

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/d65c7b5b/src/test/scripts/functions/codegen/SumAdditionChain.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/codegen/SumAdditionChain.dml 
b/src/test/scripts/functions/codegen/SumAdditionChain.dml
new file mode 100644
index 0000000..87b0143
--- /dev/null
+++ b/src/test/scripts/functions/codegen/SumAdditionChain.dml
@@ -0,0 +1,29 @@
+#-------------------------------------------------------------
+#
+# 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.
+#
+#-------------------------------------------------------------
+
+X = read($1)
+Y = X + 2;
+Z = X + 3;
+
+if(1==1){}
+
+R = as.matrix(sum(X+Y+Z));
+write(R, $2)

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/d65c7b5b/src/test/scripts/functions/codegen/SumProductChain.R
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/codegen/SumProductChain.R 
b/src/test/scripts/functions/codegen/SumProductChain.R
new file mode 100644
index 0000000..cc862d6
--- /dev/null
+++ b/src/test/scripts/functions/codegen/SumProductChain.R
@@ -0,0 +1,32 @@
+#-------------------------------------------------------------
+#
+# 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.
+#
+#-------------------------------------------------------------
+
+args <- commandArgs(TRUE)
+library("Matrix")
+library("matrixStats")
+
+X = readMM(paste(args[1], "X.mtx", sep=""));
+Y = X + 2;
+Z = X + 3;
+
+R = as.matrix(sum(X*Y*Z));
+
+writeMM(as(R,"CsparseMatrix"), paste(args[2], "R", sep=""));

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/d65c7b5b/src/test/scripts/functions/codegen/SumProductChain.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/codegen/SumProductChain.dml 
b/src/test/scripts/functions/codegen/SumProductChain.dml
new file mode 100644
index 0000000..2b65ee1
--- /dev/null
+++ b/src/test/scripts/functions/codegen/SumProductChain.dml
@@ -0,0 +1,29 @@
+#-------------------------------------------------------------
+#
+# 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.
+#
+#-------------------------------------------------------------
+
+X = read($1)
+Y = X + 2;
+Z = X + 3;
+
+if(1==1){}
+
+R = as.matrix(sum(X*Y*Z));
+write(R, $2)

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/d65c7b5b/src/test_suites/java/org/apache/sysml/test/integration/functions/codegen/ZPackageSuite.java
----------------------------------------------------------------------
diff --git 
a/src/test_suites/java/org/apache/sysml/test/integration/functions/codegen/ZPackageSuite.java
 
b/src/test_suites/java/org/apache/sysml/test/integration/functions/codegen/ZPackageSuite.java
index 644751b..dd960bf 100644
--- 
a/src/test_suites/java/org/apache/sysml/test/integration/functions/codegen/ZPackageSuite.java
+++ 
b/src/test_suites/java/org/apache/sysml/test/integration/functions/codegen/ZPackageSuite.java
@@ -36,6 +36,7 @@ import org.junit.runners.Suite;
        DAGCellwiseTmplTest.class,
        OuterProdTmplTest.class,
        RowAggTmplTest.class,
+       SumProductChainTest.class,
 })
 
 

Reply via email to