This is an automated email from the ASF dual-hosted git repository.

baunsgaard pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/systemds.git


The following commit(s) were added to refs/heads/main by this push:
     new e96877eea2 [SYSTEMDS-3489] CLA Compress NaN
e96877eea2 is described below

commit e96877eea2d36dd92cdc79146da5774be403ccc8
Author: baunsgaard <[email protected]>
AuthorDate: Mon Jan 23 14:06:30 2023 +0100

    [SYSTEMDS-3489] CLA Compress NaN
    
    Currently, the compression framework does not allow one to compress a
    MatrixBlock containing NaN values. While the allocated compression block
    does not support operations on matrices containing NaN it does not
    mean we cannot compress it still.
    
    This commit compress a MatrixBlock containing NaN values, and in the
    process of compressing replacing all NaN values with 0 and write a
    warning in case a NaN is discovered.
    
    Also fixed in this commit is edge cases of slice in compressed blocks.
    where a slice of SDC would slice slices that should be SDCSingle.
    
    Closes #1771
---
 .../runtime/compress/colgroup/ColGroupFactory.java |  50 +++++-
 .../runtime/compress/colgroup/ColGroupSDC.java     |  10 +-
 .../runtime/compress/colgroup/ColGroupSDCFOR.java  |  13 +-
 .../compress/colgroup/ColGroupSDCSingle.java       |  48 ++----
 .../compress/colgroup/ColGroupSDCSingleZeros.java  |   8 +-
 .../compress/colgroup/ColGroupSDCZeros.java        |  14 +-
 .../compress/colgroup/mapping/AMapToData.java      |   1 -
 .../compress/colgroup/mapping/MapToBit.java        |  12 +-
 .../runtime/compress/colgroup/offset/AOffset.java  |  45 +++++
 .../compress/colgroup/offset/OffsetByte.java       |   2 +-
 .../compress/estim/encoding/EncodingFactory.java   |  78 ++++++---
 .../runtime/compress/estim/encoding/IEncode.java   |   5 +
 .../compress/estim/encoding/SparseEncoding.java    |   4 -
 .../compress/readers/ReaderColumnSelection.java    |   9 +
 .../ReaderColumnSelectionDenseMultiBlock.java      |  12 +-
 ...erColumnSelectionDenseMultiBlockTransposed.java |  13 +-
 .../ReaderColumnSelectionDenseSingleBlock.java     |  11 +-
 ...rColumnSelectionDenseSingleBlockTransposed.java |  15 +-
 .../readers/ReaderColumnSelectionSparse.java       |  14 +-
 .../ReaderColumnSelectionSparseTransposed.java     |  24 ++-
 .../runtime/compress/utils/DoubleCountHashMap.java |  18 +-
 .../component/compress/CompressedCustomTests.java  |  52 ++++++
 .../component/compress/colgroup/ColGroupTest.java  |  13 +-
 .../estim/encoding/EncodeSampleCustom.java         |  53 ++++++
 .../compress/offset/OffsetReverseTest.java         | 146 +++++++++++++++++
 .../component/compress/readers/ReadersTest.java    | 182 +++++++++++++++++++++
 .../readers/ReadersTestCompareReaders.java         |  10 +-
 27 files changed, 756 insertions(+), 106 deletions(-)

