[SYSTEMML-382] Initial runtime integration sparse matrix blocks

This changes integrates the new sparse block abstraction into our matrix
block data structure and modifies all operations of all backends
accordingly. For the sake of a seamless integration without major
performance regressions, some operations still rely on SparseRows as
temporary container for obtaining and inserting entire rows. Also, all
created matrix blocks still use the old MCSR representation.

As a next step, we need to tune important operations according to the
new sparse block abstraction.

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

Branch: refs/heads/master
Commit: 8ba0fdccad91cd91ca8fdeef0f51d0c071b6fb7d
Parents: 2af90e0
Author: Matthias Boehm <[email protected]>
Authored: Wed Jan 20 14:55:50 2016 -0800
Committer: Matthias Boehm <[email protected]>
Committed: Wed Jan 20 14:58:34 2016 -0800

----------------------------------------------------------------------
 .../controlprogram/caching/CacheDataInput.java  |  10 +-
 .../controlprogram/caching/CacheDataOutput.java |  19 +-
 .../spark/utils/RDDConverterUtils.java          |  10 +-
 .../apache/sysml/runtime/io/WriterTextCSV.java  |  19 +-
 .../sysml/runtime/io/WriterTextCSVParallel.java |  19 +-
 .../sysml/runtime/matrix/data/LibMatrixAgg.java | 555 +++++-------
 .../runtime/matrix/data/LibMatrixBincell.java   | 265 +++---
 .../runtime/matrix/data/LibMatrixDatagen.java   |  14 +-
 .../runtime/matrix/data/LibMatrixMult.java      | 565 ++++++------
 .../runtime/matrix/data/LibMatrixOuterAgg.java  |  60 +-
 .../runtime/matrix/data/LibMatrixReorg.java     | 291 +++---
 .../sysml/runtime/matrix/data/MatrixBlock.java  | 897 +++++++++----------
 .../matrix/data/MatrixBlockDataInput.java       |   2 +-
 .../matrix/data/MatrixBlockDataOutput.java      |   2 +-
 .../runtime/matrix/data/SparseRowsIterator.java | 110 ---
 .../util/FastBufferedDataInputStream.java       |  12 +-
 .../util/FastBufferedDataOutputStream.java      |  20 +-
 .../functions/sparse/SparseBlockDelete.java     |   9 +-
 .../sparse/SparseBlockGetFirstIndex.java        |   9 +-
 .../functions/sparse/SparseBlockGetSet.java     |   9 +-
 .../functions/sparse/SparseBlockIndexRange.java |   9 +-
 .../functions/sparse/SparseBlockIterator.java   |   9 +-
 .../functions/sparse/SparseBlockScan.java       |   9 +-
 .../functions/sparse/SparseBlockSize.java       |   9 +-
 24 files changed, 1339 insertions(+), 1594 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/8ba0fdcc/src/main/java/org/apache/sysml/runtime/controlprogram/caching/CacheDataInput.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/runtime/controlprogram/caching/CacheDataInput.java
 
b/src/main/java/org/apache/sysml/runtime/controlprogram/caching/CacheDataInput.java
index 712ad8a..bc81361 100644
--- 
a/src/main/java/org/apache/sysml/runtime/controlprogram/caching/CacheDataInput.java
+++ 
b/src/main/java/org/apache/sysml/runtime/controlprogram/caching/CacheDataInput.java
@@ -23,7 +23,7 @@ import java.io.DataInput;
 import java.io.IOException;
 
 import org.apache.sysml.runtime.matrix.data.MatrixBlockDataInput;
-import org.apache.sysml.runtime.matrix.data.SparseRow;
+import org.apache.sysml.runtime.matrix.data.SparseBlock;
 
 public class CacheDataInput implements DataInput, MatrixBlockDataInput
 {
@@ -163,7 +163,7 @@ public class CacheDataInput implements DataInput, 
MatrixBlockDataInput
        }
 
        @Override
