[SYSTEMML-675] Fix missing support negative for/parfor increments, tests

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

Branch: refs/heads/master
Commit: 9b7f8b621c9a57e107f43171776b807791f65f59
Parents: d7dedce
Author: Matthias Boehm <[email protected]>
Authored: Mon May 9 23:32:49 2016 -0700
Committer: Matthias Boehm <[email protected]>
Committed: Tue May 10 11:39:22 2016 -0700

----------------------------------------------------------------------
 .../sysml/hops/rewrite/ProgramRewriter.java     |   3 +
 .../rewrite/RewriteForLoopVectorization.java    |   7 +-
 .../org/apache/sysml/parser/DMLTranslator.java  |   4 +-
 .../apache/sysml/parser/ForStatementBlock.java  |   2 +-
 .../apache/sysml/parser/IterablePredicate.java  |  26 ++--
 .../sysml/parser/ParForStatementBlock.java      |   7 +-
 .../parser/common/CommonSyntacticValidator.java |   1 -
 .../sysml/parser/dml/DmlSyntacticValidator.java |   6 +-
 .../parser/pydml/PydmlSyntacticValidator.java   |   5 +-
 .../runtime/controlprogram/ForProgramBlock.java |  81 ++++++++----
 .../controlprogram/ParForProgramBlock.java      |   8 +-
 .../controlprogram/parfor/TaskPartitioner.java  |  36 ++++--
 .../parfor/opt/OptTreeConverter.java            |  12 +-
 .../misc/NegativeLoopIncrementsTest.java        | 129 +++++++++++++++++++
 .../functions/misc/NegativeForIncrTest.R        |  43 +++++++
 .../functions/misc/NegativeForIncrTest.dml      |  35 +++++
 .../functions/misc/NegativeParForIncrTest.R     |  43 +++++++
 .../functions/misc/NegativeParForIncrTest.dml   |  36 ++++++
 .../functions/misc/conditionalValidate3.dml     |   2 +-
 .../functions/misc/ZPackageSuite.java           |   1 +
 20 files changed, 419 insertions(+), 68 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/9b7f8b62/src/main/java/org/apache/sysml/hops/rewrite/ProgramRewriter.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/rewrite/ProgramRewriter.java 
