Repository: systemml
Updated Branches:
  refs/heads/master 15971f797 -> 5f580f02e


[SYSTEMML-2371] New nary min/max operations (language, CP dense/sparse)

This patch introduces new nary min/max operations to avoid unnecessary
nesting of binary operations at script level. As a by-product this also
significantly improves performance if codegen is not enabled.

On a scenario of 10 iterations of min(X, Y, Z, 3, 7) this patch improved
performance compared to the equivalent formulation with binary
operations as follows:
10 x 100K x 1K, dense: 45.1s -> 27.2
10 x 100K x 1K, sparse 0.1: 113.7s -> 8s.

Furthermore, this also includes a refactoring of the existing nary
cbind/rbind operations into a separate package.


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

Branch: refs/heads/master
Commit: 231a36489685d8057f6129ed7ca25dba46f999fe
Parents: 15971f7
Author: Matthias Boehm <[email protected]>
Authored: Thu Jun 7 12:04:22 2018 -0700
Committer: Matthias Boehm <[email protected]>
Committed: Thu Jun 7 20:30:35 2018 -0700

----------------------------------------------------------------------
 src/main/java/org/apache/sysml/hops/Hop.java    |   4 +-
 src/main/java/org/apache/sysml/hops/NaryOp.java |   5 +
 src/main/java/org/apache/sysml/lops/Nary.java   |   6 +-
 .../sysml/parser/BuiltinFunctionExpression.java |  37 +++-
 .../org/apache/sysml/parser/DMLTranslator.java  |  13 +-
 .../org/apache/sysml/parser/Expression.java     |  11 +-
 .../instructions/CPInstructionParser.java       |   4 +-
 .../cp/BuiltinNaryCPInstruction.java            |   5 +
 .../cp/MatrixBuiltinNaryCPInstruction.java      |  48 ++++-
 .../sysml/runtime/matrix/data/MatrixBlock.java  | 100 ++++++++++
 .../functions/append/NaryCBindTest.java         | 192 -------------------
 .../functions/append/NaryRBindTest.java         | 192 -------------------
 .../functions/nary/NaryCBindTest.java           | 192 +++++++++++++++++++
 .../functions/nary/NaryMinMaxTest.java          | 123 ++++++++++++
 .../functions/nary/NaryRBindTest.java           | 192 +++++++++++++++++++
 src/test/scripts/functions/append/NaryCbind.R   |  32 ----
 src/test/scripts/functions/append/NaryCbind.dml |  26 ---
 src/test/scripts/functions/append/NaryRbind.R   |  32 ----
 src/test/scripts/functions/append/NaryRbind.dml |  26 ---
 src/test/scripts/functions/nary/NaryCbind.R     |  32 ++++
 src/test/scripts/functions/nary/NaryCbind.dml   |  26 +++
 src/test/scripts/functions/nary/NaryMinMax.R    |  37 ++++
 src/test/scripts/functions/nary/NaryMinMax.dml  |  31 +++
 src/test/scripts/functions/nary/NaryRbind.R     |  32 ++++
 src/test/scripts/functions/nary/NaryRbind.dml   |  26 +++
 .../functions/append/ZPackageSuite.java         |   2 -
 .../functions/nary/ZPackageSuite.java           |  38 ++++
 27 files changed, 933 insertions(+), 531 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/main/java/org/apache/sysml/hops/Hop.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/Hop.java 
