in src/main/java/org/apache/sysds/parser/ParForStatementBlock.java [1285:1470]
private LinearFunction getLinearFunction(DataIdentifier dat)
{
/* Notes:
* - Currently, this function supports 2dim matrix subscripts with arbitrary linear functions
* however, this could be extended to d-dim if necessary
* - Trick for range indexing: introduce a pseudo index variable with lower and upper according to
* the index range (e.g., [1:4,...]) or matrix dimensionality (e.g., [:,...]). This allows us to
* apply existing tests even for range indexing (multi-value instead of single-value functions)
*/
LinearFunction out = null;
if( ! (dat instanceof IndexedIdentifier ) ) //happens if matrix is now used as scalar
return new LinearFunction(0,0,dat.getName());
IndexedIdentifier idat = (IndexedIdentifier) dat;
if( USE_FN_CACHE ) {
out = _fncache.get( getFunctionID(idat) );
if( out != null )
return out;
}
Expression sub1 = idat.getRowLowerBound();
Expression sub2 = idat.getColLowerBound();
//parse row expressions
try
{
//loop index or constant (default case)
if( idat.getRowLowerBound()!=null && idat.getRowUpperBound()!=null &&
idat.getRowLowerBound() == idat.getRowUpperBound() )
{
if( sub1 instanceof IntIdentifier )
out = new LinearFunction(((IntIdentifier)sub1).getValue(), 0, null);
else if( sub1 instanceof DataIdentifier )
out = new LinearFunction(0, 1, ((DataIdentifier)sub1)._name);
else
out = rParseBinaryExpression((BinaryExpression)sub1);
if( !CONSERVATIVE_CHECK )
if(out.hasNonIndexVariables())
{
String id = INTERAL_FN_INDEX_ROW+_idSeqfn.getNextID();
out = new LinearFunction(0, 1L, id);
_bounds._lower.put(id, 1L);
_bounds._upper.put(id, _vsParent.getVariable(idat._name).getDim1()); //row dim
_bounds._increment.put(id, 1L);
}
}
else //range indexing
{
Expression sub1a = sub1;
Expression sub1b = idat.getRowUpperBound();
String id = INTERAL_FN_INDEX_ROW+_idSeqfn.getNextID();
out = new LinearFunction(0, 1L, id);
if( sub1a == null && sub1b == null //: operator
|| !(sub1a instanceof IntIdentifier) || !(sub1b instanceof IntIdentifier) ) { //for robustness
_bounds._lower.put(id, 1L);
_bounds._upper.put(id, _vsParent.getVariable(idat._name).getDim1()); //row dim
_bounds._increment.put(id, 1L);
}
else if( sub1a instanceof IntIdentifier && sub1b instanceof IntIdentifier ) {
_bounds._lower.put(id, ((IntIdentifier)sub1a).getValue());
_bounds._upper.put(id, ((IntIdentifier)sub1b).getValue());
_bounds._increment.put(id, 1L);
}
else {
out = null;
}
}
//scale row function 'out' with col dimensionality
long colDim = _vsParent.getVariable(idat._name).getDim2();
if( colDim >= 0 ) {
out.scale( colDim );
}
else {
//NOTE: we could mark sb for deferred validation and evaluate on execute (see ParForProgramBlock)
LOG.debug("PARFOR: Warning - matrix dimensionality of '"+idat._name+"' unknown, cannot scale linear functions.");
}
}
catch(Exception ex) {
LOG.debug("PARFOR: Unable to parse MATRIX subscript expression for '"+String.valueOf(sub1)+"'.", ex);
out = null; //let dependency analysis fail
}
//parse col expression and merge functions
if( out!=null )
{
try
{
LinearFunction tmpOut = null;
//loop index or constant (default case)
if( idat.getColLowerBound()!=null && idat.getColUpperBound()!=null &&
idat.getColLowerBound() == idat.getColUpperBound() )
{
if( sub2 instanceof IntIdentifier )
out.addConstant( ((IntIdentifier)sub2).getValue() );
else if( sub2 instanceof DataIdentifier )
tmpOut = new LinearFunction(0, 1, ((DataIdentifier)sub2)._name) ;
else
tmpOut = rParseBinaryExpression((BinaryExpression)sub2);
if( !CONSERVATIVE_CHECK )
if(tmpOut!=null && tmpOut.hasNonIndexVariables())
{
String id = INTERAL_FN_INDEX_COL+_idSeqfn.getNextID();
tmpOut = new LinearFunction(0, 1L, id);
_bounds._lower.put(id, 1l);
_bounds._upper.put(id, _vsParent.getVariable(idat._name).getDim2()); //col dim
_bounds._increment.put(id, 1L);
}
}
else //range indexing
{
Expression sub2a = sub2;
Expression sub2b = idat.getColUpperBound();
String id = INTERAL_FN_INDEX_COL+_idSeqfn.getNextID();
tmpOut = new LinearFunction(0, 1L, id);
if( sub2a == null && sub2b == null //: operator
|| !(sub2a instanceof IntIdentifier) || !(sub2b instanceof IntIdentifier) ) //for robustness
{
_bounds._lower.put(id, 1L);
_bounds._upper.put(id, _vsParent.getVariable(idat._name).getDim2()); //col dim
_bounds._increment.put(id, 1L);
}
else if( sub2a instanceof IntIdentifier && sub2b instanceof IntIdentifier )
{
_bounds._lower.put(id, ((IntIdentifier)sub2a).getValue());
_bounds._upper.put(id, ((IntIdentifier)sub2b).getValue());
_bounds._increment.put(id, 1L);
}
else
{
out = null;
}
}
//final merge of row and col functions
if( tmpOut != null )
out.addFunction(tmpOut);
}
catch(Exception ex)
{
LOG.debug("PARFOR: Unable to parse MATRIX subscript expression for '"+String.valueOf(sub2)+"'.", ex);
out = null; //let dependency analysis fail
}
}
//post processing after creation
if( out != null )
{
//cleanup and verify created function; raise exceptions if needed
cleanupFunction(out);
verifyFunction(out);
// pseudo loop normalization of functions (incr=1, from=1 not necessary due to Banerjee)
// (precondition for GCD test)
if( NORMALIZE ) {
int index=0;
for( String var : out._vars ) {
long low = _bounds._lower.get(var);
long up = _bounds._upper.get(var);
long incr = _bounds._increment.get(var);
if( incr < 0 || 1 < incr ) { //does never apply to internal (artificial) vars
out.normalize(index,low,incr); // normalize linear functions
_bounds._upper.put(var,(long)Math.ceil(((double)up)/incr)); // normalize upper bound
}
index++;
}
}
//put into cache
if( USE_FN_CACHE )
_fncache.put( getFunctionID(idat), out );
}
return out;
}