b/src/main/java/org/apache/sysml/hops/rewrite/ProgramRewriter.java
index cfc5855..9837a62 100644
--- a/src/main/java/org/apache/sysml/hops/rewrite/ProgramRewriter.java
+++ b/src/main/java/org/apache/sysml/hops/rewrite/ProgramRewriter.java
@@ -296,6 +296,9 @@ public class ProgramRewriter
        public Hop rewriteHopDAG(Hop root, ProgramRewriteStatus state) 
                throws HopsException
        {       
+               if( root == null )
+                       return root;
+               
                for( HopRewriteRule r : _dagRuleSet )
                {
                        root.resetVisitStatus(); //reset for each rule

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/9b7f8b62/src/main/java/org/apache/sysml/hops/rewrite/RewriteForLoopVectorization.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/hops/rewrite/RewriteForLoopVectorization.java 
b/src/main/java/org/apache/sysml/hops/rewrite/RewriteForLoopVectorization.java
index 31bd306..c773319 100644
--- 
a/src/main/java/org/apache/sysml/hops/rewrite/RewriteForLoopVectorization.java
+++ 
b/src/main/java/org/apache/sysml/hops/rewrite/RewriteForLoopVectorization.java
@@ -77,7 +77,7 @@ public class RewriteForLoopVectorization extends 
StatementBlockRewriteRule
                                          || csb instanceof IfStatementBlock 
                                          || csb instanceof ForStatementBlock ) 
)
                                {
-                                       //auto vectorzation pattern
+                                       //auto vectorization pattern
                                        sb = vectorizeScalarAggregate(sb, csb, 
from, to, incr, iterVar);           //e.g., for(i){s = s + as.scalar(X[i,2])}
                                        sb = vectorizeElementwiseBinary(sb, 
csb, from, to, incr, iterVar);
                                        sb = vectorizeElementwiseUnary(sb, csb, 
from, to, incr, iterVar);
@@ -110,8 +110,9 @@ public class RewriteForLoopVectorization extends 
StatementBlockRewriteRule
        {
                StatementBlock ret = sb;
                
-               //check supported increment values
-               if( !(increment instanceof LiteralOp && 
((LiteralOp)increment).getDoubleValue()==1.0) ){
+               //check missing and supported increment values
+               if( !(increment!=null && increment instanceof LiteralOp 
+                               && 
((LiteralOp)increment).getDoubleValue()==1.0) ) {
                        return ret;
                }
                        

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/9b7f8b62/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 b2b91c9..9e710e3 100644
--- a/src/main/java/org/apache/sysml/parser/DMLTranslator.java
+++ b/src/main/java/org/apache/sysml/parser/DMLTranslator.java
@@ -1377,7 +1377,7 @@ public class DMLTranslator
                                varsRead = ip.getFromExpr().variablesRead();
                        else if (i==1)
                                varsRead = ip.getToExpr().variablesRead();
-                       else
+                       else if( ip.getIncrementExpr() != null )
                                varsRead = 
ip.getIncrementExpr().variablesRead();
 
                        if(varsRead != null) {
@@ -1405,7 +1405,7 @@ public class DMLTranslator
                                fsb.setFromHops(      processTempIntExpression( 
ip.getFromExpr(),      _ids ));
                        else if(i==1)
                                fsb.setToHops(        processTempIntExpression( 
ip.getToExpr(),        _ids ));
-                       else
+                       else if( ip.getIncrementExpr() != null )
                                fsb.setIncrementHops( processTempIntExpression( 
ip.getIncrementExpr(), _ids ));                                 
                                
                }

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/9b7f8b62/src/main/java/org/apache/sysml/parser/ForStatementBlock.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/parser/ForStatementBlock.java 
b/src/main/java/org/apache/sysml/parser/ForStatementBlock.java
index a13db39..782b682 100644
--- a/src/main/java/org/apache/sysml/parser/ForStatementBlock.java
+++ b/src/main/java/org/apache/sysml/parser/ForStatementBlock.java
@@ -358,7 +358,7 @@ public class ForStatementBlock extends StatementBlock
                if (replacementExpr != null)
                        ip.setFromExpr(replacementExpr);
                
-               // handle replacment in to expression
+               // handle replacement in to expression
                replacementExpr = replaceConstantVar(ip.getToExpr(), 
currConstVars);  
                if (replacementExpr != null)
                        ip.setToExpr(replacementExpr);

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/9b7f8b62/src/main/java/org/apache/sysml/parser/IterablePredicate.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/parser/IterablePredicate.java 
b/src/main/java/org/apache/sysml/parser/IterablePredicate.java
index 5c86350..e145eb7 100644
--- a/src/main/java/org/apache/sysml/parser/IterablePredicate.java
+++ b/src/main/java/org/apache/sysml/parser/IterablePredicate.java
@@ -73,19 +73,18 @@ public class IterablePredicate extends Expression
        }
        
         
-       public VariableSet variablesRead() 
-       {
+       public VariableSet variablesRead() {
                VariableSet result = new VariableSet();
                result.addVariables( _fromExpr.variablesRead()      );
                result.addVariables( _toExpr.variablesRead()        );
-               result.addVariables( _incrementExpr.variablesRead() );
+               if( _incrementExpr != null )
+                       result.addVariables( _incrementExpr.variablesRead() );
 
                return result;
        }
 
         
-       public VariableSet variablesUpdated() 
-       {
+       public VariableSet variablesUpdated() {
                VariableSet result = new VariableSet();
                result.addVariable(_iterVar.getName(), _iterVar);
                
@@ -105,7 +104,6 @@ public class IterablePredicate extends Expression
        public void validateExpression(HashMap<String, DataIdentifier> ids, 
HashMap<String, ConstIdentifier> constVars, boolean conditional) 
                throws LanguageException 
        {               
-               
                //recursive validate
                if (_iterVar instanceof FunctionCallIdentifier
                                || _fromExpr instanceof FunctionCallIdentifier
@@ -115,8 +113,6 @@ public class IterablePredicate extends Expression
                            false, 
LanguageException.LanguageErrorCodes.UNSUPPORTED_EXPRESSION);
                }
                
-               
-               
                //1) VALIDATE ITERATION VARIABLE (index)
                // check the variable has either 1) not been defined already OR 
2) defined as integer scalar   
                if (ids.containsKey(_iterVar.getName())){
@@ -134,10 +130,20 @@ public class IterablePredicate extends Expression
                
                
                //2) VALIDATE FOR PREDICATE in (from, to, increment)            
+               // handle default increment if unspecified
+               if( _incrementExpr == null && _fromExpr instanceof 
ConstIdentifier 
+                       && _toExpr instanceof ConstIdentifier ) {
+                       ConstIdentifier cFrom = (ConstIdentifier) _fromExpr;
+                       ConstIdentifier cTo = (ConstIdentifier) _toExpr;
+                       _incrementExpr = new IntIdentifier( 
(cFrom.getLongValue() <= cTo.getLongValue()) ? 1 : -1, 
+                                       getFilename(), getBeginLine(), 
getBeginColumn(), getEndLine(), getEndColumn());
+               }
+               
                //recursively validate the individual expression
                _fromExpr.validateExpression(ids, constVars, conditional);
                _toExpr.validateExpression(ids, constVars, conditional);
-               _incrementExpr.validateExpression(ids, constVars, conditional);
+               if( _incrementExpr != null )
+                       _incrementExpr.validateExpression(ids, constVars, 
conditional);
                
                //check for scalar expression output
                checkNumericScalarOutput( _fromExpr );
@@ -195,7 +201,7 @@ public class IterablePredicate extends Expression
                        ret[1] = from.getOutputParameters().getLabel();
                if( to.getType()==Lop.Type.Data )
                        ret[2] = to.getOutputParameters().getLabel();
-               if( incr.getType()==Lop.Type.Data )
+               if( incr != null && incr.getType()==Lop.Type.Data )
                        ret[3] = incr.getOutputParameters().getLabel();
                
                return ret;

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/9b7f8b62/src/main/java/org/apache/sysml/parser/ParForStatementBlock.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/parser/ParForStatementBlock.java 
b/src/main/java/org/apache/sysml/parser/ParForStatementBlock.java
index 64cffec..fb5a8eb 100644
--- a/src/main/java/org/apache/sysml/parser/ParForStatementBlock.java
+++ b/src/main/java/org/apache/sysml/parser/ParForStatementBlock.java
@@ -1050,10 +1050,9 @@ public class ParForStatementBlock extends 
ForStatementBlock
                                        //NOTE: conservative approach: include 
all index variables (also from for)
                                        if( ip.getIncrementExpr() instanceof 
IntIdentifier )
                                                incr = 
((IntIdentifier)ip.getIncrementExpr()).getValue();
-                                       else
-                                               throw new 
LanguageException("PARFOR loop dependency analysis: cannot check for 
dependencies " +
-                                                                               
    "because increment expression '"+ip.getIncrementExpr().toString()+"' cannot 
be normalized.");
-                               
+                                       else 
+                                               incr = ( low <= up ) ? 1 : -1;
+
                                        
_bounds._lower.put(ip.getIterVar()._name, low);
                                        
_bounds._upper.put(ip.getIterVar()._name, up);
                                        
_bounds._increment.put(ip.getIterVar()._name, incr);

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/9b7f8b62/src/main/java/org/apache/sysml/parser/common/CommonSyntacticValidator.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/parser/common/CommonSyntacticValidator.java 
b/src/main/java/org/apache/sysml/parser/common/CommonSyntacticValidator.java
index e75c31d..78ba3d6 100644
--- a/src/main/java/org/apache/sysml/parser/common/CommonSyntacticValidator.java
+++ b/src/main/java/org/apache/sysml/parser/common/CommonSyntacticValidator.java
@@ -40,7 +40,6 @@ import org.apache.sysml.parser.DoubleIdentifier;
 import org.apache.sysml.parser.Expression;
 import org.apache.sysml.parser.Expression.DataOp;
 import org.apache.sysml.parser.FunctionCallIdentifier;
-import org.apache.sysml.parser.IndexedIdentifier;
 import org.apache.sysml.parser.IntIdentifier;
 import org.apache.sysml.parser.LanguageException;
 import org.apache.sysml.parser.MultiAssignmentStatement;

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/9b7f8b62/src/main/java/org/apache/sysml/parser/dml/DmlSyntacticValidator.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/parser/dml/DmlSyntacticValidator.java 
b/src/main/java/org/apache/sysml/parser/dml/DmlSyntacticValidator.java
index 5f5b2f3..81538bc 100644
--- a/src/main/java/org/apache/sysml/parser/dml/DmlSyntacticValidator.java
+++ b/src/main/java/org/apache/sysml/parser/dml/DmlSyntacticValidator.java
@@ -47,7 +47,6 @@ import org.apache.sysml.parser.FunctionStatement;
 import org.apache.sysml.parser.IfStatement;
 import org.apache.sysml.parser.ImportStatement;
 import org.apache.sysml.parser.IndexedIdentifier;
-import org.apache.sysml.parser.IntIdentifier;
 import org.apache.sysml.parser.IterablePredicate;
 import org.apache.sysml.parser.LanguageException;
 import org.apache.sysml.parser.ParForStatement;
@@ -651,7 +650,7 @@ public class DmlSyntacticValidator extends 
CommonSyntacticValidator implements D
 
                DataIdentifier iterVar = new 
DataIdentifier(ctx.iterVar.getText());
                HashMap<String, String> parForParamValues = null;
-               Expression incrementExpr = new IntIdentifier(1, currentFile, 
line, col, line, col);
+               Expression incrementExpr = null; //1/-1
                if(ctx.iterPred.info.increment != null) {
                        incrementExpr = ctx.iterPred.info.increment;
                }
@@ -682,8 +681,7 @@ public class DmlSyntacticValidator extends 
CommonSyntacticValidator implements D
                        }
                }
 
-               Expression incrementExpr = new IntIdentifier(1, currentFile, 
line, col, line, col);
-
+               Expression incrementExpr = null; //1/-1
                if( ctx.iterPred.info.increment != null ) {
                        incrementExpr = ctx.iterPred.info.increment;
                }

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/9b7f8b62/src/main/java/org/apache/sysml/parser/pydml/PydmlSyntacticValidator.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/parser/pydml/PydmlSyntacticValidator.java 
b/src/main/java/org/apache/sysml/parser/pydml/PydmlSyntacticValidator.java
index aa09e0d..3e2215c 100644
--- a/src/main/java/org/apache/sysml/parser/pydml/PydmlSyntacticValidator.java
+++ b/src/main/java/org/apache/sysml/parser/pydml/PydmlSyntacticValidator.java
@@ -1210,7 +1210,7 @@ public class PydmlSyntacticValidator extends 
CommonSyntacticValidator implements
 
                DataIdentifier iterVar = new 
DataIdentifier(ctx.iterVar.getText());
                HashMap<String, String> parForParamValues = null;
-               Expression incrementExpr = new IntIdentifier(1, currentFile, 
line, col, line, col);
+               Expression incrementExpr = null; //1/-1
                if(ctx.iterPred.info.increment != null) {
                        incrementExpr = ctx.iterPred.info.increment;
                }
@@ -1241,8 +1241,7 @@ public class PydmlSyntacticValidator extends 
CommonSyntacticValidator implements
                        }
                }
 
-               Expression incrementExpr = new IntIdentifier(1, currentFile, 
line, col, line, col);
-
+               Expression incrementExpr = null; //1/-1
                if( ctx.iterPred.info.increment != null ) {
                        incrementExpr = ctx.iterPred.info.increment;
                }

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/9b7f8b62/src/main/java/org/apache/sysml/runtime/controlprogram/ForProgramBlock.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/runtime/controlprogram/ForProgramBlock.java 
b/src/main/java/org/apache/sysml/runtime/controlprogram/ForProgramBlock.java
index db853f6..535f318 100644
--- a/src/main/java/org/apache/sysml/runtime/controlprogram/ForProgramBlock.java
+++ b/src/main/java/org/apache/sysml/runtime/controlprogram/ForProgramBlock.java
@@ -20,6 +20,7 @@
 package org.apache.sysml.runtime.controlprogram;
 
 import java.util.ArrayList;
+import java.util.Iterator;
 
 import org.apache.sysml.api.DMLScript;
 import org.apache.sysml.hops.Hop;
@@ -162,43 +163,35 @@ public class ForProgramBlock extends ProgramBlock
                // evaluate from, to, incr only once (assumption: known at for 
entry)
                IntObject from = executePredicateInstructions( 1, 
_fromInstructions, ec );
                IntObject to   = executePredicateInstructions( 2, 
_toInstructions, ec );
-               IntObject incr = executePredicateInstructions( 3, 
_incrementInstructions, ec );
+               IntObject incr = (_incrementInstructions == null || 
_incrementInstructions.isEmpty()) && _iterablePredicateVars[3]==null ? 
+                               new 
IntObject((from.getLongValue()<=to.getLongValue()) ? 1 : -1) :
+                               executePredicateInstructions( 3, 
_incrementInstructions, ec );
                
-               if ( incr.getLongValue() <= 0 ) //would produce infinite loop
-                       throw new 
DMLRuntimeException(this.printBlockErrorLocation() + "Expression for increment 
of variable '" + iterVarName + "' must evaluate to a positive value.");
-                               
-               // initialize iter var to from value
-               IntObject iterVar = new IntObject(iterVarName, 
from.getLongValue() );
+               if ( incr.getLongValue() == 0 ) //would produce infinite loop
+                       throw new 
DMLRuntimeException(this.printBlockErrorLocation() + "Expression for increment 
of variable '" + iterVarName + "' must evaluate to a non-zero value.");
                
                // execute for loop
                try 
                {
-                       // run for loop body as long as predicate is true 
-                       // (for supporting dynamic TO, move expression 
execution to end of while loop)
-                       while( iterVar.getLongValue() <= to.getLongValue() )
+                       // run for loop body for each instance of predicate 
sequence 
+                       SequenceIterator seqIter = new 
SequenceIterator(iterVarName, from, to, incr);
+                       for( IntObject iterVar : seqIter ) 
                        {
+                               //set iteration variable
                                ec.setVariable(iterVarName, iterVar); 
                                
-                               //for all child blocks
-                               for (int i=0 ; i < this._childBlocks.size() ; 
i++) {
+                               //execute all child blocks
+                               for(int i=0 ; i < this._childBlocks.size() ; 
i++) {
                                        ec.updateDebugState( i );
                                        _childBlocks.get(i).execute(ec);
                                }                               
-                       
-                               // update the iterable predicate variable 
-                               if(ec.getVariable(iterVarName) == null || 
!(ec.getVariable(iterVarName) instanceof IntObject))
-                                       throw new DMLRuntimeException("Iterable 
predicate variable " + iterVarName + " must remain of type scalar int.");
-                               
-                               //increment of iterVar (changes  in loop body 
get discarded)
-                               iterVar = new IntObject( iterVarName, 
iterVar.getLongValue()+incr.getLongValue() );
                        }
                }
-               catch (DMLScriptException e)
-               {
+               catch (DMLScriptException e) {
+                       //propagate stop call
                        throw e;
                }
-               catch (Exception e)
-               {
+               catch (Exception e) {
                        throw new DMLRuntimeException(printBlockErrorLocation() 
+ "Error evaluating for program block", e);
                }
                
@@ -286,4 +279,48 @@ public class ForProgramBlock extends ProgramBlock
        public String printBlockErrorLocation(){
                return "ERROR: Runtime error in for program block generated 
from for statement block between lines " + _beginLine + " and " + _endLine + " 
-- ";
        }
+       
+       /**
+        * Utility class for iterating over positive or negative predicate 
sequences.
+        */
+       protected class SequenceIterator implements Iterator<IntObject>, 
Iterable<IntObject>
+       {
+               private String _varName = null;
+               private long _cur = -1;
+               private long _to = -1;
+               private long _incr = -1;
+               private boolean _inuse = false;
+               
+               protected SequenceIterator(String varName, IntObject from, 
IntObject to, IntObject incr) {
+                       _varName = varName;
+                       _cur = from.getLongValue();
+                       _to = to.getLongValue();
+                       _incr = incr.getLongValue();
+               }
+
+               @Override
+               public boolean hasNext() {
+                       return _incr > 0 ? _cur <= _to : _cur >= _to;
+               }
+
+               @Override
+               public IntObject next() {
+                       IntObject ret = new IntObject( _varName, _cur );
+                       _cur += _incr; //update current val
+                       return ret;
+               }
+
+               @Override
+               public Iterator<IntObject> iterator() {
+                       if( _inuse )
+                               throw new RuntimeException("Unsupported reuse 
of iterator.");                           
+                       _inuse = true;
+                       return this;
+               }
+
+               @Override
+               public void remove() {
+                       throw new RuntimeException("Unsupported remove on 
iterator.");
+               }
+       }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/9b7f8b62/src/main/java/org/apache/sysml/runtime/controlprogram/ParForProgramBlock.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/runtime/controlprogram/ParForProgramBlock.java 
b/src/main/java/org/apache/sysml/runtime/controlprogram/ParForProgramBlock.java
index fd53f4d..d03d3b8 100644
--- 
a/src/main/java/org/apache/sysml/runtime/controlprogram/ParForProgramBlock.java
+++ 
b/src/main/java/org/apache/sysml/runtime/controlprogram/ParForProgramBlock.java
@@ -529,10 +529,12 @@ public class ParForProgramBlock extends ForProgramBlock
                // evaluate from, to, incr only once (assumption: known at for 
entry)
                IntObject from = executePredicateInstructions( 1, 
_fromInstructions, ec );
                IntObject to   = executePredicateInstructions( 2, 
_toInstructions, ec );
-               IntObject incr = executePredicateInstructions( 3, 
_incrementInstructions, ec );
+               IntObject incr = (_incrementInstructions == null || 
_incrementInstructions.isEmpty()) && _iterablePredicateVars[3]==null ? 
+                               new 
IntObject((from.getLongValue()<=to.getLongValue()) ? 1 : -1) :
+                               executePredicateInstructions( 3, 
_incrementInstructions, ec );
                
-               if ( incr.getLongValue() <= 0 ) //would produce infinite loop
-                       throw new 
DMLRuntimeException(this.printBlockErrorLocation() + "Expression for increment 
of variable '" + iterVarName + "' must evaluate to a positive value.");
+               if ( incr.getLongValue() == 0 ) //would produce infinite loop
+                       throw new 
DMLRuntimeException(this.printBlockErrorLocation() + "Expression for increment 
of variable '" + iterVarName + "' must evaluate to a non-zero value.");
                
                //early exit on num iterations = zero
                if( computeNumIterations(from, to, incr) <= 0 )

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/9b7f8b62/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/TaskPartitioner.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/TaskPartitioner.java
 
b/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/TaskPartitioner.java
index e96e9ee..9349402 100644
--- 
a/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/TaskPartitioner.java
+++ 
b/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/TaskPartitioner.java
@@ -33,27 +33,26 @@ import org.apache.sysml.runtime.instructions.cp.IntObject;
  * 
  */
 public abstract class TaskPartitioner 
-{
-       
-       protected long            _taskSize     = -1;
-       
+{      
+       protected long           _taskSize     = -1;    
        protected String                 _iterVarName  = null;
        protected IntObject      _fromVal      = null;
        protected IntObject      _toVal        = null;
        protected IntObject      _incrVal      = null;
-       
-       protected long            _numIter      = -1;
-       
+       protected long           _numIter      = -1;
        
        protected TaskPartitioner( long taskSize, String iterVarName, IntObject 
fromVal, IntObject toVal, IntObject incrVal ) 
        {
                _taskSize    = taskSize;
-               
                _iterVarName = iterVarName;
                _fromVal     = fromVal;
                _toVal       = toVal;
                _incrVal     = incrVal;
                
+               //normalize predicate if necessary
+               normalizePredicate();
+               
+               //compute number of iterations
                _numIter     = 
(long)Math.ceil(((double)(_toVal.getLongValue()-_fromVal.getLongValue()+1 )) / 
_incrVal.getLongValue()); 
        }
        
@@ -79,8 +78,25 @@ public abstract class TaskPartitioner
         * 
         * @return
         */
-       public long getNumIterations()
-       {
+       public long getNumIterations() {
                return _numIter;
        }
+       
+       /**
+        * Normalizes the (from, to, incr) predicate to a predicate w/
+        * positive increment.
+        */
+       private void normalizePredicate() {
+               //check for positive increment
+               if( _incrVal.getLongValue() >= 0 )
+                       return;
+               
+               long lfrom = _fromVal.getLongValue();
+               long lto = _toVal.getLongValue();
+               long lincr = _incrVal.getLongValue();
+               
+               _fromVal = new IntObject(lfrom - ((lfrom - lto)/lincr * lincr));
+               _toVal   = new IntObject(lfrom);
+               _incrVal = new IntObject(-1 * lincr);
+       }
 }

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/9b7f8b62/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/opt/OptTreeConverter.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/opt/OptTreeConverter.java
 
b/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/opt/OptTreeConverter.java
index 35d8b84..c65a627 100644
--- 
a/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/opt/OptTreeConverter.java
+++ 
b/src/main/java/org/apache/sysml/runtime/controlprogram/parfor/opt/OptTreeConverter.java
@@ -447,10 +447,12 @@ public class OptTreeConverter
                        //handle predicate
                        fsb.getFromHops().resetVisitStatus();
                        fsb.getToHops().resetVisitStatus();
-                       fsb.getIncrementHops().resetVisitStatus();
+                       if( fsb.getIncrementHops()!=null )
+                               fsb.getIncrementHops().resetVisitStatus();
                        node.addChilds( rCreateAbstractOptNodes( 
fsb.getFromHops(), vars, memo ) );
                        node.addChilds( rCreateAbstractOptNodes( 
fsb.getToHops(), vars, memo ) );
-                       node.addChilds( rCreateAbstractOptNodes( 
fsb.getIncrementHops(), vars, memo ) );
+                       if( fsb.getIncrementHops()!=null )
+                               node.addChilds( rCreateAbstractOptNodes( 
fsb.getIncrementHops(), vars, memo ) );
                        
                        //process body
                        int len = fs.getBody().size();
@@ -495,10 +497,12 @@ public class OptTreeConverter
                        {
                                fsb.getFromHops().resetVisitStatus();
                                fsb.getToHops().resetVisitStatus();
-                               fsb.getIncrementHops().resetVisitStatus();
+                               if( fsb.getIncrementHops()!=null )
+                                       
fsb.getIncrementHops().resetVisitStatus();
                                node.addChilds( rCreateAbstractOptNodes( 
fsb.getFromHops(), vars, memo ) );
                                node.addChilds( rCreateAbstractOptNodes( 
fsb.getToHops(), vars, memo ) );
-                               node.addChilds( rCreateAbstractOptNodes( 
fsb.getIncrementHops(), vars, memo ) );
+                               if( fsb.getIncrementHops()!=null )
+                                       node.addChilds( 
rCreateAbstractOptNodes( fsb.getIncrementHops(), vars, memo ) );
                        }
                        
                        //process body

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/9b7f8b62/src/test/java/org/apache/sysml/test/integration/functions/misc/NegativeLoopIncrementsTest.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/sysml/test/integration/functions/misc/NegativeLoopIncrementsTest.java
 
b/src/test/java/org/apache/sysml/test/integration/functions/misc/NegativeLoopIncrementsTest.java
new file mode 100644
index 0000000..fde3893
--- /dev/null
+++ 
b/src/test/java/org/apache/sysml/test/integration/functions/misc/NegativeLoopIncrementsTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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.misc;
+
+import java.util.HashMap;
+
+import org.junit.Test;
+
+import org.apache.sysml.runtime.matrix.MatrixCharacteristics;
+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 NegativeLoopIncrementsTest extends AutomatedTestBase 
+{
+       private final static String TEST_NAME1 = "NegativeForIncrTest";
+       private final static String TEST_NAME2 = "NegativeParforIncrTest";
+       
+       private final static String TEST_DIR = "functions/misc/";
+       private static final String TEST_CLASS_DIR = TEST_DIR + 
NegativeLoopIncrementsTest.class.getSimpleName() + "/";
+       private final static int rows = 372;
+       private final static int cols = 1;
+       private final static double eps = 1e-8;
+       
+       @Override
+       public void setUp()  {
+               TestUtils.clearAssertionInformation();
+               addTestConfiguration(TEST_NAME1, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME1, new String[] { "R" })); 
+               addTestConfiguration(TEST_NAME2, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME2, new String[] { "R" })); 
+       }
+       
+       @Test
+       public void testNegativeForIncrementsScalar() {
+               runNegativeLoopIncrementsTest(TEST_NAME1, false, false);
+       }
+       
+       @Test
+       public void testNegativeForIncrementsVector() {
+               runNegativeLoopIncrementsTest(TEST_NAME1, true, false);
+       }
+       
+       @Test
+       public void testNegativeParForIncrementsScalar() {
+               runNegativeLoopIncrementsTest(TEST_NAME2, false, false);
+       }
+       
+       @Test
+       public void testNegativeParForIncrementsVector() {
+               runNegativeLoopIncrementsTest(TEST_NAME2, true, false);
+       }
+       
+       @Test
+       public void testNegativeForIncrementsScalarMulti() {
+               runNegativeLoopIncrementsTest(TEST_NAME1, false, true);
+       }
+       
+       @Test
+       public void testNegativeForIncrementsVectorMulti() {
+               runNegativeLoopIncrementsTest(TEST_NAME1, true, true);
+       }
+       
+       @Test
+       public void testNegativeParForIncrementsScalarMulti() {
+               runNegativeLoopIncrementsTest(TEST_NAME2, false, true);
+       }
+       
+       @Test
+       public void testNegativeParForIncrementsVectorMulti() {
+               runNegativeLoopIncrementsTest(TEST_NAME2, true, true);
+       }
+       
+       /**
+        * 
+        * @param sparseM1
+        * @param sparseM2
+        * @param instType
+        */
+       private void runNegativeLoopIncrementsTest( String testname, boolean 
vect, boolean multiStep )
+       {
+               String TEST_NAME = testname;
+               TestConfiguration config = getTestConfiguration(TEST_NAME);
+               loadTestConfiguration(config);
+               
+               double[][] A = getRandomMatrix(rows, cols, -5, 5, 0.9, 7);
+               writeInputMatrixWithMTD("A", A, true);
+               
+               String HOME = SCRIPT_DIR + TEST_DIR;                    
+               fullDMLScriptName = HOME + TEST_NAME + ".dml";
+               programArgs = new String[]{"-args", input("A"), 
String.valueOf(vect?0:1), 
+                               String.valueOf(multiStep).toUpperCase(), 
output("R")};
+               
+               fullRScriptName = HOME + TEST_NAME +".R";
+               rCmd = getRCmd(inputDir(), String.valueOf(vect?0:1), 
+                               String.valueOf(multiStep).toUpperCase(), 
expectedDir());
+
+               //run Tests
+               runTest(true, false, null, -1); 
+               runRScript(true); 
+               
+               //compare matrices 
+               HashMap<CellIndex, Double> dmlfile = readDMLMatrixFromHDFS("R");
+               HashMap<CellIndex, Double> rfile  = readRMatrixFromFS("R");
+               TestUtils.compareMatrices(dmlfile, rfile, eps, "Stat-DML", 
"Stat-R");
+                       
+               //check meta data
+               checkDMLMetaDataFile("R", new MatrixCharacteristics(1,1,1,1));
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/9b7f8b62/src/test/scripts/functions/misc/NegativeForIncrTest.R
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/misc/NegativeForIncrTest.R 
b/src/test/scripts/functions/misc/NegativeForIncrTest.R
new file mode 100644
index 0000000..a084986
--- /dev/null
+++ b/src/test/scripts/functions/misc/NegativeForIncrTest.R
@@ -0,0 +1,43 @@
+#-------------------------------------------------------------
+#
+# 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="")))
+c = as.integer(args[2]);
+mStep = as.logical(args[3]);
+
+s = 0;
+if( mStep ) {
+   for( i in seq(nrow(A),1,-7) ) {
+      s = s + A[i,1] + c;
+   }
+} else {
+   for( i in nrow(A):1 ) {
+      s = s + A[i,1] + c;
+   }
+}
+
+R = as.matrix(s);
+writeMM(as(R, "CsparseMatrix"), paste(args[4], "R", sep="")); 

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/9b7f8b62/src/test/scripts/functions/misc/NegativeForIncrTest.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/misc/NegativeForIncrTest.dml 
b/src/test/scripts/functions/misc/NegativeForIncrTest.dml
new file mode 100644
index 0000000..2a5e742
--- /dev/null
+++ b/src/test/scripts/functions/misc/NegativeForIncrTest.dml
@@ -0,0 +1,35 @@
+#-------------------------------------------------------------
+#
+# 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);
+c = as.integer($2);
+mStep = as.logical($3);
+
+s = 0;
+if( mStep )
+   for( i in seq(nrow(A),1,-7) )
+      s = s + as.scalar(A[i,1]) + c;
+else
+   for( i in nrow(A):1 )
+      s = s + as.scalar(A[i,1]) + c; 
+
+R = as.matrix(s);
+write(R, $4);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/9b7f8b62/src/test/scripts/functions/misc/NegativeParForIncrTest.R
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/misc/NegativeParForIncrTest.R 
b/src/test/scripts/functions/misc/NegativeParForIncrTest.R
new file mode 100644
index 0000000..a084986
--- /dev/null
+++ b/src/test/scripts/functions/misc/NegativeParForIncrTest.R
@@ -0,0 +1,43 @@
+#-------------------------------------------------------------
+#
+# 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="")))
+c = as.integer(args[2]);
+mStep = as.logical(args[3]);
+
+s = 0;
+if( mStep ) {
+   for( i in seq(nrow(A),1,-7) ) {
+      s = s + A[i,1] + c;
+   }
+} else {
+   for( i in nrow(A):1 ) {
+      s = s + A[i,1] + c;
+   }
+}
+
+R = as.matrix(s);
+writeMM(as(R, "CsparseMatrix"), paste(args[4], "R", sep="")); 

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/9b7f8b62/src/test/scripts/functions/misc/NegativeParForIncrTest.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/misc/NegativeParForIncrTest.dml 
b/src/test/scripts/functions/misc/NegativeParForIncrTest.dml
new file mode 100644
index 0000000..c53ce1c
--- /dev/null
+++ b/src/test/scripts/functions/misc/NegativeParForIncrTest.dml
@@ -0,0 +1,36 @@
+#-------------------------------------------------------------
+#
+# 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);
+c = as.integer($2);
+mStep = as.logical($3);
+
+tmp = matrix(0, rows=nrow(A), cols=1);
+if( mStep )
+   parfor( i in seq(nrow(A),1,-7) )
+      tmp[i,1] = as.scalar(A[i,1]) + c;
+else
+   parfor( i in nrow(A):1 )
+      tmp[i,1] = as.scalar(A[i,1]) + c;      
+s = sum(tmp);
+
+R = as.matrix(s);
+write(R, $4);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/9b7f8b62/src/test/scripts/functions/misc/conditionalValidate3.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/misc/conditionalValidate3.dml 
b/src/test/scripts/functions/misc/conditionalValidate3.dml
index 94d8cdc..3b0f2f7 100644
--- a/src/test/scripts/functions/misc/conditionalValidate3.dml
+++ b/src/test/scripts/functions/misc/conditionalValidate3.dml
@@ -23,7 +23,7 @@
 Y = matrix(1, rows=10, cols=10);
 
 
-for( i in 1:0 ) {
+for( i in seq(1,0,1) ) {
    Y = read($1);
 }   
    

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/9b7f8b62/src/test_suites/java/org/apache/sysml/test/integration/functions/misc/ZPackageSuite.java
----------------------------------------------------------------------
diff --git 
a/src/test_suites/java/org/apache/sysml/test/integration/functions/misc/ZPackageSuite.java
 
b/src/test_suites/java/org/apache/sysml/test/integration/functions/misc/ZPackageSuite.java
index 5fa4d3a..23d8947 100644
--- 
a/src/test_suites/java/org/apache/sysml/test/integration/functions/misc/ZPackageSuite.java
+++ 
b/src/test_suites/java/org/apache/sysml/test/integration/functions/misc/ZPackageSuite.java
@@ -37,6 +37,7 @@ import org.junit.runners.Suite;
        IPAScalarRecursionTest.class,
        IPAUnknownRecursionTest.class,
        LongOverflowTest.class,
+       NegativeLoopIncrementsTest.class,
        NrowNcolStringTest.class,
        NrowNcolUnknownCSVReadTest.class,
        OuterTableExpandTest.class,


Reply via email to