-       public long readSparseRows(int rlen, SparseRow[] rows) 
+       public long readSparseRows(int rlen, SparseBlock rows) 
                throws IOException 
        {
                //counter for non-zero elements
@@ -177,9 +177,7 @@ public class CacheDataInput implements DataInput, 
MatrixBlockDataInput
                        if( lnnz > 0 ) //non-zero row
                        {
                                //get handle to sparse (allocate if necessary)
-                               if( rows[i] == null )
-                                       rows[i] = new SparseRow(lnnz);
-                               SparseRow arow = rows[i];
+                               rows.allocate(i, lnnz);
                                
                                //read single sparse row
                                for( int j=0; j<lnnz; j++ ) 
@@ -187,7 +185,7 @@ public class CacheDataInput implements DataInput, 
MatrixBlockDataInput
                                        int aix = baToInt(_buff, _count);
                                        long tmp = baToLong(_buff, _count+4);
                                        double aval = Double.longBitsToDouble( 
tmp );
-                                       arow.append(aix, aval);
+                                       rows.append(i, aix, aval);
                                        _count+=12;
                                }
                                

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/8ba0fdcc/src/main/java/org/apache/sysml/runtime/controlprogram/caching/CacheDataOutput.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/runtime/controlprogram/caching/CacheDataOutput.java
 
b/src/main/java/org/apache/sysml/runtime/controlprogram/caching/CacheDataOutput.java
index 66ad552..5fd0b4b 100644
--- 
a/src/main/java/org/apache/sysml/runtime/controlprogram/caching/CacheDataOutput.java
+++ 
b/src/main/java/org/apache/sysml/runtime/controlprogram/caching/CacheDataOutput.java
@@ -22,9 +22,8 @@ package org.apache.sysml.runtime.controlprogram.caching;
 import java.io.DataOutput;
 import java.io.IOException;
 
-
 import org.apache.sysml.runtime.matrix.data.MatrixBlockDataOutput;
-import org.apache.sysml.runtime.matrix.data.SparseRow;
+import org.apache.sysml.runtime.matrix.data.SparseBlock;
 
 /**
  * Customer DataOutput to serialize directly into the given byte array.
@@ -158,24 +157,24 @@ public class CacheDataOutput implements DataOutput, 
MatrixBlockDataOutput
        }
        
        @Override
-       public void writeSparseRows(int rlen, SparseRow[] rows) 
+       public void writeSparseRows(int rlen, SparseBlock rows) 
                throws IOException
        {
-               int lrlen = Math.min(rows.length, rlen);
+               int lrlen = Math.min(rows.numRows(), rlen);
                
                //process existing rows
                for( int i=0; i<lrlen; i++ )
                {
-                       SparseRow arow = rows[i];
-                       if( arow!=null && !arow.isEmpty() )
+                       if( !rows.isEmpty(i) )
                        {
-                               int alen = arow.size();
-                               int[] aix = arow.getIndexContainer();
-                               double[] avals = arow.getValueContainer();
+                               int apos = rows.pos(i);
+                               int alen = rows.size(i);
+                               int[] aix = rows.indexes(i);
+                               double[] avals = rows.values(i);
                                
                                writeInt( alen );
 
-                               for( int j=0; j<alen; j++ )
+                               for( int j=apos; j<apos+alen; j++ )
                                {
                                        intToBa(aix[j], _buff, _count);
                                        long tmp2 = 
Double.doubleToRawLongBits(avals[j]);

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/8ba0fdcc/src/main/java/org/apache/sysml/runtime/instructions/spark/utils/RDDConverterUtils.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/runtime/instructions/spark/utils/RDDConverterUtils.java
 
b/src/main/java/org/apache/sysml/runtime/instructions/spark/utils/RDDConverterUtils.java
index 656a618..3867dac 100644
--- 
a/src/main/java/org/apache/sysml/runtime/instructions/spark/utils/RDDConverterUtils.java
+++ 
b/src/main/java/org/apache/sysml/runtime/instructions/spark/utils/RDDConverterUtils.java
@@ -48,7 +48,7 @@ import 
org.apache.sysml.runtime.matrix.data.CSVFileFormatProperties;
 import org.apache.sysml.runtime.matrix.data.MatrixBlock;
 import org.apache.sysml.runtime.matrix.data.MatrixCell;
 import org.apache.sysml.runtime.matrix.data.MatrixIndexes;
-import org.apache.sysml.runtime.matrix.data.SparseRow;
+import org.apache.sysml.runtime.matrix.data.SparseBlock;
 import org.apache.sysml.runtime.matrix.mapred.IndexedMatrixValue;
 import org.apache.sysml.runtime.matrix.mapred.ReblockBuffer;
 import org.apache.sysml.runtime.util.DataConverter;
@@ -280,11 +280,9 @@ public class RDDConverterUtils
                                }
                                else if( tmp.isInSparseFormat() ) //SPARSE ROW
                                {
-                                       SparseRow row = 
tmp.getSparseBlock()[0]; 
-                                       int rlen = row.size();
-                                       int[] rix = row.getIndexContainer();
-                                       double[] rvals = 
row.getValueContainer();
-                                       ret.add(new 
LabeledPoint(arg0.getValue(i, arg0.getNumColumns()-1), Vectors.sparse(rlen, 
rix, rvals)));
+                                       SparseBlock sblock = 
tmp.getSparseBlock();
+                                       ret.add(new 
LabeledPoint(arg0.getValue(i, arg0.getNumColumns()-1), 
+                                                       
Vectors.sparse(sblock.size(0), sblock.indexes(0), sblock.values(0))));
                                }
                                else // DENSE ROW
                                {

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/8ba0fdcc/src/main/java/org/apache/sysml/runtime/io/WriterTextCSV.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/io/WriterTextCSV.java 
b/src/main/java/org/apache/sysml/runtime/io/WriterTextCSV.java
index 96e31db..54ec1a4 100644
--- a/src/main/java/org/apache/sysml/runtime/io/WriterTextCSV.java
+++ b/src/main/java/org/apache/sysml/runtime/io/WriterTextCSV.java
@@ -34,14 +34,13 @@ import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.io.IOUtils;
 import org.apache.hadoop.mapred.JobConf;
-
 import org.apache.sysml.conf.ConfigurationManager;
 import org.apache.sysml.runtime.DMLRuntimeException;
 import org.apache.sysml.runtime.DMLUnsupportedOperationException;
 import org.apache.sysml.runtime.matrix.CSVReblockMR;
 import org.apache.sysml.runtime.matrix.data.CSVFileFormatProperties;
 import org.apache.sysml.runtime.matrix.data.MatrixBlock;
-import org.apache.sysml.runtime.matrix.data.SparseRow;
+import org.apache.sysml.runtime.matrix.data.SparseBlock;
 import org.apache.sysml.runtime.util.MapReduceTool;
 
 /**
@@ -138,20 +137,20 @@ public class WriterTextCSV extends MatrixWriter
                        // Write data lines
                        if( sparse ) //SPARSE
                        {       
-                               SparseRow[] sparseRows = src.getSparseBlock();
+                               SparseBlock sblock = src.getSparseBlock();
                                for(int i=0; i < rlen; i++) 
                    {
                                        //write row chunk-wise to prevent OOM 
on large number of columns
                                        int prev_jix = -1;
-                                       if(    sparseRows!=null && 
i<sparseRows.length 
-                                               && sparseRows[i]!=null && 
!sparseRows[i].isEmpty() )
+                                       if(    sblock!=null && 
i<sblock.numRows() 
+                                               && !sblock.isEmpty(i) )
                                        {
-                                               SparseRow arow = sparseRows[i];
-                                               int alen = arow.size();
-                                               int[] aix = 
arow.getIndexContainer();
-                                               double[] avals = 
arow.getValueContainer();
+                                               int pos = sblock.pos(i);
+                                               int alen = sblock.size(i);
+                                               int[] aix = sblock.indexes(i);
+                                               double[] avals = 
sblock.values(i);
                                                
-                                               for(int j=0; j < alen; j++) 
+                                               for(int j=pos; j<pos+alen; j++) 
                                                {
                                                        int jix = aix[j];
                                                        

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/8ba0fdcc/src/main/java/org/apache/sysml/runtime/io/WriterTextCSVParallel.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/runtime/io/WriterTextCSVParallel.java 
b/src/main/java/org/apache/sysml/runtime/io/WriterTextCSVParallel.java
index 9758dc5..cd400fe 100644
--- a/src/main/java/org/apache/sysml/runtime/io/WriterTextCSVParallel.java
+++ b/src/main/java/org/apache/sysml/runtime/io/WriterTextCSVParallel.java
@@ -32,14 +32,13 @@ import java.util.concurrent.Future;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.mapred.JobConf;
-
 import org.apache.sysml.conf.DMLConfig;
 import org.apache.sysml.hops.OptimizerUtils;
 import 
org.apache.sysml.runtime.controlprogram.parfor.stat.InfrastructureAnalyzer;
 import org.apache.sysml.runtime.matrix.data.CSVFileFormatProperties;
 import org.apache.sysml.runtime.matrix.data.MatrixBlock;
 import org.apache.sysml.runtime.matrix.data.OutputInfo;
-import org.apache.sysml.runtime.matrix.data.SparseRow;
+import org.apache.sysml.runtime.matrix.data.SparseBlock;
 import org.apache.sysml.runtime.util.MapReduceTool;
 
 /**
@@ -172,20 +171,20 @@ public class WriterTextCSVParallel extends WriterTextCSV
                                // Write data lines
                                if( sparse ) //SPARSE
                                {       
-                                       SparseRow[] sparseRows = 
_src.getSparseBlock();
+                                       SparseBlock sblock = 
_src.getSparseBlock();
                                        for( int i=_rl; i<_ru; i++ )
                                        {
                                                //write row chunk-wise to 
prevent OOM on large number of columns
                                                int prev_jix = -1;
-                                               if(    sparseRows!=null && 
i<sparseRows.length 
-                                                       && sparseRows[i]!=null 
&& !sparseRows[i].isEmpty() )
+                                               if(    sblock!=null && 
i<sblock.numRows() 
+                                                       && !sblock.isEmpty(i) )
                                                {
-                                                       SparseRow arow = 
sparseRows[i];
-                                                       int alen = arow.size();
-                                                       int[] aix = 
arow.getIndexContainer();
-                                                       double[] avals = 
arow.getValueContainer();
+                                                       int pos = sblock.pos(i);
+                                                       int alen = 
sblock.size(i);
+                                                       int[] aix = 
sblock.indexes(i);
+                                                       double[] avals = 
sblock.values(i);
                                                        
-                                                       for(int j=0; j < alen; 
j++) 
+                                                       for(int j=pos; 
j<pos+alen; j++) 
                                                        {
                                                                int jix = 
aix[j];
                                                                

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/8ba0fdcc/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixAgg.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixAgg.java 
b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixAgg.java
index f856e06..b52aaaf 100644
--- a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixAgg.java
+++ b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixAgg.java
@@ -689,14 +689,15 @@ public class LibMatrixAgg
                
                if( in1.sparse )
                {
-                       SparseRow[] a = in1.sparseBlock;
+                       SparseBlock a = in1.sparseBlock;
                        
                        for( int i=rl; i<ru; i++ )
-                               if( a[i]!=null && !a[i].isEmpty() ) {
-                                       int alen = a[i].size();
-                                       int[] aix = a[i].getIndexContainer();
-                                       double[] avals = 
a[i].getValueContainer();
-                                       for( int j=0; j<alen; j++ ) {
+                               if( !a.isEmpty(i) ) {
+                                       int apos = a.pos(i);
+                                       int alen = a.size(i);
+                                       int[] aix = a.indexes(i);
+                                       double[] avals = a.values(i);
+                                       for( int j=apos; j<apos+alen; j++ ) {
                                                double val1 = avals[j];
                                                double val2 = 
in2.quickGetValue(i, aix[j]);
                                                double val = val1 * val2;
@@ -757,12 +758,13 @@ public class LibMatrixAgg
                        
                        if( target.sparse ) //SPARSE target
                        {
-                               if( target.sparseBlock[0]!=null )
+                               if( !target.sparseBlock.isEmpty(0) )
                                {
-                                       int len = target.sparseBlock[0].size();
-                                       int[] aix = 
target.sparseBlock[0].getIndexContainer();
-                                       double[] avals = 
target.sparseBlock[0].getValueContainer();     
-                                       for( int j=0; j<len; j++ ) //for each 
nnz
+                                       int pos = target.sparseBlock.pos(0);
+                                       int len = target.sparseBlock.size(0);
+                                       int[] aix = 
target.sparseBlock.indexes(0);
+                                       double[] avals = 
target.sparseBlock.values(0);  
+                                       for( int j=pos; j<pos+len; j++ ) //for 
each nnz
                                        {
                                                int g = (int) 
groups.quickGetValue(aix[j], 0);          
                                                if ( g > numGroups )
@@ -795,7 +797,7 @@ public class LibMatrixAgg
                {
                        if( target.sparse ) //SPARSE target
                        {
-                               SparseRow[] a = target.sparseBlock;
+                               SparseBlock a = target.sparseBlock;
                                
                                for( int i=0; i < groups.getNumRows(); i++ ) 
                                {
@@ -803,15 +805,16 @@ public class LibMatrixAgg
                                        if ( g > numGroups )
                                                continue;
                                        
-                                       if( a[i] != null && !a[i].isEmpty() )
+                                       if( !a.isEmpty(i) )
                                        {
-                                               int len = a[i].size();
-                                               int[] aix = 
a[i].getIndexContainer();
-                                               double[] avals = 
a[i].getValueContainer();      
-                                               int j = (cl==0) ? 0 : 
a[i].searchIndexesFirstGTE(cl);
+                                               int pos = a.pos(i);
+                                               int len = a.size(i);
+                                               int[] aix = a.indexes(i);
+                                               double[] avals = a.values(i);   
+                                               int j = (cl==0) ? pos : 
a.posFIndexGTE(i,cl);
                                                j = (j>=0) ? j : len;
                                                
-                                               for( ; j<len && aix[j]<cu; j++ 
) //for each nnz
+                                               for( ; j<pos+len && aix[j]<cu; 
j++ ) //for each nnz
                                                {
                                                        if ( weights != null )
                                                                w = 
weights.quickGetValue(aix[j],0);
@@ -873,7 +876,7 @@ public class LibMatrixAgg
                //column vector or matrix
                if( target.sparse ) //SPARSE target
                {
-                       SparseRow[] a = target.sparseBlock;
+                       SparseBlock a = target.sparseBlock;
                        
                        for( int i=0; i < groups.getNumRows(); i++ ) 
                        {
@@ -881,15 +884,16 @@ public class LibMatrixAgg
                                if ( g > numGroups )
                                        continue;
                                
-                               if( a[i] != null && !a[i].isEmpty() )
+                               if( !a.isEmpty(i) )
                                {
-                                       int len = a[i].size();
-                                       int[] aix = a[i].getIndexContainer();
-                                       double[] avals = 
a[i].getValueContainer();      
-                                       int j = (cl==0) ? 0 : 
a[i].searchIndexesFirstGTE(cl);
-                                       j = (j>=0) ? j : len;
+                                       int pos = a.pos(i);
+                                       int len = a.size(i);
+                                       int[] aix = a.indexes(i);
+                                       double[] avals = a.values(i);   
+                                       int j = (cl==0) ? pos : 
a.posFIndexGTE(i,cl);
+                                       j = (j>=0) ? j : pos+len;
                                        
-                                       for( ; j<len && aix[j]<cu; j++ ) //for 
each nnz
+                                       for( ; j<pos+len && aix[j]<cu; j++ ) 
//for each nnz
                                        {
                                                if ( weights != null )
                                                        w = 
weights.quickGetValue(i, 0);
@@ -1001,8 +1005,6 @@ public class LibMatrixAgg
                
                aggVal.nonZeros = nnzC;
                aggCorr.nonZeros = nnzCC;
-               //aggVal.examSparsity();
-               //aggCorr.examSparsity(); 
        }
 
        /**
@@ -1022,7 +1024,7 @@ public class LibMatrixAgg
                aggVal.allocateDenseBlock(); //should always stay in dense
                aggCorr.allocateDenseBlock(); //should always stay in dense
                
-               SparseRow[] a = in.getSparseBlock();
+               SparseBlock a = in.getSparseBlock();
                double[] c = aggVal.getDenseBlock();
                double[] cc = aggCorr.getDenseBlock();
                
@@ -1031,18 +1033,18 @@ public class LibMatrixAgg
                
                final int m = in.rlen;
                final int n = in.clen;
-               final int rlen = Math.min(a.length, m);
+               final int rlen = Math.min(a.numRows(), m);
                
                for( int i=0, cix=0; i<rlen; i++, cix+=n )
                {
-                       SparseRow arow = a[i];
-                       if( arow!=null && !arow.isEmpty() )
+                       if( !a.isEmpty(i) )
                        {
-                               int alen = arow.size();
-                               int[] aix = arow.getIndexContainer();
-                               double[] avals = arow.getValueContainer();
+                               int apos = a.pos(i);
+                               int alen = a.size(i);
+                               int[] aix = a.indexes(i);
+                               double[] avals = a.values(i);
                                
-                               for( int j=0; j<alen; j++ )
+                               for( int j=apos; j<apos+alen; j++ )
                                {
                                        int ix = cix+aix[j];
                                        buffer1._sum        = c[ix];
@@ -1055,9 +1057,7 @@ public class LibMatrixAgg
                }
                
                aggVal.recomputeNonZeros();
-               aggCorr.recomputeNonZeros();
-               //aggVal.examSparsity();
-               //aggCorr.examSparsity(); 
+               aggCorr.recomputeNonZeros(); 
        }
        
        /**
@@ -1073,24 +1073,24 @@ public class LibMatrixAgg
                if( in.isEmptyBlock(false) )
                        return;
                
-               SparseRow[] a = in.getSparseBlock();
+               SparseBlock a = in.getSparseBlock();
                
                KahanObject buffer1 = new KahanObject(0, 0);
                KahanPlus akplus = KahanPlus.getKahanPlusFnObject();
                
                final int m = in.rlen;
-               final int rlen = Math.min(a.length, m);
+               final int rlen = Math.min(a.numRows(), m);
                
                for( int i=0; i<rlen; i++ )
                {
-                       SparseRow arow = a[i];
-                       if( arow!=null && !arow.isEmpty() )
+                       if( !a.isEmpty(i) )
                        {
-                               int alen = arow.size();
-                               int[] aix = arow.getIndexContainer();
-                               double[] avals = arow.getValueContainer();
+                               int apos = a.pos(i);
+                               int alen = a.size(i);
+                               int[] aix = a.indexes(i);
+                               double[] avals = a.values(i);
                                
-                               for( int j=0; j<alen; j++ )
+                               for( int j=apos; j<apos+alen; j++ )
                                {
                                        int jix = aix[j];
                                        buffer1._sum        = 
aggVal.quickGetValue(i, jix);
@@ -1194,24 +1194,24 @@ public class LibMatrixAgg
                if( in.isEmptyBlock(false) )
                        return;
                
-               SparseRow[] a = in.getSparseBlock();
+               SparseBlock a = in.getSparseBlock();
                
                KahanObject buffer1 = new KahanObject(0, 0);
                KahanPlus akplus = KahanPlus.getKahanPlusFnObject();
                
                final int m = in.rlen;
-               final int rlen = Math.min(a.length, m);
+               final int rlen = Math.min(a.numRows(), m);
                
                for( int i=0; i<rlen-1; i++ )
                {
-                       SparseRow arow = a[i];
-                       if( arow!=null && !arow.isEmpty() )
+                       if( !a.isEmpty(i) )
                        {
-                               int alen = arow.size();
-                               int[] aix = arow.getIndexContainer();
-                               double[] avals = arow.getValueContainer();
+                               int apos = a.pos(i);
+                               int alen = a.size(i);
+                               int[] aix = a.indexes(i);
+                               double[] avals = a.values(i);
                                
-                               for( int j=0; j<alen; j++ )
+                               for( int j=apos; j<apos+alen; j++ )
                                {
                                        int jix = aix[j];
                                        double corr = in.quickGetValue(m-1, 
jix);
@@ -1276,25 +1276,25 @@ public class LibMatrixAgg
                if( in.isEmptyBlock(false) )
                        return;
                
-               SparseRow[] a = in.getSparseBlock();
+               SparseBlock a = in.getSparseBlock();
                
                KahanObject buffer1 = new KahanObject(0, 0);
                KahanPlus akplus = KahanPlus.getKahanPlusFnObject();
                
                final int m = in.rlen;
                final int n = in.clen;
-               final int rlen = Math.min(a.length, m);
+               final int rlen = Math.min(a.numRows(), m);
                
                for( int i=0; i<rlen; i++ )
                {
-                       SparseRow arow = a[i];
-                       if( arow!=null && !arow.isEmpty() )
+                       if( !a.isEmpty(i) )
                        {
-                               int alen = arow.size();
-                               int[] aix = arow.getIndexContainer();
-                               double[] avals = arow.getValueContainer();
+                               int apos = a.pos(i);
+                               int alen = a.size(i);
+                               int[] aix = a.indexes(i);
+                               double[] avals = a.values(i);
                                
-                               for( int j=0; j<alen && aix[j]<n-1; j++ )
+                               for( int j=apos; j<apos+alen && aix[j]<n-1; j++ 
)
                                {
                                        int jix = aix[j];
                                        double corr = in.quickGetValue(i, n-1);
@@ -1455,7 +1455,7 @@ public class LibMatrixAgg
                final int m = in.rlen;
                final int n = in.clen;
                
-               SparseRow[] a = in.getSparseBlock();
+               SparseBlock a = in.getSparseBlock();
                double[] c = out.getDenseBlock();
                
                switch( optype )
@@ -2116,17 +2116,11 @@ public class LibMatrixAgg
         * @param kbuff
         * @param kplus
         */
-       private static void s_uakp( SparseRow[] a, double[] c, int m, int n, 
KahanObject kbuff, KahanPlus kplus, int rl, int ru )
+       private static void s_uakp( SparseBlock a, double[] c, int m, int n, 
KahanObject kbuff, KahanPlus kplus, int rl, int ru )
        {
-               for( int i=rl; i<ru; i++ )
-               {
-                       SparseRow arow = a[i];
-                       if( arow!=null && !arow.isEmpty() )
-                       {
-                               int alen = arow.size();
-                               double[] avals = arow.getValueContainer();
-                               sum(avals, 0, alen, kbuff, kplus);
-                       }
+               for( int i=rl; i<ru; i++ ) {
+                       if( !a.isEmpty(i) )
+                               sum(a.values(i), a.pos(i), a.size(i), kbuff, 
kplus);
                }
                c[0] = kbuff._sum;
                c[1] = kbuff._correction;       
@@ -2142,22 +2136,16 @@ public class LibMatrixAgg
         * @param kbuff
         * @param kplus
         */
-       private static void s_uarkp( SparseRow[] a, double[] c, int m, int n, 
KahanObject kbuff, KahanPlus kplus, int rl, int ru ) 
+       private static void s_uarkp( SparseBlock a, double[] c, int m, int n, 
KahanObject kbuff, KahanPlus kplus, int rl, int ru ) 
        {
                //compute row aggregates
                for( int i=rl, cix=rl*2; i<ru; i++, cix+=2 )
-               {
-                       SparseRow arow = a[i];
-                       if( arow!=null && !arow.isEmpty() )
-                       {
-                               int alen = arow.size();
-                               double[] avals = arow.getValueContainer();
+                       if( !a.isEmpty(i) ) {
                                kbuff.set(0, 0); //reset buffer
-                               sum( avals, 0, alen, kbuff, kplus );
+                               sum( a.values(i), a.pos(i), a.size(i), kbuff, 
kplus );
                                c[cix+0] = kbuff._sum;
                                c[cix+1] = kbuff._correction;                   
                        }
-               }
        }
        
        /**
@@ -2170,20 +2158,13 @@ public class LibMatrixAgg
         * @param kbuff
         * @param kplus
         */
-       private static void s_uackp( SparseRow[] a, double[] c, int m, int n, 
KahanObject kbuff, KahanPlus kplus, int rl, int ru ) 
+       private static void s_uackp( SparseBlock a, double[] c, int m, int n, 
KahanObject kbuff, KahanPlus kplus, int rl, int ru ) 
        {
                //compute column aggregates
                for( int i=rl; i<ru; i++ )
-               {
-                       SparseRow arow = a[i];
-                       if( arow!=null && !arow.isEmpty() )
-                       {
-                               int alen = arow.size();
-                               double[] avals = arow.getValueContainer();
-                               int[] aix = arow.getIndexContainer();
-                               sumAgg( avals, c, aix, alen, n, kbuff, kplus );
+                       if( !a.isEmpty(i) ) {
+                               sumAgg( a.values(i), c, a.indexes(i), a.pos(i), 
a.size(i), n, kbuff, kplus );
                        }
-               }
        }
 
        /**
@@ -2201,15 +2182,12 @@ public class LibMatrixAgg
         * @param rl Lower row limit.
         * @param ru Upper row limit.
         */
-       private static void s_uasqkp(SparseRow[] a, double[] c, int m, int n, 
KahanObject kbuff,
+       private static void s_uasqkp(SparseBlock a, double[] c, int m, int n, 
KahanObject kbuff,
                                     KahanPlusSq kplusSq, int rl, int ru )
        {
                for (int i=rl; i<ru; i++) {
-                       SparseRow arow = a[i];
-                       if (arow!=null && !arow.isEmpty()) {
-                               int alen = arow.size();
-                               double[] avals = arow.getValueContainer();
-                               sumSq(avals, 0, alen, kbuff, kplusSq);
+                       if (!a.isEmpty(i)) {
+                               sumSq(a.values(i), a.pos(i), a.size(i), kbuff, 
kplusSq);
                        }
                }
                c[0] = kbuff._sum;
@@ -2232,17 +2210,14 @@ public class LibMatrixAgg
         * @param rl Lower row limit.
         * @param ru Upper row limit.
         */
-       private static void s_uarsqkp(SparseRow[] a, double[] c, int m, int n, 
KahanObject kbuff,
+       private static void s_uarsqkp(SparseBlock a, double[] c, int m, int n, 
KahanObject kbuff,
                                      KahanPlusSq kplusSq, int rl, int ru )
        {
                //compute row aggregates
                for (int i=rl, cix=rl*2; i<ru; i++, cix+=2) {
-                       SparseRow arow = a[i];
-                       if (arow!=null && !arow.isEmpty()) {
-                               int alen = arow.size();
-                               double[] avals = arow.getValueContainer();
+                       if (!a.isEmpty(i)) {
                                kbuff.set(0, 0); //reset buffer
-                               sumSq(avals, 0, alen, kbuff, kplusSq);
+                               sumSq(a.values(i), a.pos(i), a.size(i), kbuff, 
kplusSq);
                                c[cix+0] = kbuff._sum;
                                c[cix+1] = kbuff._correction;
                        }
@@ -2265,17 +2240,13 @@ public class LibMatrixAgg
         * @param rl Lower row limit.
         * @param ru Upper row limit.
         */
-       private static void s_uacsqkp(SparseRow[] a, double[] c, int m, int n, 
KahanObject kbuff,
+       private static void s_uacsqkp(SparseBlock a, double[] c, int m, int n, 
KahanObject kbuff,
                                      KahanPlusSq kplusSq, int rl, int ru )
        {
                //compute column aggregates
                for (int i=rl; i<ru; i++) {
-                       SparseRow arow = a[i];
-                       if (arow!=null && !arow.isEmpty()) {
-                               int alen = arow.size();
-                               double[] avals = arow.getValueContainer();
-                               int[] aix = arow.getIndexContainer();
-                               sumSqAgg(avals, c, aix, alen, n, kbuff, 
kplusSq);
+                       if (!a.isEmpty(i)) {
+                               sumSqAgg(a.values(i), c, a.indexes(i), 
a.pos(i), a.size(i), n, kbuff, kplusSq);
                        }
                }
        }
@@ -2290,22 +2261,16 @@ public class LibMatrixAgg
         * @param kbuff
         * @param kplus
         */
-       private static void s_ucumkp( SparseRow[] a, double[] c, int m, int n, 
KahanObject kbuff, KahanPlus kplus )
+       private static void s_ucumkp( SparseBlock a, double[] c, int m, int n, 
KahanObject kbuff, KahanPlus kplus )
        {
                //init current row sum/correction arrays w/ neutral 0
                double[] csums = new double[ 2*n ]; 
 
                //scan once and compute prefix sums
-               for( int i=0, ix=0; i<m; i++, ix+=n )
-               {
-                       SparseRow arow = a[i];
-                       if( arow!=null && !arow.isEmpty() )
-                       {
-                               int alen = arow.size();
-                               double[] avals = arow.getValueContainer();
-                               int[] aix = arow.getIndexContainer();
-                               sumAgg( avals, csums, aix, alen, n, kbuff, 
kplus );
-                       }
+               for( int i=0, ix=0; i<m; i++, ix+=n ) {
+                       if( !a.isEmpty(i) )
+                               sumAgg( a.values(i), csums, a.indexes(i), 
a.pos(i), a.size(i), n, kbuff, kplus );
+
                        //always copy current sum (not sparse-safe)
                        System.arraycopy(csums, 0, c, ix, n);
                }
@@ -2319,7 +2284,7 @@ public class LibMatrixAgg
         * @param m
         * @param n
         */
-       private static void s_ucumm( SparseRow[] a, double[] c, int m, int n )
+       private static void s_ucumm( SparseBlock a, double[] c, int m, int n )
        {
                //init current row prod arrays w/ neutral 1
                double[] cprod = new double[ n ]; 
@@ -2331,15 +2296,14 @@ public class LibMatrixAgg
                //scan once and compute prefix products
                for( int i=0, ix=0; i<m; i++, ix+=n )
                {
-                       SparseRow arow = a[i];
-                       
                        //multiply row of non-zero elements
-                       if( arow!=null && !arow.isEmpty() ) {
-                               int alen = arow.size();
-                               double[] avals = arow.getValueContainer();
-                               int[] aix = arow.getIndexContainer();
-                               productAgg( avals, cprod, aix, 0, alen );
-                               countAgg( avals, cnt, aix, alen );
+                       if( !a.isEmpty(i) ) {
+                               int apos = a.pos(i);
+                               int alen = a.size(i);
+                               int[] aix = a.indexes(i);
+                               double[] avals = a.values(i);
+                               productAgg( avals, cprod, aix, apos, 0, alen );
+                               countAgg( avals, cnt, aix, apos, alen );
                        }
 
                        //correction (not sparse-safe and cumulative)
@@ -2363,7 +2327,7 @@ public class LibMatrixAgg
         * @param init
         * @param builtin
         */
-       private static void s_ucummxx( SparseRow[] a, double[] c, int m, int n, 
double init, Builtin builtin ) 
+       private static void s_ucummxx( SparseBlock a, double[] c, int m, int n, 
double init, Builtin builtin ) 
        {
                //init current row min/max array w/ extreme value 
                double[] cmxx = new double[ n ]; 
@@ -2375,14 +2339,13 @@ public class LibMatrixAgg
                //compute column aggregates min/max
                for( int i=0, ix=0; i<m; i++, ix+=n )
                {
-                       SparseRow arow = a[i];
-                       if( arow!=null && !arow.isEmpty() )
-                       {
-                               int alen = arow.size();
-                               double[] avals = arow.getValueContainer();
-                               int[] aix = arow.getIndexContainer();
-                               builtinAgg( avals, cmxx, aix, alen, builtin );
-                               countAgg( avals, cnt, aix, alen );
+                       if( !a.isEmpty(i) ) {
+                               int apos = a.pos(i);
+                               int alen = a.size(i);
+                               int[] aix = a.indexes(i);
+                               double[] avals = a.values(i);
+                               builtinAgg( avals, cmxx, aix, apos, alen, 
builtin );
+                               countAgg( avals, cnt, aix, apos, alen );
                        }
                        
                        //correction (not sparse-safe and cumulative)
@@ -2406,15 +2369,11 @@ public class LibMatrixAgg
         * @param kbuff
         * @param kplus
         */
-       private static void s_uakptrace( SparseRow[] a, double[] c, int m, int 
n, KahanObject kbuff, KahanPlus kplus, int rl, int ru ) 
+       private static void s_uakptrace( SparseBlock a, double[] c, int m, int 
n, KahanObject kbuff, KahanPlus kplus, int rl, int ru ) 
        {
                for( int i=rl; i<ru; i++ ) {
-                       SparseRow arow = a[i];
-                       if( arow!=null && !arow.isEmpty() ) 
-                       {
-                               double val = arow.get( i );
-                               kplus.execute2(kbuff, val);
-                       }
+                       if( !a.isEmpty(i) ) 
+                               kplus.execute2(kbuff, a.get(i,i));
                }
                c[0] = kbuff._sum;
                c[1] = kbuff._correction;       
@@ -2430,22 +2389,18 @@ public class LibMatrixAgg
         * @param init
         * @param builtin
         */
-       private static void s_uamxx( SparseRow[] a, double[] c, int m, int n, 
double init, Builtin builtin, int rl, int ru )
+       private static void s_uamxx( SparseBlock a, double[] c, int m, int n, 
double init, Builtin builtin, int rl, int ru )
        {
                double ret = init; //keep init val
                for( int i=rl; i<ru; i++ )
                {
-                       SparseRow arow = a[i];
-                       if( arow!=null && !arow.isEmpty() )
-                       {
-                               int alen = arow.size();
-                               double[] avals = arow.getValueContainer();
-                               double lval = builtin(avals, 0, init, alen, 
builtin);
+                       if( !a.isEmpty(i) ) {
+                               double lval = builtin(a.values(i), a.pos(i), 
init, a.size(i), builtin);
                                ret = builtin.execute2(ret, lval);
                        }
                
                        //correction (not sparse-safe)
-                       if( arow==null || arow.size()<n )
+                       if( a.size(i) < n )
                                ret = builtin.execute2(ret, 0); 
                }
                c[0] = ret; 
@@ -2461,22 +2416,18 @@ public class LibMatrixAgg
         * @param init
         * @param builtin
         */
-       private static void s_uarmxx( SparseRow[] a, double[] c, int m, int n, 
double init, Builtin builtin, int rl, int ru ) 
+       private static void s_uarmxx( SparseBlock a, double[] c, int m, int n, 
double init, Builtin builtin, int rl, int ru ) 
        {
                //init result (for empty rows)
                Arrays.fill(c, rl, ru, init); //not sparse-safe
                
                for( int i=rl; i<ru; i++ )
                {
-                       SparseRow arow = a[i];
-                       if( arow!=null && !arow.isEmpty() )
-                       {
-                               int alen = arow.size();
-                               double[] avals = arow.getValueContainer();
-                               c[ i ] = builtin(avals, 0, init, alen, builtin);
-                       }
+                       if( !a.isEmpty(i) )
+                               c[ i ] = builtin(a.values(i), a.pos(i), init, 
a.size(i), builtin);
+               
                        //correction (not sparse-safe)
-                       if( arow==null || arow.size()<n )
+                       if( a.size(i) < n )
                                c[ i ] = builtin.execute2(c[ i ], 0); 
                }
        }
@@ -2491,7 +2442,7 @@ public class LibMatrixAgg
         * @param init
         * @param builtin
         */
-       private static void s_uacmxx( SparseRow[] a, double[] c, int m, int n, 
double init, Builtin builtin, int rl, int ru ) 
+       private static void s_uacmxx( SparseBlock a, double[] c, int m, int n, 
double init, Builtin builtin, int rl, int ru ) 
        {
                //init output (base for incremental agg)
                Arrays.fill(c, init);
@@ -2502,14 +2453,13 @@ public class LibMatrixAgg
                //compute column aggregates min/max
                for( int i=rl; i<ru; i++ )
                {
-                       SparseRow arow = a[i];
-                       if( arow!=null && !arow.isEmpty() )
-                       {
-                               int alen = arow.size();
-                               double[] avals = arow.getValueContainer();
-                               int[] aix = arow.getIndexContainer();
-                               builtinAgg( avals, c, aix, alen, builtin );
-                               countAgg( avals, cnt, aix, alen );
+                       if( !a.isEmpty(i) ) {
+                               int apos = a.pos(i);
+                               int alen = a.size(i);
+                               double[] avals = a.values(i);
+                               int[] aix = a.indexes(i);
+                               builtinAgg( avals, c, aix, apos, alen, builtin 
);
+                               countAgg( avals, cnt, aix, apos, alen );
                        }
                }
                
@@ -2532,19 +2482,18 @@ public class LibMatrixAgg
         * @param init
         * @param builtin
         */
-       private static void s_uarimxx( SparseRow[] a, double[] c, int m, int n, 
double init, Builtin builtin, int rl, int ru ) 
+       private static void s_uarimxx( SparseBlock a, double[] c, int m, int n, 
double init, Builtin builtin, int rl, int ru ) 
        {
                for( int i=rl, cix=rl*2; i<ru; i++, cix+=2 )
                {
-                       SparseRow arow = a[i];
-                       if( arow!=null && !arow.isEmpty() )
-                       {
-                               int alen = arow.size();
-                               double[] avals = arow.getValueContainer();
-                               int[] aix = arow.getIndexContainer();
-                               int maxindex = indexmax(avals, 0, init, alen, 
builtin);
-                               c[cix+0] = (double)aix[maxindex] + 1;
-                               c[cix+1] = avals[maxindex]; //max value
+                       if( !a.isEmpty(i) ) {
+                               int apos = a.pos(i);
+                               int alen = a.size(i);
+                               int[] aix = a.indexes(i);
+                               double[] avals = a.values(i);
+                               int maxindex = indexmax(a.values(i), apos, 
init, alen, builtin);
+                               c[cix+0] = (double)aix[apos+maxindex] + 1;
+                               c[cix+1] = avals[apos+maxindex]; //max value
                                
                                //correction (not sparse-safe)  
                                if(alen < n && (builtin.execute2( 0, c[cix+1] ) 
== 1))
@@ -2576,26 +2525,26 @@ public class LibMatrixAgg
         * @param init
         * @param builtin
         */
-       private static void s_uarimin( SparseRow[] a, double[] c, int m, int n, 
double init, Builtin builtin, int rl, int ru ) 
+       private static void s_uarimin( SparseBlock a, double[] c, int m, int n, 
double init, Builtin builtin, int rl, int ru ) 
        {
                for( int i=rl, cix=rl*2; i<ru; i++, cix+=2 )
                {
-                       SparseRow arow = a[i];
-                       if( arow!=null && !arow.isEmpty() )
+                       if( !a.isEmpty(i) )
                        {
-                               int alen = arow.size();
-                               double[] avals = arow.getValueContainer();
-                               int[] aix = arow.getIndexContainer();
-                               int minindex = indexmin(avals, 0, init, alen, 
builtin);
-                               c[cix+0] = (double)aix[minindex] + 1;
-                               c[cix+1] = avals[minindex]; //min value among 
non-zeros
+                               int apos = a.pos(i);
+                               int alen = a.size(i);
+                               int[] aix = a.indexes(i);
+                               double[] avals = a.values(i);
+                               int minindex = indexmin(avals, apos, init, 
alen, builtin);
+                               c[cix+0] = (double)aix[apos+minindex] + 1;
+                               c[cix+1] = avals[apos+minindex]; //min value 
among non-zeros
                                
                                //correction (not sparse-safe)  
                                if(alen < n && (builtin.execute2( 0, c[cix+1] ) 
== 1))
                                {
                                        int ix = n-1; //find last 0 value
                                        for( int j=alen-1; j>=0; j--, ix-- )
-                                               if( aix[j]!=ix )
+                                               if( aix[apos+j]!=ix )
                                                        break;
                                        c[cix+0] = ix + 1; //min index (last)
                                        c[cix+1] = 0; //min value
@@ -2620,7 +2569,7 @@ public class LibMatrixAgg
         * @param kbuff
         * @param kplus
         */
-       private static void s_uamean( SparseRow[] a, double[] c, int m, int n, 
KahanObject kbuff, Mean kmean, int rl, int ru )
+       private static void s_uamean( SparseBlock a, double[] c, int m, int n, 
KahanObject kbuff, Mean kmean, int rl, int ru )
        {
                int len = (ru-rl) * n;
                int count = 0;
@@ -2629,17 +2578,14 @@ public class LibMatrixAgg
                //note: before aggregate computation in order to
                //exploit 0 sum (noop) and better numerical stability
                for( int i=rl; i<ru; i++ )
-                       count += (a[i]==null)? n : n-a[i].size();
+                       count += (a.isEmpty(i)) ? n : n-a.size(i);
                
                //compute aggregate mean
                for( int i=rl; i<ru; i++ )
                {
-                       SparseRow arow = a[i];
-                       if( arow!=null && !arow.isEmpty() )
-                       {
-                               int alen = arow.size();
-                               double[] avals = arow.getValueContainer();
-                               mean(avals, 0, alen, count, kbuff, kmean);
+                       if( !a.isEmpty(i) ) {
+                               int alen = a.size(i);
+                               mean(a.values(i), a.pos(i), alen, count, kbuff, 
kmean);
                                count += alen;
                        }
                }
@@ -2662,22 +2608,18 @@ public class LibMatrixAgg
         * @param kbuff
         * @param kplus
         */
-       private static void s_uarmean( SparseRow[] a, double[] c, int m, int n, 
KahanObject kbuff, Mean kmean, int rl, int ru ) 
+       private static void s_uarmean( SparseBlock a, double[] c, int m, int n, 
KahanObject kbuff, Mean kmean, int rl, int ru ) 
        {
                for( int i=rl, cix=rl*3; i<ru; i++, cix+=3 )
                {
                        //correction remaining tuples (not sparse-safe)
                        //note: before aggregate computation in order to
                        //exploit 0 sum (noop) and better numerical stability
-                       int count = (a[i]==null)? n : n-a[i].size();
+                       int count = (a.isEmpty(i)) ? n : n-a.size(i);
                        
                        kbuff.set(0, 0); //reset buffer
-                       SparseRow arow = a[i];
-                       if( arow!=null && !arow.isEmpty() )
-                       {
-                               int alen = arow.size();
-                               double[] avals = arow.getValueContainer();
-                               mean(avals, 0, alen, count, kbuff, kmean);
+                       if( !a.isEmpty(i) ) {
+                               mean(a.values(i), a.pos(i), a.size(i), count, 
kbuff, kmean);
                        }
                        
                        //OLD VERSION: correction remaining tuples (not 
sparse-safe)
@@ -2701,7 +2643,7 @@ public class LibMatrixAgg
         * @param kbuff
         * @param kplus
         */
-       private static void s_uacmean( SparseRow[] a, double[] c, int m, int n, 
KahanObject kbuff, Mean kmean, int rl, int ru ) 
+       private static void s_uacmean( SparseBlock a, double[] c, int m, int n, 
KahanObject kbuff, Mean kmean, int rl, int ru ) 
        {
                //correction remaining tuples (not sparse-safe)
                //note: before aggregate computation in order to
@@ -2709,26 +2651,16 @@ public class LibMatrixAgg
                Arrays.fill(c, n, n*2, ru-rl);
                for( int i=rl; i<ru; i++ ) 
                {
-                       SparseRow arow = a[i];
-                       if( arow!=null && !arow.isEmpty() )
-                       {
-                               int alen = arow.size();
-                               double[] avals = arow.getValueContainer();
-                               int[] aix = arow.getIndexContainer();
-                               countDisAgg( avals, c, aix, n, alen );
+                       if( !a.isEmpty(i) ) {
+                               countDisAgg( a.values(i), c, a.indexes(i), 
a.pos(i), n, a.size(i) );
                        }
                } 
                
                //compute column aggregate means
                for( int i=rl; i<ru; i++ )
                {
-                       SparseRow arow = a[i];
-                       if( arow!=null && !arow.isEmpty() )
-                       {
-                               int alen = arow.size();
-                               double[] avals = arow.getValueContainer();
-                               int[] aix = arow.getIndexContainer();
-                               meanAgg( avals, c, aix, alen, n, kbuff, kmean );
+                       if( !a.isEmpty(i) ) {
+                               meanAgg( a.values(i), c, a.indexes(i), 
a.pos(i), a.size(i), n, kbuff, kmean );
                        }
                }
        }
@@ -2748,23 +2680,19 @@ public class LibMatrixAgg
         * @param rl Lower row limit.
         * @param ru Upper row limit.
         */
-       private static void s_uavar(SparseRow[] a, double[] c, int m, int n, 
CM_COV_Object cbuff, CM cm,
+       private static void s_uavar(SparseBlock a, double[] c, int m, int n, 
CM_COV_Object cbuff, CM cm,
                                    int rl, int ru) throws DMLRuntimeException
        {
                // compute and store count of empty cells before aggregation
                int count = 0;
                for (int i=rl; i<ru; i++)
-                       count += (a[i]==null) ? n : n-a[i].size();
+                       count += (a.isEmpty(i)) ? n : n-a.size(i);
                cbuff.w = count;
 
                // calculate aggregated variance (only using non-empty cells)
                for (int i=rl; i<ru; i++) {
-                       SparseRow arow = a[i];
-                       if (arow!=null && !arow.isEmpty()) {
-                               int alen = arow.size();
-                               double[] avals = arow.getValueContainer();
-                               var(avals, 0, alen, cbuff, cm);
-                       }
+                       if (!a.isEmpty(i))
+                               var(a.values(i), a.pos(i), a.size(i), cbuff, 
cm);
                }
 
                // store results: { var | mean, count, m2 correction, mean 
correction }
@@ -2790,7 +2718,7 @@ public class LibMatrixAgg
         * @param rl Lower row limit.
         * @param ru Upper row limit.
         */
-       private static void s_uarvar(SparseRow[] a, double[] c, int m, int n, 
CM_COV_Object cbuff, CM cm,
+       private static void s_uarvar(SparseBlock a, double[] c, int m, int n, 
CM_COV_Object cbuff, CM cm,
                                     int rl, int ru) throws DMLRuntimeException
        {
                // calculate aggregated variance for each row
@@ -2799,14 +2727,11 @@ public class LibMatrixAgg
 
                        // compute and store count of empty cells in this row
                        // before aggregation
-                       int count = (a[i] == null) ? n : n-a[i].size();
+                       int count = (a.isEmpty(i)) ? n : n-a.size(i);
                        cbuff.w = count;
 
-                       SparseRow arow = a[i];
-                       if (arow != null && !arow.isEmpty()) {
-                               int alen = arow.size();
-                               double[] avals = arow.getValueContainer();
-                               var(avals, 0, alen, cbuff, cm);
+                       if (!a.isEmpty(i)) {
+                               var(a.values(i), a.pos(i), a.size(i), cbuff, 
cm);
                        }
 
                        // store results: { var | mean, count, m2 correction, 
mean correction }
@@ -2833,7 +2758,7 @@ public class LibMatrixAgg
         * @param rl Lower row limit.
         * @param ru Upper row limit.
         */
-       private static void s_uacvar(SparseRow[] a, double[] c, int m, int n, 
CM_COV_Object cbuff, CM cm,
+       private static void s_uacvar(SparseBlock a, double[] c, int m, int n, 
CM_COV_Object cbuff, CM cm,
                                     int rl, int ru) throws DMLRuntimeException
        {
                // compute and store counts of empty cells per column before 
aggregation
@@ -2842,23 +2767,16 @@ public class LibMatrixAgg
                Arrays.fill(c, n*2, n*3, ru-rl); // counts stored in 3rd row
                // - then subtract one from the column count for each dense 
value in the column
                for (int i=rl; i<ru; i++) {
-                       SparseRow arow = a[i];
-                       if (arow!=null && !arow.isEmpty()) {
-                               int alen = arow.size();
-                               double[] avals = arow.getValueContainer();
-                               int[] aix = arow.getIndexContainer();
-                               countDisAgg(avals, c, aix, n*2, alen); // 
counts stored in 3rd row
+                       if (!a.isEmpty(i)) {
+                               // counts stored in 3rd row
+                               countDisAgg(a.values(i), c, a.indexes(i), 
a.pos(i), n*2, a.size(i)); 
                        }
                }
 
                // calculate aggregated variance for each column
                for (int i=rl; i<ru; i++) {
-                       SparseRow arow = a[i];
-                       if (arow != null && !arow.isEmpty()) {
-                               int alen = arow.size();
-                               double[] avals = arow.getValueContainer();
-                               int[] aix = arow.getIndexContainer();
-                               varAgg(avals, c, aix, alen, n, cbuff, cm);
+                       if (!a.isEmpty(i)) {
+                               varAgg(a.values(i), c, a.indexes(i), a.pos(i), 
a.size(i), n, cbuff, cm);
                        }
                }
        }
@@ -2871,17 +2789,14 @@ public class LibMatrixAgg
         * @param m
         * @param n
         */
-       private static void s_uam( SparseRow[] a, double[] c, int m, int n, int 
rl, int ru )
+       private static void s_uam( SparseBlock a, double[] c, int m, int n, int 
rl, int ru )
        {
                double ret = 1;
                for( int i=rl; i<ru; i++ )
                {
-                       SparseRow arow = a[i];
-                       if( arow!=null && !arow.isEmpty() )
-                       {
-                               int alen = arow.size();
-                               double[] avals = arow.getValueContainer();
-                               ret *= product(avals, 0, alen);
+                       if( !a.isEmpty(i) ) {
+                               int alen = a.size(i);
+                               ret *= product(a.values(i), 0, alen);
                                ret *= (alen<n) ? 0 : 1;
                        }
                        
@@ -2919,10 +2834,10 @@ public class LibMatrixAgg
         * Aggregated summation using the Kahan summation algorithm with
         * the KahanPlus function.
         */
-       private static void sumAgg(double[] a, double[] c, int[] ai, final int 
len, final int n,
+       private static void sumAgg(double[] a, double[] c, int[] aix, int ai, 
final int len, final int n,
                                   KahanObject kbuff, KahanPlus kplus)
        {
-               sumAggWithFn(a, c, ai, len, n, kbuff, kplus);
+               sumAggWithFn(a, c, aix, ai, len, n, kbuff, kplus);
        }
 
        /**
@@ -2949,10 +2864,10 @@ public class LibMatrixAgg
         * Aggregated summation of squared values using the Kahan
         * summation algorithm with the KahanPlusSq function.
         */
-       private static void sumSqAgg(double[] a, double[] c, int[] ai, final 
int len, final int n,
+       private static void sumSqAgg(double[] a, double[] c, int[] aix, int ai, 
final int len, final int n,
                                     KahanObject kbuff, KahanPlusSq kplusSq)
        {
-               sumAggWithFn(a, c, ai, len, n, kbuff, kplusSq);
+               sumAggWithFn(a, c, aix, ai, len, n, kbuff, kplusSq);
        }
 
        /**
@@ -3017,15 +2932,15 @@ public class LibMatrixAgg
         *              algorithm.
         * @param kfunc A KahanFunction object to perform the summation.
         */
-       private static void sumAggWithFn(double[] a, double[] c, int[] ai, 
final int len, final int n,
+       private static void sumAggWithFn(double[] a, double[] c, int[] aix, int 
ai, final int len, final int n,
                                         KahanObject kbuff, KahanFunction kfunc)
        {
-               for (int i=0; i<len; i++) {
-                       kbuff._sum = c[ai[i]];
-                       kbuff._correction = c[ai[i]+n];
+               for (int i=ai; i<ai+len; i++) {
+                       kbuff._sum = c[aix[i]];
+                       kbuff._correction = c[aix[i]+n];
                        kfunc.execute2(kbuff, a[i]);
-                       c[ai[i]] = kbuff._sum;
-                       c[ai[i]+n] = kbuff._correction;
+                       c[aix[i]] = kbuff._sum;
+                       c[aix[i]+n] = kbuff._correction;
                }
        }
        /**
@@ -3081,13 +2996,13 @@ public class LibMatrixAgg
         * @param ci
         * @param len
         */
-       private static void productAgg( double[] a, double[] c, int[] ai, int 
ci, final int len )
+       private static void productAgg( double[] a, double[] c, int[] aix, int 
ai, int ci, final int len )
        {
                //always w/ NAN_AWARENESS: product without early abort; 
                //even if val is 0, it might turn into NaN.
                //(early abort would require column-flags and branches)
-               for( int i=0; i<len; i++ )
-                       c[ ci + ai[i] ] *= a[ i ];      
+               for( int i=ai; i<ai+len; i++ )
+                       c[ ci + aix[i] ] *= a[ i ];     
        }
        
        /**
@@ -3140,17 +3055,17 @@ public class LibMatrixAgg
         * @param kbuff
         * @param kplus
         */
-       private static void meanAgg( double[] a, double[] c, int[] ai, final 
int len, final int n, KahanObject kbuff, Mean mean )
+       private static void meanAgg( double[] a, double[] c, int[] aix, int ai, 
final int len, final int n, KahanObject kbuff, Mean mean )
        {
-               for( int i=0; i<len; i++ )
+               for( int i=ai; i<ai+len; i++ )
                {
-                       kbuff._sum        = c[ai[i]];
-                       double count      = c[ai[i]+n] + 1;
-                       kbuff._correction = c[ai[i]+2*n];
+                       kbuff._sum        = c[aix[i]];
+                       double count      = c[aix[i]+n] + 1;
+                       kbuff._correction = c[aix[i]+2*n];
                        mean.execute2(kbuff, a[ i ], count);
-                       c[ai[i]]     = kbuff._sum;
-                       c[ai[i]+n]   = count;
-                       c[ai[i]+2*n] = kbuff._correction;
+                       c[aix[i]]     = kbuff._sum;
+                       c[aix[i]+n]   = count;
+                       c[aix[i]+2*n] = kbuff._correction;
                }
        }
 
@@ -3222,24 +3137,24 @@ public class LibMatrixAgg
         * @param cm A CM object of type Variance to perform the variance
         *           calculation.
         */
-       private static void varAgg(double[] a, double[] c, int[] ai, final int 
len, final int n,
+       private static void varAgg(double[] a, double[] c, int[] aix, int ai, 
final int len, final int n,
                                   CM_COV_Object cbuff, CM cm) throws 
DMLRuntimeException
        {
-               for (int i=0; i<len; i++) {
+               for (int i=ai; i<ai+len; i++) {
                        // extract current values: { var | mean, count, m2 
correction, mean correction }
-                       cbuff.w = c[ai[i]+2*n]; // count
-                       cbuff.m2._sum = c[ai[i]] * (cbuff.w - 1); // m2 = var * 
(n - 1)
-                       cbuff.mean._sum = c[ai[i]+n]; // mean
-                       cbuff.m2._correction = c[ai[i]+3*n];
-                       cbuff.mean._correction = c[ai[i]+4*n];
+                       cbuff.w = c[aix[i]+2*n]; // count
+                       cbuff.m2._sum = c[aix[i]] * (cbuff.w - 1); // m2 = var 
* (n - 1)
+                       cbuff.mean._sum = c[aix[i]+n]; // mean
+                       cbuff.m2._correction = c[aix[i]+3*n];
+                       cbuff.mean._correction = c[aix[i]+4*n];
                        // calculate incremental aggregated variance
                        cbuff = (CM_COV_Object) cm.execute(cbuff, a[i]);
                        // store updated values: { var | mean, count, m2 
correction, mean correction }
-                       c[ai[i]] = 
cbuff.getRequiredResult(AggregateOperationTypes.VARIANCE);
-                       c[ai[i]+n] = cbuff.mean._sum;
-                       c[ai[i]+2*n] = cbuff.w;
-                       c[ai[i]+3*n] = cbuff.m2._correction;
-                       c[ai[i]+4*n] = cbuff.mean._correction;
+                       c[aix[i]] = 
cbuff.getRequiredResult(AggregateOperationTypes.VARIANCE);
+                       c[aix[i]+n] = cbuff.mean._sum;
+                       c[aix[i]+2*n] = cbuff.w;
+                       c[aix[i]+3*n] = cbuff.m2._correction;
+                       c[aix[i]+4*n] = cbuff.mean._correction;
                }
        }
 
@@ -3285,10 +3200,10 @@ public class LibMatrixAgg
         * @param len
         * @param aggop
         */
-       private static void builtinAgg( double[] a, double[] c, int[] ai, final 
int len, Builtin aggop ) 
+       private static void builtinAgg( double[] a, double[] c, int[] aix, int 
ai, final int len, Builtin aggop ) 
        {
-               for( int i=0; i<len; i++ )
-                       c[ ai[i] ] = aggop.execute2( c[ ai[i] ], a[ i ] );
+               for( int i=ai; i<ai+len; i++ )
+                       c[ aix[i] ] = aggop.execute2( c[ aix[i] ], a[ i ] );
        }
        
        /**
@@ -3342,47 +3257,47 @@ public class LibMatrixAgg
         * @param ai
         * @param len
         */
-       private static void countAgg( double[] a, int[] c, int[] ai, final int 
len ) 
+       private static void countAgg( double[] a, int[] c, int[] aix, int ai, 
final int len ) 
        {
                final int bn = len%8;
                
                //compute rest, not aligned to 8-block
-               for( int i=0; i<bn; i++ )
-                       c[ ai[i] ]++;
+               for( int i=ai; i<ai+bn; i++ )
+                       c[ aix[i] ]++;
                
                //unrolled 8-block (for better instruction level parallelism)
-               for( int i=bn; i<len; i+=8 )
+               for( int i=ai+bn; i<ai+len; i+=8 )
                {
-                       c[ ai[ i+0 ] ] ++;
-                       c[ ai[ i+1 ] ] ++;
-                       c[ ai[ i+2 ] ] ++;
-                       c[ ai[ i+3 ] ] ++;
-                       c[ ai[ i+4 ] ] ++;
-                       c[ ai[ i+5 ] ] ++;
-                       c[ ai[ i+6 ] ] ++;
-                       c[ ai[ i+7 ] ] ++;
+                       c[ aix[ i+0 ] ] ++;
+                       c[ aix[ i+1 ] ] ++;
+                       c[ aix[ i+2 ] ] ++;
+                       c[ aix[ i+3 ] ] ++;
+                       c[ aix[ i+4 ] ] ++;
+                       c[ aix[ i+5 ] ] ++;
+                       c[ aix[ i+6 ] ] ++;
+                       c[ aix[ i+7 ] ] ++;
                }
        }
        
-       private static void countDisAgg( double[] a, double[] c, int[] ai, 
final int ci, final int len ) 
+       private static void countDisAgg( double[] a, double[] c, int[] aix, int 
ai, final int ci, final int len ) 
        {
                final int bn = len%8;
                
                //compute rest, not aligned to 8-block
-               for( int i=0; i<bn; i++ )
-                       c[ ci+ai[i] ]--;
+               for( int i=ai; i<ai+bn; i++ )
+                       c[ ci+aix[i] ]--;
                
                //unrolled 8-block (for better instruction level parallelism)
-               for( int i=bn; i<len; i+=8 )
+               for( int i=ai+bn; i<ai+len; i+=8 )
                {
-                       c[ ci+ai[ i+0 ] ] --;
-                       c[ ci+ai[ i+1 ] ] --;
-                       c[ ci+ai[ i+2 ] ] --;
-                       c[ ci+ai[ i+3 ] ] --;
-                       c[ ci+ai[ i+4 ] ] --;
-                       c[ ci+ai[ i+5 ] ] --;
-                       c[ ci+ai[ i+6 ] ] --;
-                       c[ ci+ai[ i+7 ] ] --;
+                       c[ ci+aix[ i+0 ] ] --;
+                       c[ ci+aix[ i+1 ] ] --;
+                       c[ ci+aix[ i+2 ] ] --;
+                       c[ ci+aix[ i+3 ] ] --;
+                       c[ ci+aix[ i+4 ] ] --;
+                       c[ ci+aix[ i+5 ] ] --;
+                       c[ ci+aix[ i+6 ] ] --;
+                       c[ ci+aix[ i+7 ] ] --;
                }
        }
        

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/8ba0fdcc/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixBincell.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixBincell.java 
b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixBincell.java
index 1147c5e..5428c96 100644
--- a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixBincell.java
+++ b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixBincell.java
@@ -264,25 +264,22 @@ public class LibMatrixBincell
                                //both sparse blocks existing
                                if(m1.sparseBlock!=null && m2.sparseBlock!=null)
                                {
+                                       SparseBlock lsblock = m1.sparseBlock;
+                                       SparseBlock rsblock = m2.sparseBlock;
+                                       
                                        for(int r=0; r<rlen; r++)
                                        {
-                                               SparseRow lrow = 
(m1.sparseBlock.length>r && m1.sparseBlock[r]!=null) ? m1.sparseBlock[r] : 
null; 
-                                               SparseRow rrow = 
(m2.sparseBlock.length>r && m2.sparseBlock[r]!=null) ? m2.sparseBlock[r] : 
null; 
-                                               
-                                               if( lrow!=null && rrow!=null)
-                                               {
-                                                       
mergeForSparseBinary(op, lrow.getValueContainer(), lrow.getIndexContainer(), 
lrow.size(),
-                                                                       
rrow.getValueContainer(), rrow.getIndexContainer(), rrow.size(), r, ret);       
+                                               if( !lsblock.isEmpty(r) && 
!rsblock.isEmpty(r) ) {
+                                                       
mergeForSparseBinary(op, lsblock.values(r), lsblock.indexes(r), lsblock.pos(r), 
lsblock.size(r),
+                                                                       
rsblock.values(r), rsblock.indexes(r), rsblock.pos(r), rsblock.size(r), r, 
ret);        
                                                }
-                                               else if( rrow!=null )
-                                               {
-                                                       
appendRightForSparseBinary(op, rrow.getValueContainer(), 
-                                                                       
rrow.getIndexContainer(), rrow.size(), 0, r, ret);
+                                               else if( !rsblock.isEmpty(r) ) {
+                                                       
appendRightForSparseBinary(op, rsblock.values(r), rsblock.indexes(r), 
+                                                                       
rsblock.pos(r), rsblock.size(r), 0, r, ret);
                                                }
-                                               else if( lrow!=null )
-                                               {
-                                                       
appendLeftForSparseBinary(op, lrow.getValueContainer(), 
-                                                                       
lrow.getIndexContainer(), lrow.size(), 0, r, ret);
+                                               else if( !lsblock.isEmpty(r) ){
+                                                       
appendLeftForSparseBinary(op, lsblock.values(r), lsblock.indexes(r), 
+                                                                       
lsblock.pos(r), lsblock.size(r), 0, r, ret);
                                                }
                                                
                                                // do nothing if both not 
existing
@@ -291,21 +288,25 @@ public class LibMatrixBincell
                                //right sparse block existing
                                else if( m2.sparseBlock!=null )
                                {
-                                       for(int r=0; r<Math.min(rlen, 
m2.sparseBlock.length); r++)
-                                               if(m2.sparseBlock[r]!=null)
+                                       SparseBlock rsblock = m2.sparseBlock;
+                                       
+                                       for(int r=0; r<Math.min(rlen, 
rsblock.numRows()); r++)
+                                               if( !rsblock.isEmpty(r) )
                                                {
-                                                       
appendRightForSparseBinary(op, m2.sparseBlock[r].getValueContainer(), 
-                                                                       
m2.sparseBlock[r].getIndexContainer(), m2.sparseBlock[r].size(), 0, r, ret);
+                                                       
appendRightForSparseBinary(op, rsblock.values(r), rsblock.indexes(r), 
+                                                                       
rsblock.pos(r), rsblock.size(r), 0, r, ret);
                                                }
                                }
                                //left sparse block existing
                                else
                                {
+                                       SparseBlock lsblock = m1.sparseBlock;
+                                       
                                        for(int r=0; r<rlen; r++)
-                                               if( m1.sparseBlock[r]!=null )
+                                               if( !lsblock.isEmpty(r) )
                                                {
-                                                       
appendLeftForSparseBinary(op, m1.sparseBlock[r].getValueContainer(), 
-                                                                       
m1.sparseBlock[r].getIndexContainer(), m1.sparseBlock[r].size(), 0, r, ret);
+                                                       
appendLeftForSparseBinary(op, lsblock.values(r), lsblock.indexes(r), 
+                                                                       
lsblock.pos(r), lsblock.size(r), 0, r, ret);
                                                }
                                }
                        }
@@ -320,9 +321,6 @@ public class LibMatrixBincell
                                double[] c = ret.denseBlock;
                                
                                //1) process left input: assignment
-                               int alen;
-                               int[] aix;
-                               double[] avals;
                                
                                if( m1.sparse ) //SPARSE left
                                {
@@ -330,14 +328,16 @@ public class LibMatrixBincell
                                        
                                        if( m1.sparseBlock != null )
                                        {
+                                               SparseBlock a = m1.sparseBlock;
+                                               
                                                for( int i=0, ix=0; i<m; i++, 
ix+=n ) {
-                                                       SparseRow arow = 
m1.sparseBlock[i];
-                                                       if( arow != null && 
!arow.isEmpty() )
+                                                       if( !a.isEmpty(i) )
                                                        {
-                                                               alen = 
arow.size();
-                                                               aix = 
arow.getIndexContainer();
-                                                               avals = 
arow.getValueContainer();
-                                                               for(int k = 0; 
k < alen; k++) 
+                                                               int apos = 
a.pos(i);
+                                                               int alen = 
a.size(i);
+                                                               int[] aix = 
a.indexes(i);
+                                                               double[] avals 
= a.values(i);
+                                                               for(int k = 
apos; k < apos+alen; k++) 
                                                                        
c[ix+aix[k]] = avals[k];
                                                        }
                                                }
@@ -356,14 +356,15 @@ public class LibMatrixBincell
                                {                               
                                        if(m2.sparseBlock!=null)
                                        {
+                                               SparseBlock a = m2.sparseBlock;
+                                               
                                                for( int i=0, ix=0; i<m; i++, 
ix+=n ) {
-                                                       SparseRow arow = 
m2.sparseBlock[i];
-                                                       if( arow != null && 
!arow.isEmpty() )
-                                                       {
-                                                               alen = 
arow.size();
-                                                               aix = 
arow.getIndexContainer();
-                                                               avals = 
arow.getValueContainer();
-                                                               for(int k = 0; 
k < alen; k++) 
+                                                       if( !a.isEmpty(i) ) {
+                                                               int apos = 
a.pos(i);
+                                                               int alen = 
a.size(i);
+                                                               int[] aix = 
a.indexes(i);
+                                                               double[] avals 
= a.values(i);
+                                                               for(int k = 
apos; k < apos+alen; k++) 
                                                                        
c[ix+aix[k]] = op.fn.execute(c[ix+aix[k]], avals[k]);
                                                        }
                                                }       
@@ -509,7 +510,7 @@ public class LibMatrixBincell
                
                int rlen = m1.rlen;
                int clen = m1.clen;
-               SparseRow[] a = m1.sparseBlock;
+               SparseBlock a = m1.sparseBlock;
                BinaryAccessType atype = getBinaryAccessType(m1, m2);
                
                //early abort on skip and empty
@@ -525,28 +526,28 @@ public class LibMatrixBincell
                        for( int i=0; i<rlen; i++ )
                        {
                                double v2 = m2.quickGetValue(i, 0);
-                               SparseRow arow = (a==null) ? null : a[i];
                                
-                               if( (skipEmpty && (arow==null || arow.isEmpty() 
|| v2 == 0 ))
-                                       || ((arow==null || arow.isEmpty()) && 
v2 == 0) )
+                               if( (skipEmpty && (a==null || a.isEmpty(i) || 
v2 == 0 ))
+                                       || ((a==null || a.isEmpty(i)) && v2 == 
0) )
                                {
                                        continue; //skip empty rows
                                }
                                        
                                if( isMultiply && v2==1 ) //ROW COPY
                                {
-                                       if( arow != null && !arow.isEmpty()  )
-                                               ret.appendRow(i, arow);
+                                       if( a != null && !a.isEmpty(i)  )
+                                               ret.appendRow(i, a.get(i));
                                }
                                else //GENERAL CASE
                                {
                                        int lastIx = -1;
-                                       if( arow != null && !arow.isEmpty() ) 
+                                       if( a != null && !a.isEmpty(i) ) 
                                        {
-                                               int alen = arow.size();
-                                               int[] aix = 
arow.getIndexContainer();
-                                               double[] avals = 
arow.getValueContainer();
-                                               for( int j=0; j<alen; j++ )
+                                               int apos = a.pos(i);
+                                               int alen = a.size(i);
+                                               int[] aix = a.indexes(i);
+                                               double[] avals = a.values(i);
+                                               for( int j=apos; j<apos+alen; 
j++ )
                                                {
                                                        //empty left
                                                        for( int k = lastIx+1; 
k<aix[j]; k++ ){
@@ -572,18 +573,17 @@ public class LibMatrixBincell
                {
                        for( int i=0; i<rlen; i++ )
                        {
-                               SparseRow arow = (a==null) ? null : a[i];
-                               
-                               if( skipEmpty && (arow==null || arow.isEmpty()) 
)
+                               if( skipEmpty && (a==null || a.isEmpty(i)) )
                                        continue; //skip empty rows
                                        
                                int lastIx = -1;
-                               if( arow != null && !arow.isEmpty() ) 
+                               if( a!=null && !a.isEmpty(i) ) 
                                {
-                                       int alen = arow.size();
-                                       int[] aix = arow.getIndexContainer();
-                                       double[] avals = 
arow.getValueContainer();
-                                       for( int j=0; j<alen; j++ )
+                                       int apos = a.pos(i);
+                                       int alen = a.size(i);
+                                       int[] aix = a.indexes(i);
+                                       double[] avals = a.values(i);
+                                       for( int j=apos; j<apos+alen; j++ )
                                        {
                                                //empty left
                                                for( int k = lastIx+1; 
k<aix[j]; k++ ){
@@ -672,12 +672,12 @@ public class LibMatrixBincell
                        if( m2.sparse && isMultiply ) //SPARSE *
                        {
                                //note: sparse block guaranteed to be allocated 
(otherwise early about)
-                               SparseRow brow = m2.sparseBlock[0];
-                               if( brow != null && !brow.isEmpty() ) 
+                               SparseBlock b = m2.sparseBlock;
+                               if( !b.isEmpty(0) ) 
                                {
-                                       int blen = brow.size();
-                                       int[] bix = brow.getIndexContainer();
-                                       double[] bvals = 
brow.getValueContainer();
+                                       int blen = b.size(0); //always pos 0
+                                       int[] bix = b.indexes(0);
+                                       double[] bvals = b.values(0);
                                        for( int i=0; i<rlen; i++ ) {
                                                //for each row iterate only 
over non-zeros elements in rhs
                                                for( int j=0; j<blen; j++ ) {
@@ -921,15 +921,16 @@ public class LibMatrixBincell
                {       
                        //allocate sparse row structure
                        ret.allocateSparseRowsBlock();
-                       SparseRow[] a = m1.sparseBlock;
-                       SparseRow[] c = ret.sparseBlock;
+                       SparseBlock a = m1.sparseBlock;
+                       SparseBlock c = ret.sparseBlock;
                        
-                       for(int r=0; r<Math.min(m1.rlen, 
m1.sparseBlock.length); r++) {
-                               if( a[r]!=null && !a[r].isEmpty() )
+                       for(int r=0; r<Math.min(m1.rlen, 
m1.sparseBlock.numRows()); r++) {
+                               if( !a.isEmpty(r) )
                                {
-                                       int alen = a[r].size();
-                                       int[] aix = a[r].getIndexContainer();
-                                       double[] avals = 
a[r].getValueContainer();
+                                       int apos = a.pos(r);
+                                       int alen = a.size(r);
+                                       int[] aix = a.indexes(r);
+                                       double[] avals = a.values(r);
                                        
                                        if( copyOnes ) //SPECIAL CASE: e.g., (X 
!= 0) 
                                        {
@@ -940,12 +941,12 @@ public class LibMatrixBincell
                                                //memcopy/memset of indexes and 
values
                                                //note: currently we do a safe 
copy of values because in special cases there
                                                //might exist zeros in a 
sparserow and we need to ensure result correctness
-                                               System.arraycopy(aix, 0, 
crow.getIndexContainer(), 0, alen);
+                                               System.arraycopy(aix, apos, 
crow.indexes(), 0, alen);
                                                
//Arrays.fill(crow.getValueContainer(), 0, alen, 1);
-                                               double[] cvals = 
crow.getValueContainer();
+                                               double[] cvals = crow.values();
                                                for(int j=0; j<alen; j++)
-                                                       cvals[j] = (avals[j] != 
0) ? 1 : 0;
-                                               c[r] = crow;
+                                                       cvals[j] = 
(avals[apos+j] != 0) ? 1 : 0;
+                                               c.set(r, crow);
                                                ret.nonZeros+=alen;
                                        }
                                        else //GENERAL CASE
@@ -954,7 +955,9 @@ public class LibMatrixBincell
                                                if( op.fn instanceof Multiply 
|| op.fn instanceof Multiply2 
                                                        || op.fn instanceof 
Power2  )
                                                {
-                                                       c[r] = new 
SparseRow(alen);
+                                                       c.allocate(r, alen, -1);
+                                                       //TODO perf sparse block
+                                                       //c[r] = new 
SparseRow(alen);
                                                }
                                                
                                                for(int j=0; j<alen; j++) {
@@ -1012,7 +1015,7 @@ public class LibMatrixBincell
                {
                        ret.allocateDenseBlock();
                        
-                       SparseRow[] a = m1.sparseBlock;
+                       SparseBlock a = m1.sparseBlock;
                        double[] c = ret.denseBlock;                    
                        int m = m1.rlen;
                        int n = m1.clen;
@@ -1024,12 +1027,12 @@ public class LibMatrixBincell
                        //compute non-zero input values
                        for(int i=0, cix=0; i<m; i++, cix+=n) 
                        {
-                               if( a[i]!=null && !a[i].isEmpty() )
-                               {
-                                       int alen = a[i].size();
-                                       int[] aix = a[i].getIndexContainer();
-                                       double[] avals = 
a[i].getValueContainer();
-                                       for(int j=0; j<alen; j++) {
+                               if( !a.isEmpty(i) ) {
+                                       int apos = a.pos(i);
+                                       int alen = a.size(i);
+                                       int[] aix = a.indexes(i);
+                                       double[] avals = a.values(i);
+                                       for(int j=apos; j<apos+alen; j++) {
                                                double val = 
op.executeScalar(avals[j]);
                                                c[ cix+aix[j] ] = val;
                                        }
@@ -1087,72 +1090,76 @@ public class LibMatrixBincell
                        if(m2.sparseBlock!=null)
                                m2.allocateSparseRowsBlock(false);
                        
-                       if(m1ret.sparseBlock!=null && m2.sparseBlock!=null)
+                       SparseBlock c = m1ret.sparseBlock;
+                       SparseBlock b = m2.sparseBlock;
+                       
+                       if( c!=null && b!=null )
                        {
                                for(int r=0; r<rlen; r++)
                                {
-                                       if(m1ret.sparseBlock[r]==null && 
m2.sparseBlock[r]==null)
+                                       if(c.isEmpty(r) && b.isEmpty(r))
                                                continue;
                                        
-                                       if(m2.sparseBlock[r]==null)
+                                       if( b.isEmpty(r) )
                                        {
-                                               double[] 
values=m1ret.sparseBlock[r].getValueContainer();
-                                               for(int i=0; 
i<m1ret.sparseBlock[r].size(); i++)
+                                               int apos = c.pos(r);
+                                               int alen = c.size(r);
+                                               double[] values=c.values(r);
+                                               for(int i=apos; i<apos+alen; 
i++)
                                                        
values[i]=op.fn.execute(values[i], 0);
                                        }else
                                        {
                                                int estimateSize=0;
-                                               if(m1ret.sparseBlock[r]!=null)
-                                                       
estimateSize+=m1ret.sparseBlock[r].size();
-                                               if(m2.sparseBlock[r]!=null)
-                                                       
estimateSize+=m2.sparseBlock[r].size();
+                                               if( !c.isEmpty(r) )
+                                                       estimateSize+=c.size(r);
+                                               if( !b.isEmpty(r))
+                                                       estimateSize+=b.size(r);
                                                estimateSize=Math.min(clen, 
estimateSize);
                                                
                                                //temp
-                                               SparseRow 
thisRow=m1ret.sparseBlock[r];
-                                               m1ret.sparseBlock[r]=new 
SparseRow(estimateSize, clen);
+                                               SparseRow thisRow = c.get(r);
+                                               c.set(r, new 
SparseRow(estimateSize, clen));
                                                
                                                if(thisRow!=null)
                                                {
                                                        
m1ret.nonZeros-=thisRow.size();
-                                                       
mergeForSparseBinary(op, thisRow.getValueContainer(), 
-                                                                       
thisRow.getIndexContainer(), thisRow.size(),
-                                                                       
m2.sparseBlock[r].getValueContainer(), 
-                                                                       
m2.sparseBlock[r].getIndexContainer(), m2.sparseBlock[r].size(), r, m1ret);
+                                                       
mergeForSparseBinary(op, thisRow.values(), thisRow.indexes(), 0, 
+                                                                       
thisRow.size(), b.values(r), b.indexes(r), b.pos(r), b.size(r), r, m1ret);
                                                        
-                                               }else
+                                               }
+                                               else
                                                {
-                                                       
appendRightForSparseBinary(op, m2.sparseBlock[r].getValueContainer(), 
-                                                                       
m2.sparseBlock[r].getIndexContainer(), m2.sparseBlock[r].size(), 0, r, m1ret);
+                                                       
appendRightForSparseBinary(op, b.values(r), b.indexes(r), b.pos(r), b.size(r), 
0, r, m1ret);
                                                }
                                        }
                                }       
                        }
                        else if(m1ret.sparseBlock==null)
                        {
-                               m1ret.sparseBlock=new SparseRow[rlen];
+                               m1ret.sparseBlock = 
SparseBlockFactory.createSparseBlock(rlen);
+                               
                                for(int r=0; r<rlen; r++)
                                {
-                                       SparseRow brow = m2.sparseBlock[r];
-                                       if( brow!=null && !brow.isEmpty() )
-                                       {
-                                               m1ret.sparseBlock[r] = new 
SparseRow( brow.size(), clen );
-                                               appendRightForSparseBinary(op, 
brow.getValueContainer(), brow.getIndexContainer(), brow.size(), 0, r, m1ret);
+                                       if( !b.isEmpty(r) ) {
+                                               SparseRow tmp = new SparseRow( 
b.size(r), clen );
+                                               appendRightForSparseBinary(op, 
b.values(r), b.indexes(r), b.pos(r), b.size(r), 0, r, m1ret);
+                                               m1ret.sparseBlock.set(r, tmp);
                                        }
                                }                               
                        }
                        else //that.sparseRows==null
                        {
-                               if( !(op.fn instanceof Plus || op.fn instanceof 
Minus || op.fn instanceof Or) ){
+                               if( !(op.fn instanceof Plus || op.fn instanceof 
Minus || op.fn instanceof Or) ) {
                                        for(int r=0; r<rlen; r++){
-                                               SparseRow arow = 
m1ret.sparseBlock[r];
-                                               if( arow!=null && 
!arow.isEmpty() )
+                                               if( !c.isEmpty(r) )
                                                {
-                                                       int alen = arow.size();
-                                                       double[] avals = 
arow.getValueContainer();
+                                                       SparseRow tmp = 
c.get(r);
+                                                       int alen = tmp.size();
+                                                       double[] avals = 
tmp.values();
                                                        for( int j=0; j<alen; 
j++ )
                                                                avals[j] = 
op.fn.execute(avals[j], 0);
-                                                       arow.compact(); 
//handle removed entries (e.g., mult, and)
+                                                       tmp.compact(); //handle 
removed entries (e.g., mult, and)
+                                                       c.set(r, tmp);
                                                        
                                                        //NOTE: for left 
in-place, we cannot use append because it would create duplicates
                                                        
//appendLeftForSparseBinary(op, arow.getValueContainer(), 
arow.getIndexContainer(), arow.size(), 0, r, m1ret);
@@ -1240,39 +1247,39 @@ public class LibMatrixBincell
         * @param result
         * @throws DMLRuntimeException
         */
-       private static void mergeForSparseBinary(BinaryOperator op, double[] 
values1, int[] cols1, int size1, 
-                               double[] values2, int[] cols2, int size2, int 
resultRow, MatrixBlock result) 
+       private static void mergeForSparseBinary(BinaryOperator op, double[] 
values1, int[] cols1, int pos1, int size1, 
+                               double[] values2, int[] cols2, int pos2, int 
size2, int resultRow, MatrixBlock result) 
                throws DMLRuntimeException
        {
                int p1=0, p2=0, column;
                while( p1<size1 && p2< size2 )
                {
                        double value = 0;
-                       if(cols1[p1]<cols2[p2])
+                       if(cols1[pos1+p1]<cols2[pos2+p2])
                        {
-                               value = op.fn.execute(values1[p1], 0);
-                               column = cols1[p1];
+                               value = op.fn.execute(values1[pos1+p1], 0);
+                               column = cols1[pos1+p1];
                                p1++;
                        }
-                       else if(cols1[p1]==cols2[p2])
+                       else if(cols1[pos1+p1]==cols2[pos2+p2])
                        {
-                               value = op.fn.execute(values1[p1], values2[p2]);
-                               column = cols1[p1];
+                               value = op.fn.execute(values1[pos1+p1], 
values2[pos2+p2]);
+                               column = cols1[pos1+p1];
                                p1++;
                                p2++;
                        }
                        else
                        {
-                               value = op.fn.execute(0, values2[p2]);
-                               column = cols2[p2];
+                               value = op.fn.execute(0, values2[pos2+p2]);
+                               column = cols2[pos2+p2];
                                p2++;
                        }
                        result.appendValue(resultRow, column, value);   
                }
                
                //add left over
-               appendLeftForSparseBinary(op, values1, cols1, size1, p1, 
resultRow, result);
-               appendRightForSparseBinary(op, values2, cols2, size2, p2, 
resultRow, result);
+               appendLeftForSparseBinary(op, values1, cols1, pos1, size1, p1, 
resultRow, result);
+               appendRightForSparseBinary(op, values2, cols2, pos2, size2, p2, 
resultRow, result);
        }
        
        /**
@@ -1280,18 +1287,18 @@ public class LibMatrixBincell
         * @param op
         * @param values1
         * @param cols1
+        * @param pos1
         * @param size1
         * @param pos
         * @param resultRow
         * @param result
         * @throws DMLRuntimeException
         */
-       private static void appendLeftForSparseBinary(BinaryOperator op, 
double[] values1, int[] cols1, int size1, 
+       private static void appendLeftForSparseBinary(BinaryOperator op, 
double[] values1, int[] cols1, int pos1, int size1, 
                                int pos, int resultRow, MatrixBlock result) 
                throws DMLRuntimeException
        {
-               for(int j=pos; j<size1; j++)
-               {
+               for(int j=pos1+pos; j<pos1+size1; j++) {
                        double v = op.fn.execute(values1[j], 0);
                        result.appendValue(resultRow, cols1[j], v);
                }
@@ -1302,17 +1309,17 @@ public class LibMatrixBincell
         * @param op
         * @param values2
         * @param cols2
+        * @param pos2
         * @param size2
         * @param pos
         * @param resultRow
         * @param result
         * @throws DMLRuntimeException
         */
-       private static void appendRightForSparseBinary(BinaryOperator op, 
double[] values2, int[] cols2, int size2, 
+       private static void appendRightForSparseBinary(BinaryOperator op, 
double[] values2, int[] cols2, int pos2, int size2, 
                int pos, int resultRow, MatrixBlock result) throws 
DMLRuntimeException
        {
-               for( int j=pos; j<size2; j++ )
-               {
+               for( int j=pos2+pos; j<pos2+size2; j++ ) {
                        double v = op.fn.execute(0, values2[j]);
                        result.appendValue(resultRow, cols2[j], v);
                }

http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/8ba0fdcc/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixDatagen.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixDatagen.java 
b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixDatagen.java
index 96b929f..dcaaf1a 100644
--- a/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixDatagen.java
+++ b/src/main/java/org/apache/sysml/runtime/matrix/data/LibMatrixDatagen.java
@@ -671,7 +671,7 @@ public class LibMatrixDatagen
                                // irrelevant but we need to ensure consistency 
with MR)
                                boolean localSparse = 
MatrixBlock.evalSparseFormatInMemory(blockrows, blockcols, nnzInBlocks[blockID] 
); //(long)(sparsity*blockrows*blockcols));  
                                if ( localSparse ) {
-                                       SparseRow[] c = out.sparseBlock;
+                                       SparseBlock c = out.sparseBlock;
                                        
                                        int idx = 0;  // takes values in range 
[1, brlen*bclen] (both ends including)
                                        int ridx=0, cidx=0; // idx translates 
into (ridx, cidx) entry within the block
@@ -692,9 +692,8 @@ public class LibMatrixDatagen
                                                ridx = (idx-1)/blockcols;
                                                cidx = (idx-1)%blockcols;
                                                double val = min + (range * 
valuePRNG.nextDouble());
-                                               if( c[rowoffset+ridx]==null )
-                                                       c[rowoffset+ridx]=new 
SparseRow(estimatedNNzsPerRow, clen);
-                                               
c[rowoffset+ridx].append(coloffset+cidx, val);
+                                               c.allocate(rowoffset+ridx, 
estimatedNNzsPerRow, clen);
+                                               c.append(rowoffset+ridx, 
coloffset+cidx, val);
                                        }
                                }
                                else {
@@ -716,14 +715,13 @@ public class LibMatrixDatagen
                                                         * 
                                                         */
                                                        // In this case, entire 
matrix is in sparse format but the current block is dense
-                                                       SparseRow[] c = 
out.sparseBlock;
+                                                       SparseBlock c = 
out.sparseBlock;
                                                        for(int ii=0; ii < 
blockrows; ii++) {
                                                                for(int jj=0; 
jj < blockcols; jj++) {
                                                                        
if(nnzPRNG.nextDouble() <= sparsity) {
                                                                                
double val = min + (range * valuePRNG.nextDouble());
-                                                                               
if( c[ii+rowoffset]==null )
-                                                                               
        c[ii+rowoffset]=new SparseRow(estimatedNNzsPerRow, clen);
-                                                                               
c[ii+rowoffset].append(jj+coloffset, val);
+                                                                               
c.allocate(ii+rowoffset, estimatedNNzsPerRow, clen);
+                                                                               
c.append(ii+rowoffset, jj+coloffset, val);
                                                                        }
                                                                }
                                                        }

Reply via email to