b/src/main/java/org/apache/sysml/hops/Hop.java
index 5d789df..bfff50a 100644
--- a/src/main/java/org/apache/sysml/hops/Hop.java
+++ b/src/main/java/org/apache/sysml/hops/Hop.java
@@ -1089,7 +1089,7 @@ public abstract class Hop implements ParseInfo
        
        // Operations that require a variable number of operands
        public enum OpOpN {
-               PRINTF, CBIND, RBIND, EVAL, LIST
+               PRINTF, CBIND, RBIND, MIN, MAX, EVAL, LIST
        }
        
        public enum AggOp {
@@ -1375,6 +1375,8 @@ public abstract class Hop implements ParseInfo
                HopsOpOpNLops.put(OpOpN.PRINTF, Nary.OperationType.PRINTF);
                HopsOpOpNLops.put(OpOpN.CBIND, Nary.OperationType.CBIND);
                HopsOpOpNLops.put(OpOpN.RBIND, Nary.OperationType.RBIND);
+               HopsOpOpNLops.put(OpOpN.MIN, Nary.OperationType.MIN);
+               HopsOpOpNLops.put(OpOpN.MAX, Nary.OperationType.MAX);
                HopsOpOpNLops.put(OpOpN.EVAL, Nary.OperationType.EVAL);
                HopsOpOpNLops.put(OpOpN.LIST, Nary.OperationType.LIST);
        }

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/main/java/org/apache/sysml/hops/NaryOp.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/NaryOp.java 
b/src/main/java/org/apache/sysml/hops/NaryOp.java
index 8927087..0847659 100644
--- a/src/main/java/org/apache/sysml/hops/NaryOp.java
+++ b/src/main/java/org/apache/sysml/hops/NaryOp.java
@@ -195,6 +195,11 @@ public class NaryOp extends Hop {
                                
setDim1(HopRewriteUtils.getSumValidInputDims(this, true));
                                setDim2(HopRewriteUtils.getMaxInputDim(this, 
false));
                                break;
+                       case MIN:
+                       case MAX:
+                               setDim1(getDataType().isScalar() ? 0 : 
HopRewriteUtils.getMaxInputDim(this, true));
+                               setDim2(getDataType().isScalar() ? 0 : 
HopRewriteUtils.getMaxInputDim(this, false));
+                               break;
                        case LIST:
                                setDim1(getInput().size());
                                setDim2(1);

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/main/java/org/apache/sysml/lops/Nary.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/lops/Nary.java 
b/src/main/java/org/apache/sysml/lops/Nary.java
index f7d5952..568b1e7 100644
--- a/src/main/java/org/apache/sysml/lops/Nary.java
+++ b/src/main/java/org/apache/sysml/lops/Nary.java
@@ -32,7 +32,7 @@ import org.apache.sysml.parser.Expression.ValueType;
 public class Nary extends Lop {
 
        public enum OperationType {
-               PRINTF, CBIND, RBIND, EVAL, LIST
+               PRINTF, CBIND, RBIND, MIN, MAX, EVAL, LIST
        }
        
        private OperationType operationType;
@@ -121,6 +121,10 @@ public class Nary extends Lop {
                        case EVAL:
                        case LIST:
                                return operationType.name().toLowerCase();
+                       case MIN:
+                       case MAX:
+                               //need to differentiate from binary min/max 
operations
+                               return "n"+operationType.name().toLowerCase();
                        default:
                                throw new UnsupportedOperationException(
                                        "Nary operation type (" + operationType 
+ ") is not defined.");

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/main/java/org/apache/sysml/parser/BuiltinFunctionExpression.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/parser/BuiltinFunctionExpression.java 
b/src/main/java/org/apache/sysml/parser/BuiltinFunctionExpression.java
index eb9e2c3..d38f445 100644
--- a/src/main/java/org/apache/sysml/parser/BuiltinFunctionExpression.java
+++ b/src/main/java/org/apache/sysml/parser/BuiltinFunctionExpression.java
@@ -20,6 +20,7 @@
 package org.apache.sysml.parser;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
 
@@ -566,11 +567,14 @@ public class BuiltinFunctionExpression extends 
DataIdentifier
                case BITWXOR:
                case BITWSHIFTL:
                case BITWSHIFTR:
+                       checkNumParameters(2);
+                       setBinaryOutputProperties(output);
+                       break;
+               
                case MIN:
                case MAX:
                        //min(X), min(X,s), min(s,X), min(s,r), min(X,Y)
-                       
-                       //unary aggregate
+                       //unary
                        if (getSecondExpr() == null) {
                                checkNumParameters(1);
                                checkMatrixParam(getFirstExpr());
@@ -579,12 +583,13 @@ public class BuiltinFunctionExpression extends 
DataIdentifier
                                output.setDimensions(0, 0);
                                output.setBlockDimensions (0, 0);
                        }
-                       //binary operation
+                       
+                       //nary operation
                        else {
-                               checkNumParameters(2);
-                               setBinaryOutputProperties(output);
+                               for( Expression e : getAllExpr() )
+                                       checkMatrixScalarParam(e);
+                               setNaryOutputProperties(output);
                        }
-                       
                        break;
                
                case CUMSUM:
@@ -1420,7 +1425,7 @@ public class BuiltinFunctionExpression extends 
DataIdentifier
                DataType dt1 = getFirstExpr().getOutput().getDataType();
                DataType dt2 = getSecondExpr().getOutput().getDataType();
                DataType dtOut = (dt1==DataType.MATRIX || dt2==DataType.MATRIX) 
?
-                       DataType.MATRIX : DataType.SCALAR;                      
        
+                       DataType.MATRIX : DataType.SCALAR;
                if( dt1==DataType.MATRIX && dt2==DataType.MATRIX )
                        checkMatchingDimensions(getFirstExpr(), 
getSecondExpr(), true);
                MatrixCharacteristics dims = 
getBinaryMatrixCharacteristics(getFirstExpr(), getSecondExpr());
@@ -1453,6 +1458,24 @@ public class BuiltinFunctionExpression extends 
DataIdentifier
                        Math.max(dims1.getColsPerBlock(), 
dims2.getColsPerBlock()));
        }
        
+       private void setNaryOutputProperties(DataIdentifier output) {
+               DataType dt = Arrays.stream(getAllExpr()).allMatch(
+                       e -> e.getOutput().getDataType().isScalar()) ? 
DataType.SCALAR : DataType.MATRIX;
+               Expression firstM = dt.isMatrix() ? 
Arrays.stream(getAllExpr()).filter(
+                       e -> 
e.getOutput().getDataType().isMatrix()).findFirst().get() : null;
+               ValueType vt = dt.isMatrix() ? ValueType.DOUBLE : 
ValueType.BOOLEAN;
+               for( Expression e : getAllExpr() ) {
+                       vt = computeValueType(e, e.getOutput().getValueType(), 
vt, true);
+                       if( e.getOutput().getDataType().isMatrix() )
+                               checkMatchingDimensions(firstM, e, true);
+               }
+               output.setDataType(dt);
+               output.setValueType(vt);
+               output.setDimensions(firstM.getOutput().getDim1(), 
firstM.getOutput().getDim2());
+               output.setBlockDimensions (
+                       firstM.getOutput().getRowsInBlock(), 
firstM.getOutput().getColumnsInBlock());
+       }
+       
        private void expandArguments() {
        
                if ( _args == null ) {

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/main/java/org/apache/sysml/parser/DMLTranslator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/parser/DMLTranslator.java 
b/src/main/java/org/apache/sysml/parser/DMLTranslator.java
index 3dce294..2349b56 100644
--- a/src/main/java/org/apache/sysml/parser/DMLTranslator.java
+++ b/src/main/java/org/apache/sysml/parser/DMLTranslator.java
@@ -2408,10 +2408,15 @@ public class DMLTranslator
 
                case MIN:
                case MAX:
-                       //construct AggUnary for min(X) but BinaryOp for 
min(X,Y)
-                       currBuiltinOp = (expr2 == null) ? new 
AggUnaryOp(target.getName(), target.getDataType(), target.getValueType(),
-                               AggOp.valueOf(source.getOpCode().name()), 
Direction.RowCol, expr) : new BinaryOp(target.getName(),
-                               target.getDataType(), target.getValueType(), 
OpOp2.valueOf(source.getOpCode().name()), expr, expr2);
+                       //construct AggUnary for min(X) but BinaryOp for 
min(X,Y) and NaryOp for min(X,Y,Z)
+                       currBuiltinOp = (expr2 == null) ? 
+                               new AggUnaryOp(target.getName(), 
target.getDataType(), target.getValueType(),
+                                       
AggOp.valueOf(source.getOpCode().name()), Direction.RowCol, expr) : 
+                               (source.getAllExpr().length == 2) ?
+                               new BinaryOp(target.getName(), 
target.getDataType(), target.getValueType(),
+                                       
OpOp2.valueOf(source.getOpCode().name()), expr, expr2) : 
+                               new NaryOp(target.getName(), 
target.getDataType(), target.getValueType(),
+                                       
OpOpN.valueOf(source.getOpCode().name()), 
processAllExpressions(source.getAllExpr(), hops));
                        break;
                
                case PPRED:

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/main/java/org/apache/sysml/parser/Expression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/parser/Expression.java 
b/src/main/java/org/apache/sysml/parser/Expression.java
index 4355bd5..2808609 100644
--- a/src/main/java/org/apache/sysml/parser/Expression.java
+++ b/src/main/java/org/apache/sysml/parser/Expression.java
@@ -453,9 +453,10 @@ public abstract class Expression implements ParseInfo
         * @return The value type ({@link ValueType})
         */
        public static ValueType computeValueType(Identifier identifier1, 
Identifier identifier2, boolean cast) {
-               ValueType v1 = identifier1.getValueType();
-               ValueType v2 = identifier2.getValueType();
-
+               return computeValueType(identifier1, 
identifier1.getValueType(), identifier2.getValueType(), cast);
+       }
+       
+       public static ValueType computeValueType(Expression expr1, ValueType 
v1, ValueType v2, boolean cast) {
                if (v1 == v2)
                        return v1;
 
@@ -472,8 +473,8 @@ public abstract class Expression implements ParseInfo
                }
 
                //raise error with id1 location
-               identifier1.raiseValidateError("Invalid Valuetypes for 
operation "+v1+" "+v2, false, 
-                               
LanguageException.LanguageErrorCodes.INVALID_PARAMETERS);
+               expr1.raiseValidateError("Invalid Valuetypes for operation 
"+v1+" "+v2, false,
+                       
LanguageException.LanguageErrorCodes.INVALID_PARAMETERS);
                return null; //never reached because unconditional
        }
 

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/main/java/org/apache/sysml/runtime/instructions/CPInstructionParser.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/runtime/instructions/CPInstructionParser.java 
b/src/main/java/org/apache/sysml/runtime/instructions/CPInstructionParser.java
index ece9d65..f01d3ae 100644
--- 
a/src/main/java/org/apache/sysml/runtime/instructions/CPInstructionParser.java
+++ 
b/src/main/java/org/apache/sysml/runtime/instructions/CPInstructionParser.java
@@ -146,9 +146,11 @@ public class CPInstructionParser extends InstructionParser
                String2CPInstructionType.put( "log"  , CPType.Builtin);
                String2CPInstructionType.put( "log_nz"  , CPType.Builtin);
 
+               String2CPInstructionType.put( "solve"  , CPType.Binary);
                String2CPInstructionType.put( "max"  , CPType.Binary);
                String2CPInstructionType.put( "min"  , CPType.Binary);
-               String2CPInstructionType.put( "solve"  , CPType.Binary);
+               String2CPInstructionType.put( "nmax"  , CPType.BuiltinNary);
+               String2CPInstructionType.put( "nmin"  , CPType.BuiltinNary);
                
                String2CPInstructionType.put( "exp"   , CPType.Unary);
                String2CPInstructionType.put( "abs"   , CPType.Unary);

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/main/java/org/apache/sysml/runtime/instructions/cp/BuiltinNaryCPInstruction.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/runtime/instructions/cp/BuiltinNaryCPInstruction.java
 
b/src/main/java/org/apache/sysml/runtime/instructions/cp/BuiltinNaryCPInstruction.java
index eac9c32..8077575 100644
--- 
a/src/main/java/org/apache/sysml/runtime/instructions/cp/BuiltinNaryCPInstruction.java
+++ 
b/src/main/java/org/apache/sysml/runtime/instructions/cp/BuiltinNaryCPInstruction.java
@@ -65,6 +65,11 @@ public abstract class BuiltinNaryCPInstruction extends 
CPInstruction
                }
                else if( opcode.equals("cbind") || opcode.equals("rbind") ) {
                        return new MatrixBuiltinNaryCPInstruction(null, 
+                               opcode, str, outputOperand, inputOperands);
+               }
+               else if( opcode.equals("nmin") || opcode.equals("nmax") ) {
+                       ValueFunction func = 
Builtin.getBuiltinFnObject(opcode.substring(1));
+                       return new MatrixBuiltinNaryCPInstruction(new 
SimpleOperator(func), 
                                        opcode, str, outputOperand, 
inputOperands);
                } 
                else if 
(Nary.OperationType.EVAL.name().equalsIgnoreCase(opcode)) {

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/main/java/org/apache/sysml/runtime/instructions/cp/MatrixBuiltinNaryCPInstruction.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/runtime/instructions/cp/MatrixBuiltinNaryCPInstruction.java
 
b/src/main/java/org/apache/sysml/runtime/instructions/cp/MatrixBuiltinNaryCPInstruction.java
index 3f16447..50e3721 100644
--- 
a/src/main/java/org/apache/sysml/runtime/instructions/cp/MatrixBuiltinNaryCPInstruction.java
+++ 
b/src/main/java/org/apache/sysml/runtime/instructions/cp/MatrixBuiltinNaryCPInstruction.java
@@ -19,6 +19,10 @@
 
 package org.apache.sysml.runtime.instructions.cp;
 
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
 import org.apache.sysml.runtime.DMLRuntimeException;
 import org.apache.sysml.runtime.controlprogram.context.ExecutionContext;
 import org.apache.sysml.runtime.matrix.data.MatrixBlock;
@@ -32,24 +36,48 @@ public class MatrixBuiltinNaryCPInstruction extends 
BuiltinNaryCPInstruction {
 
        @Override
        public void processInstruction(ExecutionContext ec) {
-               //pin input matrix blocks
-               MatrixBlock in1 = ec.getMatrixInput(inputs[0].getName());
-               MatrixBlock[] in2 = new MatrixBlock[inputs.length-1];
-               for( int i=1; i<inputs.length; i++ )
-                       in2[i-1] = ec.getMatrixInput(inputs[i].getName());
+               //separate scalars and matrices and pin all input matrices
+               List<MatrixBlock> matrices = getMatrices(ec);
+               List<ScalarObject> scalars = getScalars(ec);
                
                MatrixBlock outBlock = null;
                if( "cbind".equals(getOpcode()) || "rbind".equals(getOpcode()) 
) {
                        boolean cbind = "cbind".equals(getOpcode());
-                       outBlock = in1.append(in2, new MatrixBlock(), cbind);
+                       outBlock = matrices.get(0).append(matrices.subList(1, 
matrices.size())
+                               .toArray(new MatrixBlock[0]), new 
MatrixBlock(), cbind);
+               }
+               
+               else if( "nmin".equals(getOpcode()) || 
"nmax".equals(getOpcode()) ) {
+                       outBlock = MatrixBlock.naryOperations(_optr, 
matrices.toArray(new MatrixBlock[0]),
+                               scalars.toArray(new ScalarObject[0]), new 
MatrixBlock());
                }
                else {
                        throw new DMLRuntimeException("Unknown opcode: 
"+getOpcode());
                }
                
-               //release inputs and set output
-               for( int i=0; i<inputs.length; i++ )
-                       ec.releaseMatrixInput(inputs[i].getName());
-               ec.setMatrixOutput(output.getName(), outBlock);
+               //release inputs and set output matrix or scalar
+               releaseInputs(ec);
+               if( output.getDataType().isMatrix() ) {
+                       ec.setMatrixOutput(output.getName(), outBlock);
+               }
+               else {
+                       ec.setVariable(output.getName(), 
ScalarObjectFactory.createScalarObject(
+                               output.getValueType(), 
outBlock.quickGetValue(0, 0)));
+               }
+       }
+       
+       private List<MatrixBlock> getMatrices(ExecutionContext ec) {
+               return Arrays.stream(inputs).filter(in -> 
in.getDataType().isMatrix())
+                       .map(in -> 
ec.getMatrixInput(in.getName())).collect(Collectors.toList());
+       }
+       
+       private List<ScalarObject> getScalars(ExecutionContext ec) {
+               return Arrays.stream(inputs).filter(in -> 
in.getDataType().isScalar())
+                       .map(in -> 
ec.getScalarInput(in)).collect(Collectors.toList());
+       }
+       
+       private void releaseInputs(ExecutionContext ec) {
+               Arrays.stream(inputs).filter(in -> in.getDataType().isMatrix())
+                       .forEach(in -> ec.releaseMatrixInput(in.getName()));
        }
 }

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixBlock.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixBlock.java 
b/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixBlock.java
index 78f4fde..755bca1 100644
--- a/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixBlock.java
+++ b/src/main/java/org/apache/sysml/runtime/matrix/data/MatrixBlock.java
@@ -44,6 +44,7 @@ import org.apache.sysml.runtime.DMLRuntimeException;
 import org.apache.sysml.runtime.controlprogram.caching.CacheBlock;
 import org.apache.sysml.runtime.controlprogram.caching.MatrixObject.UpdateType;
 import org.apache.sysml.runtime.functionobjects.Builtin;
+import org.apache.sysml.runtime.functionobjects.Builtin.BuiltinCode;
 import org.apache.sysml.runtime.functionobjects.CM;
 import org.apache.sysml.runtime.functionobjects.CTable;
 import org.apache.sysml.runtime.functionobjects.DiagIndex;
@@ -83,6 +84,7 @@ import org.apache.sysml.runtime.matrix.operators.Operator;
 import org.apache.sysml.runtime.matrix.operators.QuaternaryOperator;
 import org.apache.sysml.runtime.matrix.operators.ReorgOperator;
 import org.apache.sysml.runtime.matrix.operators.ScalarOperator;
+import org.apache.sysml.runtime.matrix.operators.SimpleOperator;
 import org.apache.sysml.runtime.matrix.operators.TernaryOperator;
 import org.apache.sysml.runtime.matrix.operators.UnaryOperator;
 import org.apache.sysml.runtime.util.DataConverter;
@@ -3458,6 +3460,104 @@ public class MatrixBlock extends MatrixValue implements 
CacheBlock, Externalizab
                return result;
        }
        
+       public static MatrixBlock naryOperations(Operator op, MatrixBlock[] 
matrices, ScalarObject[] scalars, MatrixBlock ret) {
+               //note: currently only min and max supported and hence 
specialized implementation
+               
+               //prepare operator
+               Builtin fn = (Builtin)((SimpleOperator)op).fn;
+               
+               //process all scalars
+               double init = (fn.getBuiltinCode() == BuiltinCode.MIN) ?
+                       Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY;
+               for( ScalarObject so : scalars )
+                       init = fn.execute(init, so.getDoubleValue());
+
+               //compute output dimensions and estimate sparsity
+               final int m = matrices.length > 0 ? matrices[0].rlen : 1;
+               final int n = matrices.length > 0 ? matrices[0].clen : 1;
+               final long mn = (long) m * n;
+               final long nnz = (fn.getBuiltinCode()==BuiltinCode.MIN && init 
< 0)
+                       || (fn.getBuiltinCode()==BuiltinCode.MAX && init > 0) ? 
mn :
+                       Math.min(Arrays.stream(matrices).mapToLong(mb -> 
mb.nonZeros).sum(), mn);
+               boolean sp = evalSparseFormatInMemory(m, n, nnz);
+               
+               //init result matrix 
+               if( ret == null )
+                       ret = new MatrixBlock(m, n, sp, nnz);
+               else
+                       ret.reset(m, n, sp, nnz);
+               
+               //main processing
+               if( matrices.length > 0 ) {
+                       ret.allocateBlock();
+                       int[] cnt = Arrays.stream(matrices).allMatch(mb -> 
+                               mb.sparse || mb.isEmpty()) ? new int[n] : null;
+                       if( ret.isInSparseFormat() ) {
+                               double[] tmp = new double[n];
+                               for(int i = 0; i < m; i++) {
+                                       //reset tmp and compute row output
+                                       Arrays.fill(tmp, 0);
+                                       processMinMaxRow(fn, matrices, init, 
tmp, 0, n, i, cnt);
+                                       //copy to sparse output
+                                       for(int j = 0; j < n; j++)
+                                               if( tmp[j] != 0 )
+                                                       ret.appendValue(i, j, 
tmp[j]);
+                               }
+                       }
+                       else {
+                               DenseBlock c = ret.getDenseBlock();
+                               for(int i = 0; i < m; i++) {
+                                       processMinMaxRow(fn, matrices, init,
+                                               c.values(i), c.pos(i), n, i, 
cnt);
+                               }
+                       }
+               }
+               else {
+                       ret.quickSetValue(0, 0, init);
+               }
+               
+               return ret;
+       }
+       
+       private static void processMinMaxRow(Builtin fn, MatrixBlock[] inputs, 
double init, double[] c, int cix, int n, int i, int[] cnt) {
+               //always init entire output vector
+               Arrays.fill(c, cix, cix+n, init);
+               if( cnt != null )
+                       Arrays.fill(cnt, 0);
+               
+               //sparse-safe update over all input matrices
+               for( MatrixBlock in : inputs ) {
+                       if( in.isEmptyBlock(false) )
+                               continue;
+                       if( in.isInSparseFormat() ) {
+                               SparseBlock a = in.sparseBlock;
+                               int alen = a.size(i);
+                               int apos = a.pos(i);
+                               int[] aix = a.indexes(i);
+                               double[] avals = a.values(i);
+                               for( int k=apos; k<apos+alen; k++ ) {
+                                       c[aix[k]] = fn.execute(c[aix[k]], 
avals[k]);
+                                       if( cnt != null ) //maintain seen values
+                                               cnt[aix[k]]++;
+                               }
+                       }
+                       else {
+                               double[] avals = in.getDenseBlock().values(i);
+                               int aix = in.getDenseBlock().pos(i);
+                               for( int j=0; j<n; j++ )
+                                       c[cix+j] = fn.execute(c[cix+j], 
avals[aix+j]);
+                       }
+               }
+               
+               //corrections for all sparse inputs
+               if( Arrays.stream(inputs).allMatch(m -> m.sparse || 
m.isEmpty()) ) {
+                       for( int j=0; j<n; j++ ) {
+                               if( cnt[j]!=inputs.length )
+                                       c[cix+j] = fn.execute(c[cix+j], 0);
+                       }
+               }
+       }
+       
        public MatrixBlock transposeSelfMatrixMultOperations( MatrixBlock out, 
MMTSJType tstype ) {
                return transposeSelfMatrixMultOperations(out, tstype, 1);
        }

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/test/java/org/apache/sysml/test/integration/functions/append/NaryCBindTest.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/sysml/test/integration/functions/append/NaryCBindTest.java
 
b/src/test/java/org/apache/sysml/test/integration/functions/append/NaryCBindTest.java
deleted file mode 100644
index 13ba799..0000000
--- 
a/src/test/java/org/apache/sysml/test/integration/functions/append/NaryCBindTest.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * 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.append;
-
-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.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 NaryCBindTest extends AutomatedTestBase
-{      
-       private final static String TEST_NAME = "NaryCbind";
-       private final static String TEST_DIR = "functions/append/";
-       private final static String TEST_CLASS_DIR = TEST_DIR + 
NaryCBindTest.class.getSimpleName() + "/";
-
-       private final static double epsilon=0.0000000001;
-       
-       private final static int rows = 1101;
-       private final static int cols1 = 101;
-       private final static int cols2 = 79;
-       private final static int cols3 = 123;
-       
-       private final static double sparsity1 = 0.7;
-       private final static double sparsity2 = 0.07;
-       
-       @Override
-       public void setUp() {
-               TestUtils.clearAssertionInformation();
-               addTestConfiguration(TEST_NAME, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME, new String[] {"R"}));
-       }
-
-       @Test
-       public void testNaryCbindDenseDenseDenseCP() {
-               runCbindTest(false, false, false, ExecType.CP);
-       }
-       
-       @Test
-       public void testNaryCbindDenseDenseSparseCP() {
-               runCbindTest(false, false, true, ExecType.CP);
-       }
-       
-       @Test
-       public void testNaryCbindDenseSparseDenseCP() {
-               runCbindTest(false, true, false, ExecType.CP);
-       }
-       
-       @Test
-       public void testNaryCbindDenseSparseSparseCP() {
-               runCbindTest(false, true, true, ExecType.CP);
-       }
-       
-       @Test
-       public void testNaryCbindSparseDenseDenseCP() {
-               runCbindTest(true, false, false, ExecType.CP);
-       }
-       
-       @Test
-       public void testNaryCbindSparseDenseSparseCP() {
-               runCbindTest(true, false, true, ExecType.CP);
-       }
-       
-       @Test
-       public void testNaryCbindSparseSparseDenseCP() {
-               runCbindTest(true, true, false, ExecType.CP);
-       }
-       
-       @Test
-       public void testNaryCbindSparseSparseSparseCP() {
-               runCbindTest(true, true, true, ExecType.CP);
-       }
-       
-       @Test
-       public void testNaryCbindDenseDenseDenseSP() {
-               runCbindTest(false, false, false, ExecType.SPARK);
-       }
-       
-       @Test
-       public void testNaryCbindDenseDenseSparseSP() {
-               runCbindTest(false, false, true, ExecType.SPARK);
-       }
-       
-       @Test
-       public void testNaryCbindDenseSparseDenseSP() {
-               runCbindTest(false, true, false, ExecType.SPARK);
-       }
-       
-       @Test
-       public void testNaryCbindDenseSparseSparseSP() {
-               runCbindTest(false, true, true, ExecType.SPARK);
-       }
-       
-       @Test
-       public void testNaryCbindSparseDenseDenseSP() {
-               runCbindTest(true, false, false, ExecType.SPARK);
-       }
-       
-       @Test
-       public void testNaryCbindSparseDenseSparseSP() {
-               runCbindTest(true, false, true, ExecType.SPARK);
-       }
-       
-       @Test
-       public void testNaryCbindSparseSparseDenseSP() {
-               runCbindTest(true, true, false, ExecType.SPARK);
-       }
-       
-       @Test
-       public void testNaryCbindSparseSparseSparseSP() {
-               runCbindTest(true, true, true, ExecType.CP);
-       }
-       
-       
-       public void runCbindTest(boolean sparse1, boolean sparse2, boolean 
sparse3, ExecType et)
-       {
-               RUNTIME_PLATFORM platformOld = rtplatform;
-               switch( et ) {
-                       case MR: rtplatform = RUNTIME_PLATFORM.HADOOP; break;
-                       case SPARK: rtplatform = RUNTIME_PLATFORM.SPARK; break;
-                       default: rtplatform = RUNTIME_PLATFORM.HYBRID_SPARK; 
break;
-               }
-               
-               boolean sparkConfigOld = DMLScript.USE_LOCAL_SPARK_CONFIG;
-               if( rtplatform == RUNTIME_PLATFORM.SPARK || rtplatform == 
RUNTIME_PLATFORM.HYBRID_SPARK )
-                       DMLScript.USE_LOCAL_SPARK_CONFIG = true;
-               
-               try
-               {
-                       TestConfiguration config = 
getAndLoadTestConfiguration(TEST_NAME);
-                       loadTestConfiguration(config);
-                       
-                       String RI_HOME = SCRIPT_DIR + TEST_DIR;
-                       fullDMLScriptName = RI_HOME + TEST_NAME + ".dml";
-                       programArgs = new String[]{"-stats", "-args", 
input("A"),
-                               input("B"), input("C"), output("R") };
-                       fullRScriptName = RI_HOME + TEST_NAME + ".R";
-                       rCmd = "Rscript" + " " + fullRScriptName + " " +
-                               inputDir() + " "+ expectedDir();
-                       
-                       //generate input data
-                       double sp1 = sparse1 ? sparsity2 : sparsity1; 
-                       double sp2 = sparse2 ? sparsity2 : sparsity1; 
-                       double sp3 = sparse3 ? sparsity2 : sparsity1; 
-                       double[][] A = getRandomMatrix(rows, cols1, -1, 1, sp1, 
711);
-                       double[][] B = getRandomMatrix(rows, cols2, -1, 1, sp2, 
722);
-                       double[][] C = getRandomMatrix(rows, cols3, -1, 1, sp3, 
733);
-                       writeInputMatrixWithMTD("A", A, true);
-                       writeInputMatrixWithMTD("B", B, true);
-                       writeInputMatrixWithMTD("C", C, true);
-                       
-                       //run tests
-                       runTest(true, false, null, -1);
-                       runRScript(true);
-                       
-                       //compare result data
-                       HashMap<CellIndex, Double> dmlfile = 
readDMLMatrixFromHDFS("R");
-                       HashMap<CellIndex, Double> rfile = 
readRMatrixFromFS("R");
-                       TestUtils.compareMatrices(dmlfile, rfile, epsilon, 
"DML", "R");
-                       
-                       //check for spark instructions
-                       
Assert.assertTrue(heavyHittersContainsSubString("sp_cbind")==(et==ExecType.SPARK));
-               }
-               finally {
-                       rtplatform = platformOld;
-                       DMLScript.USE_LOCAL_SPARK_CONFIG = sparkConfigOld;
-               }
-       }
-}

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/test/java/org/apache/sysml/test/integration/functions/append/NaryRBindTest.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/sysml/test/integration/functions/append/NaryRBindTest.java
 
b/src/test/java/org/apache/sysml/test/integration/functions/append/NaryRBindTest.java
deleted file mode 100644
index f820bf5..0000000
--- 
a/src/test/java/org/apache/sysml/test/integration/functions/append/NaryRBindTest.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * 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.append;
-
-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.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 NaryRBindTest extends AutomatedTestBase
-{      
-       private final static String TEST_NAME = "NaryRbind";
-       private final static String TEST_DIR = "functions/append/";
-       private final static String TEST_CLASS_DIR = TEST_DIR + 
NaryRBindTest.class.getSimpleName() + "/";
-
-       private final static double epsilon=0.0000000001;
-       
-       private final static int cols = 101;
-       private final static int rows1 = 1101;
-       private final static int rows2 = 1179;
-       private final static int rows3 = 1123;
-       
-       private final static double sparsity1 = 0.7;
-       private final static double sparsity2 = 0.07;
-       
-       @Override
-       public void setUp() {
-               TestUtils.clearAssertionInformation();
-               addTestConfiguration(TEST_NAME, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME, new String[] {"R"}));
-       }
-
-       @Test
-       public void testNaryRbindDenseDenseDenseCP() {
-               runRbindTest(false, false, false, ExecType.CP);
-       }
-       
-       @Test
-       public void testNaryRbindDenseDenseSparseCP() {
-               runRbindTest(false, false, true, ExecType.CP);
-       }
-       
-       @Test
-       public void testNaryRbindDenseSparseDenseCP() {
-               runRbindTest(false, true, false, ExecType.CP);
-       }
-       
-       @Test
-       public void testNaryRbindDenseSparseSparseCP() {
-               runRbindTest(false, true, true, ExecType.CP);
-       }
-       
-       @Test
-       public void testNaryRbindSparseDenseDenseCP() {
-               runRbindTest(true, false, false, ExecType.CP);
-       }
-       
-       @Test
-       public void testNaryRbindSparseDenseSparseCP() {
-               runRbindTest(true, false, true, ExecType.CP);
-       }
-       
-       @Test
-       public void testNaryRbindSparseSparseDenseCP() {
-               runRbindTest(true, true, false, ExecType.CP);
-       }
-       
-       @Test
-       public void testNaryRbindSparseSparseSparseCP() {
-               runRbindTest(true, true, true, ExecType.CP);
-       }
-       
-       @Test
-       public void testNaryRbindDenseDenseDenseSP() {
-               runRbindTest(false, false, false, ExecType.SPARK);
-       }
-       
-       @Test
-       public void testNaryRbindDenseDenseSparseSP() {
-               runRbindTest(false, false, true, ExecType.SPARK);
-       }
-       
-       @Test
-       public void testNaryRbindDenseSparseDenseSP() {
-               runRbindTest(false, true, false, ExecType.SPARK);
-       }
-       
-       @Test
-       public void testNaryRbindDenseSparseSparseSP() {
-               runRbindTest(false, true, true, ExecType.SPARK);
-       }
-       
-       @Test
-       public void testNaryRbindSparseDenseDenseSP() {
-               runRbindTest(true, false, false, ExecType.SPARK);
-       }
-       
-       @Test
-       public void testNaryRbindSparseDenseSparseSP() {
-               runRbindTest(true, false, true, ExecType.SPARK);
-       }
-       
-       @Test
-       public void testNaryRbindSparseSparseDenseSP() {
-               runRbindTest(true, true, false, ExecType.SPARK);
-       }
-       
-       @Test
-       public void testNaryRbindSparseSparseSparseSP() {
-               runRbindTest(true, true, true, ExecType.CP);
-       }
-       
-       
-       public void runRbindTest(boolean sparse1, boolean sparse2, boolean 
sparse3, ExecType et)
-       {
-               RUNTIME_PLATFORM platformOld = rtplatform;
-               switch( et ) {
-                       case MR: rtplatform = RUNTIME_PLATFORM.HADOOP; break;
-                       case SPARK: rtplatform = RUNTIME_PLATFORM.SPARK; break;
-                       default: rtplatform = RUNTIME_PLATFORM.HYBRID_SPARK; 
break;
-               }
-               
-               boolean sparkConfigOld = DMLScript.USE_LOCAL_SPARK_CONFIG;
-               if( rtplatform == RUNTIME_PLATFORM.SPARK || rtplatform == 
RUNTIME_PLATFORM.HYBRID_SPARK )
-                       DMLScript.USE_LOCAL_SPARK_CONFIG = true;
-               
-               try
-               {
-                       TestConfiguration config = 
getAndLoadTestConfiguration(TEST_NAME);
-                       loadTestConfiguration(config);
-                       
-                       String RI_HOME = SCRIPT_DIR + TEST_DIR;
-                       fullDMLScriptName = RI_HOME + TEST_NAME + ".dml";
-                       programArgs = new String[]{"-stats", "-args", 
input("A"), 
-                               input("B"), input("C"), output("R") };
-                       fullRScriptName = RI_HOME + TEST_NAME + ".R";
-                       rCmd = "Rscript" + " " + fullRScriptName + " " + 
-                               inputDir() + " "+ expectedDir();
-                       
-                       //generate input data
-                       double sp1 = sparse1 ? sparsity2 : sparsity1; 
-                       double sp2 = sparse2 ? sparsity2 : sparsity1; 
-                       double sp3 = sparse3 ? sparsity2 : sparsity1; 
-                       double[][] A = getRandomMatrix(rows1, cols, -1, 1, sp1, 
711);
-                       double[][] B = getRandomMatrix(rows2, cols, -1, 1, sp2, 
722);
-                       double[][] C = getRandomMatrix(rows3, cols, -1, 1, sp3, 
733);
-                       writeInputMatrixWithMTD("A", A, true);
-                       writeInputMatrixWithMTD("B", B, true);
-                       writeInputMatrixWithMTD("C", C, true);
-                       
-                       //run tests
-                       runTest(true, false, null, -1);
-                       runRScript(true);
-                       
-                       //compare result data
-                       HashMap<CellIndex, Double> dmlfile = 
readDMLMatrixFromHDFS("R");
-                       HashMap<CellIndex, Double> rfile = 
readRMatrixFromFS("R");
-                       TestUtils.compareMatrices(dmlfile, rfile, epsilon, 
"DML", "R");
-                       
-                       //check for spark instructions
-                       
Assert.assertTrue(heavyHittersContainsSubString("sp_rbind")==(et==ExecType.SPARK));
-               }
-               finally {
-                       rtplatform = platformOld;
-                       DMLScript.USE_LOCAL_SPARK_CONFIG = sparkConfigOld;
-               }
-       }
-}

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/test/java/org/apache/sysml/test/integration/functions/nary/NaryCBindTest.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/sysml/test/integration/functions/nary/NaryCBindTest.java
 
