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
commit 11d07737a61d2142774c89857fb00d3338d6cc1d Author: baunsgaard <[email protected]> AuthorDate: Tue Oct 25 19:55:18 2022 +0200 [MINOR] Add scheme for empty Add a empty scheme for empty column groups. Closes #1711 --- .../runtime/compress/colgroup/ColGroupEmpty.java | 3 +- .../runtime/compress/colgroup/ColGroupSDC.java | 3 +- .../runtime/compress/colgroup/ColGroupSDCFOR.java | 9 +- .../compress/colgroup/ColGroupSDCSingle.java | 2 +- .../compress/colgroup/ColGroupSDCSingleZeros.java | 3 +- .../compress/colgroup/ColGroupSDCZeros.java | 9 +- .../compress/colgroup/dictionary/Dictionary.java | 5 +- .../colgroup/dictionary/MatrixBlockDictionary.java | 4 +- .../compress/colgroup/scheme/ConstScheme.java | 18 +- .../scheme/{ConstScheme.java => EmptyScheme.java} | 82 +++-- .../org/apache/sysds/runtime/data/SparseBlock.java | 12 + .../component/compress/colgroup/ColGroupTest.java | 62 +++- .../colgroup/scheme/CLAEmptySchemeTest.java | 354 +++++++++++++++++++++ 13 files changed, 491 insertions(+), 75 deletions(-) diff --git a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupEmpty.java b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupEmpty.java index 81dd5cb6d7..32d66fcdba 100644 --- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupEmpty.java +++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupEmpty.java @@ -25,6 +25,7 @@ import java.util.Arrays; import org.apache.sysds.runtime.DMLRuntimeException; import org.apache.sysds.runtime.compress.colgroup.dictionary.Dictionary; +import org.apache.sysds.runtime.compress.colgroup.scheme.EmptyScheme; import org.apache.sysds.runtime.compress.colgroup.scheme.ICLAScheme; import org.apache.sysds.runtime.compress.cost.ComputationCostEstimator; import org.apache.sysds.runtime.compress.utils.Util; @@ -330,6 +331,6 @@ public class ColGroupEmpty extends AColGroupCompressed { @Override public ICLAScheme getCompressionScheme() { - return null; + return EmptyScheme.create(this); } } 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 a665149aa5..db9cc6f1a5 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 @@ -586,7 +586,7 @@ public class ColGroupSDC extends ASDC implements AMapToDataGroup { @Override public AColGroup appendNInternal(AColGroup[] g) { - int sumRows = 0; + int sumRows = getNumRows(); for(int i = 1; i < g.length; i++) { if(!Arrays.equals(_colIndexes, g[i]._colIndexes)) { LOG.warn("Not same columns therefore not appending \n" + Arrays.toString(_colIndexes) + "\n\n" @@ -617,7 +617,6 @@ public class ColGroupSDC extends ASDC implements AMapToDataGroup { return null; } - @Override public String toString() { StringBuilder sb = new StringBuilder(); 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 b381e81665..dd953c283a 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 @@ -57,7 +57,7 @@ import org.apache.sysds.runtime.matrix.operators.UnaryOperator; * with no modifications. * */ -public class ColGroupSDCFOR extends ASDC { +public class ColGroupSDCFOR extends ASDC implements AMapToDataGroup { private static final long serialVersionUID = 3883228464052204203L; @@ -116,6 +116,11 @@ public class ColGroupSDCFOR extends ASDC { return _data.getCounts(counts); } + @Override + public AMapToData getMapToData() { + return _data; + } + @Override protected void computeRowSums(double[] c, int rl, int ru, double[] preAgg) { ColGroupSDC.computeRowSums(c, rl, ru, preAgg, _data, _indexes, _numRows); @@ -447,7 +452,7 @@ public class ColGroupSDCFOR extends ASDC { @Override public AColGroup appendNInternal(AColGroup[] g) { - int sumRows = 0; + int sumRows = getNumRows(); for(int i = 1; i < g.length; i++) { if(!Arrays.equals(_colIndexes, g[i]._colIndexes)) { LOG.warn("Not same columns therefore not appending \n" + Arrays.toString(_colIndexes) + "\n\n" 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 a66f4387de..739eb33379 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 @@ -584,7 +584,7 @@ public class ColGroupSDCSingle extends ASDC { @Override public AColGroup appendNInternal(AColGroup[] g) { - int sumRows = 0; + int sumRows = getNumRows(); for(int i = 1; i < g.length; i++) { if(!Arrays.equals(_colIndexes, g[i]._colIndexes)) { LOG.warn("Not same columns therefore not appending \n" + Arrays.toString(_colIndexes) + "\n\n" 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 46657d2b7a..e4a53b3cfb 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 @@ -817,7 +817,7 @@ public class ColGroupSDCSingleZeros extends ASDCZero { @Override public AColGroup appendNInternal(AColGroup[] g) { - int sumRows = 0; + int sumRows = getNumRows(); for(int i = 1; i < g.length; i++) { if(!Arrays.equals(_colIndexes, g[i]._colIndexes)) { LOG.warn("Not same columns therefore not appending \n" + Arrays.toString(_colIndexes) + "\n\n" @@ -839,7 +839,6 @@ public class ColGroupSDCSingleZeros extends ASDCZero { } AOffset no = _indexes.appendN(Arrays.copyOf(g, g.length, AOffsetsGroup[].class), getNumRows()); return create(_colIndexes, sumRows, _dict, no, 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 3ffb070b26..f926cdac6f 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 @@ -56,7 +56,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 { +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. */ @@ -89,6 +89,11 @@ public class ColGroupSDCZeros extends ASDCZero { return ColGroupType.SDCZeros; } + @Override + public AMapToData getMapToData(){ + return _data; + } + @Override protected void decompressToDenseBlockDenseDictionary(DenseBlock db, int rl, int ru, int offR, int offC, double[] values) { @@ -728,7 +733,7 @@ public class ColGroupSDCZeros extends ASDCZero { @Override public AColGroup appendNInternal(AColGroup[] g) { - int sumRows = 0; + int sumRows = getNumRows(); for(int i = 1; i < g.length; i++) { if(!Arrays.equals(_colIndexes, g[i]._colIndexes)) { LOG.warn("Not same columns therefore not appending \n" + Arrays.toString(_colIndexes) + "\n\n" diff --git a/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/Dictionary.java b/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/Dictionary.java index 7cfc49e32b..852cc733c1 100644 --- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/Dictionary.java +++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/Dictionary.java @@ -26,7 +26,6 @@ import java.math.BigDecimal; import java.math.MathContext; import java.util.Arrays; -import org.apache.commons.lang.NotImplementedException; import org.apache.sysds.runtime.compress.DMLCompressionException; import org.apache.sysds.runtime.data.SparseBlock; import org.apache.sysds.runtime.functionobjects.Builtin; @@ -1070,10 +1069,10 @@ public class Dictionary extends ADictionary { public boolean eq(ADictionary o) { if(o instanceof Dictionary) return Arrays.equals(_values, ((Dictionary) o)._values); - else if(o instanceof MatrixBlockDictionary){ + else if(o instanceof MatrixBlockDictionary) { final MatrixBlock mb = ((MatrixBlockDictionary) o).getMatrixBlock(); if(mb.isInSparseFormat()) - throw new NotImplementedException(); + return mb.getSparseBlock().equals(_values, mb.getNumColumns()); final double[] dv = mb.getDenseBlockValues(); return Arrays.equals(_values, dv); } diff --git a/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/MatrixBlockDictionary.java b/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/MatrixBlockDictionary.java index d575f5232f..b13efbe4c1 100644 --- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/MatrixBlockDictionary.java +++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/MatrixBlockDictionary.java @@ -2147,10 +2147,10 @@ public class MatrixBlockDictionary extends ADictionary { @Override public boolean eq(ADictionary o) { if(o instanceof MatrixBlockDictionary) - throw new NotImplementedException("Comparison if a MatrixBlock is equivalent is not implemented yet"); + return _data.equals(((MatrixBlockDictionary) o)._data); else if(o instanceof Dictionary) { if(_data.isInSparseFormat()) - throw new NotImplementedException(); + return _data.getSparseBlock().equals(((Dictionary) o)._values, _data.getNumColumns()); final double[] dv = _data.getDenseBlockValues(); return Arrays.equals(dv, ((Dictionary) o)._values); } diff --git a/src/main/java/org/apache/sysds/runtime/compress/colgroup/scheme/ConstScheme.java b/src/main/java/org/apache/sysds/runtime/compress/colgroup/scheme/ConstScheme.java index 1a65f1417f..91896d5c3b 100644 --- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/scheme/ConstScheme.java +++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/scheme/ConstScheme.java @@ -77,7 +77,7 @@ public class ConstScheme implements ICLAScheme { if(dv[off + cols[ci]] != values[ci]) return null; } - return g; + return returnG(cols); } private AColGroup encodeSparse(final MatrixBlock data, final int[] cols, final double[] values, final int nRow, @@ -92,7 +92,9 @@ public class ConstScheme implements ICLAScheme { final double[] aval = sb.values(r); final int[] aix = sb.indexes(r); int p = 0; // pointer into cols; - while(p < cols.length && values[p] == 0.0) + while(values[p] == 0.0) + // technically also check for&& p < cols.length + // but this verification is indirectly maintained p++; for(int j = apos; j < alen && p < cols.length; j++) { if(aix[j] == cols[p]) { @@ -106,7 +108,7 @@ public class ConstScheme implements ICLAScheme { return null; // not matching } } - return g; + return returnG(cols); } private AColGroup encodeGeneric(final MatrixBlock data, final int[] cols, final double[] values, final int nRow, @@ -115,6 +117,14 @@ public class ConstScheme implements ICLAScheme { for(int ci = 0; ci < cols.length; ci++) if(data.quickGetValue(r, cols[ci]) != values[ci]) return null; - return g; + return returnG(cols); } + + private AColGroup returnG(int[] columns) { + if(columns == g.getColIndices()) + return g;// great! + else + return ColGroupConst.create(columns, g.getValues()); + } + } diff --git a/src/main/java/org/apache/sysds/runtime/compress/colgroup/scheme/ConstScheme.java b/src/main/java/org/apache/sysds/runtime/compress/colgroup/scheme/EmptyScheme.java similarity index 59% copy from src/main/java/org/apache/sysds/runtime/compress/colgroup/scheme/ConstScheme.java copy to src/main/java/org/apache/sysds/runtime/compress/colgroup/scheme/EmptyScheme.java index 1a65f1417f..fff5b70981 100644 --- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/scheme/ConstScheme.java +++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/scheme/EmptyScheme.java @@ -20,101 +20,95 @@ package org.apache.sysds.runtime.compress.colgroup.scheme; import org.apache.sysds.runtime.compress.colgroup.AColGroup; -import org.apache.sysds.runtime.compress.colgroup.ColGroupConst; +import org.apache.sysds.runtime.compress.colgroup.ColGroupEmpty; import org.apache.sysds.runtime.data.SparseBlock; import org.apache.sysds.runtime.matrix.data.MatrixBlock; -public class ConstScheme implements ICLAScheme { +public class EmptyScheme implements ICLAScheme { + /** The instance of a empty column group that in all cases here would be returned to be the same */ + final ColGroupEmpty g; - /** The instance of a constant column group that in all cases here would be returned to be the same */ - final ColGroupConst g; - - protected ConstScheme(ColGroupConst g) { + protected EmptyScheme(ColGroupEmpty g) { this.g = g; } - public static ICLAScheme create(ColGroupConst g) { - return new ConstScheme(g); + public static EmptyScheme create(ColGroupEmpty g) { + return new EmptyScheme(g); } @Override public AColGroup encode(MatrixBlock data) { - return encode(data, g.getColIndices(), g.getValues()); + return encode(data, g.getColIndices()); } @Override public AColGroup encode(MatrixBlock data, int[] columns) { + if(columns.length != g.getColIndices().length) throw new IllegalArgumentException("Invalid columns to encode"); - return encode(data, columns, g.getValues()); - } - - private AColGroup encode(final MatrixBlock data, final int[] cols, final double[] values) { final int nCol = data.getNumColumns(); final int nRow = data.getNumRows(); - if(nCol < cols[cols.length - 1]) { + if(nCol < columns[columns.length - 1]) { LOG.warn("Invalid to encode matrix with less columns than encode scheme max column"); return null; } - else if(data.isEmpty()) { - LOG.warn("Invalid to encode an empty matrix into constant column group"); - return null; // Invalid to encode this. - } + else if(data.isEmpty()) + return returnG(columns); else if(data.isInSparseFormat()) - return encodeSparse(data, cols, values, nRow, nCol); + return encodeSparse(data, columns, nRow, nCol); else if(data.getDenseBlock().isContiguous()) - return encodeDense(data, cols, values, nRow, nCol); + return encodeDense(data, columns, nRow, nCol); else - return encodeGeneric(data, cols, values, nRow, nCol); + return encodeGeneric(data, columns, nRow, nCol); } - private AColGroup encodeDense(final MatrixBlock data, final int[] cols, final double[] values, final int nRow, - final int nCol) { + private AColGroup encodeDense(final MatrixBlock data, final int[] cols, final int nRow, final int nCol) { final double[] dv = data.getDenseBlockValues(); for(int r = 0; r < nRow; r++) { final int off = r * nCol; for(int ci = 0; ci < cols.length; ci++) - if(dv[off + cols[ci]] != values[ci]) + if(dv[off + cols[ci]] != 0.0) return null; } return g; } - private AColGroup encodeSparse(final MatrixBlock data, final int[] cols, final double[] values, final int nRow, - final int nCol) { + private AColGroup encodeSparse(final MatrixBlock data, final int[] cols, final int nRow, final int nCol) { SparseBlock sb = data.getSparseBlock(); for(int r = 0; r < nRow; r++) { if(sb.isEmpty(r)) - return null; + continue; // great! final int apos = sb.pos(r); final int alen = apos + sb.size(r); - final double[] aval = sb.values(r); final int[] aix = sb.indexes(r); int p = 0; // pointer into cols; - while(p < cols.length && values[p] == 0.0) - p++; - for(int j = apos; j < alen && p < cols.length; j++) { - if(aix[j] == cols[p]) { - if(aval[j] != values[p]) - return null; + for(int j = apos; j < alen ; j++) { + while(p < cols.length && cols[p] < aix[j]) p++; - while(p < cols.length && values[p] == 0.0) - p++; - } - else if(aix[j] > cols[p]) - return null; // not matching + if(p < cols.length && aix[j] == cols[p]) + return null; + + if(p >= cols.length) + continue; } } - return g; + return returnG(cols); } - private AColGroup encodeGeneric(final MatrixBlock data, final int[] cols, final double[] values, final int nRow, - final int nCol) { + private AColGroup encodeGeneric(final MatrixBlock data, final int[] cols, final int nRow, final int nCol) { for(int r = 0; r < nRow; r++) for(int ci = 0; ci < cols.length; ci++) - if(data.quickGetValue(r, cols[ci]) != values[ci]) + if(data.quickGetValue(r, cols[ci]) != 0.0) return null; - return g; + return returnG(cols); + } + + private AColGroup returnG(int[] columns) { + if(columns == g.getColIndices()) + return g;// great! + else + return new ColGroupEmpty(columns); } + } diff --git a/src/main/java/org/apache/sysds/runtime/data/SparseBlock.java b/src/main/java/org/apache/sysds/runtime/data/SparseBlock.java index e5310dc23c..bbddb9a178 100644 --- a/src/main/java/org/apache/sysds/runtime/data/SparseBlock.java +++ b/src/main/java/org/apache/sysds/runtime/data/SparseBlock.java @@ -573,6 +573,18 @@ public abstract class SparseBlock implements Serializable, Block return true; } + + /** + * Get if the dense double array is equivalent to this sparse Block. + * + * @param denseValues row major double values same dimensions of sparse Block. + * @param nCol Number of columns in dense values (and hopefully in this sparse block) + * @return If the dense array is equivalent + */ + public boolean equals(double[] denseValues, int nCol) { + return equals(denseValues, nCol, Double.MIN_NORMAL * 1024); + } + /** * Get if the dense double array is equivalent to this sparse Block. * 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 fa3d1d44d3..f609f0bcea 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 @@ -2112,18 +2112,6 @@ public class ColGroupTest extends ColGroupBase { assertTrue(co < eo); } - // @Test - // public void copyMaintainPointers() { - // AColGroup a = base.copy(); - // AColGroup b = other.copy(); - - // assertTrue(a.getColIndices() == base.getColIndices()); - // assertTrue(b.getColIndices() == other.getColIndices()); - // // assertFalse(a.getColIndices() == other.getColIndices()); - // assertFalse(a == base); - // assertFalse(b == other); - // } - @Test public void sliceRowsBeforeEnd() { if(nRow > 10) @@ -2241,4 +2229,54 @@ public class ColGroupTest extends ColGroupBase { fail(e.getMessage()); } } + + @Test + public void testAppendSelf() { + appendSelfVerification(base); + appendSelfVerification(other); + } + + @Test + public void testAppendSomethingElse() { + // This is under the assumption that if one is appending + // to the other then other should append to this. + // If this property does not hold it is because some cases are missing in the append logic. + try { + + AColGroup g2 = base.append(other); + AColGroup g2n = other.append(base); + // both should be null, or both should not be. + if(g2 == null) + assertTrue(g2n == null); + else if(g2 != null) + assertTrue(g2n != null); + } + catch(Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + private void appendSelfVerification(AColGroup g) { + try { + + AColGroup g2 = g.append(g); + AColGroup g2n = AColGroup.appendN(new AColGroup[] {g, g}); + + if(g2 != null && g2n != null) { + double s2 = g2.getSum(nRow * 2); + double s = g.getSum(nRow) * 2; + double s2n = g2n.getSum(nRow * 2); + assertEquals(s2, s, 0.0001); + assertEquals(s2n, s, 0.0001); + + UA_ROW(InstructionUtils.parseBasicAggregateUnaryOperator("uar+", 1), 0, nRow * 2, g2, g2n, nRow * 2); + } + } + catch(Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + } diff --git a/src/test/java/org/apache/sysds/test/component/compress/colgroup/scheme/CLAEmptySchemeTest.java b/src/test/java/org/apache/sysds/test/component/compress/colgroup/scheme/CLAEmptySchemeTest.java new file mode 100644 index 0000000000..bfcf2012b8 --- /dev/null +++ b/src/test/java/org/apache/sysds/test/component/compress/colgroup/scheme/CLAEmptySchemeTest.java @@ -0,0 +1,354 @@ +/* + * 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.colgroup.scheme; + +import static org.junit.Assert.assertTrue; + +import org.apache.sysds.runtime.compress.colgroup.AColGroup; +import org.apache.sysds.runtime.compress.colgroup.ColGroupEmpty; +import org.apache.sysds.runtime.compress.colgroup.scheme.ICLAScheme; +import org.apache.sysds.runtime.data.DenseBlockFP64; +import org.apache.sysds.runtime.matrix.data.MatrixBlock; +import org.junit.Test; + +public class CLAEmptySchemeTest { + + private final AColGroup g; + private final ICLAScheme sh; + + public CLAEmptySchemeTest() { + g = new ColGroupEmpty(// + new int[] {1, 3, 5} // Columns + ); + sh = g.getCompressionScheme(); + } + + @Test + public void testConstValid() { + assertTrue(sh != null); + } + + @Test + public void testToSmallMatrix() { + assertTrue(sh.encode(new MatrixBlock(1, 3, new double[] {// + 1.1, 1.2, 1.3})) == null); + } + + @Test + public void testWrongValuesSingleRow() { + assertTrue(sh.encode(new MatrixBlock(1, 6, new double[] {// + 0.0, 1.1, 0.2, 1.2, 0.2, 1.2})) == null); + } + + @Test + public void testWrongValuesSingleRowV2() { + assertTrue(sh.encode(new MatrixBlock(1, 6, new double[] {// + 0.0, 1.0, 0.2, 1.2, 0.2, 1.3})) == null); + } + + @Test + public void testValidEncodeSingleRow() { + assertTrue(sh.encode(new MatrixBlock(1, 6, new double[] {// + 0.1, 0.0, 0.04, 0.0, 0.03, 0.0})) != null); + } + + @Test + public void testValidEncodeMultiRow() { + assertTrue(sh.encode(new MatrixBlock(2, 6, new double[] {// + 132, 0.0, 241, 0.0, 142, 0.0, // + 132, 0.0, 241, 0.0, 142, 0.0, // + })) != null); + } + + @Test + public void testValidEncodeMultiRowsLarger() { + assertTrue(sh.encode(new MatrixBlock(2, 10, new double[] {// + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1, 1, 1, 1, // + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1, 1, 1, 1, // + })) != null); + } + + @Test + public void testInvalidEncodeMultiRowsValue() { + assertTrue(sh.encode(new MatrixBlock(4, 8, new double[] {// + 0.0, 0.0, 0.2, 0.0, 1.2, 0.0, 0.2, 1.3, // + 0.0, 0.0, 0.2, 0.0, 1.2, 0.0, 0.2, 1.3, // + 0.0, 0.0, 0.2, 0.0, 1.2, 0.0, 0.2, 1.3, // + 0.0, 0.0, 0.2, 0.0, 1.2, 0.0, 0.2, 1.3, // + })) != null); + } + + @Test + public void testValidEncodeMultiRowDifferentValuesOtherColumns() { + assertTrue(sh.encode(new MatrixBlock(4, 12, new double[] {// + 0.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.1, 0.4, 1.2, 0.3, 1.3, // + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.1, 0.2, 1.2, 0.2, 1.3, // + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.1, 0.2, 1.2, 0.1, 1.3, // + 0.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.1, 0.4, 1.2, 0.1, 1.3, // + })) != null); + } + + @Test + public void testInvalidEncodeValueMultiRowMultiError() { + assertTrue(sh.encode(new MatrixBlock(4, 6, new double[] {// + 0.0, 1.1, 0.2, 1.2, 0.2, 1.3, // + 0.0, 1.1, 0.2, 1.2, 0.2, 1.3, // + 0.0, 1.1, 0.2, 1.2, 0.2, 1.4, // + 0.0, 1.1, 0.2, 1.2, 0.2, 1.3, // + })) == null); + } + + @Test + public void testInvalidEncodeMultiRow() { + assertTrue(sh.encode(new MatrixBlock(4, 6, new double[] {// + 0.0, 1.3, 0.2, 1.2, 0.2, 1.3, // + 0.0, 1.1, 0.2, 1.2, 0.2, 1.3, // + 0.0, 1.1, 0.2, 1.2, 0.2, 1.4, // + 0.0, 1.1, 0.2, 1.2, 0.2, 1.3, // + })) == null); + } + + @Test + public void testEncodeOtherColumns() { + assertTrue(sh.encode(new MatrixBlock(4, 5, new double[] {// + 1.1, 0.2, 1.2, 0.2, 1.3, // + 1.1, 0.2, 1.2, 0.2, 1.3, // + 1.1, 0.2, 1.2, 0.2, 1.3, // + 1.1, 0.2, 1.2, 0.2, 1.3, // + }), new int[] {0, 2, 4}// other columns + ) == null); + } + + @Test + public void testEncodeOtherColumnsValid() { + assertTrue(sh.encode(new MatrixBlock(4, 8, new double[] {// + 0.0, 1.1, 0.0, 0.2, 0.0, 1.2, 0.2, 1.3, // + 0.0, 1.1, 0.0, 0.2, 0.0, 1.2, 0.2, 1.3, // + 0.0, 1.1, 0.0, 0.2, 0.0, 1.2, 0.2, 1.3, // + 0.0, 1.1, 0.0, 0.2, 0.0, 1.2, 0.2, 1.3, // + }), new int[] {0, 2, 4}// other columns + ) != null); + } + + @Test + public void testEncodeOtherColumnsInvalid() { + assertTrue(sh.encode(new MatrixBlock(4, 5, new double[] {// + 1.1, 0.2, 1.2, 0.2, 1.3, // + 1.1, 0.2, 1.2, 0.2, 1.3, // + 1.1, 0.2, 1.4, 0.2, 1.3, // + 1.1, 0.2, 1.2, 0.2, 1.3, // + }), new int[] {0, 2, 4}// other columns + ) == null); + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidArgument_1() { + sh.encode(null, new int[] {0, 2, 4, 5}); + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidArgument_2() { + sh.encode(null, new int[] {0, 2}); + } + + @Test + public void testSparse() { + MatrixBlock mb = new MatrixBlock(4, 6, new double[] {// + 0.01, 0.0, 0.2, 0.0, 0.2, 0.0, // + 0.01, 0.0, 0.2, 0.0, 0.2, 0.0, // + 0.01, 0.0, 0.2, 0.0, 0.2, 0.0, // + 0.01, 0.0, 0.2, 0.0, 0.2, 0.0, // + }); + + MatrixBlock empty = new MatrixBlock(4, 1000, 0.0); + mb = mb.append(empty); + + assertTrue(sh.encode(mb) != null); + } + + @Test + public void testSpars_AllCosOver() { + MatrixBlock mb = new MatrixBlock(4, 6, new double[] {// + 0.01, 0.0, 0.2, 0.0, 0.2, 0.0, // + 0.01, 0.0, 0.2, 0.0, 0.2, 0.0, // + 0.01, 0.0, 0.2, 0.0, 0.2, 0.0, // + 0.01, 0.0, 0.2, 0.0, 0.2, 0.0, // + }); + + MatrixBlock empty = new MatrixBlock(4, 1000, 0.0); + mb = mb.append(empty); + + assertTrue(sh.encode(mb, new int[] {100, 102, 999}) != null); + } + + @Test + public void testSpars_InsideInvalid() { + MatrixBlock mb = new MatrixBlock(4, 6, new double[] {// + 0.01, 0.0, 0.2, 0.0, 0.2, 0.0, // + 0.01, 0.0, 0.2, 0.0, 0.2, 0.0, // + 0.01, 0.0, 0.2, 0.0, 0.2, 0.0, // + 0.01, 0.0, 0.2, 0.0, 0.2, 0.0, // + }); + + MatrixBlock empty = new MatrixBlock(4, 1000, 0.0); + mb = mb.append(empty); + + assertTrue(sh.encode(mb, new int[] {1, 4, 5}) == null); + } + + @Test + public void testSparse_Append() { + MatrixBlock mb = new MatrixBlock(4, 6, new double[] {// + 0.0, 0.0, 0.2, 0.0, 0.2, 1.3, // + 0.0, 0.0, 0.2, 0.0, 0.2, 1.3, // + 0.0, 0.0, 0.2, 0.0, 0.2, 1.3, // + 0.0, 0.0, 0.2, 0.0, 0.2, 1.3, // + }); + + MatrixBlock empty = new MatrixBlock(4, 1000, 0.0); + mb = empty.append(mb); + + assertTrue(sh.encode(mb) != null); + } + + @Test + public void testSparseValidCustom() { + MatrixBlock mb = new MatrixBlock(4, 9, new double[] {// + 0.0, 0.0, 1.1, 0.0, 0.2, 0.0, 1.2, 0.2, 1.3, // + 0.0, 0.0, 1.1, 0.0, 0.2, 0.0, 1.2, 0.2, 1.3, // + 0.0, 0.0, 1.1, 0.0, 0.2, 0.0, 1.2, 0.2, 1.3, // + 0.0, 0.0, 1.1, 0.0, 0.2, 0.0, 1.2, 0.2, 1.3, // + }); + + MatrixBlock empty = new MatrixBlock(4, 1000, 0.0); + mb = empty.append(mb); + + assertTrue(sh.encode(mb, new int[] {1001, 1003, 1005}) != null); + } + + @Test + public void testSparseValidCustom2() { + MatrixBlock mb = new MatrixBlock(4, 9, new double[] {// + 0.0, 0.0, 1.1, 0.0, 0.2, 0.0, 1.2, 0.2, 1.3, // + 0.0, 0.0, 1.1, 0.0, 0.2, 0.0, 1.2, 0.2, 1.3, // + 0.0, 0.0, 1.1, 0.0, 0.2, 0.0, 1.2, 0.2, 1.3, // + 0.0, 0.0, 1.1, 0.0, 0.2, 0.0, 1.2, 0.2, 1.3, // + }); + + MatrixBlock empty = new MatrixBlock(4, 1000, 0.0); + MatrixBlock comb = empty.append(mb).append(mb); + + assertTrue(sh.encode(comb, new int[] {1001, 1003, 1005}) != null); + } + + @Test + public void testSparseValidCustom3Valid() { + MatrixBlock mb = new MatrixBlock(4, 9, new double[] {// + 0.0, 0.0, 1.1, 0.0, 0.2, 0.0, 1.2, 0.2, 1.3, // + 0.0, 0.0, 1.1, 0.0, 0.2, 0.0, 1.33, 0.2, 1.3, // + 0.0, 0.0, 1.1, 0.0, 0.2, 0.0, 1.2, 0.2, 1.3, // + 0.0, 0.0, 1.1, 0.0, 0.2, 0.0, 1.2, 0.2, 1.3, // + }); + + MatrixBlock empty = new MatrixBlock(4, 1000, 0.0); + MatrixBlock comb = empty.append(mb).append(mb); + + assertTrue(sh.encode(comb, new int[] {1001, 1003, 1005}) != null); + } + + @Test + public void testSparseEmptyRow() { + MatrixBlock mb = new MatrixBlock(4, 6, new double[] {// + 0.0, 1.1, 0.2, 1.2, 0.2, 1.3, // + 0.0, 1.1, 0.2, 1.2, 0.2, 1.3, // + 0.0, 1.1, 0.2, 1.2, 0.2, 1.3, // + 0.0, 1.1, 0.2, 1.2, 0.2, 1.3, // + }); + + MatrixBlock empty = new MatrixBlock(4, 1000, 0.0); + mb = empty.append(mb); + MatrixBlock emptyRow = new MatrixBlock(1, 1006, 0.0); + mb = mb.append(emptyRow, false); + + assertTrue(sh.encode(mb, new int[] {44, 45, 999}) != null); + } + + @Test + public void testEmpty() { + MatrixBlock empty = new MatrixBlock(4, 1000, 0.0); + assertTrue(sh.encode(empty) != null); + } + + @Test + public void testEmptyOtherColumns() { + MatrixBlock empty = new MatrixBlock(4, 1000, 0.0); + assertTrue(sh.encode(empty, new int[] {33, 34, 99}) != null); + } + + @Test + public void testGenericNonContinuosBlockValid() { + MatrixBlock mb = new MatrixBlock(4, 6, // + new DenseBlockFP64Mock(new int[] {4, 9}, new double[] {// + 0.2, 0.0, 1.1, 0.0, 0.4, 0.0, 1.2, 0.3, 1.3, // + 0.0, 0.0, 1.1, 0.0, 0.2, 0.0, 1.2, 0.2, 1.3, // + 0.0, 0.0, 1.1, 0.0, 0.2, 0.0, 1.2, 0.1, 1.3, // + 0.2, 0.0, 1.1, 0.0, 0.4, 0.0, 1.2, 0.1, 1.3, // + })); + mb.recomputeNonZeros(); + assertTrue(sh.encode(mb) != null); + } + + @Test + public void testGenericNonContinuosBlockInValid() { + MatrixBlock mb = new MatrixBlock(4, 6, // + new DenseBlockFP64Mock(new int[] {4, 6}, new double[] {// + 0.2, 1.1, 0.4, 1.2, 0.3, 1.3, // + 0.0, 1.1, 0.2, 1.2, 0.2, 1.3, // + 0.0, 1.1, 0.2, 1.2, 0.1, 1.3, // + 0.2, 1.22, 0.4, 1.2, 0.1, 1.3, // + })); + mb.recomputeNonZeros(); + assertTrue(sh.encode(mb) == null); + } + + @Test(expected = NullPointerException.class) + public void testNull() { + sh.encode(null, null); + } + + private class DenseBlockFP64Mock extends DenseBlockFP64 { + private static final long serialVersionUID = -3601232958390554672L; + + public DenseBlockFP64Mock(int[] dims, double[] data) { + super(dims, data); + } + + @Override + public boolean isContiguous() { + return false; + } + + @Override + public int numBlocks() { + return 2; + } + } + +}