diff --git 
a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupFactory.java 
b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupFactory.java
index 178527d2b2..9eee973a70 100644
--- 
a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupFactory.java
+++ 
b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupFactory.java
@@ -252,7 +252,7 @@ public class ColGroupFactory {
                final boolean t = cs.transposed;
 
                // Fast path compressions
-               if(ct == CompressionType.EMPTY && !t)
+               if(ct == CompressionType.EMPTY && (!t || 
isAllNanTransposed(cg)))
                        return new ColGroupEmpty(colIndexes);
                else if(ct == CompressionType.UNCOMPRESSED) // don't construct 
mapping if uncompressed
                        return ColGroupUncompressed.create(colIndexes, in, t);
@@ -323,7 +323,7 @@ public class ColGroupFactory {
 
                if(map.size() == 0)
                        return new ColGroupEmpty(colIndexes);
-               
+
                ADictionary dict = DictionaryFactory.create(map);
                final int nUnique = map.size();
                final AMapToData resData = MapToFactory.resize(d, nUnique);
@@ -704,6 +704,52 @@ public class ColGroupFactory {
                }
        }
 
+       private boolean isAllNanTransposed(CompressedSizeInfoColGroup cg) {
+               final int[] cols = cg.getColumns();
+               return in.isInSparseFormat() ? isAllNanTransposedSparse(cols) : 
isAllNanTransposedDense(cols);
+       }
+
+       private boolean isAllNanTransposedSparse(int[] cols) {
+               SparseBlock sb = in.getSparseBlock();
+               for(int c : cols){
+                       if(sb.isEmpty(c))
+                               continue;
+                       double[] vl = sb.values(c);
+                       for(double v : vl){
+                               if(!Double.isNaN(v))
+                                       return false;
+                       }
+               }
+               return true;
+       }
+
+       private boolean isAllNanTransposedDense(int[] cols) {
+               if(in.getDenseBlock().isContiguous()){
+                       double[] vals = in.getDenseBlockValues();
+                       for(int c : cols){
+                               int off = c *nRow;
+                               for(int r = 0; r < nRow; r++ ){
+                                       if(!Double.isNaN(vals[off + r])){
+                                               return false;
+                                       }
+                               }
+                       }
+                       return true;
+               }
+               else{
+                       DenseBlock db = in.getDenseBlock();
+                       for(int c : cols){
+                               double[] vals = db.values(c);
+                               int off = db.pos(c);
+                               for(int r = 0; r < nRow; r++ ){
+                                       if(!Double.isNaN(vals[off + r]))
+                                               return false;
+                               }
+                       }
+                       return true;
+               }
+       }
+
        private class CompressTask implements Callable<Object> {
 
                private final List<CompressedSizeInfoColGroup> _groups;
diff --git 
a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupSDC.java 
b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupSDC.java
index d1c12f535c..7e928e668f 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupSDC.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupSDC.java
@@ -29,6 +29,7 @@ import 
org.apache.sysds.runtime.compress.DMLCompressionException;
 import org.apache.sysds.runtime.compress.colgroup.dictionary.ADictionary;
 import org.apache.sysds.runtime.compress.colgroup.dictionary.Dictionary;
 import org.apache.sysds.runtime.compress.colgroup.dictionary.DictionaryFactory;
+import 
org.apache.sysds.runtime.compress.colgroup.dictionary.MatrixBlockDictionary;
 import org.apache.sysds.runtime.compress.colgroup.mapping.AMapToData;
 import org.apache.sysds.runtime.compress.colgroup.mapping.MapToFactory;
 import org.apache.sysds.runtime.compress.colgroup.offset.AIterator;
@@ -40,6 +41,7 @@ import 
org.apache.sysds.runtime.compress.cost.ComputationCostEstimator;
 import org.apache.sysds.runtime.compress.utils.Util;
 import org.apache.sysds.runtime.functionobjects.Builtin;
 import org.apache.sysds.runtime.instructions.cp.CM_COV_Object;
+import org.apache.sysds.runtime.matrix.data.MatrixBlock;
 import org.apache.sysds.runtime.matrix.operators.BinaryOperator;
 import org.apache.sysds.runtime.matrix.operators.CMOperator;
 import org.apache.sysds.runtime.matrix.operators.ScalarOperator;
@@ -86,6 +88,10 @@ public class ColGroupSDC extends ASDC implements 
AMapToDataGroup {
                        return ColGroupSDCSingle.create(colIndices, numRows, 
dict, defaultTuple, offsets, null);
                else if(allZero)
                        return ColGroupSDCZeros.create(colIndices, numRows, 
dict, offsets, data, cachedCounts);
+               else if(data.getUnique() == 1){
+                       MatrixBlock mb = 
dict.getMBDict(colIndices.length).getMatrixBlock().slice(0,0);
+                       return ColGroupSDCSingle.create(colIndices, numRows, 
MatrixBlockDictionary.create(mb), defaultTuple, offsets, null);
+               }
                else
                        return new ColGroupSDC(colIndices, numRows, dict, 
defaultTuple, offsets, data, cachedCounts);
        }
@@ -559,11 +565,13 @@ public class ColGroupSDC extends ASDC implements 
AMapToDataGroup {
        @Override
        public AColGroup sliceRows(int rl, int ru) {
 
+               if(ru > _numRows)
+                       throw new DMLRuntimeException("Invalid row range");
                OffsetSliceInfo off = _indexes.slice(rl, ru);
                if(off.lIndex == -1)
                        return ColGroupConst.create(_colIndexes, 
Dictionary.create(_defaultTuple));
                AMapToData newData = _data.slice(off.lIndex, off.uIndex);
-               return new ColGroupSDC(_colIndexes, _numRows, _dict, 
_defaultTuple, off.offsetSlice, newData, null);
+               return create(_colIndexes, ru - rl, _dict, _defaultTuple, 
off.offsetSlice, newData, null);
        }
 
        @Override
diff --git 
a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupSDCFOR.java 
b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupSDCFOR.java
index 276d5703aa..b306c09862 100644
--- 
a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupSDCFOR.java
+++ 
b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupSDCFOR.java
@@ -70,7 +70,10 @@ public class ColGroupSDCFOR extends ASDC implements 
AMapToDataGroup {
        private ColGroupSDCFOR(int[] colIndices, int numRows, ADictionary dict, 
AOffset indexes, AMapToData data,
                int[] cachedCounts, double[] reference) {
                super(colIndices, numRows, dict, indexes, cachedCounts);
-               if(data.getUnique() != 
dict.getNumberOfValues(colIndices.length))
+               // allow for now 1 data unique.
+               if(data.getUnique() == 1)
+                       LOG.warn("SDCFor unique is 1, indicate it should have 
been SDCSingle please add support");
+               else if(data.getUnique() != 
dict.getNumberOfValues(colIndices.length))
                        throw new DMLCompressionException("Invalid construction 
of SDCZero group");
                _data = data;
                _reference = reference;
@@ -85,8 +88,10 @@ public class ColGroupSDCFOR extends ASDC implements 
AMapToDataGroup {
                        return ColGroupConst.create(colIndexes, reference);
                else if(allZero)
                        return ColGroupSDCZeros.create(colIndexes, numRows, 
dict, offsets, data, cachedCounts);
-               else
-                       return new ColGroupSDCFOR(colIndexes, numRows, dict, 
offsets, data, cachedCounts, reference);
+               // else if(data.getUnique() == 1){
+               // TODO add support for changing to SDCSINGLE.
+               // }
+               return new ColGroupSDCFOR(colIndexes, numRows, dict, offsets, 
data, cachedCounts, reference);
        }
 
        public static AColGroup sparsifyFOR(ColGroupSDC g) {
@@ -437,7 +442,7 @@ public class ColGroupSDCFOR extends ASDC implements 
AMapToDataGroup {
                if(off.lIndex == -1)
                        return ColGroupConst.create(_colIndexes, 
Dictionary.create(_reference));
                AMapToData newData = _data.slice(off.lIndex, off.uIndex);
-               return new ColGroupSDCFOR(_colIndexes, _numRows, _dict, 
off.offsetSlice, newData, null, _reference);
+               return create(_colIndexes, ru - rl, _dict, off.offsetSlice, 
newData, null, _reference);
        }
 
        @Override
diff --git 
a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupSDCSingle.java
 
b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupSDCSingle.java
index 60b567996a..23a38bfbe4 100644
--- 
a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupSDCSingle.java
+++ 
b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupSDCSingle.java
@@ -70,48 +70,24 @@ public class ColGroupSDCSingle extends ASDC {
                final boolean allZero = ColGroupUtils.allZero(defaultTuple);
                if(dict == null && allZero)
                        return new ColGroupEmpty(colIndexes);
-               else if(dict == null) {
-                       if(offsets.getSize() * 2 > numRows + 2) {
-                               AOffset rev = reverse(numRows, offsets);
-                               return 
ColGroupSDCSingleZeros.create(colIndexes, numRows, 
Dictionary.create(defaultTuple), rev,
-                                       cachedCounts);
-                       }
-                       else
-                               return new ColGroupSDCSingle(colIndexes, 
numRows, null, defaultTuple, offsets, cachedCounts);
+               else if(dict == null && offsets.getSize() * 2 > numRows + 2) {
+                       AOffset rev = AOffset.reverse(numRows, offsets);
+                       return ColGroupSDCSingleZeros.create(colIndexes, 
numRows, Dictionary.create(defaultTuple), rev, cachedCounts);
                }
+               else if(dict == null)
+                       return new ColGroupSDCSingle(colIndexes, numRows, null, 
defaultTuple, offsets, cachedCounts);
                else if(allZero)
                        return ColGroupSDCSingleZeros.create(colIndexes, 
numRows, dict, offsets, cachedCounts);
-               else {
-                       if(offsets.getSize() * 2.0 > numRows + 2.0) {
-                               AOffset rev = reverse(numRows, offsets);
-                               return new ColGroupSDCSingle(colIndexes, 
numRows, null, dict.getValues(), rev, null);
-                       }
-                       else
-                               return new ColGroupSDCSingle(colIndexes, 
numRows, dict, defaultTuple, offsets, cachedCounts);
+               else if(offsets.getSize() * 2 > numRows + 2) {
+                       AOffset rev = AOffset.reverse(numRows, offsets);
+                       return new ColGroupSDCSingle(colIndexes, numRows, 
Dictionary.create(defaultTuple), dict.getValues(), rev, null);
                }
-       }
-
-       private static AOffset reverse(int numRows, AOffset offsets) {
-               int[] newOff = new int[numRows - offsets.getSize()];
-               final AOffsetIterator it = offsets.getOffsetIterator();
-               final int last = offsets.getOffsetToLast();
-               int i = 0;
-               int j = 0;
+               else
+                       return new ColGroupSDCSingle(colIndexes, numRows, dict, 
defaultTuple, offsets, cachedCounts);
 
-               while(i < last) {
-                       if(i == it.value()) {
-                               i++;
-                               it.next();
-                       }
-                       else
-                               newOff[j++] = i++;
-               }
-               i++; // last
-               while(i < numRows)
-                       newOff[j++] = i++;
-               return OffsetFactory.createOffset(newOff);
        }
 
+
        @Override
        public CompressionType getCompType() {
                return CompressionType.SDC;
@@ -569,7 +545,7 @@ public class ColGroupSDCSingle extends ASDC {
                OffsetSliceInfo off = _indexes.slice(rl, ru);
                if(off.lIndex == -1)
                        return ColGroupConst.create(_colIndexes, 
Dictionary.create(_defaultTuple));
-               return new ColGroupSDCSingle(_colIndexes, _numRows, _dict, 
_defaultTuple, off.offsetSlice, null);
+               return create(_colIndexes, ru -rl, _dict, _defaultTuple, 
off.offsetSlice, null);
        }
 
        @Override
diff --git 
a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupSDCSingleZeros.java
 
b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupSDCSingleZeros.java
index bc6756b18c..59fe6ec26d 100644
--- 
a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupSDCSingleZeros.java
+++ 
b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupSDCSingleZeros.java
@@ -29,6 +29,7 @@ import 
org.apache.sysds.runtime.compress.DMLCompressionException;
 import org.apache.sysds.runtime.compress.colgroup.dictionary.ADictionary;
 import org.apache.sysds.runtime.compress.colgroup.dictionary.Dictionary;
 import org.apache.sysds.runtime.compress.colgroup.dictionary.DictionaryFactory;
+import 
org.apache.sysds.runtime.compress.colgroup.dictionary.MatrixBlockDictionary;
 import org.apache.sysds.runtime.compress.colgroup.offset.AIterator;
 import org.apache.sysds.runtime.compress.colgroup.offset.AOffset;
 import 
org.apache.sysds.runtime.compress.colgroup.offset.AOffset.OffsetSliceInfo;
@@ -67,6 +68,11 @@ public class ColGroupSDCSingleZeros extends ASDCZero {
                int[] cachedCounts) {
                if(dict == null)
                        return new ColGroupEmpty(colIndices);
+               else if(offsets.getSize() * 2 > numRows + 2) {
+                       AOffset rev = AOffset.reverse(numRows, offsets);
+                       ADictionary empty = MatrixBlockDictionary.create(new 
MatrixBlock(1, colIndices.length, true));
+                       return ColGroupSDCSingle.create(colIndices, numRows, 
empty, dict.getValues(), rev, null);
+               }
                else
                        return new ColGroupSDCSingleZeros(colIndices, numRows, 
dict, offsets, cachedCounts);
        }
@@ -802,7 +808,7 @@ public class ColGroupSDCSingleZeros extends ASDCZero {
                OffsetSliceInfo off = _indexes.slice(rl, ru);
                if(off.lIndex == -1)
                        return null;
-               return new ColGroupSDCSingleZeros(_colIndexes, _numRows, _dict, 
off.offsetSlice, null);
+               return create(_colIndexes, ru - rl, _dict, off.offsetSlice, 
null);
        }
 
        @Override
diff --git 
a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupSDCZeros.java
 
b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupSDCZeros.java
index ae2ecd334e..a678f8cedc 100644
--- 
a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupSDCZeros.java
+++ 
b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupSDCZeros.java
@@ -24,10 +24,12 @@ import java.io.DataOutput;
 import java.io.IOException;
 import java.util.Arrays;
 
+import org.apache.sysds.runtime.DMLRuntimeException;
 import org.apache.sysds.runtime.compress.DMLCompressionException;
 import org.apache.sysds.runtime.compress.colgroup.dictionary.ADictionary;
 import org.apache.sysds.runtime.compress.colgroup.dictionary.Dictionary;
 import org.apache.sysds.runtime.compress.colgroup.dictionary.DictionaryFactory;
+import 
org.apache.sysds.runtime.compress.colgroup.dictionary.MatrixBlockDictionary;
 import org.apache.sysds.runtime.compress.colgroup.mapping.AMapToData;
 import org.apache.sysds.runtime.compress.colgroup.mapping.MapToFactory;
 import org.apache.sysds.runtime.compress.colgroup.offset.AIterator;
@@ -56,7 +58,7 @@ import 
org.apache.sysds.runtime.matrix.operators.UnaryOperator;
  * 
  * This column group is handy in cases where sparse unsafe operations is 
executed on very sparse columns.
  */
-public class ColGroupSDCZeros extends ASDCZero implements AMapToDataGroup{
+public class ColGroupSDCZeros extends ASDCZero implements AMapToDataGroup {
        private static final long serialVersionUID = -3703199743391937991L;
 
        /** Pointers to row indexes in the dictionary. Note the dictionary has 
one extra entry. */
@@ -75,6 +77,10 @@ public class ColGroupSDCZeros extends ASDCZero implements 
AMapToDataGroup{
                int[] cachedCounts) {
                if(dict == null)
                        return new ColGroupEmpty(colIndices);
+               else if(data.getUnique() == 1){
+                       MatrixBlock mb = 
dict.getMBDict(colIndices.length).getMatrixBlock().slice(0,0);
+                       return ColGroupSDCSingleZeros.create(colIndices, 
numRows, MatrixBlockDictionary.create(mb), offsets, null);
+               }
                else
                        return new ColGroupSDCZeros(colIndices, numRows, dict, 
offsets, data, cachedCounts);
        }
@@ -90,7 +96,7 @@ public class ColGroupSDCZeros extends ASDCZero implements 
AMapToDataGroup{
        }
 
        @Override
-       public AMapToData getMapToData(){
+       public AMapToData getMapToData() {
                return _data;
        }
 
@@ -714,11 +720,13 @@ public class ColGroupSDCZeros extends ASDCZero implements 
AMapToDataGroup{
 
        @Override
        public AColGroup sliceRows(int rl, int ru) {
+               if(ru > _numRows)
+                       throw new DMLRuntimeException("Invalid row range");
                OffsetSliceInfo off = _indexes.slice(rl, ru);
                if(off.lIndex == -1)
                        return null;
                AMapToData newData = _data.slice(off.lIndex, off.uIndex);
-               return new ColGroupSDCZeros(_colIndexes, _numRows, _dict, 
off.offsetSlice, newData, null);
+               return create(_colIndexes, ru - rl, _dict, off.offsetSlice, 
newData, null);
        }
 
        @Override
diff --git 
a/src/main/java/org/apache/sysds/runtime/compress/colgroup/mapping/AMapToData.java
 
b/src/main/java/org/apache/sysds/runtime/compress/colgroup/mapping/AMapToData.java
index 4e781cf5bc..a506734a9c 100644
--- 
a/src/main/java/org/apache/sysds/runtime/compress/colgroup/mapping/AMapToData.java
+++ 
b/src/main/java/org/apache/sysds/runtime/compress/colgroup/mapping/AMapToData.java
@@ -816,7 +816,6 @@ public abstract class AMapToData implements Serializable {
         */
        public abstract AMapToData slice(int l, int u);
 
-
        public abstract AMapToData append(AMapToData t);
 
        public abstract AMapToData appendN(AMapToDataGroup[] d);
diff --git 
a/src/main/java/org/apache/sysds/runtime/compress/colgroup/mapping/MapToBit.java
 
b/src/main/java/org/apache/sysds/runtime/compress/colgroup/mapping/MapToBit.java
index a69bb0cb93..01ab2a4bb1 100644
--- 
a/src/main/java/org/apache/sysds/runtime/compress/colgroup/mapping/MapToBit.java
+++ 
b/src/main/java/org/apache/sysds/runtime/compress/colgroup/mapping/MapToBit.java
@@ -25,6 +25,7 @@ import java.io.IOException;
 import java.util.BitSet;
 
 import org.apache.commons.lang.NotImplementedException;
+import org.apache.sysds.runtime.DMLRuntimeException;
 import org.apache.sysds.runtime.compress.colgroup.AMapToDataGroup;
 import org.apache.sysds.runtime.compress.colgroup.dictionary.ADictionary;
 import 
org.apache.sysds.runtime.compress.colgroup.mapping.MapToFactory.MAP_TYPE;
@@ -52,8 +53,9 @@ public class MapToBit extends AMapToData {
                _data = d;
                _size = size;
                if(_data.isEmpty()) {
-                       unique = 1;
-                       LOG.warn("Empty bit set should not happen");
+                       // unique = 1;
+                       throw new DMLRuntimeException("Empty BitSet should not 
happen it should return MapToZero");
+                       // LOG.warn("Empty bit set should not happen");
                }
        }
 
@@ -324,7 +326,11 @@ public class MapToBit extends AMapToData {
 
        @Override
        public AMapToData slice(int l, int u) {
-               return new MapToBit(getUnique(), _data.get(l, u), u - l);
+               BitSet s = _data.get(l,u);
+               if(s.isEmpty())
+                       return new MapToZero(u-l);
+               else 
+                       return new MapToBit(getUnique(), s, u - l);
        }
 
        @Override
diff --git 
a/src/main/java/org/apache/sysds/runtime/compress/colgroup/offset/AOffset.java 
b/src/main/java/org/apache/sysds/runtime/compress/colgroup/offset/AOffset.java
index e871e1bd27..5af9b46ce9 100644
--- 
a/src/main/java/org/apache/sysds/runtime/compress/colgroup/offset/AOffset.java
+++ 
b/src/main/java/org/apache/sysds/runtime/compress/colgroup/offset/AOffset.java
@@ -21,10 +21,12 @@ package org.apache.sysds.runtime.compress.colgroup.offset;
 import java.io.DataOutput;
 import java.io.IOException;
 import java.io.Serializable;
+import java.util.Arrays;
 
 import org.apache.commons.lang.NotImplementedException;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.sysds.runtime.DMLRuntimeException;
 import org.apache.sysds.runtime.compress.DMLCompressionException;
 import org.apache.sysds.runtime.compress.colgroup.AOffsetsGroup;
 import org.apache.sysds.runtime.compress.colgroup.mapping.AMapToData;
@@ -523,6 +525,36 @@ public abstract class AOffset implements Serializable {
                return sb.toString();
        }
 
+       public static AOffset reverse(int numRows, AOffset offsets) {
+               if(numRows < offsets.getOffsetToLast()) {
+                       throw new DMLRuntimeException("Invalid number of rows 
for reverse");
+               }
+
+               int[] newOff = new int[numRows - offsets.getSize()];
+               final AOffsetIterator it = offsets.getOffsetIterator();
+               final int last = offsets.getOffsetToLast();
+               int i = 0;
+               int j = 0;
+
+               while(i < last) {
+                       if(i == it.value()) {
+                               i++;
+                               it.next();
+                       }
+                       else
+                               newOff[j++] = i++;
+               }
+               i++; // last
+               while(i < numRows)
+                       newOff[j++] = i++;
+
+               if(j != newOff.length)
+                       throw new DMLRuntimeException(
+                               "Not assigned all offsets ... something must be 
wrong:\n" + offsets + "\n" + Arrays.toString(newOff));
+               return OffsetFactory.createOffset(newOff);
+
+       }
+
        public static final class OffsetSliceInfo {
                public final int lIndex;
                public final int uIndex;
@@ -533,6 +565,19 @@ public abstract class AOffset implements Serializable {
                        this.uIndex = u;
                        this.offsetSlice = off;
                }
+
+               @Override
+               public String toString() {
+                       StringBuilder sb = new StringBuilder();
+                       sb.append("sliceInfo: ");
+                       sb.append(lIndex);
+                       sb.append("->");
+                       sb.append(uIndex);
+                       sb.append("  --  ");
+                       sb.append(offsetSlice);
+                       return sb.toString();
+               }
+
        }
 
        protected static class OffsetCache {
diff --git 
a/src/main/java/org/apache/sysds/runtime/compress/colgroup/offset/OffsetByte.java
 
b/src/main/java/org/apache/sysds/runtime/compress/colgroup/offset/OffsetByte.java
index f29feae572..08140a2d50 100644
--- 
a/src/main/java/org/apache/sysds/runtime/compress/colgroup/offset/OffsetByte.java
+++ 
b/src/main/java/org/apache/sysds/runtime/compress/colgroup/offset/OffsetByte.java
@@ -127,7 +127,7 @@ public class OffsetByte extends AOffset {
        }
 
        protected OffsetSliceInfo slice(int lowOff, int highOff, int lowValue, 
int highValue, int low, int high) {
-               int newSize = high - low - 1;
+               int newSize = high - low +1 ;
                byte[] newOffsets = Arrays.copyOfRange(offsets, lowOff, 
highOff);
                AOffset off = new OffsetByte(newOffsets, lowValue, highValue, 
newSize, noOverHalf, noZero);
                return new OffsetSliceInfo(low, high + 1, off);
diff --git 
a/src/main/java/org/apache/sysds/runtime/compress/estim/encoding/EncodingFactory.java
 
b/src/main/java/org/apache/sysds/runtime/compress/estim/encoding/EncodingFactory.java
index 2fe6d5e6e5..92a8cea937 100644
--- 
a/src/main/java/org/apache/sysds/runtime/compress/estim/encoding/EncodingFactory.java
+++ 
b/src/main/java/org/apache/sysds/runtime/compress/estim/encoding/EncodingFactory.java
@@ -22,6 +22,8 @@ package org.apache.sysds.runtime.compress.estim.encoding;
 import java.util.Arrays;
 
 import org.apache.commons.lang.NotImplementedException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.sysds.runtime.compress.colgroup.mapping.AMapToData;
 import org.apache.sysds.runtime.compress.colgroup.mapping.MapToFactory;
 import org.apache.sysds.runtime.compress.colgroup.offset.AOffset;
@@ -37,6 +39,8 @@ import org.apache.sysds.runtime.matrix.data.MatrixBlock;
 
 public interface EncodingFactory {
 
+       public static final Log LOG = 
LogFactory.getLog(EncodingFactory.class.getName());
+
        /**
         * Encode a list of columns together from the input matrix, as if it is 
cocoded.
         * 
@@ -122,14 +126,18 @@ public interface EncodingFactory {
 
                // Iteration 1, make Count HashMap.
                for(int i = off; i < end; i++) // sequential access
-                       map.increment(vals[i]);
+                       if(!Double.isNaN(vals[i]))
+                               map.increment(vals[i]);
+                       else
+                               map.increment(0);
 
                final int nUnique = map.size();
 
                if(nUnique == 1)
                        return new ConstEncoding(m.getNumColumns());
-
-               if(map.getOrDefault(0, -1) > nCol / 4) {
+               else if(nUnique == 0)
+                       return new EmptyEncoding();
+               else if(map.getOrDefault(0, -1) > nCol / 4) {
                        map.replaceWithUIDsNoZero();
                        final int zeroCount = map.get(0);
                        final int nV = nCol - zeroCount;
@@ -141,7 +149,10 @@ public interface EncodingFactory {
                        for(int i = off, r = 0, di = 0; i < end; i++, r++) {
                                if(vals[i] != 0) {
                                        offsets.appendValue(r);
-                                       d.set(di++, map.get(vals[i]));
+                                       if(!Double.isNaN(vals[i]))
+                                               d.set(di++, map.get(vals[i]));
+                                       else
+                                               d.set(di++, map.get(0.0));
                                }
                        }
 
@@ -154,8 +165,12 @@ public interface EncodingFactory {
                        final AMapToData d = MapToFactory.create(nCol, nUnique);
 
                        // Iteration 2, make final map
-                       for(int i = off, r = 0; i < end; i++, r++)
-                               d.set(r, map.get(vals[i]));
+                       for(int i = off, r = 0; i < end; i++, r++) {
+                               if(!Double.isNaN(vals[i]))
+                                       d.set(r, map.get(vals[i]));
+                               else
+                                       d.set(r, map.get(0.0));
+                       }
 
                        return new DenseEncoding(d);
                }
@@ -172,25 +187,30 @@ public interface EncodingFactory {
                final int[] aix = sb.indexes(row);
 
                // Iteration 1 of non zero values, make Count HashMap.
-               for(int i = apos; i < alen; i++) // sequential of non zero 
cells.
-                       map.increment(avals[i]);
+               for(int i = apos; i < alen; i++) {
+                       // sequential of non zero cells.
+                       if(!Double.isNaN(avals[i]))
+                               map.increment(avals[i]);
 
-               final int nUnique = map.size();
+               }
 
+               final int nUnique = map.size();
                map.replaceWithUIDs();
 
                final int nCol = m.getNumColumns();
-               if(alen - apos > nCol / 4) { // return a dense encoding
+               if(nUnique == 0) // only if all NaN
+                       return new EmptyEncoding();
+               else if(alen - apos > nCol / 4) { // return a dense encoding
                        // If the row was full but the overall matrix is sparse.
                        final int correct = (alen - apos == m.getNumColumns()) 
? 0 : 1;
                        final AMapToData d = MapToFactory.create(nCol, nUnique 
+ correct);
                        // Since the dictionary is allocated with zero then we 
exploit that here and
                        // only iterate through non zero entries.
                        for(int i = apos; i < alen; i++)
-                               // correction one to assign unique IDs taking 
into account zero
-                               d.set(aix[i], map.get(avals[i]) + correct);
-                       // the rest is automatically set to zero.
+                               if(!Double.isNaN(avals[i])) // correction one 
to assign unique IDs taking into account zero
+                                       d.set(aix[i], map.get(avals[i]) + 
correct);
 
+                       // the rest is automatically set to zero.
                        return new DenseEncoding(d);
                }
                else { // return a sparse encoding
@@ -199,7 +219,8 @@ public interface EncodingFactory {
 
                        // Iteration 2 of non zero values, make either a 
IEncode Dense or sparse map.
                        for(int i = apos, j = 0; i < alen; i++, j++)
-                               d.set(j, map.get(avals[i]));
+                               if(!Double.isNaN(avals[i]))
+                                       d.set(j, map.get(avals[i]));
 
                        // Iteration 3 of non zero indexes, make a Offset 
Encoding to know what cells are zero and not.
                        // not done yet
@@ -221,8 +242,10 @@ public interface EncodingFactory {
 
                // Iteration 1, make Count HashMap.
                for(int i = off; i < end; i += nCol) // jump down through rows.
-                       map.increment(vals[i]);
-
+                       if(!Double.isNaN(vals[i]))
+                               map.increment(vals[i]);
+                       else
+                               map.increment(0);
                final int nUnique = map.size();
                if(nUnique == 1)
                        return new ConstEncoding(m.getNumColumns());
@@ -236,7 +259,7 @@ public interface EncodingFactory {
                        final AMapToData d = MapToFactory.create(nV, nUnique - 
1);
 
                        for(int i = off, r = 0, di = 0; i < end; i += nCol, 
r++) {
-                               if(vals[i] != 0) {
+                               if(vals[i] != 0 && !Double.isNaN(vals[i])) {
                                        offsets.appendValue(r);
                                        d.set(di++, map.get(vals[i]));
                                }
@@ -252,7 +275,10 @@ public interface EncodingFactory {
                        final AMapToData d = MapToFactory.create(nRow, nUnique);
                        // Iteration 2, make final map
                        for(int i = off, r = 0; i < end; i += nCol, r++)
-                               d.set(r, map.get(vals[i]));
+                               if(!Double.isNaN(vals[i]))
+                                       d.set(r, map.get(vals[i]));
+                               else
+                                       d.set(r, map.get(0));
                        return new DenseEncoding(d);
                }
        }
@@ -274,8 +300,11 @@ public interface EncodingFactory {
                        final int[] aix = sb.indexes(r);
                        final int index = Arrays.binarySearch(aix, apos, alen, 
col);
                        if(index >= 0) {
-                               offsets.appendValue(r);
-                               map.increment(sb.values(r)[index]);
+                               final double v = sb.values(r)[index];
+                               if(!Double.isNaN(v)) {
+                                       offsets.appendValue(r);
+                                       map.increment(sb.values(r)[index]);
+                               }
                        }
                }
                if(offsets.size() == 0)
@@ -295,8 +324,11 @@ public interface EncodingFactory {
                        final int[] aix = sb.indexes(r);
                        // Performance hit because of binary search for each 
row.
                        final int index = Arrays.binarySearch(aix, apos, alen, 
col);
-                       if(index >= 0)
-                               d.set(off++, map.get(sb.values(r)[index]));
+                       if(index >= 0) {
+                               final double v = sb.values(r)[index];
+                               if(index >= 0 && !Double.isNaN(v))
+                                       d.set(off++, map.get(v));
+                       }
                }
 
                // Iteration 3 of non zero indexes, make a Offset Encoding to 
know what cells are zero and not.
@@ -369,7 +401,7 @@ public interface EncodingFactory {
                return new SparseEncoding(d, o, nRows);
        }
 
-       public static SparseEncoding createSparse(AMapToData map, AOffset off, 
int nRows){
+       public static SparseEncoding createSparse(AMapToData map, AOffset off, 
int nRows) {
                return new SparseEncoding(map, off, nRows);
        }
 }
diff --git 
a/src/main/java/org/apache/sysds/runtime/compress/estim/encoding/IEncode.java 
b/src/main/java/org/apache/sysds/runtime/compress/estim/encoding/IEncode.java
index 5f15c147ac..26b2201428 100644
--- 
a/src/main/java/org/apache/sysds/runtime/compress/estim/encoding/IEncode.java
+++ 
b/src/main/java/org/apache/sysds/runtime/compress/estim/encoding/IEncode.java
@@ -19,6 +19,8 @@
 
 package org.apache.sysds.runtime.compress.estim.encoding;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.sysds.runtime.compress.CompressionSettings;
 import org.apache.sysds.runtime.compress.estim.EstimationFactors;
 
@@ -27,6 +29,9 @@ import 
org.apache.sysds.runtime.compress.estim.EstimationFactors;
  * column groups.
  */
 public interface IEncode {
+
+       public static final Log LOG = 
LogFactory.getLog(IEncode.class.getName());
+
        /**
         * Combine two encodings, note it should be guaranteed by the caller 
that the number of unique multiplied does not
         * overflow Integer.
diff --git 
a/src/main/java/org/apache/sysds/runtime/compress/estim/encoding/SparseEncoding.java
 
b/src/main/java/org/apache/sysds/runtime/compress/estim/encoding/SparseEncoding.java
index 66af6c7ec5..2b242e0ffb 100644
--- 
a/src/main/java/org/apache/sysds/runtime/compress/estim/encoding/SparseEncoding.java
+++ 
b/src/main/java/org/apache/sysds/runtime/compress/estim/encoding/SparseEncoding.java
@@ -19,8 +19,6 @@
 
 package org.apache.sysds.runtime.compress.estim.encoding;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 import org.apache.sysds.runtime.compress.CompressionSettings;
 import org.apache.sysds.runtime.compress.colgroup.mapping.AMapToData;
 import org.apache.sysds.runtime.compress.colgroup.mapping.MapToFactory;
@@ -33,8 +31,6 @@ import org.apache.sysds.runtime.compress.utils.IntArrayList;
 /** Most common is zero encoding */
 public class SparseEncoding implements IEncode {
 
-       static final Log LOG = 
LogFactory.getLog(SparseEncoding.class.getName());
-
        /** A map to the distinct values contained */
        protected final AMapToData map;
 
diff --git 
a/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelection.java
 
b/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelection.java
index d02e73536b..54d7ff28cf 100644
--- 
a/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelection.java
+++ 
b/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelection.java
@@ -30,6 +30,8 @@ public abstract class ReaderColumnSelection {
 
        protected static final Log LOG = 
LogFactory.getLog(ReaderColumnSelection.class.getName());
 
+       protected static boolean nanEncountered = false;
+
        protected final int[] _colIndexes;
        protected final DblArray reusableReturn;
        protected final double[] reusableArr;
@@ -101,4 +103,11 @@ public abstract class ReaderColumnSelection {
                else if(rl >= ru)
                        throw new DMLCompressionException("Invalid inverse 
range for reader " + rl + " to " + ru);
        }
+
+       protected void warnNaN(){
+               if(!nanEncountered){
+                       LOG.warn("NaN value encountered, replaced by 0 in 
compression, since nan is not supported");
+                       nanEncountered = true;
+               }
+       }
 }
diff --git 
a/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelectionDenseMultiBlock.java
 
b/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelectionDenseMultiBlock.java
index 9619b08b2d..0daa79e7fa 100644
--- 
a/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelectionDenseMultiBlock.java
+++ 
b/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelectionDenseMultiBlock.java
@@ -37,8 +37,16 @@ public class ReaderColumnSelectionDenseMultiBlock extends 
ReaderColumnSelection
                        _rl++;
                        for(int i = 0; i < _colIndexes.length; i++) {
                                final double v = _data.get(_rl, _colIndexes[i]);
-                               empty &= v == 0;
-                               reusableArr[i] = v;
+                               boolean isNan = Double.isNaN(v);
+                               if(isNan){
+                                       warnNaN();
+                                       reusableArr[i] = 0;
+                               }
+                               else{
+                                       
+                                       empty &= v == 0 ;
+                                       reusableArr[i] = v;
+                               }
                        }
                }
                return empty ? null : reusableReturn;
diff --git 
a/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelectionDenseMultiBlockTransposed.java
 
b/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelectionDenseMultiBlockTransposed.java
index 507fa03191..1273d3fc4d 100644
--- 
a/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelectionDenseMultiBlockTransposed.java
+++ 
b/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelectionDenseMultiBlockTransposed.java
@@ -36,9 +36,16 @@ public class ReaderColumnSelectionDenseMultiBlockTransposed 
extends ReaderColumn
                while(empty && _rl < _ru) {
                        _rl++;
                        for(int i = 0; i < _colIndexes.length; i++) {
-                               double v = _data.get(_colIndexes[i], _rl);
-                               empty &= v == 0;
-                               reusableArr[i] = v;
+                               final double v = _data.get(_colIndexes[i], _rl);
+                               boolean isNan = Double.isNaN(v);
+                               if(isNan){
+                                       warnNaN();
+                                       reusableArr[i] = 0;
+                               }
+                               else{
+                                       empty &= v == 0;
+                                       reusableArr[i] = v;
+                               }
                        }
                }
                return empty ? null : reusableReturn;
diff --git 
a/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelectionDenseSingleBlock.java
 
b/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelectionDenseSingleBlock.java
index 6a073a7532..c24ab5c17b 100644
--- 
a/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelectionDenseSingleBlock.java
+++ 
b/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelectionDenseSingleBlock.java
@@ -40,8 +40,15 @@ public class ReaderColumnSelectionDenseSingleBlock extends 
ReaderColumnSelection
                        final int indexOff = _rl * _numCols;
                        for(int i = 0; i < _colIndexes.length; i++) {
                                double v = _data[indexOff + _colIndexes[i]];
-                               empty &= v == 0;
-                               reusableArr[i] = v;
+                               boolean isNan = Double.isNaN(v);
+                               if(isNan){
+                                       warnNaN();
+                                       reusableArr[i] = 0;
+                               }
+                               else{
+                                       empty &= v == 0;
+                                       reusableArr[i] = v;
+                               }
                        }
                }
 
diff --git 
a/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelectionDenseSingleBlockTransposed.java
 
b/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelectionDenseSingleBlockTransposed.java
index 291a3de2c9..ebdd2548de 100644
--- 
a/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelectionDenseSingleBlockTransposed.java
+++ 
b/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelectionDenseSingleBlockTransposed.java
@@ -26,7 +26,7 @@ public class ReaderColumnSelectionDenseSingleBlockTransposed 
extends ReaderColum
        private final double[] _data;
 
        protected ReaderColumnSelectionDenseSingleBlockTransposed(MatrixBlock 
data, int[] colIndexes, int rl, int ru) {
-               super(colIndexes.clone(), rl, Math.min(ru, 
data.getNumColumns()) -1 );
+               super(colIndexes.clone(), rl, Math.min(ru, 
data.getNumColumns()) - 1);
                _data = data.getDenseBlockValues();
                for(int i = 0; i < _colIndexes.length; i++)
                        _colIndexes[i] = _colIndexes[i] * data.getNumColumns();
@@ -34,12 +34,19 @@ public class 
ReaderColumnSelectionDenseSingleBlockTransposed extends ReaderColum
 
        protected DblArray getNextRow() {
                boolean empty = true;
-               while(empty && _rl < _ru ) {
+               while(empty && _rl < _ru) {
                        _rl++;
                        for(int i = 0; i < _colIndexes.length; i++) {
                                final double v = _data[_colIndexes[i] + _rl];
-                               empty &= v == 0;
-                               reusableArr[i] = v;
+                               boolean isNan = Double.isNaN(v);
+                               if(isNan) {
+                                       warnNaN();
+                                       reusableArr[i] = 0;
+                               }
+                               else {
+                                       empty &= v == 0;
+                                       reusableArr[i] = v;
+                               }
                        }
 
                }
diff --git 
a/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelectionSparse.java
 
b/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelectionSparse.java
index 0379b5850b..f9af95b440 100644
--- 
a/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelectionSparse.java
+++ 
b/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelectionSparse.java
@@ -66,12 +66,20 @@ public class ReaderColumnSelectionSparse extends 
ReaderColumnSelection {
                int skip = 0;
                int j = Arrays.binarySearch(aix, apos, alen, _colIndexes[0]);
                if(j < 0)
-                       j = Math.abs(j+1);
+                       j = Math.abs(j + 1);
 
                while(skip < _colIndexes.length && j < alen) {
                        if(_colIndexes[skip] == aix[j]) {
-                               reusableArr[skip] = avals[j];
-                               zeroResult = false;
+                               final Double v = avals[j];
+                               boolean isNan = Double.isNaN(v);
+                               if(isNan) {
+                                       warnNaN();
+                                       reusableArr[skip] = 0;
+                               }
+                               else {
+                                       reusableArr[skip] = avals[j];
+                                       zeroResult = false;
+                               }
                                skip++;
                                j++;
                        }
diff --git 
a/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelectionSparseTransposed.java
 
b/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelectionSparseTransposed.java
index b6bfa1b92c..021e1489e5 100644
--- 
a/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelectionSparseTransposed.java
+++ 
b/src/main/java/org/apache/sysds/runtime/compress/readers/ReaderColumnSelectionSparseTransposed.java
@@ -87,13 +87,23 @@ public class ReaderColumnSelectionSparseTransposed extends 
ReaderColumnSelection
                        _rl = _ru;
                        return null;
                }
+               boolean empty = true;
                for(int i = 0; i < _colIndexes.length; i++) {
                        final int c = _colIndexes[i];
                        final int sp = sparsePos[i];
                        final int[] aix = a.indexes(c);
                        if(aix[sp] == _rl) {
                                final double[] avals = a.values(c);
-                               reusableArr[i] = avals[sp];
+                               double v = avals[sp];
+                               boolean isNan = Double.isNaN(v);
+                               if(isNan) {
+                                       warnNaN();
+                                       reusableArr[i] = 0;
+                               }
+                               else {
+                                       empty = false;
+                                       reusableArr[i] = avals[sp];
+                               }
                                final int spa = sparsePos[i]++;
                                final int len = a.size(c) + a.pos(c) - 1;
                                if(spa >= len || aix[spa] >= _ru) {
@@ -105,7 +115,7 @@ public class ReaderColumnSelectionSparseTransposed extends 
ReaderColumnSelection
                                reusableArr[i] = 0;
                }
 
-               return reusableReturn;
+               return empty ? getNextRow(): reusableReturn;
        }
 
        private void skipToRow() {
@@ -130,7 +140,15 @@ public class ReaderColumnSelectionSparseTransposed extends 
ReaderColumnSelection
                                final int[] aix = a.indexes(c);
                                if(aix[sp] == _rl) {
                                        final double[] avals = a.values(c);
-                                       reusableArr[i] = avals[sp];
+                                       final double v = avals[sp];
+                                       boolean isNan = Double.isNaN(v);
+                                       if(isNan) {
+                                               warnNaN();
+                                               reusableArr[i] = 0;
+                                       }
+                                       else {
+                                               reusableArr[i] = v;
+                                       }
                                        if(++sparsePos[i] >= a.size(c) + 
a.pos(c))
                                                sparsePos[i] = -1;
                                }
diff --git 
a/src/main/java/org/apache/sysds/runtime/compress/utils/DoubleCountHashMap.java 
b/src/main/java/org/apache/sysds/runtime/compress/utils/DoubleCountHashMap.java
index ddf344c71d..15b0f8ebb9 100644
--- 
a/src/main/java/org/apache/sysds/runtime/compress/utils/DoubleCountHashMap.java
+++ 
b/src/main/java/org/apache/sysds/runtime/compress/utils/DoubleCountHashMap.java
@@ -105,12 +105,18 @@ public class DoubleCountHashMap {
         * @return count on key
         */
        public int get(double key) {
-               int ix = hashIndex(key);
-               Bucket l = _data[ix];
-               while(!(l.v.key == key))
-                       l = l.n;
-
-               return l.v.count;
+               try{
+                       int ix = hashIndex(key);
+                       Bucket l = _data[ix];
+                       while(!(l.v.key == key))
+                               l = l.n;
+       
+                       return l.v.count;
+               } catch( Exception e){
+                       if(Double.isNaN(key))
+                               return get(0.0);
+                       throw e;
+               }
        }
 
        public int getOrDefault(double key, int def) {
diff --git 
a/src/test/java/org/apache/sysds/test/component/compress/CompressedCustomTests.java
 
b/src/test/java/org/apache/sysds/test/component/compress/CompressedCustomTests.java
new file mode 100644
index 0000000000..2816504c98
--- /dev/null
+++ 
b/src/test/java/org/apache/sysds/test/component/compress/CompressedCustomTests.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sysds.test.component.compress;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.sysds.runtime.compress.CompressedMatrixBlockFactory;
+import org.apache.sysds.runtime.matrix.data.MatrixBlock;
+import org.junit.Test;
+
+public class CompressedCustomTests {
+       @Test
+       public void compressNaNDense() {
+               MatrixBlock m = new MatrixBlock(100, 100, Double.NaN);
+
+               MatrixBlock m2 = 
CompressedMatrixBlockFactory.compress(m).getLeft();
+
+               for(int i = 0; i < m.getNumRows(); i++)
+                       for(int j = 0; j < m.getNumColumns(); j++)
+                               assertEquals(0.0, m2.quickGetValue(i, j), 0.0);
+       }
+
+       @Test
+       public void compressNaNSparse() {
+               MatrixBlock m = new MatrixBlock(100, 100, true);
+               for(int i = 0; i < m.getNumRows(); i++)
+                       m.setValue(i, i, Double.NaN);
+               assertTrue(m.isInSparseFormat());
+               MatrixBlock m2 = 
CompressedMatrixBlockFactory.compress(m).getLeft();
+               for(int i = 0; i < m.getNumRows(); i++)
+                       for(int j = 0; j < m.getNumColumns(); j++)
+                               assertEquals(0.0, m2.quickGetValue(i, j), 0.0);
+       }
+}
diff --git 
a/src/test/java/org/apache/sysds/test/component/compress/colgroup/ColGroupTest.java
 
b/src/test/java/org/apache/sysds/test/component/compress/colgroup/ColGroupTest.java
index f609f0bcea..ed25cbc59f 100644
--- 
a/src/test/java/org/apache/sysds/test/component/compress/colgroup/ColGroupTest.java
+++ 
b/src/test/java/org/apache/sysds/test/component/compress/colgroup/ColGroupTest.java
@@ -2156,7 +2156,13 @@ public class ColGroupTest extends ColGroupBase {
                        }
 
                        AColGroup a = base.sliceRows(rl, ru);
+                       
                        AColGroup b = other.sliceRows(rl, ru);
+                       // LOG.error(rl + " " +ru);
+                       // LOG.error(base);
+                       // LOG.error(a);
+
+
                        final int newNRow = ru - rl;
 
                        if(a == null || b == null)
@@ -2166,17 +2172,18 @@ public class ColGroupTest extends ColGroupBase {
                                return;
                        assertTrue(a.getColIndices() == base.getColIndices());
                        assertTrue(b.getColIndices() == other.getColIndices());
-                       
UA_ROW(InstructionUtils.parseBasicAggregateUnaryOperator("uar+", 1), 0, 
newNRow, a, b, newNRow);
-
+                       
                        int nRow = ru - rl;
                        MatrixBlock ot = sparseMB(ru - rl, maxCol);
                        MatrixBlock bt = sparseMB(ru - rl, maxCol);
                        decompressToSparseBlock(a, b, ot, bt, 0, nRow);
-
+                       
                        MatrixBlock otd = denseMB(ru - rl, maxCol);
                        MatrixBlock btd = denseMB(ru - rl, maxCol);
                        decompressToDenseBlock(otd, btd, a, b, 0, nRow);
 
+                       
UA_ROW(InstructionUtils.parseBasicAggregateUnaryOperator("uar+", 1), 0, 
newNRow, a, b, newNRow);
+
                }
                catch(Exception e) {
                        e.printStackTrace();
diff --git 
a/src/test/java/org/apache/sysds/test/component/compress/estim/encoding/EncodeSampleCustom.java
 
b/src/test/java/org/apache/sysds/test/component/compress/estim/encoding/EncodeSampleCustom.java
index 7d3d9d3a83..9807ca2f91 100644
--- 
a/src/test/java/org/apache/sysds/test/component/compress/estim/encoding/EncodeSampleCustom.java
+++ 
b/src/test/java/org/apache/sysds/test/component/compress/estim/encoding/EncodeSampleCustom.java
@@ -19,6 +19,7 @@
 
 package org.apache.sysds.test.component.compress.estim.encoding;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -39,6 +40,7 @@ import 
org.apache.sysds.runtime.compress.estim.encoding.DenseEncoding;
 import org.apache.sysds.runtime.compress.estim.encoding.EncodingFactory;
 import org.apache.sysds.runtime.compress.estim.encoding.IEncode;
 import org.apache.sysds.runtime.compress.estim.encoding.SparseEncoding;
+import org.apache.sysds.runtime.matrix.data.MatrixBlock;
 import org.apache.sysds.test.component.compress.offset.OffsetTests;
 import org.junit.Test;
 
@@ -254,4 +256,55 @@ public class EncodeSampleCustom {
                        throw new NotImplementedError();
                }
        }
+
+       private static MatrixBlock getSparseNaNMatrix() {
+               MatrixBlock m = new MatrixBlock(100, 100, true);
+               for(int i = 0; i < m.getNumRows(); i++)
+                       m.setValue(i, i, Double.NaN);
+               return m;
+       }
+
+       private static MatrixBlock getDenseNaNMatrix() {
+               return new MatrixBlock(100, 100, Double.NaN);
+
+       }
+
+       @Test
+       public void testNaNDense() {
+               MatrixBlock m = getDenseNaNMatrix();
+               IEncode e = EncodingFactory.createFromMatrixBlock(m, false, 0);
+               // Technically it could have returned a sparse Encoding, but 
nulls, are considered values therefore the branching
+               // is saying that there is values in all cells making it chose 
a dense encoding.
+               // This is not a problem in the general compression, only in 
the edge case a entire or most of a column is null
+               assertTrue(e.isDense());
+               assertEquals(1, e.getUnique());
+       }
+
+
+       @Test
+       public void testNaNDenseTransposed() {
+               MatrixBlock m = getDenseNaNMatrix();
+               IEncode e = EncodingFactory.createFromMatrixBlock(m, true, 0);
+               // Technically it could have returned a sparse Encoding, but 
nulls, are considered values therefore the branching
+               // is saying that there is values in all cells making it chose 
a dense encoding.
+               // This is not a problem in the general compression, only in 
the edge case a entire or most of a column is null
+               assertTrue(e.isDense());
+               assertEquals(1, e.getUnique());
+       }
+
+       @Test
+       public void testNaNSparse() {
+               MatrixBlock m = getSparseNaNMatrix();
+               IEncode e = EncodingFactory.createFromMatrixBlock(m, false, 0);
+               assertTrue(!e.isDense());
+               assertEquals(1, e.getUnique());
+       }
+
+       @Test
+       public void testNaNSparseTransposed() {
+               MatrixBlock m = getSparseNaNMatrix();
+               IEncode e = EncodingFactory.createFromMatrixBlock(m, true, 0);
+               assertTrue(!e.isDense());
+               assertEquals(1, e.getUnique());
+       }
 }
diff --git 
a/src/test/java/org/apache/sysds/test/component/compress/offset/OffsetReverseTest.java
 
b/src/test/java/org/apache/sysds/test/component/compress/offset/OffsetReverseTest.java
new file mode 100644
index 0000000000..23e63bd7ae
--- /dev/null
+++ 
b/src/test/java/org/apache/sysds/test/component/compress/offset/OffsetReverseTest.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sysds.test.component.compress.offset;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.sysds.runtime.compress.colgroup.offset.AOffset;
+import org.apache.sysds.runtime.compress.colgroup.offset.OffsetFactory;
+import org.junit.Test;
+
+public class OffsetReverseTest {
+
+       @Test
+       public void reverse1() {
+               AOffset off = OffsetFactory.createOffset(new int[] {1, 10, 13, 
14});
+               AOffset rev = AOffset.reverse(16, off);
+               OffsetTests.compare(rev, new int[] {0, 2, 3, 4, 5, 6, 7, 8, 9, 
11, 12, 15});
+       }
+
+       @Test
+       public void reverse2() {
+               AOffset off = OffsetFactory.createOffset(new int[] {1, 10});
+               AOffset rev = AOffset.reverse(16, off);
+               OffsetTests.compare(rev, new int[] {0, 2, 3, 4, 5, 6, 7, 8, 9, 
11, 12, 13, 14, 15});
+       }
+
+       @Test
+       public void reverse3() {
+               AOffset off = OffsetFactory.createOffset(new int[] {1});
+               AOffset rev = AOffset.reverse(16, off);
+               OffsetTests.compare(rev, new int[] {0, 2, 3, 4, 5, 6, 7, 8, 9, 
10, 11, 12, 13, 14, 15});
+       }
+
+       @Test
+       public void reverse4() {
+               AOffset off = OffsetFactory.createOffset(new int[] {1, 10, 13, 
14, 15});
+               AOffset rev = AOffset.reverse(16, off);
+               OffsetTests.compare(rev, new int[] {0, 2, 3, 4, 5, 6, 7, 8, 9, 
11, 12});
+       }
+
+       @Test
+       public void reverse4_withCreateMethod() {
+               int[] exp = new int[] {0, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12};
+               AOffset off = OffsetFactory.createOffset(create(exp, 16));
+               AOffset rev = AOffset.reverse(16, off);
+               OffsetTests.compare(rev, exp);
+       }
+
+       @Test
+       public void reverse1_withCreateMethod() {
+               int[] exp = new int[] {0, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 15};
+               AOffset off = OffsetFactory.createOffset(create(exp, 16));
+               AOffset rev = AOffset.reverse(16, off);
+               OffsetTests.compare(rev, exp);
+       }
+
+       @Test
+       public void reverseCreate1() {
+               test(new int[] {100, 132, 520}, 1000);
+       }
+
+       @Test
+       public void reverseCreate2() {
+               test(new int[] {100, 132, 520, 999}, 1000);
+       }
+
+       @Test
+       public void reverseCreate3() {
+               test(new int[] {1, 999}, 1000);
+       }
+
+       @Test
+       public void reverseCreate4() {
+               test(new int[] {256, 512, 999}, 1000);
+       }
+
+       @Test
+       public void reverse() {
+               AOffset off = OffsetFactory
+                       .createOffset(
+                               new int[] {1, 3, 7, 8, 10, 11, 14, 15, 16, 23, 
25, 26, 28, 31, 32, 34, 36, 38, 42, 43, 44, 46, 47, 52, 55,
+                                       56, 57, 62, 63, 67, 68, 69, 70, 72, 74, 
75, 79, 81, 82, 83, 84, 85, 87, 88, 92, 93, 94, 95, 96, 98, 100,
+                                       105, 108, 109, 110, 111, 117, 120, 121, 
124, 125, 126, 128, 129, 132, 135, 137, 139, 144, 147, 148, 149,
+                                       150, 152, 155, 156, 157, 158, 159, 161, 
165, 166, 167, 168, 170, 173, 176, 179, 180, 182, 183, 185, 187,
+                                       188, 190, 191, 192, 194, 195, 196, 197, 
200, 202, 203, 206, 209, 211, 215, 216, 217, 220, 221, 222, 223,
+                                       224, 225, 226, 227, 228, 230, 234, 239, 
240, 241, 246, 249, 253, 255, 256, 257, 261, 262, 263, 266, 268,
+                                       269, 270, 271, 277, 280, 281, 282, 283, 
284, 285, 286, 287, 288, 289, 292, 293, 294, 297, 299, 302, 305,
+                                       308, 313, 314, 318, 319, 323, 324, 325, 
329, 330, 331, 332, 333, 338, 339, 341, 342, 343, 344, 345, 346,
+                                       347, 350, 351, 352, 354, 355, 356, 358, 
362, 363, 365, 367, 373, 374, 375, 376, 379, 380, 381, 382, 384,
+                                       385, 387, 388, 390, 391, 392, 395, 397, 
401, 402, 405, 406, 407, 411, 415, 416, 418, 419, 420, 423, 424,
+                                       426, 427, 428, 429, 431, 435, 436, 438, 
439, 440, 441, 445, 446, 447, 450, 451, 452, 456, 458, 461, 462,
+                                       464, 465, 467, 468, 469, 470, 477, 481, 
484, 485, 487, 488, 489, 494, 495, 500, 504, 505, 506, 508, 510,
+                                       512, 513, 517, 518, 520, 524, 525, 526, 
527, 528, 529, 531, 532, 534, 538, 540, 543, 544, 546, 548, 551,
+                                       553, 554, 556, 560, 562, 563, 564, 567, 
569, 570, 571, 575, 577, 578, 579, 581, 582, 585, 586, 587, 589,
+                                       592, 593, 594, 598, 600, 605, 607, 613, 
615, 617, 618, 623, 624, 629, 630, 632, 633, 634, 635, 636, 637,
+                                       638, 639, 641, 644, 645, 646, 649, 651, 
652, 654, 657, 659, 663, 664, 669, 671, 672, 673, 677, 678, 679,
+                                       680, 683, 684, 685, 686, 687, 691, 692, 
694, 696, 698, 700, 702, 705, 706, 713, 715, 720, 722, 723, 724,
+                                       728, 729, 730, 733, 735, 736, 737, 739, 
740, 741, 742, 743, 744, 745, 746, 747, 750, 751, 752, 758, 762,
+                                       763, 764, 767, 768, 771, 772, 775, 776, 
778, 779, 781, 785, 788, 789, 791, 792, 793, 794, 797, 804, 806,
+                                       807, 809, 810, 811, 812, 813, 815, 816, 
818, 819, 820, 821, 822, 824, 825, 827, 831, 833, 834, 835, 837,
+                                       838, 839, 840, 841, 843, 848, 849, 851, 
852, 853, 859, 862, 863, 864, 865, 866, 870, 871, 872, 873, 874,
+                                       875, 877, 879, 880, 882, 883, 887, 889, 
891, 892, 894, 896, 897, 898, 899, 901, 902, 903, 905, 906, 908,
+                                       911, 912, 913, 917, 919, 920, 922, 926, 
927, 931, 933, 935, 936, 938, 940, 941, 943, 944, 945, 946, 948,
+                                       950, 953, 957, 959, 961, 967, 968, 974, 
979, 980, 982, 983, 984, 986, 989, 990, 991, 993, 995, 996, 997});
+               AOffset rev = AOffset.reverse(1000, off);
+               // System.out.println(off);
+               // System.out.println(rev);
+               assertEquals(0, rev.getOffsetIterator().value());
+       }
+
+       private void test(int[] missing, int max) {
+               AOffset off = OffsetFactory.createOffset(create(missing, max));
+               AOffset rev = AOffset.reverse(max, off);
+               OffsetTests.compare(rev, missing);
+       }
+
+       private static int[] create(int[] missing, int max) {
+               int[] ret = new int[max - missing.length];
+               int j = 0;
+               int k = 0;
+               for(int i = 0; i < max; i++) {
+                       if(j < missing.length && missing[j] == i)
+                               j++;
+                       else
+                               ret[k++] = i;
+               }
+               return ret;
+       }
+}
diff --git 
a/src/test/java/org/apache/sysds/test/component/compress/readers/ReadersTest.java
 
b/src/test/java/org/apache/sysds/test/component/compress/readers/ReadersTest.java
index a834f42848..7b90eefede 100644
--- 
a/src/test/java/org/apache/sysds/test/component/compress/readers/ReadersTest.java
+++ 
b/src/test/java/org/apache/sysds/test/component/compress/readers/ReadersTest.java
@@ -20,6 +20,8 @@
 package org.apache.sysds.test.component.compress.readers;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.fail;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -132,4 +134,184 @@ public class ReadersTest {
                mb.allocateDenseBlock();
                ReaderColumnSelection.createReader(mb, new int[] {0, 1}, false, 
10, 9);
        }
+
+       @Test
+       public void isEmptyNan() {
+               try {
+
+                       MatrixBlock mb = new MatrixBlock(10, 5, Double.NaN);
+
+                       ReaderColumnSelection reader = 
ReaderColumnSelection.createReader(mb, new int[] {0, 1}, false, 0,
+                               mb.getNumRows());
+                       assertEquals(null, reader.nextRow());
+               }
+               catch(Exception e) {
+                       e.printStackTrace();
+                       fail(e.getMessage());
+               }
+       }
+
+       @Test
+       public void isNaN() {
+               try {
+
+                       MatrixBlock mb = new MatrixBlock(10, 5, Double.NaN);
+                       mb.setValue(1, 1, 3214);
+
+                       ReaderColumnSelection reader = 
ReaderColumnSelection.createReader(mb, new int[] {0, 1}, false, 0,
+                               mb.getNumRows());
+                       DblArray a = reader.nextRow();
+                       assertNotEquals(null, a);
+                       assertEquals(3214.0, a.getData()[1], 0.0);
+                       assertEquals(0.0, a.getData()[0], 0.0);
+               }
+               catch(Exception e) {
+                       e.printStackTrace();
+                       fail(e.getMessage());
+               }
+       }
+
+       @Test
+       public void isEmptyNanTransposed() {
+               try {
+
+                       MatrixBlock mb = new MatrixBlock(10, 5, Double.NaN);
+
+                       ReaderColumnSelection reader = 
ReaderColumnSelection.createReader(mb, new int[] {0, 1}, true, 0,
+                               mb.getNumRows());
+                       assertEquals(null, reader.nextRow());
+               }
+               catch(Exception e) {
+                       e.printStackTrace();
+                       fail(e.getMessage());
+               }
+       }
+
+       @Test
+       public void isNaNTransposed() {
+               try {
+
+                       MatrixBlock mb = new MatrixBlock(10, 5, Double.NaN);
+                       mb.setValue(1, 1, 3214);
+
+                       ReaderColumnSelection reader = 
ReaderColumnSelection.createReader(mb, new int[] {0, 1}, true, 0,
+                               mb.getNumRows());
+                       DblArray a = reader.nextRow();
+                       assertNotEquals(null, a);
+                       assertEquals(3214.0, a.getData()[1], 0.0);
+                       assertEquals(0.0, a.getData()[0], 0.0);
+               }
+               catch(Exception e) {
+                       e.printStackTrace();
+                       fail(e.getMessage());
+               }
+       }
+
+       @Test
+       public void isEmptyNanMultiBlock() {
+               try {
+
+                       MatrixBlock mb = 
ReadersTestCompareReaders.createMock(new MatrixBlock(10, 5, Double.NaN));
+
+                       ReaderColumnSelection reader = 
ReaderColumnSelection.createReader(mb, new int[] {0, 1}, false, 0,
+                               mb.getNumRows());
+                       assertEquals(null, reader.nextRow());
+               }
+               catch(Exception e) {
+                       e.printStackTrace();
+                       fail(e.getMessage());
+               }
+       }
+
+       @Test
+       public void isNaNMultiBlock() {
+               try {
+
+                       MatrixBlock mb = 
ReadersTestCompareReaders.createMock(new MatrixBlock(10, 5, Double.NaN));
+                       mb.setValue(1, 1, 3214);
+
+                       ReaderColumnSelection reader = 
ReaderColumnSelection.createReader(mb, new int[] {0, 1}, false, 0,
+                               mb.getNumRows());
+                       DblArray a = reader.nextRow();
+                       assertNotEquals(null, a);
+                       assertEquals(3214.0, a.getData()[1], 0.0);
+                       assertEquals(0.0, a.getData()[0], 0.0);
+               }
+               catch(Exception e) {
+                       e.printStackTrace();
+                       fail(e.getMessage());
+               }
+       }
+
+       @Test
+       public void isEmptyNanMultiBlockTransposed() {
+               try {
+
+                       MatrixBlock mb = 
ReadersTestCompareReaders.createMock(new MatrixBlock(10, 5, Double.NaN));
+
+                       ReaderColumnSelection reader = 
ReaderColumnSelection.createReader(mb, new int[] {0, 1}, true, 0,
+                               mb.getNumRows());
+                       assertEquals(null, reader.nextRow());
+               }
+               catch(Exception e) {
+                       e.printStackTrace();
+                       fail(e.getMessage());
+               }
+       }
+
+       @Test
+       public void isNaNMultiBlockTransposed() {
+               try {
+
+                       MatrixBlock mb = 
ReadersTestCompareReaders.createMock(new MatrixBlock(10, 5, Double.NaN));
+                       mb.setValue(1, 1, 3214);
+
+                       ReaderColumnSelection reader = 
ReaderColumnSelection.createReader(mb, new int[] {0, 1}, true, 0,
+                               mb.getNumRows());
+                       DblArray a = reader.nextRow();
+                       assertNotEquals(null, a);
+                       assertEquals(3214.0, a.getData()[1], 0.0);
+                       assertEquals(0.0, a.getData()[0], 0.0);
+               }
+               catch(Exception e) {
+                       e.printStackTrace();
+                       fail(e.getMessage());
+               }
+       }
+
+       @Test
+       public void isNanSparseBlock() {
+               MatrixBlock mbs = new MatrixBlock(10, 10, true);
+               mbs.setValue(1, 1, 3214);
+               mbs.setValue(0, 0, Double.NaN);
+               mbs.setValue(0, 1, Double.NaN);
+               mbs.setValue(1, 0, Double.NaN);
+
+               ReaderColumnSelection reader = 
ReaderColumnSelection.createReader(mbs, new int[] {0, 1}, false, 0,
+                       mbs.getNumRows());
+
+               DblArray a = reader.nextRow();
+               assertNotEquals(null, a);
+               assertEquals(3214.0, a.getData()[1], 0.0);
+               assertEquals(0.0, a.getData()[0], 0.0);
+               assertEquals(null, reader.nextRow());
+       }
+
+       @Test
+       public void isNanSparseBlockTransposed() {
+               MatrixBlock mbs = new MatrixBlock(10, 10, true);
+               mbs.setValue(1, 1, 3214);
+               mbs.setValue(0, 0, Double.NaN);
+               mbs.setValue(0, 1, Double.NaN);
+               mbs.setValue(1, 0, Double.NaN);
+
+               ReaderColumnSelection reader = 
ReaderColumnSelection.createReader(mbs, new int[] {0, 1}, true, 0,
+                       mbs.getNumRows());
+
+               DblArray a = reader.nextRow();
+               assertNotEquals(null, a);
+               assertEquals(3214.0, a.getData()[1], 0.0);
+               assertEquals(0.0, a.getData()[0], 0.0);
+               assertEquals(null, reader.nextRow());
+       }
 }
diff --git 
a/src/test/java/org/apache/sysds/test/component/compress/readers/ReadersTestCompareReaders.java
 
b/src/test/java/org/apache/sysds/test/component/compress/readers/ReadersTestCompareReaders.java
index 724ea79a63..f9958f73d0 100644
--- 
a/src/test/java/org/apache/sysds/test/component/compress/readers/ReadersTestCompareReaders.java
+++ 
b/src/test/java/org/apache/sysds/test/component/compress/readers/ReadersTestCompareReaders.java
@@ -575,9 +575,17 @@ public class ReadersTestCompareReaders {
                return subCols;
        }
 
-       private class DenseBlockFP64Mock extends DenseBlockFP64 {
+       public static MatrixBlock createMock(MatrixBlock d){
+               DenseBlockFP64 a = new DenseBlockFP64Mock(new 
int[]{d.getNumRows(), d.getNumColumns()}, d.getDenseBlockValues());
+               MatrixBlock b =  new MatrixBlock(d.getNumRows(), 
d.getNumColumns(), a);
+               b.setNonZeros(d.getNumRows() * d.getNumColumns());
+               return b;
+       }
+
+       protected static class DenseBlockFP64Mock extends DenseBlockFP64 {
                private static final long serialVersionUID = 
-3601232958390554672L;
 
+
                public DenseBlockFP64Mock(int[] dims, double[] data) {
                        super(dims, data);
                }

Reply via email to