b/src/test/java/org/apache/sysml/test/integration/functions/nary/NaryCBindTest.java
new file mode 100644
index 0000000..dc4812d
--- /dev/null
+++ 
b/src/test/java/org/apache/sysml/test/integration/functions/nary/NaryCBindTest.java
@@ -0,0 +1,192 @@
+/*
+ * 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.nary;
+
+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.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 NaryCBindTest extends AutomatedTestBase
+{      
+       private final static String TEST_NAME = "NaryCbind";
+       private final static String TEST_DIR = "functions/nary/";
+       private final static String TEST_CLASS_DIR = TEST_DIR + 
NaryCBindTest.class.getSimpleName() + "/";
+
+       private final static double epsilon=0.0000000001;
+       
+       private final static int rows = 1101;
+       private final static int cols1 = 101;
+       private final static int cols2 = 79;
+       private final static int cols3 = 123;
+       
+       private final static double sparsity1 = 0.7;
+       private final static double sparsity2 = 0.07;
+       
+       @Override
+       public void setUp() {
+               TestUtils.clearAssertionInformation();
+               addTestConfiguration(TEST_NAME, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME, new String[] {"R"}));
+       }
+
+       @Test
+       public void testNaryCbindDenseDenseDenseCP() {
+               runCbindTest(false, false, false, ExecType.CP);
+       }
+       
+       @Test
+       public void testNaryCbindDenseDenseSparseCP() {
+               runCbindTest(false, false, true, ExecType.CP);
+       }
+       
+       @Test
+       public void testNaryCbindDenseSparseDenseCP() {
+               runCbindTest(false, true, false, ExecType.CP);
+       }
+       
+       @Test
+       public void testNaryCbindDenseSparseSparseCP() {
+               runCbindTest(false, true, true, ExecType.CP);
+       }
+       
+       @Test
+       public void testNaryCbindSparseDenseDenseCP() {
+               runCbindTest(true, false, false, ExecType.CP);
+       }
+       
+       @Test
+       public void testNaryCbindSparseDenseSparseCP() {
+               runCbindTest(true, false, true, ExecType.CP);
+       }
+       
+       @Test
+       public void testNaryCbindSparseSparseDenseCP() {
+               runCbindTest(true, true, false, ExecType.CP);
+       }
+       
+       @Test
+       public void testNaryCbindSparseSparseSparseCP() {
+               runCbindTest(true, true, true, ExecType.CP);
+       }
+       
+       @Test
+       public void testNaryCbindDenseDenseDenseSP() {
+               runCbindTest(false, false, false, ExecType.SPARK);
+       }
+       
+       @Test
+       public void testNaryCbindDenseDenseSparseSP() {
+               runCbindTest(false, false, true, ExecType.SPARK);
+       }
+       
+       @Test
+       public void testNaryCbindDenseSparseDenseSP() {
+               runCbindTest(false, true, false, ExecType.SPARK);
+       }
+       
+       @Test
+       public void testNaryCbindDenseSparseSparseSP() {
+               runCbindTest(false, true, true, ExecType.SPARK);
+       }
+       
+       @Test
+       public void testNaryCbindSparseDenseDenseSP() {
+               runCbindTest(true, false, false, ExecType.SPARK);
+       }
+       
+       @Test
+       public void testNaryCbindSparseDenseSparseSP() {
+               runCbindTest(true, false, true, ExecType.SPARK);
+       }
+       
+       @Test
+       public void testNaryCbindSparseSparseDenseSP() {
+               runCbindTest(true, true, false, ExecType.SPARK);
+       }
+       
+       @Test
+       public void testNaryCbindSparseSparseSparseSP() {
+               runCbindTest(true, true, true, ExecType.CP);
+       }
+       
+       
+       public void runCbindTest(boolean sparse1, boolean sparse2, boolean 
sparse3, ExecType et)
+       {
+               RUNTIME_PLATFORM platformOld = rtplatform;
+               switch( et ) {
+                       case MR: rtplatform = RUNTIME_PLATFORM.HADOOP; break;
+                       case SPARK: rtplatform = RUNTIME_PLATFORM.SPARK; break;
+                       default: rtplatform = RUNTIME_PLATFORM.HYBRID_SPARK; 
break;
+               }
+               
+               boolean sparkConfigOld = DMLScript.USE_LOCAL_SPARK_CONFIG;
+               if( rtplatform == RUNTIME_PLATFORM.SPARK || rtplatform == 
RUNTIME_PLATFORM.HYBRID_SPARK )
+                       DMLScript.USE_LOCAL_SPARK_CONFIG = true;
+               
+               try
+               {
+                       TestConfiguration config = 
getAndLoadTestConfiguration(TEST_NAME);
+                       loadTestConfiguration(config);
+                       
+                       String RI_HOME = SCRIPT_DIR + TEST_DIR;
+                       fullDMLScriptName = RI_HOME + TEST_NAME + ".dml";
+                       programArgs = new String[]{"-stats", "-args", 
input("A"),
+                               input("B"), input("C"), output("R") };
+                       fullRScriptName = RI_HOME + TEST_NAME + ".R";
+                       rCmd = "Rscript" + " " + fullRScriptName + " " +
+                               inputDir() + " "+ expectedDir();
+                       
+                       //generate input data
+                       double sp1 = sparse1 ? sparsity2 : sparsity1; 
+                       double sp2 = sparse2 ? sparsity2 : sparsity1; 
+                       double sp3 = sparse3 ? sparsity2 : sparsity1; 
+                       double[][] A = getRandomMatrix(rows, cols1, -1, 1, sp1, 
711);
+                       double[][] B = getRandomMatrix(rows, cols2, -1, 1, sp2, 
722);
+                       double[][] C = getRandomMatrix(rows, cols3, -1, 1, sp3, 
733);
+                       writeInputMatrixWithMTD("A", A, true);
+                       writeInputMatrixWithMTD("B", B, true);
+                       writeInputMatrixWithMTD("C", C, true);
+                       
+                       //run tests
+                       runTest(true, false, null, -1);
+                       runRScript(true);
+                       
+                       //compare result data
+                       HashMap<CellIndex, Double> dmlfile = 
readDMLMatrixFromHDFS("R");
+                       HashMap<CellIndex, Double> rfile = 
readRMatrixFromFS("R");
+                       TestUtils.compareMatrices(dmlfile, rfile, epsilon, 
"DML", "R");
+                       
+                       //check for spark instructions
+                       
Assert.assertTrue(heavyHittersContainsSubString("sp_cbind")==(et==ExecType.SPARK));
+               }
+               finally {
+                       rtplatform = platformOld;
+                       DMLScript.USE_LOCAL_SPARK_CONFIG = sparkConfigOld;
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/test/java/org/apache/sysml/test/integration/functions/nary/NaryMinMaxTest.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/sysml/test/integration/functions/nary/NaryMinMaxTest.java
 
b/src/test/java/org/apache/sysml/test/integration/functions/nary/NaryMinMaxTest.java
new file mode 100644
index 0000000..c5a026a
--- /dev/null
+++ 
b/src/test/java/org/apache/sysml/test/integration/functions/nary/NaryMinMaxTest.java
@@ -0,0 +1,123 @@
+/*
+ * 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.nary;
+
+import java.util.HashMap;
+
+import org.junit.Test;
+
+import org.apache.sysml.api.DMLScript;
+import org.apache.sysml.api.DMLScript.RUNTIME_PLATFORM;
+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 NaryMinMaxTest extends AutomatedTestBase
+{
+       private final static String TEST_NAME = "NaryMinMax";
+       private final static String TEST_DIR = "functions/nary/";
+       private final static String TEST_CLASS_DIR = TEST_DIR + 
NaryMinMaxTest.class.getSimpleName() + "/";
+
+       private final static double epsilon=0.0000000001;
+       
+       private final static int rows = 2101;
+       private final static int cols = 110;
+       
+       private final static double sparsity1 = 0.7;
+       private final static double sparsity2 = 0.07;
+       
+       @Override
+       public void setUp() {
+               TestUtils.clearAssertionInformation();
+               addTestConfiguration(TEST_NAME, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME, new String[] {"R"}));
+       }
+
+       @Test
+       public void testNaryMinDenseCP() {
+               runMinMaxTest(true, false, ExecType.CP);
+       }
+       
+       @Test
+       public void testNaryMinSparseCP() {
+               runMinMaxTest(true, true, ExecType.CP);
+       }
+       
+       @Test
+       public void testNaryMaxDenseCP() {
+               runMinMaxTest(false, false, ExecType.CP);
+       }
+       
+       @Test
+       public void testNaryMaxSparseCP() {
+               runMinMaxTest(false, true, ExecType.CP);
+       }
+       
+       public void runMinMaxTest(boolean min, boolean sparse, ExecType et)
+       {
+               RUNTIME_PLATFORM platformOld = rtplatform;
+               switch( et ) {
+                       case MR: rtplatform = RUNTIME_PLATFORM.HADOOP; break;
+                       case SPARK: rtplatform = RUNTIME_PLATFORM.SPARK; break;
+                       default: rtplatform = RUNTIME_PLATFORM.HYBRID_SPARK; 
break;
+               }
+               
+               boolean sparkConfigOld = DMLScript.USE_LOCAL_SPARK_CONFIG;
+               if( rtplatform == RUNTIME_PLATFORM.SPARK || rtplatform == 
RUNTIME_PLATFORM.HYBRID_SPARK )
+                       DMLScript.USE_LOCAL_SPARK_CONFIG = true;
+               
+               try
+               {
+                       TestConfiguration config = 
getAndLoadTestConfiguration(TEST_NAME);
+                       loadTestConfiguration(config);
+                       
+                       String RI_HOME = SCRIPT_DIR + TEST_DIR;
+                       fullDMLScriptName = RI_HOME + TEST_NAME + ".dml";
+                       programArgs = new String[]{"-stats", "-args", 
input("A"),
+                               input("B"), input("C"), 
String.valueOf(min).toUpperCase(), output("R") };
+                       fullRScriptName = RI_HOME + TEST_NAME + ".R";
+                       rCmd = "Rscript" + " " + fullRScriptName + " " + 
inputDir() + " " 
+                               + String.valueOf(min).toUpperCase() + " "+ 
expectedDir();
+                       
+                       //generate input data
+                       double sp = sparse ? sparsity2 : sparsity1;
+                       double[][] A = getRandomMatrix(rows, cols, -1, 1, sp, 
3);
+                       double[][] B = getRandomMatrix(rows, cols, -1, 1, sp, 
7);
+                       double[][] C = getRandomMatrix(rows, cols, -1, 1, sp, 
10);
+                       writeInputMatrixWithMTD("A", A, true);
+                       writeInputMatrixWithMTD("B", B, true);
+                       writeInputMatrixWithMTD("C", C, true);
+                       
+                       //run tests
+                       runTest(true, false, null, -1);
+                       runRScript(true);
+                       
+                       //compare result data
+                       HashMap<CellIndex, Double> dmlfile = 
readDMLMatrixFromHDFS("R");
+                       HashMap<CellIndex, Double> rfile = 
readRMatrixFromFS("R");
+                       TestUtils.compareMatrices(dmlfile, rfile, epsilon, 
"DML", "R");
+               }
+               finally {
+                       rtplatform = platformOld;
+                       DMLScript.USE_LOCAL_SPARK_CONFIG = sparkConfigOld;
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/test/java/org/apache/sysml/test/integration/functions/nary/NaryRBindTest.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/sysml/test/integration/functions/nary/NaryRBindTest.java
 
b/src/test/java/org/apache/sysml/test/integration/functions/nary/NaryRBindTest.java
new file mode 100644
index 0000000..1e51ac9
--- /dev/null
+++ 
b/src/test/java/org/apache/sysml/test/integration/functions/nary/NaryRBindTest.java
@@ -0,0 +1,192 @@
+/*
+ * 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.nary;
+
+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.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 NaryRBindTest extends AutomatedTestBase
+{      
+       private final static String TEST_NAME = "NaryRbind";
+       private final static String TEST_DIR = "functions/nary/";
+       private final static String TEST_CLASS_DIR = TEST_DIR + 
NaryRBindTest.class.getSimpleName() + "/";
+
+       private final static double epsilon=0.0000000001;
+       
+       private final static int cols = 101;
+       private final static int rows1 = 1101;
+       private final static int rows2 = 1179;
+       private final static int rows3 = 1123;
+       
+       private final static double sparsity1 = 0.7;
+       private final static double sparsity2 = 0.07;
+       
+       @Override
+       public void setUp() {
+               TestUtils.clearAssertionInformation();
+               addTestConfiguration(TEST_NAME, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME, new String[] {"R"}));
+       }
+
+       @Test
+       public void testNaryRbindDenseDenseDenseCP() {
+               runRbindTest(false, false, false, ExecType.CP);
+       }
+       
+       @Test
+       public void testNaryRbindDenseDenseSparseCP() {
+               runRbindTest(false, false, true, ExecType.CP);
+       }
+       
+       @Test
+       public void testNaryRbindDenseSparseDenseCP() {
+               runRbindTest(false, true, false, ExecType.CP);
+       }
+       
+       @Test
+       public void testNaryRbindDenseSparseSparseCP() {
+               runRbindTest(false, true, true, ExecType.CP);
+       }
+       
+       @Test
+       public void testNaryRbindSparseDenseDenseCP() {
+               runRbindTest(true, false, false, ExecType.CP);
+       }
+       
+       @Test
+       public void testNaryRbindSparseDenseSparseCP() {
+               runRbindTest(true, false, true, ExecType.CP);
+       }
+       
+       @Test
+       public void testNaryRbindSparseSparseDenseCP() {
+               runRbindTest(true, true, false, ExecType.CP);
+       }
+       
+       @Test
+       public void testNaryRbindSparseSparseSparseCP() {
+               runRbindTest(true, true, true, ExecType.CP);
+       }
+       
+       @Test
+       public void testNaryRbindDenseDenseDenseSP() {
+               runRbindTest(false, false, false, ExecType.SPARK);
+       }
+       
+       @Test
+       public void testNaryRbindDenseDenseSparseSP() {
+               runRbindTest(false, false, true, ExecType.SPARK);
+       }
+       
+       @Test
+       public void testNaryRbindDenseSparseDenseSP() {
+               runRbindTest(false, true, false, ExecType.SPARK);
+       }
+       
+       @Test
+       public void testNaryRbindDenseSparseSparseSP() {
+               runRbindTest(false, true, true, ExecType.SPARK);
+       }
+       
+       @Test
+       public void testNaryRbindSparseDenseDenseSP() {
+               runRbindTest(true, false, false, ExecType.SPARK);
+       }
+       
+       @Test
+       public void testNaryRbindSparseDenseSparseSP() {
+               runRbindTest(true, false, true, ExecType.SPARK);
+       }
+       
+       @Test
+       public void testNaryRbindSparseSparseDenseSP() {
+               runRbindTest(true, true, false, ExecType.SPARK);
+       }
+       
+       @Test
+       public void testNaryRbindSparseSparseSparseSP() {
+               runRbindTest(true, true, true, ExecType.CP);
+       }
+       
+       
+       public void runRbindTest(boolean sparse1, boolean sparse2, boolean 
sparse3, ExecType et)
+       {
+               RUNTIME_PLATFORM platformOld = rtplatform;
+               switch( et ) {
+                       case MR: rtplatform = RUNTIME_PLATFORM.HADOOP; break;
+                       case SPARK: rtplatform = RUNTIME_PLATFORM.SPARK; break;
+                       default: rtplatform = RUNTIME_PLATFORM.HYBRID_SPARK; 
break;
+               }
+               
+               boolean sparkConfigOld = DMLScript.USE_LOCAL_SPARK_CONFIG;
+               if( rtplatform == RUNTIME_PLATFORM.SPARK || rtplatform == 
RUNTIME_PLATFORM.HYBRID_SPARK )
+                       DMLScript.USE_LOCAL_SPARK_CONFIG = true;
+               
+               try
+               {
+                       TestConfiguration config = 
getAndLoadTestConfiguration(TEST_NAME);
+                       loadTestConfiguration(config);
+                       
+                       String RI_HOME = SCRIPT_DIR + TEST_DIR;
+                       fullDMLScriptName = RI_HOME + TEST_NAME + ".dml";
+                       programArgs = new String[]{"-stats", "-args", 
input("A"), 
+                               input("B"), input("C"), output("R") };
+                       fullRScriptName = RI_HOME + TEST_NAME + ".R";
+                       rCmd = "Rscript" + " " + fullRScriptName + " " + 
+                               inputDir() + " "+ expectedDir();
+                       
+                       //generate input data
+                       double sp1 = sparse1 ? sparsity2 : sparsity1; 
+                       double sp2 = sparse2 ? sparsity2 : sparsity1; 
+                       double sp3 = sparse3 ? sparsity2 : sparsity1; 
+                       double[][] A = getRandomMatrix(rows1, cols, -1, 1, sp1, 
711);
+                       double[][] B = getRandomMatrix(rows2, cols, -1, 1, sp2, 
722);
+                       double[][] C = getRandomMatrix(rows3, cols, -1, 1, sp3, 
733);
+                       writeInputMatrixWithMTD("A", A, true);
+                       writeInputMatrixWithMTD("B", B, true);
+                       writeInputMatrixWithMTD("C", C, true);
+                       
+                       //run tests
+                       runTest(true, false, null, -1);
+                       runRScript(true);
+                       
+                       //compare result data
+                       HashMap<CellIndex, Double> dmlfile = 
readDMLMatrixFromHDFS("R");
+                       HashMap<CellIndex, Double> rfile = 
readRMatrixFromFS("R");
+                       TestUtils.compareMatrices(dmlfile, rfile, epsilon, 
"DML", "R");
+                       
+                       //check for spark instructions
+                       
Assert.assertTrue(heavyHittersContainsSubString("sp_rbind")==(et==ExecType.SPARK));
+               }
+               finally {
+                       rtplatform = platformOld;
+                       DMLScript.USE_LOCAL_SPARK_CONFIG = sparkConfigOld;
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/test/scripts/functions/append/NaryCbind.R
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/append/NaryCbind.R 
b/src/test/scripts/functions/append/NaryCbind.R
deleted file mode 100644
index 4cc8d89..0000000
--- a/src/test/scripts/functions/append/NaryCbind.R
+++ /dev/null
@@ -1,32 +0,0 @@
-#-------------------------------------------------------------
-#
-# 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")
-
-A = as.matrix(readMM(paste(args[1], "A.mtx", sep="")))
-B = as.matrix(readMM(paste(args[1], "B.mtx", sep="")))
-C = as.matrix(readMM(paste(args[1], "C.mtx", sep="")))
-
-R = cbind(cbind(A, B), C);
-
-writeMM(as(R,"CsparseMatrix"), paste(args[2], "R", sep=""))

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/test/scripts/functions/append/NaryCbind.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/append/NaryCbind.dml 
b/src/test/scripts/functions/append/NaryCbind.dml
deleted file mode 100644
index 18331ad..0000000
--- a/src/test/scripts/functions/append/NaryCbind.dml
+++ /dev/null
@@ -1,26 +0,0 @@
-#-------------------------------------------------------------
-#
-# 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.
-#
-#-------------------------------------------------------------
-
-A = read($1)
-B = read($2)
-C = read($3)
-R = cbind(A, B, C);
-write(R, $4)

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/test/scripts/functions/append/NaryRbind.R
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/append/NaryRbind.R 
b/src/test/scripts/functions/append/NaryRbind.R
deleted file mode 100644
index 30ed40b..0000000
--- a/src/test/scripts/functions/append/NaryRbind.R
+++ /dev/null
@@ -1,32 +0,0 @@
-#-------------------------------------------------------------
-#
-# 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")
-
-A = as.matrix(readMM(paste(args[1], "A.mtx", sep="")))
-B = as.matrix(readMM(paste(args[1], "B.mtx", sep="")))
-C = as.matrix(readMM(paste(args[1], "C.mtx", sep="")))
-
-R = rbind(rbind(A, B), C);
-
-writeMM(as(R,"CsparseMatrix"), paste(args[2], "R", sep=""))

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/test/scripts/functions/append/NaryRbind.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/append/NaryRbind.dml 
b/src/test/scripts/functions/append/NaryRbind.dml
deleted file mode 100644
index 515c4ce..0000000
--- a/src/test/scripts/functions/append/NaryRbind.dml
+++ /dev/null
@@ -1,26 +0,0 @@
-#-------------------------------------------------------------
-#
-# 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.
-#
-#-------------------------------------------------------------
-
-A = read($1)
-B = read($2)
-C = read($3)
-R = rbind(A, B, C);
-write(R, $4)

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/test/scripts/functions/nary/NaryCbind.R
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/nary/NaryCbind.R 
b/src/test/scripts/functions/nary/NaryCbind.R
new file mode 100644
index 0000000..4cc8d89
--- /dev/null
+++ b/src/test/scripts/functions/nary/NaryCbind.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)
+options(digits=22)
+library("Matrix")
+
+A = as.matrix(readMM(paste(args[1], "A.mtx", sep="")))
+B = as.matrix(readMM(paste(args[1], "B.mtx", sep="")))
+C = as.matrix(readMM(paste(args[1], "C.mtx", sep="")))
+
+R = cbind(cbind(A, B), C);
+
+writeMM(as(R,"CsparseMatrix"), paste(args[2], "R", sep=""))

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/test/scripts/functions/nary/NaryCbind.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/nary/NaryCbind.dml 
b/src/test/scripts/functions/nary/NaryCbind.dml
new file mode 100644
index 0000000..18331ad
--- /dev/null
+++ b/src/test/scripts/functions/nary/NaryCbind.dml
@@ -0,0 +1,26 @@
+#-------------------------------------------------------------
+#
+# 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.
+#
+#-------------------------------------------------------------
+
+A = read($1)
+B = read($2)
+C = read($3)
+R = cbind(A, B, C);
+write(R, $4)

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/test/scripts/functions/nary/NaryMinMax.R
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/nary/NaryMinMax.R 
b/src/test/scripts/functions/nary/NaryMinMax.R
new file mode 100644
index 0000000..fb34545
--- /dev/null
+++ b/src/test/scripts/functions/nary/NaryMinMax.R
@@ -0,0 +1,37 @@
+#-------------------------------------------------------------
+#
+# 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")
+
+A = as.matrix(readMM(paste(args[1], "A.mtx", sep="")))
+B = as.matrix(readMM(paste(args[1], "B.mtx", sep="")))
+C = as.matrix(readMM(paste(args[1], "C.mtx", sep="")))
+
+#note: R requires that the first argument is a matrix
+if( as.logical(args[2]) ) {
+  R = pmin(A, B, C, 3, 7);
+} else {
+  R = pmax(A, B, C, -3, -7);
+}
+
+writeMM(as(R,"CsparseMatrix"), paste(args[3], "R", sep=""))

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/test/scripts/functions/nary/NaryMinMax.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/nary/NaryMinMax.dml 
b/src/test/scripts/functions/nary/NaryMinMax.dml
new file mode 100644
index 0000000..a02b09c
--- /dev/null
+++ b/src/test/scripts/functions/nary/NaryMinMax.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.
+#
+#-------------------------------------------------------------
+
+A = read($1)
+B = read($2)
+C = read($3)
+
+if( as.logical($4) )
+  R = min(3, A, B, 7, C);
+else
+  R = max(-3, A, B, -7, C);
+
+write(R, $5)

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/test/scripts/functions/nary/NaryRbind.R
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/nary/NaryRbind.R 
b/src/test/scripts/functions/nary/NaryRbind.R
new file mode 100644
index 0000000..30ed40b
--- /dev/null
+++ b/src/test/scripts/functions/nary/NaryRbind.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)
+options(digits=22)
+library("Matrix")
+
+A = as.matrix(readMM(paste(args[1], "A.mtx", sep="")))
+B = as.matrix(readMM(paste(args[1], "B.mtx", sep="")))
+C = as.matrix(readMM(paste(args[1], "C.mtx", sep="")))
+
+R = rbind(rbind(A, B), C);
+
+writeMM(as(R,"CsparseMatrix"), paste(args[2], "R", sep=""))

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/test/scripts/functions/nary/NaryRbind.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/nary/NaryRbind.dml 
b/src/test/scripts/functions/nary/NaryRbind.dml
new file mode 100644
index 0000000..515c4ce
--- /dev/null
+++ b/src/test/scripts/functions/nary/NaryRbind.dml
@@ -0,0 +1,26 @@
+#-------------------------------------------------------------
+#
+# 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.
+#
+#-------------------------------------------------------------
+
+A = read($1)
+B = read($2)
+C = read($3)
+R = rbind(A, B, C);
+write(R, $4)

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/test_suites/java/org/apache/sysml/test/integration/functions/append/ZPackageSuite.java
----------------------------------------------------------------------
diff --git 
a/src/test_suites/java/org/apache/sysml/test/integration/functions/append/ZPackageSuite.java
 
b/src/test_suites/java/org/apache/sysml/test/integration/functions/append/ZPackageSuite.java
index df7cdd1..5f0842b 100644
--- 
a/src/test_suites/java/org/apache/sysml/test/integration/functions/append/ZPackageSuite.java
+++ 
b/src/test_suites/java/org/apache/sysml/test/integration/functions/append/ZPackageSuite.java
@@ -29,8 +29,6 @@ import org.junit.runners.Suite;
        AppendChainTest.class,
        AppendMatrixTest.class,
        AppendVectorTest.class,
-       NaryCBindTest.class,
-       NaryRBindTest.class,
        RBindCBindMatrixTest.class,
        StringAppendTest.class,
 })

http://git-wip-us.apache.org/repos/asf/systemml/blob/231a3648/src/test_suites/java/org/apache/sysml/test/integration/functions/nary/ZPackageSuite.java
----------------------------------------------------------------------
diff --git 
a/src/test_suites/java/org/apache/sysml/test/integration/functions/nary/ZPackageSuite.java
 
b/src/test_suites/java/org/apache/sysml/test/integration/functions/nary/ZPackageSuite.java
new file mode 100644
index 0000000..5344c3a
--- /dev/null
+++ 
b/src/test_suites/java/org/apache/sysml/test/integration/functions/nary/ZPackageSuite.java
@@ -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.
+ */
+
+package org.apache.sysml.test.integration.functions.nary;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/** Group together the tests in this package into a single suite so that the 
Maven build
+ *  won't run two of them at once. */
+@RunWith(Suite.class)
[email protected]({
+       NaryCBindTest.class,
+       NaryMinMaxTest.class,
+       NaryRBindTest.class,
+})
+
+
+/** This class is just a holder for the above JUnit annotations. */
+public class ZPackageSuite {
+
+}

Reply via email to