This is an automated email from the ASF dual-hosted git repository.
mboehm7 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/systemds.git
The following commit(s) were added to refs/heads/main by this push:
new 0ec4dcd36e [SYSTEMDS-3844] Extended codegen templates w/ row/colProd
Agg
0ec4dcd36e is described below
commit 0ec4dcd36e5cce81467ffac5cabc7a8c87acb46b
Author: Frxms <[email protected]>
AuthorDate: Sat Mar 22 18:41:41 2025 +0100
[SYSTEMDS-3844] Extended codegen templates w/ row/colProd Agg
Closes #2234.
---
.../sysds/hops/codegen/template/TemplateCell.java | 2 +-
.../sysds/hops/codegen/template/TemplateRow.java | 2 +-
.../sysds/runtime/codegen/SpoofCellwise.java | 219 ++++++++++++++++++++-
.../test/functions/codegen/CellwiseTmplTest.java | 73 ++++++-
.../scripts/functions/codegen/cellwisetmpl28.R | 39 ++++
.../scripts/functions/codegen/cellwisetmpl28.dml | 32 +++
.../scripts/functions/codegen/cellwisetmpl29.R | 40 ++++
.../scripts/functions/codegen/cellwisetmpl29.dml | 33 ++++
.../scripts/functions/codegen/cellwisetmpl30.R | 39 ++++
.../scripts/functions/codegen/cellwisetmpl30.dml | 32 +++
.../scripts/functions/codegen/cellwisetmpl31.R | 38 ++++
.../scripts/functions/codegen/cellwisetmpl31.dml | 31 +++
12 files changed, 573 insertions(+), 7 deletions(-)
diff --git
a/src/main/java/org/apache/sysds/hops/codegen/template/TemplateCell.java
b/src/main/java/org/apache/sysds/hops/codegen/template/TemplateCell.java
index 8d0dc273eb..c909d86cd1 100644
--- a/src/main/java/org/apache/sysds/hops/codegen/template/TemplateCell.java
+++ b/src/main/java/org/apache/sysds/hops/codegen/template/TemplateCell.java
@@ -66,7 +66,7 @@ import org.apache.sysds.runtime.matrix.data.Pair;
public class TemplateCell extends TemplateBase
{
private static final AggOp[] SUPPORTED_AGG =
- new AggOp[]{AggOp.SUM, AggOp.SUM_SQ, AggOp.MIN,
AggOp.MAX};
+ new AggOp[]{AggOp.SUM, AggOp.SUM_SQ, AggOp.MIN,
AggOp.MAX, AggOp.PROD};
public TemplateCell() {
super(TemplateType.CELL);
diff --git
a/src/main/java/org/apache/sysds/hops/codegen/template/TemplateRow.java
b/src/main/java/org/apache/sysds/hops/codegen/template/TemplateRow.java
index 4ac38b1487..c42ea6c858 100644
--- a/src/main/java/org/apache/sysds/hops/codegen/template/TemplateRow.java
+++ b/src/main/java/org/apache/sysds/hops/codegen/template/TemplateRow.java
@@ -67,7 +67,7 @@ import org.apache.sysds.runtime.matrix.data.Pair;
public class TemplateRow extends TemplateBase
{
- private static final AggOp[] SUPPORTED_ROW_AGG = new AggOp[]{AggOp.SUM,
AggOp.MIN, AggOp.MAX, AggOp.MEAN};
+ private static final AggOp[] SUPPORTED_ROW_AGG = new AggOp[]{AggOp.SUM,
AggOp.MIN, AggOp.MAX, AggOp.MEAN, AggOp.PROD};
private static final OpOp1[] SUPPORTED_VECT_UNARY = new OpOp1[]{
OpOp1.EXP, OpOp1.SQRT, OpOp1.LOG, OpOp1.ABS, OpOp1.ROUND,
OpOp1.CEIL, OpOp1.FLOOR, OpOp1.SIGN,
OpOp1.SIN, OpOp1.COS, OpOp1.TAN, OpOp1.ASIN, OpOp1.ACOS,
OpOp1.ATAN, OpOp1.SINH, OpOp1.COSH, OpOp1.TANH,
diff --git a/src/main/java/org/apache/sysds/runtime/codegen/SpoofCellwise.java
b/src/main/java/org/apache/sysds/runtime/codegen/SpoofCellwise.java
index 6c3986bd93..d59f50a0e8 100644
--- a/src/main/java/org/apache/sysds/runtime/codegen/SpoofCellwise.java
+++ b/src/main/java/org/apache/sysds/runtime/codegen/SpoofCellwise.java
@@ -84,6 +84,7 @@ public abstract class SpoofCellwise extends SpoofOperator {
SUM_SQ,
MIN,
MAX,
+ PROD
}
protected final CellType _type;
@@ -332,12 +333,16 @@ public abstract class SpoofCellwise extends SpoofOperator
{
else if( _type == CellType.ROW_AGG ) {
if( _aggOp == AggOp.SUM || _aggOp == AggOp.SUM_SQ )
return executeDenseRowAggSum(a, lb, scalars, c,
m, n, sparseSafe, rl, ru, rix);
+ else if(_aggOp == AggOp.PROD)
+ return executeDenseRowProd(a, lb, scalars, c,
m, n, sparseSafe, rl, ru, rix);
else
return executeDenseRowAggMxx(a, lb, scalars, c,
m, n, sparseSafe, rl, ru, rix);
}
else if( _type == CellType.COL_AGG ) {
if( _aggOp == AggOp.SUM || _aggOp == AggOp.SUM_SQ )
return executeDenseColAggSum(a, lb, scalars, c,
m, n, sparseSafe, rl, ru, rix);
+ else if(_aggOp == AggOp.PROD)
+ return executeDenseColProd(a, lb, scalars, c,
m, n, sparseSafe, rl, ru, rix);
else
return executeDenseColAggMxx(a, lb, scalars, c,
m, n, sparseSafe, rl, ru, rix);
}
@@ -372,12 +377,16 @@ public abstract class SpoofCellwise extends SpoofOperator
{
else if( _type == CellType.ROW_AGG ) {
if( _aggOp == AggOp.SUM || _aggOp == AggOp.SUM_SQ )
return executeSparseRowAggSum(sblock, lb,
scalars, out, m, n, sparseSafe, rl, ru, rix);
+ else if( _aggOp == AggOp.PROD)
+ return executeSparseRowProd(sblock, lb,
scalars, out, m, n, sparseSafe, rl, ru, rix);
else
return executeSparseRowAggMxx(sblock, lb,
scalars, out, m, n, sparseSafe, rl, ru, rix);
}
else if( _type == CellType.COL_AGG ) {
if( _aggOp == AggOp.SUM || _aggOp == AggOp.SUM_SQ )
return executeSparseColAggSum(sblock, lb,
scalars, out, m, n, sparseSafe, rl, ru, rix);
+ else if( _aggOp == AggOp.PROD)
+ return executeSparseColProd(sblock, lb,
scalars, out, m, n, sparseSafe, rl, ru, rix);
else
return executeSparseColAggMxx(sblock, lb,
scalars, out, m, n, sparseSafe, rl, ru, rix);
}
@@ -930,7 +939,215 @@ public abstract class SpoofCellwise extends SpoofOperator
{
}
return ret;
}
-
+
+ private long executeDenseRowProd(DenseBlock a, SideInput[] b, double[]
scalars,
+ DenseBlock c, int m, int n, boolean sparseSafe, int rl, int ru,
long rix)
+ {
+ // single block output
+ double[] lc = c.valuesAt(0);
+ long lnnz = 0;
+ if(a == null && !sparseSafe) {
+ for(int i = rl; i < ru; i++) {
+ for(int j = 0; j < n; j++) {
+ if(j == 0) {
+ lc[i] = genexec(0, b, scalars,
m, n, rix+i, i, j);
+ } else if(lc[i] != 0) {
+ lc[i] *= genexec(0, b, scalars,
m, n, rix+i, i, j);
+ } else {
+ break;
+ }
+ }
+ lnnz += (lc[i]!=0) ? 1 : 0;
+ }
+ }
+ else if( a != null ) {
+ for(int i = rl; i < ru; i++) {
+ double[] avals = a.values(i);
+ int aix = a.pos(i);
+ for(int j = 0; j < n; j++) {
+ double aval = avals[aix + j];
+ if(aval != 0 || !sparseSafe) {
+ if(j == 0) {
+ lc[i] = genexec(aval,
b, scalars, m, n, rix+i, i, j);
+ } else if(lc[i] != 0) {
+ lc[i] *= genexec(aval,
b, scalars, m, n, rix+i, i, j);
+ } else {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ lnnz += (lc[i] != 0) ? 1 : 0;
+ }
+ }
+ return lnnz;
+ }
+
+ private long executeDenseColProd(DenseBlock a, SideInput[] b, double[]
scalars,
+ DenseBlock c, int m, int n, boolean sparseSafe, int rl, int ru,
long rix)
+ {
+ double[] lc = c.valuesAt(0);
+ //track the cols that have a zero
+ boolean[] zeroFlag = new boolean[n];
+ if(a == null && !sparseSafe) {
+ for(int i = rl; i < ru; i++) {
+ for(int j = 0; j < n; j++) {
+ if(!zeroFlag[j]) {
+ if(i == 0) {
+ lc[j] = genexec(0, b,
scalars, m, n, rix+i, i, j);
+ } else if(lc[j] != 0) {
+ lc[j] *= genexec(0, b,
scalars, m, n, rix+i, i, j);
+ } else {
+ zeroFlag[j] = true;
+ }
+ }
+ }
+ }
+ }
+ else if(a != null) {
+ for(int i = rl; i < ru; i++) {
+ double[] avals = a.values(i);
+ int aix = a.pos(i);
+ for(int j = 0; j < n; j++) {
+ if(!zeroFlag[j]) {
+ double aval = avals[aix + j];
+ if(aval != 0 || !sparseSafe) {
+ if(i == 0) {
+ lc[j] =
genexec(aval, b, scalars, m, n, rix + i, i, j);
+ } else if(lc[j] != 0) {
+ lc[j] *=
genexec(aval, b, scalars, m, n, rix + i, i, j);
+ } else {
+ zeroFlag[j] =
true;
+ }
+ }
+ } else {
+ zeroFlag[j] = true;
+ }
+ }
+ }
+ }
+ return -1;
+ }
+
+ private long executeSparseRowProd(SparseBlock sblock, SideInput[] b,
double[] scalars,
+ MatrixBlock out, int m, int n, boolean sparseSafe, int rl, int
ru, long rix)
+ {
+ double[] c = out.getDenseBlockValues();
+ long lnnz = 0;
+ for(int i = rl; i < ru; i++) {
+ int lastj = -1;
+ if(sblock != null && !sblock.isEmpty(i)) {
+ int apos = sblock.pos(i);
+ int alen = sblock.size(i);
+ int[] aix = sblock.indexes(i);
+ double[] avals = sblock.values(i);
+ for(int k = apos; k < apos+alen; k++) {
+ if(!sparseSafe) {
+ for(int j=lastj+1; j<aix[k];
j++) {
+ if(j == 0) {
+ c[i] =
genexec(0, b, scalars, m, n, rix+i, i, j);
+ } else if(c[i] != 0){
+ c[i] *=
genexec(0, b, scalars, m, n, rix+i, i, j);
+ } else {
+ break;
+ }
+ }
+ }
+ if(aix.length == n || !sparseSafe) {
+ if(aix[k] == 0) {
+ lastj = aix[k];
+ c[i] =
genexec(avals[k], b, scalars, m, n, rix+i, i, k);
+ } else if(c[i] != 0){
+ lastj = aix[k];
+ c[i] *=
genexec(avals[k], b, scalars, m, n, rix+i, i, k);
+ } else {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ }
+ //process remaining zeros
+ if(!sparseSafe)
+ for(int j=lastj+1; j<n; j++) {
+ if(j == 0) {
+ c[i] = genexec(0, b, scalars,
m, n, rix+i, i, j);
+ } else if(c[i] != 0){
+ c[i] *= genexec(0, b, scalars,
m, n, rix+i, i, j);
+ } else {
+ break;
+ }
+ }
+ lnnz += (c[i] != 0) ? 1 : 0;
+ }
+ return lnnz;
+ }
+
+ private long executeSparseColProd(SparseBlock sblock, SideInput[] b,
double[] scalars,
+ MatrixBlock out, int m, int n, boolean sparseSafe, int rl, int
ru, long rix)
+ {
+ double[] c = out.getDenseBlockValues();
+ boolean[] zeroFlag = new boolean[n];
+
+ for(int i=rl; i<ru; i++) {
+ int lastj = -1;
+ //handle non-empty rows
+ if(sblock != null && !sblock.isEmpty(i)) {
+ int apos = sblock.pos(i);
+ int alen = sblock.size(i);
+ int[] aix = sblock.indexes(i);
+ double[] avals = sblock.values(i);
+ long nnzCount = sblock.size(rl, ru);
+ //process every column, to not miss any 0's
+ for(int k=apos; k<apos+alen; k++) {
+ //process zeros before current non-zero
+ if( !sparseSafe )
+ for(int j=lastj+1; j<aix[k];
j++) {
+ if(!zeroFlag[j]) {
+ if(i == 0) {
+ c[j] =
genexec(0, b, scalars, m, n, rix+i, i, j);
+ } else if(c[j]
!= 0){
+ c[j] *=
genexec(0, b, scalars, m, n, rix+i, i, j);
+ } else {
+
zeroFlag[j] = true;
+ }
+ }
+ }
+ //process current non-zero
+ if((nnzCount == m || !sparseSafe) &&
!zeroFlag[aix[k]]) {
+ if(i == 0) {
+ lastj = aix[k];
+ c[aix[k]] =
genexec(avals[k], b, scalars, m, n, rix+i, i, lastj);
+ } else if(c[aix[k]] != 0){
+ lastj = aix[k];
+ c[aix[k]] *=
genexec(avals[k], b, scalars, m, n, rix+i, i, lastj);
+ } else {
+ zeroFlag[aix[k]] = true;
+ }
+ } else {
+ zeroFlag[aix[k]] = true;
+ }
+ }
+ }
+ //process empty rows or remaining zeros
+ if(!sparseSafe)
+ for(int j=lastj+1; j<n; j++) {
+ if(!zeroFlag[j]) {
+ if(i == 0) {
+ c[j] = genexec(0, b,
scalars, m, n, rix+i, i, j);
+ } else if(c[j] != 0){
+ c[j] *= genexec(0, b,
scalars, m, n, rix+i, i, j);
+ } else {
+ zeroFlag[j] = true;
+ }
+ }
+ }
+ }
+ return -1;
+ }
+
//local execution where grix==rix
protected final double genexec( double a, SideInput[] b,
double[] scalars, int m, int n, int rix, int cix) {
diff --git
a/src/test/java/org/apache/sysds/test/functions/codegen/CellwiseTmplTest.java
b/src/test/java/org/apache/sysds/test/functions/codegen/CellwiseTmplTest.java
index e9a1fc0d40..62ab375f2a 100644
---
a/src/test/java/org/apache/sysds/test/functions/codegen/CellwiseTmplTest.java
+++
b/src/test/java/org/apache/sysds/test/functions/codegen/CellwiseTmplTest.java
@@ -67,6 +67,10 @@ public class CellwiseTmplTest extends AutomatedTestBase
private static final String TEST_NAME25 = TEST_NAME+25; //bias_add
private static final String TEST_NAME26 = TEST_NAME+26; //bias_mult
private static final String TEST_NAME27 = TEST_NAME+27; //outer < +7
negative
+ private static final String TEST_NAME28 = TEST_NAME+28; //colProds(X^2
+ 1)
+ private static final String TEST_NAME29 = TEST_NAME+29;
//colProds(2*log(X))
+ private static final String TEST_NAME30 = TEST_NAME+30; //rowProds(X^2
+ 1)
+ private static final String TEST_NAME31 = TEST_NAME+31;
//rowProds(2*log(X))
private static final String TEST_DIR = "functions/codegen/";
private static final String TEST_CLASS_DIR = TEST_DIR +
CellwiseTmplTest.class.getSimpleName() + "/";
@@ -79,7 +83,7 @@ public class CellwiseTmplTest extends AutomatedTestBase
@Override
public void setUp() {
TestUtils.clearAssertionInformation();
- for( int i=1; i<=27; i++ ) {
+ for( int i=1; i<=31; i++ ) {
addTestConfiguration( TEST_NAME+i, new
TestConfiguration(
TEST_CLASS_DIR, TEST_NAME+i, new String[]
{String.valueOf(i)}) );
}
@@ -444,7 +448,7 @@ public class CellwiseTmplTest extends AutomatedTestBase
public void testCodegenCellwiseRewrite26_sp() {
testCodegenIntegration( TEST_NAME26, true, ExecType.SPARK );
}
-
+
@Test
public void testCodegenCellwiseRewrite27() {
testCodegenIntegration( TEST_NAME27, true, ExecType.CP );
@@ -455,10 +459,71 @@ public class CellwiseTmplTest extends AutomatedTestBase
testCodegenIntegration( TEST_NAME27, false, ExecType.CP );
}
+ @Test
public void testCodegenCellwiseRewrite27_sp() {
testCodegenIntegration( TEST_NAME27, true, ExecType.SPARK );
}
+ @Test
+ public void testCodegenCellwiseRewrite28() {
+ testCodegenIntegration( TEST_NAME28, true, ExecType.CP );
+ }
+
+ @Test
+ public void testCodegenCellwise28() {
+ testCodegenIntegration( TEST_NAME28, false, ExecType.CP );
+ }
+
+ @Test
+ public void testCodegenCellwiseRewrite28_sp() {
+ testCodegenIntegration( TEST_NAME28, true, ExecType.SPARK );
+ }
+
+ @Test
+ public void testCodegenCellwiseRewrite29() {
+ testCodegenIntegration( TEST_NAME29, true, ExecType.CP );
+ }
+
+ @Test
+ public void testCodegenCellwise29() {
+ testCodegenIntegration( TEST_NAME29, false, ExecType.CP );
+ }
+
+ @Test
+ public void testCodegenCellwiseRewrite29_sp() {
+ testCodegenIntegration( TEST_NAME29, true, ExecType.SPARK );
+ }
+
+ @Test
+ public void testCodegenCellwiseRewrite30() {
+ testCodegenIntegration( TEST_NAME30, true, ExecType.CP );
+ }
+
+ @Test
+ public void testCodegenCellwise30() {
+ testCodegenIntegration( TEST_NAME30, false, ExecType.CP );
+ }
+
+ @Test
+ public void testCodegenCellwiseRewrite30_sp() {
+ testCodegenIntegration( TEST_NAME30, true, ExecType.SPARK );
+ }
+
+ @Test
+ public void testCodegenCellwiseRewrite31() {
+ testCodegenIntegration( TEST_NAME31, true, ExecType.CP );
+ }
+
+ @Test
+ public void testCodegenCellwise31() {
+ testCodegenIntegration( TEST_NAME31, false, ExecType.CP );
+ }
+
+ @Test
+ public void testCodegenCellwiseRewrite31_sp() {
+ testCodegenIntegration( TEST_NAME31, true, ExecType.SPARK );
+ }
+
private void testCodegenIntegration( String testname, boolean rewrites,
ExecType instType )
{
boolean oldRewrites =
OptimizerUtils.ALLOW_ALGEBRAIC_SIMPLIFICATION;
@@ -467,7 +532,7 @@ public class CellwiseTmplTest extends AutomatedTestBase
if( testname.equals(TEST_NAME9) )
TEST_CONF = TEST_CONF6;
-
+
try
{
TestConfiguration config =
getTestConfiguration(testname);
@@ -475,7 +540,7 @@ public class CellwiseTmplTest extends AutomatedTestBase
String HOME = SCRIPT_DIR + TEST_DIR;
fullDMLScriptName = HOME + testname + ".dml";
- programArgs = new String[]{"-stats", "-args",
output("S") };
+ programArgs = new String[]{"-explain", "codegen",
"-stats", "-args", output("S") };
fullRScriptName = HOME + testname + ".R";
rCmd = getRCmd(inputDir(), expectedDir());
diff --git a/src/test/scripts/functions/codegen/cellwisetmpl28.R
b/src/test/scripts/functions/codegen/cellwisetmpl28.R
new file mode 100644
index 0000000000..05e31d0f19
--- /dev/null
+++ b/src/test/scripts/functions/codegen/cellwisetmpl28.R
@@ -0,0 +1,39 @@
+#-------------------------------------------------------------
+#
+# 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)
+options(digits=22)
+library("Matrix")
+library("matrixStats")
+
+# colProds <- function(X) {
+# apply(X, 2, prod)
+# }
+
+Z = matrix(0, 5, 1)
+Y = matrix(2, 5, 1)
+A = rbind(Y, Z)
+B = matrix(0, 10, 10)
+X = cbind(B, A, B)
+
+R = t(colProds(X^2 + 1));
+
+writeMM(as(R,"CsparseMatrix"), paste(args[2], "S", sep=""));
diff --git a/src/test/scripts/functions/codegen/cellwisetmpl28.dml
b/src/test/scripts/functions/codegen/cellwisetmpl28.dml
new file mode 100644
index 0000000000..ea06eafe26
--- /dev/null
+++ b/src/test/scripts/functions/codegen/cellwisetmpl28.dml
@@ -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.
+#
+#-------------------------------------------------------------
+
+Z = matrix(0, 5, 1)
+Y = matrix(2, 5, 1)
+A = rbind(Y, Z)
+B = matrix(0, 10, 10)
+X = cbind(B, A, B)
+
+while(FALSE){}
+
+R = colProds(X^2 + 1)
+
+write(R, $1)
diff --git a/src/test/scripts/functions/codegen/cellwisetmpl29.R
b/src/test/scripts/functions/codegen/cellwisetmpl29.R
new file mode 100644
index 0000000000..08c255f617
--- /dev/null
+++ b/src/test/scripts/functions/codegen/cellwisetmpl29.R
@@ -0,0 +1,40 @@
+#-------------------------------------------------------------
+#
+# 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)
+options(digits=22)
+library("Matrix")
+library("matrixStats")
+
+# colProds <- function(X) {
+# apply(X, 2, prod)
+# }
+
+X = matrix(3, 10, 10)
+# X = matrix(seq(9, 100*100+8), 100, 100, byrow=TRUE);
+# F = matrix(0.1, 10, 10)
+# X = matrix(seq(from = 1, to = 10, by = 2), 10, 20)
+# X = matrix(1.3109348721, 10, 10)
+
+R = t(colProds(2*log(X)))
+# R = t(colProds(X*min(F)));
+
+writeMM(as(R,"CsparseMatrix"), paste(args[2], "S", sep=""));
diff --git a/src/test/scripts/functions/codegen/cellwisetmpl29.dml
b/src/test/scripts/functions/codegen/cellwisetmpl29.dml
new file mode 100644
index 0000000000..72a38870a3
--- /dev/null
+++ b/src/test/scripts/functions/codegen/cellwisetmpl29.dml
@@ -0,0 +1,33 @@
+#-------------------------------------------------------------
+#
+# 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 = matrix(3, 10, 10)
+#X = matrix(seq(9, 100*100+8), 100, 100);
+#F = matrix(0.1, 10, 10)
+#X = matrix(seq(2, 10*20+1), 10, 20)
+#X = matrix(1.3109348721, 10, 10)
+
+while(FALSE){}
+
+R = colProds(2*log(X))
+#R = colProds(X*min(F))
+
+write(R, $1)
\ No newline at end of file
diff --git a/src/test/scripts/functions/codegen/cellwisetmpl30.R
b/src/test/scripts/functions/codegen/cellwisetmpl30.R
new file mode 100644
index 0000000000..7ef7086009
--- /dev/null
+++ b/src/test/scripts/functions/codegen/cellwisetmpl30.R
@@ -0,0 +1,39 @@
+#-------------------------------------------------------------
+#
+# 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)
+options(digits=22)
+library("Matrix")
+library("matrixStats")
+
+# rowProds <- function(X) {
+# apply(X, 1, prod)
+# }
+
+Z = matrix(0, 1, 5)
+Y = matrix(2, 1, 5)
+A = cbind(Y, Z)
+B = matrix(0, 10, 10)
+X = rbind(B, A, B)
+
+R = rowProds(X^2 + 1)
+
+writeMM(as(R,"CsparseMatrix"), paste(args[2], "S", sep=""));
diff --git a/src/test/scripts/functions/codegen/cellwisetmpl30.dml
b/src/test/scripts/functions/codegen/cellwisetmpl30.dml
new file mode 100644
index 0000000000..ed023ce669
--- /dev/null
+++ b/src/test/scripts/functions/codegen/cellwisetmpl30.dml
@@ -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.
+#
+#-------------------------------------------------------------
+
+Z = matrix(0, 1, 5)
+Y = matrix(2, 1, 5)
+A = cbind(Y, Z)
+B = matrix(0, 10, 10)
+X = rbind(B, A, B)
+
+while(FALSE){}
+
+R = rowProds(X^2 + 1)
+
+write(R, $1)
diff --git a/src/test/scripts/functions/codegen/cellwisetmpl31.R
b/src/test/scripts/functions/codegen/cellwisetmpl31.R
new file mode 100644
index 0000000000..24a7ed759f
--- /dev/null
+++ b/src/test/scripts/functions/codegen/cellwisetmpl31.R
@@ -0,0 +1,38 @@
+#-------------------------------------------------------------
+#
+# 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)
+options(digits=22)
+library("Matrix")
+library("matrixStats")
+
+# rowProds <- function(X) {
+# apply(X, 1, prod)
+# }
+
+X = matrix(3, 10, 10)
+# X = matrix(seq(9, 100*100+8), 100, 100, byrow=TRUE);
+# F = matrix(0.1, 10, 10)
+
+R = rowProds(2*log(X));
+# R = rowProds(X*min(F))
+
+writeMM(as(R,"CsparseMatrix"), paste(args[2], "S", sep=""));
diff --git a/src/test/scripts/functions/codegen/cellwisetmpl31.dml
b/src/test/scripts/functions/codegen/cellwisetmpl31.dml
new file mode 100644
index 0000000000..77f2e84ebe
--- /dev/null
+++ b/src/test/scripts/functions/codegen/cellwisetmpl31.dml
@@ -0,0 +1,31 @@
+#-------------------------------------------------------------
+#
+# 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 = matrix(3, 10, 10)
+#X = matrix(seq(9, 100*100+8), 100, 100);
+#F = matrix(0.1, 10, 10)
+
+while(FALSE){}
+
+R = rowProds(2*log(X))
+#R = rowProds(X*min(F))
+
+write(R, $1)
\ No newline at end of file