[SYSTEMML-472] New component test suite for sparse matrix blocks This test suite covers over 100 tests of important SparseBlock primitives of all SparseBlock implementations. The entire test suite runs in less than 10s because these tests run purely in-memory and without the need for R comparisons.
Project: http://git-wip-us.apache.org/repos/asf/incubator-systemml/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-systemml/commit/82d5c5f1 Tree: http://git-wip-us.apache.org/repos/asf/incubator-systemml/tree/82d5c5f1 Diff: http://git-wip-us.apache.org/repos/asf/incubator-systemml/diff/82d5c5f1 Branch: refs/heads/master Commit: 82d5c5f16d581aaa91bcf09854c2cfd6af427072 Parents: 7ce3707 Author: Matthias Boehm <[email protected]> Authored: Sun Jan 17 23:11:48 2016 -0800 Committer: Matthias Boehm <[email protected]> Committed: Sun Jan 17 23:12:50 2016 -0800 ---------------------------------------------------------------------- .../functions/sparse/SparseBlockAppendSort.java | 214 ++++++++++++++ .../functions/sparse/SparseBlockDelete.java | 164 +++++++++++ .../sparse/SparseBlockGetFirstIndex.java | 284 +++++++++++++++++++ .../functions/sparse/SparseBlockGetSet.java | 275 ++++++++++++++++++ .../functions/sparse/SparseBlockIndexRange.java | 225 +++++++++++++++ .../functions/sparse/SparseBlockIterator.java | 205 +++++++++++++ .../functions/sparse/SparseBlockScan.java | 157 ++++++++++ .../functions/sparse/ZPackageSuite.java | 42 +++ 8 files changed, 1566 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/82d5c5f1/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockAppendSort.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockAppendSort.java b/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockAppendSort.java new file mode 100644 index 0000000..a563fde --- /dev/null +++ b/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockAppendSort.java @@ -0,0 +1,214 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.sysml.test.integration.functions.sparse; + +import org.junit.Assert; +import org.junit.Test; +import org.apache.sysml.runtime.matrix.data.SparseBlock; +import org.apache.sysml.runtime.matrix.data.SparseBlockCOO; +import org.apache.sysml.runtime.matrix.data.SparseBlockCSR; +import org.apache.sysml.runtime.matrix.data.SparseBlockMCSR; +import org.apache.sysml.runtime.util.LongLongDoubleHashMap; +import org.apache.sysml.runtime.util.LongLongDoubleHashMap.LLDoubleEntry; +import org.apache.sysml.test.integration.AutomatedTestBase; +import org.apache.sysml.test.utils.TestUtils; + +/** + * This is a sparse matrix block component test for append, + * and sort functionality. In order to achieve broad coverage, we + * test against different init methods and sparsity values. + * + */ +public class SparseBlockAppendSort extends AutomatedTestBase +{ + private final static int rows = 632; + private final static int cols = 454; + private final static double sparsity1 = 0.11; + private final static double sparsity2 = 0.21; + private final static double sparsity3 = 0.31; + + private enum InitType { + SEQ_SET, + RAND_SET, + } + + @Override + public void setUp() { + TestUtils.clearAssertionInformation(); + } + + @Test + public void testSparseBlockMCSR1Seq() { + runSparseBlockAppendSortTest(SparseBlock.Type.MCSR, sparsity1, InitType.SEQ_SET); + } + + @Test + public void testSparseBlockMCSR2Seq() { + runSparseBlockAppendSortTest(SparseBlock.Type.MCSR, sparsity2, InitType.SEQ_SET); + } + + @Test + public void testSparseBlockMCSR3Seq() { + runSparseBlockAppendSortTest(SparseBlock.Type.MCSR, sparsity3, InitType.SEQ_SET); + } + + @Test + public void testSparseBlockMCSR1Rand() { + runSparseBlockAppendSortTest(SparseBlock.Type.MCSR, sparsity1, InitType.RAND_SET); + } + + @Test + public void testSparseBlockMCSR2Rand() { + runSparseBlockAppendSortTest(SparseBlock.Type.MCSR, sparsity2, InitType.RAND_SET); + } + + @Test + public void testSparseBlockMCSR3Rand() { + runSparseBlockAppendSortTest(SparseBlock.Type.MCSR, sparsity3, InitType.RAND_SET); + } + + @Test + public void testSparseBlockCSR1Seq() { + runSparseBlockAppendSortTest(SparseBlock.Type.CSR, sparsity1, InitType.SEQ_SET); + } + + @Test + public void testSparseBlockCSR2Seq() { + runSparseBlockAppendSortTest(SparseBlock.Type.CSR, sparsity2, InitType.SEQ_SET); + } + + @Test + public void testSparseBlockCSR3Seq() { + runSparseBlockAppendSortTest(SparseBlock.Type.CSR, sparsity3, InitType.SEQ_SET); + } + + @Test + public void testSparseBlockCSR1Rand() { + runSparseBlockAppendSortTest(SparseBlock.Type.CSR, sparsity1, InitType.RAND_SET); + } + + @Test + public void testSparseBlockCSR2Rand() { + runSparseBlockAppendSortTest(SparseBlock.Type.CSR, sparsity2, InitType.RAND_SET); + } + + @Test + public void testSparseBlockCSR3Rand() { + runSparseBlockAppendSortTest(SparseBlock.Type.CSR, sparsity3, InitType.RAND_SET); + } + + @Test + public void testSparseBlockCOO1Seq() { + runSparseBlockAppendSortTest(SparseBlock.Type.COO, sparsity1, InitType.SEQ_SET); + } + + @Test + public void testSparseBlockCOO2Seq() { + runSparseBlockAppendSortTest(SparseBlock.Type.COO, sparsity2, InitType.SEQ_SET); + } + + @Test + public void testSparseBlockCOO3Seq() { + runSparseBlockAppendSortTest(SparseBlock.Type.COO, sparsity3, InitType.SEQ_SET); + } + + @Test + public void testSparseBlockCOO1Rand() { + runSparseBlockAppendSortTest(SparseBlock.Type.COO, sparsity1, InitType.RAND_SET); + } + + @Test + public void testSparseBlockCOO2Rand() { + runSparseBlockAppendSortTest(SparseBlock.Type.COO, sparsity2, InitType.RAND_SET); + } + + @Test + public void testSparseBlockCOO3Rand() { + runSparseBlockAppendSortTest(SparseBlock.Type.COO, sparsity3, InitType.RAND_SET); + } + + /** + * + * @param sparseM1 + * @param sparseM2 + * @param instType + */ + private void runSparseBlockAppendSortTest( SparseBlock.Type btype, double sparsity, InitType itype) + { + try + { + //data generation + double[][] A = getRandomMatrix(rows, cols, -10, 10, sparsity, 7654321); + + //init sparse block + SparseBlock sblock = null; + switch( btype ) { + case MCSR: sblock = new SparseBlockMCSR(rows, cols); break; + case CSR: sblock = new SparseBlockCSR(rows, cols); break; + case COO: sblock = new SparseBlockCOO(rows, cols); break; + } + + if(itype == InitType.SEQ_SET) { + for( int i=0; i<rows; i++ ) + for( int j=0; j<cols; j++ ) + sblock.append(i, j, A[i][j]); + } + else if( itype == InitType.RAND_SET ) { + LongLongDoubleHashMap map = new LongLongDoubleHashMap(); + for( int i=0; i<rows; i++ ) + for( int j=0; j<cols; j++ ) + map.addValue(i, j, A[i][j]); + for( LLDoubleEntry e : map.extractValues() ) //random hash order + sblock.append((int)e.key1, (int)e.key2, e.value); + } + + //sort appended values + sblock.sort(); + + //check for correct number of non-zeros + int[] rnnz = new int[rows]; int nnz = 0; + for( int i=0; i<rows; i++ ) { + for( int j=0; j<cols; j++ ) + rnnz[i] += (A[i][j]!=0) ? 1 : 0; + nnz += rnnz[i]; + } + if( nnz != sblock.size() ) + Assert.fail("Wrong number of non-zeros: "+sblock.size()+", expected: "+nnz); + + //check correct isEmpty return + for( int i=0; i<rows; i++ ) + if( sblock.isEmpty(i) != (rnnz[i]==0) ) + Assert.fail("Wrong isEmpty(row) result for row nnz: "+rnnz[i]); + + //check correct values + for( int i=0; i<rows; i++ ) + if( !sblock.isEmpty(i) ) + for( int j=0; j<cols; j++ ) { + double tmp = sblock.get(i, j); + if( tmp != A[i][j] ) + Assert.fail("Wrong get value for cell ("+i+","+j+"): "+tmp+", expected: "+A[i][j]); + } + } + catch(Exception ex) { + ex.printStackTrace(); + throw new RuntimeException(ex); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/82d5c5f1/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockDelete.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockDelete.java b/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockDelete.java new file mode 100644 index 0000000..c719bcb --- /dev/null +++ b/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockDelete.java @@ -0,0 +1,164 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.sysml.test.integration.functions.sparse; + +import java.util.Iterator; + +import org.junit.Assert; +import org.junit.Test; +import org.apache.sysml.runtime.matrix.data.IJV; +import org.apache.sysml.runtime.matrix.data.MatrixBlock; +import org.apache.sysml.runtime.matrix.data.SparseBlock; +import org.apache.sysml.runtime.matrix.data.SparseBlockCOO; +import org.apache.sysml.runtime.matrix.data.SparseBlockCSR; +import org.apache.sysml.runtime.matrix.data.SparseBlockMCSR; +import org.apache.sysml.runtime.matrix.data.SparseRow; +import org.apache.sysml.runtime.util.DataConverter; +import org.apache.sysml.test.integration.AutomatedTestBase; +import org.apache.sysml.test.utils.TestUtils; + +/** + * This is a sparse matrix block component test for sparse block delete + * via set functionality. In order to achieve broad coverage, we test against + * different sparsity values. + * + */ +public class SparseBlockDelete extends AutomatedTestBase +{ + private final static int rows = 662; + private final static int cols = 444; + private final static int cl = 145; + private final static int cu = 225; + private final static double sparsity1 = 0.12; + private final static double sparsity2 = 0.22; + private final static double sparsity3 = 0.32; + + @Override + public void setUp() { + TestUtils.clearAssertionInformation(); + } + + @Test + public void testSparseBlockMCSR1() { + runSparseBlockDeleteTest(SparseBlock.Type.MCSR, sparsity1); + } + + @Test + public void testSparseBlockMCSR2() { + runSparseBlockDeleteTest(SparseBlock.Type.MCSR, sparsity2); + } + + @Test + public void testSparseBlockMCSR3() { + runSparseBlockDeleteTest(SparseBlock.Type.MCSR, sparsity3); + } + + @Test + public void testSparseBlockCSR1() { + runSparseBlockDeleteTest(SparseBlock.Type.CSR, sparsity1); + } + + @Test + public void testSparseBlockCSR2() { + runSparseBlockDeleteTest(SparseBlock.Type.CSR, sparsity2); + } + + @Test + public void testSparseBlockCSR3() { + runSparseBlockDeleteTest(SparseBlock.Type.CSR, sparsity3); + } + + @Test + public void testSparseBlockCOO1() { + runSparseBlockDeleteTest(SparseBlock.Type.COO, sparsity1); + } + + @Test + public void testSparseBlockCOO2() { + runSparseBlockDeleteTest(SparseBlock.Type.COO, sparsity2); + } + + @Test + public void testSparseBlockCOO3() { + runSparseBlockDeleteTest(SparseBlock.Type.COO, sparsity3); + } + + /** + * + * @param btype + * @param sparsity + */ + private void runSparseBlockDeleteTest( SparseBlock.Type btype, double sparsity) + { + try + { + //data generation + double[][] A = getRandomMatrix(rows, cols, -10, 10, sparsity, 456); + + //init sparse block + SparseBlock sblock = null; + MatrixBlock mbtmp = DataConverter.convertToMatrixBlock(A); + SparseRow[] srtmp = mbtmp.getSparseBlock(); + switch( btype ) { + case MCSR: sblock = new SparseBlockMCSR(srtmp,true); break; + case CSR: sblock = new SparseBlockCSR(srtmp, (int)mbtmp.getNonZeros()); break; + case COO: sblock = new SparseBlockCOO(srtmp, (int)mbtmp.getNonZeros()); break; + } + + //delete range per row via set + for( int i=0; i<rows; i++ ) + for( int j=cl; j<cu; j++ ) { + A[i][j] = 0; + sblock.set(i, j, 0); + } + + //check for correct number of non-zeros + int[] rnnz = new int[rows]; int nnz = 0; + for( int i=0; i<rows; i++ ) { + for( int j=0; j<cols; j++ ) + rnnz[i] += (A[i][j]!=0) ? 1 : 0; + nnz += rnnz[i]; + } + if( nnz != sblock.size() ) + Assert.fail("Wrong number of non-zeros: "+sblock.size()+", expected: "+nnz); + + //check correct isEmpty return + for( int i=0; i<rows; i++ ) + if( sblock.isEmpty(i) != (rnnz[i]==0) ) + Assert.fail("Wrong isEmpty(row) result for row nnz: "+rnnz[i]); + + //check correct values + Iterator<IJV> iter = sblock.getIterator(); + int count = 0; + while( iter.hasNext() ) { + IJV cell = iter.next(); + if( cell.v != A[cell.i][cell.j] ) + Assert.fail("Wrong value returned by iterator: "+cell.v+", expected: "+A[cell.i][cell.j]); + count++; + } + if( count != nnz ) + Assert.fail("Wrong number of values returned by iterator: "+count+", expected: "+nnz); + } + catch(Exception ex) { + ex.printStackTrace(); + throw new RuntimeException(ex); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/82d5c5f1/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockGetFirstIndex.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockGetFirstIndex.java b/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockGetFirstIndex.java new file mode 100644 index 0000000..7e23dd0 --- /dev/null +++ b/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockGetFirstIndex.java @@ -0,0 +1,284 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.sysml.test.integration.functions.sparse; + +import org.junit.Assert; +import org.junit.Test; +import org.apache.sysml.runtime.matrix.data.MatrixBlock; +import org.apache.sysml.runtime.matrix.data.SparseBlock; +import org.apache.sysml.runtime.matrix.data.SparseBlockCOO; +import org.apache.sysml.runtime.matrix.data.SparseBlockCSR; +import org.apache.sysml.runtime.matrix.data.SparseBlockMCSR; +import org.apache.sysml.runtime.matrix.data.SparseRow; +import org.apache.sysml.runtime.util.DataConverter; +import org.apache.sysml.test.integration.AutomatedTestBase; +import org.apache.sysml.test.utils.TestUtils; + +/** + * This is a sparse matrix block component test for sparse block get + * first index functionality. In order to achieve broad coverage, we + * test against GT, GTE, and LTE as well as different sparsity values. + * + */ +public class SparseBlockGetFirstIndex extends AutomatedTestBase +{ + private final static int rows = 571; + private final static int cols = 595; + private final static double sparsity1 = 0.09; + private final static double sparsity2 = 0.19; + private final static double sparsity3 = 0.29; + + public enum IndexType { + GT, + GTE, + LTE, + } + + @Override + public void setUp() { + TestUtils.clearAssertionInformation(); + } + + @Test + public void testSparseBlockMCSR1GT() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.MCSR, sparsity1, IndexType.GT); + } + + @Test + public void testSparseBlockMCSR2GT() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.MCSR, sparsity2, IndexType.GT); + } + + @Test + public void testSparseBlockMCSR3GT() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.MCSR, sparsity3, IndexType.GT); + } + + @Test + public void testSparseBlockMCSR1GTE() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.MCSR, sparsity1, IndexType.GTE); + } + + @Test + public void testSparseBlockMCSR2GTE() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.MCSR, sparsity2, IndexType.GTE); + } + + @Test + public void testSparseBlockMCSR3GTE() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.MCSR, sparsity3, IndexType.GTE); + } + + @Test + public void testSparseBlockMCSR1LTE() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.MCSR, sparsity1, IndexType.LTE); + } + + @Test + public void testSparseBlockMCSR2LTE() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.MCSR, sparsity2, IndexType.LTE); + } + + @Test + public void testSparseBlockMCSR3LTE() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.MCSR, sparsity3, IndexType.LTE); + } + + @Test + public void testSparseBlockCSR1GT() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.CSR, sparsity1, IndexType.GT); + } + + @Test + public void testSparseBlockCSR2GT() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.CSR, sparsity2, IndexType.GT); + } + + @Test + public void testSparseBlockCSR3GT() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.CSR, sparsity3, IndexType.GT); + } + + @Test + public void testSparseBlockCSR1GTE() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.CSR, sparsity1, IndexType.GTE); + } + + @Test + public void testSparseBlockCSR2GTE() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.CSR, sparsity2, IndexType.GTE); + } + + @Test + public void testSparseBlockCSR3GTE() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.CSR, sparsity3, IndexType.GTE); + } + + @Test + public void testSparseBlockCSR1LTE() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.CSR, sparsity1, IndexType.LTE); + } + + @Test + public void testSparseBlockCSR2LTE() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.CSR, sparsity2, IndexType.LTE); + } + + @Test + public void testSparseBlockCSR3LTE() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.CSR, sparsity3, IndexType.LTE); + } + + @Test + public void testSparseBlockCOO1GT() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.COO, sparsity1, IndexType.GT); + } + + @Test + public void testSparseBlockCOO2GT() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.COO, sparsity2, IndexType.GT); + } + + @Test + public void testSparseBlockCOO3GT() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.COO, sparsity3, IndexType.GT); + } + + @Test + public void testSparseBlockCOO1GTE() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.COO, sparsity1, IndexType.GTE); + } + + @Test + public void testSparseBlockCOO2GTE() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.COO, sparsity2, IndexType.GTE); + } + + @Test + public void testSparseBlockCOO3GTE() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.COO, sparsity3, IndexType.GTE); + } + + @Test + public void testSparseBlockCOO1LTE() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.COO, sparsity1, IndexType.LTE); + } + + @Test + public void testSparseBlockCOO2LTE() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.COO, sparsity2, IndexType.LTE); + } + + @Test + public void testSparseBlockCOO3LTE() { + runSparseBlockGetFirstIndexTest(SparseBlock.Type.COO, sparsity3, IndexType.LTE); + } + + /** + * + * @param sparseM1 + * @param sparseM2 + * @param instType + */ + private void runSparseBlockGetFirstIndexTest( SparseBlock.Type btype, double sparsity, IndexType itype) + { + try + { + //data generation + double[][] A = getRandomMatrix(rows, cols, -10, 10, sparsity, 3456); + + //init sparse block + SparseBlock sblock = null; + MatrixBlock mbtmp = DataConverter.convertToMatrixBlock(A); + SparseRow[] srtmp = mbtmp.getSparseBlock(); + switch( btype ) { + case MCSR: sblock = new SparseBlockMCSR(srtmp,true); break; + case CSR: sblock = new SparseBlockCSR(srtmp, (int)mbtmp.getNonZeros()); break; + case COO: sblock = new SparseBlockCOO(srtmp, (int)mbtmp.getNonZeros()); break; + } + + //check for correct number of non-zeros + int[] rnnz = new int[rows]; int nnz = 0; + for( int i=0; i<rows; i++ ) { + for( int j=0; j<cols; j++ ) + rnnz[i] += (A[i][j]!=0) ? 1 : 0; + nnz += rnnz[i]; + } + if( nnz != sblock.size() ) + Assert.fail("Wrong number of non-zeros: "+sblock.size()+", expected: "+nnz); + + //check correct isEmpty return + for( int i=0; i<rows; i++ ) + if( sblock.isEmpty(i) != (rnnz[i]==0) ) + Assert.fail("Wrong isEmpty(row) result for row nnz: "+rnnz[i]); + + //check correct index values + for( int i=0; i<rows; i++ ) { + int ix = getFirstIx(A, i, i, itype); + int sixpos = -1; + switch( itype ) { + case GT: sixpos = sblock.posFIndexGT(i, i); break; + case GTE: sixpos = sblock.posFIndexGTE(i, i); break; + case LTE: sixpos = sblock.posFIndexLTE(i, i); break; + } + int six = (sixpos>=0) ? sblock.indexes(i)[sixpos] : -1; + if( six != ix ) { + Assert.fail("Wrong index returned by index probe ("+ + itype.toString()+","+i+"): "+six+", expected: "+ix); + } + } + } + catch(Exception ex) { + ex.printStackTrace(); + throw new RuntimeException(ex); + } + } + + /** + * + * @param A + * @param rix + * @param cix + * @param type + * @return + */ + private int getFirstIx( double[][] A, int rix, int cix, IndexType type ) { + if( type==IndexType.GT ) { + for( int j=cix+1; j<cols; j++ ) + if( A[rix][j] != 0 ) + return j; + return -1; + } + else if( type==IndexType.GTE ) { + for( int j=cix; j<cols; j++ ) + if( A[rix][j] != 0 ) + return j; + return -1; + } + else if( type==IndexType.LTE ) { + for( int j=cix; j>=0; j-- ) + if( A[rix][j] != 0 ) + return j; + return -1; + } + + return -1; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/82d5c5f1/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockGetSet.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockGetSet.java b/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockGetSet.java new file mode 100644 index 0000000..9c9856e --- /dev/null +++ b/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockGetSet.java @@ -0,0 +1,275 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.sysml.test.integration.functions.sparse; + +import org.junit.Assert; +import org.junit.Test; +import org.apache.sysml.runtime.matrix.data.MatrixBlock; +import org.apache.sysml.runtime.matrix.data.SparseBlock; +import org.apache.sysml.runtime.matrix.data.SparseBlockCOO; +import org.apache.sysml.runtime.matrix.data.SparseBlockCSR; +import org.apache.sysml.runtime.matrix.data.SparseBlockMCSR; +import org.apache.sysml.runtime.matrix.data.SparseRow; +import org.apache.sysml.runtime.util.DataConverter; +import org.apache.sysml.runtime.util.LongLongDoubleHashMap; +import org.apache.sysml.runtime.util.LongLongDoubleHashMap.LLDoubleEntry; +import org.apache.sysml.test.integration.AutomatedTestBase; +import org.apache.sysml.test.utils.TestUtils; + +/** + * This is a sparse matrix block component test for init, get, set, + * and append functionality. In order to achieve broad coverage, we + * test against different init methods and sparsity values. + * + */ +public class SparseBlockGetSet extends AutomatedTestBase +{ + private final static int rows = 732; + private final static int cols = 354; + private final static double sparsity1 = 0.1; + private final static double sparsity2 = 0.2; + private final static double sparsity3 = 0.3; + + private enum InitType { + BULK, + SEQ_SET, + RAND_SET, + } + + @Override + public void setUp() { + TestUtils.clearAssertionInformation(); + } + + @Test + public void testSparseBlockMCSR1Bulk() { + runSparseBlockGetSetTest(SparseBlock.Type.MCSR, sparsity1, InitType.BULK); + } + + @Test + public void testSparseBlockMCSR2Bulk() { + runSparseBlockGetSetTest(SparseBlock.Type.MCSR, sparsity2, InitType.BULK); + } + + @Test + public void testSparseBlockMCSR3Bulk() { + runSparseBlockGetSetTest(SparseBlock.Type.MCSR, sparsity3, InitType.BULK); + } + + @Test + public void testSparseBlockMCSR1Seq() { + runSparseBlockGetSetTest(SparseBlock.Type.MCSR, sparsity1, InitType.SEQ_SET); + } + + @Test + public void testSparseBlockMCSR2Seq() { + runSparseBlockGetSetTest(SparseBlock.Type.MCSR, sparsity2, InitType.SEQ_SET); + } + + @Test + public void testSparseBlockMCSR3Seq() { + runSparseBlockGetSetTest(SparseBlock.Type.MCSR, sparsity3, InitType.SEQ_SET); + } + + @Test + public void testSparseBlockMCSR1Rand() { + runSparseBlockGetSetTest(SparseBlock.Type.MCSR, sparsity1, InitType.RAND_SET); + } + + @Test + public void testSparseBlockMCSR2Rand() { + runSparseBlockGetSetTest(SparseBlock.Type.MCSR, sparsity2, InitType.RAND_SET); + } + + @Test + public void testSparseBlockMCSR3Rand() { + runSparseBlockGetSetTest(SparseBlock.Type.MCSR, sparsity3, InitType.RAND_SET); + } + + @Test + public void testSparseBlockCSR1Bulk() { + runSparseBlockGetSetTest(SparseBlock.Type.CSR, sparsity1, InitType.BULK); + } + + @Test + public void testSparseBlockCSR2Bulk() { + runSparseBlockGetSetTest(SparseBlock.Type.CSR, sparsity2, InitType.BULK); + } + + @Test + public void testSparseBlockCSR3Bulk() { + runSparseBlockGetSetTest(SparseBlock.Type.CSR, sparsity3, InitType.BULK); + } + + @Test + public void testSparseBlockCSR1Seq() { + runSparseBlockGetSetTest(SparseBlock.Type.CSR, sparsity1, InitType.SEQ_SET); + } + + @Test + public void testSparseBlockCSR2Seq() { + runSparseBlockGetSetTest(SparseBlock.Type.CSR, sparsity2, InitType.SEQ_SET); + } + + @Test + public void testSparseBlockCSR3Seq() { + runSparseBlockGetSetTest(SparseBlock.Type.CSR, sparsity3, InitType.SEQ_SET); + } + + @Test + public void testSparseBlockCSR1Rand() { + runSparseBlockGetSetTest(SparseBlock.Type.CSR, sparsity1, InitType.RAND_SET); + } + + @Test + public void testSparseBlockCSR2Rand() { + runSparseBlockGetSetTest(SparseBlock.Type.CSR, sparsity2, InitType.RAND_SET); + } + + @Test + public void testSparseBlockCSR3Rand() { + runSparseBlockGetSetTest(SparseBlock.Type.CSR, sparsity3, InitType.RAND_SET); + } + + @Test + public void testSparseBlockCOO1Bulk() { + runSparseBlockGetSetTest(SparseBlock.Type.COO, sparsity1, InitType.BULK); + } + + @Test + public void testSparseBlockCOO2Bulk() { + runSparseBlockGetSetTest(SparseBlock.Type.COO, sparsity2, InitType.BULK); + } + + @Test + public void testSparseBlockCOO3Bulk() { + runSparseBlockGetSetTest(SparseBlock.Type.COO, sparsity3, InitType.BULK); + } + + @Test + public void testSparseBlockCOO1Seq() { + runSparseBlockGetSetTest(SparseBlock.Type.COO, sparsity1, InitType.SEQ_SET); + } + + @Test + public void testSparseBlockCOO2Seq() { + runSparseBlockGetSetTest(SparseBlock.Type.COO, sparsity2, InitType.SEQ_SET); + } + + @Test + public void testSparseBlockCOO3Seq() { + runSparseBlockGetSetTest(SparseBlock.Type.COO, sparsity3, InitType.SEQ_SET); + } + + @Test + public void testSparseBlockCOO1Rand() { + runSparseBlockGetSetTest(SparseBlock.Type.COO, sparsity1, InitType.RAND_SET); + } + + @Test + public void testSparseBlockCOO2Rand() { + runSparseBlockGetSetTest(SparseBlock.Type.COO, sparsity2, InitType.RAND_SET); + } + + @Test + public void testSparseBlockCOO3Rand() { + runSparseBlockGetSetTest(SparseBlock.Type.COO, sparsity3, InitType.RAND_SET); + } + + /** + * + * @param sparseM1 + * @param sparseM2 + * @param instType + */ + private void runSparseBlockGetSetTest( SparseBlock.Type btype, double sparsity, InitType itype) + { + try + { + //data generation + double[][] A = getRandomMatrix(rows, cols, -10, 10, sparsity, 7654321); + + //init sparse block + SparseBlock sblock = null; + if( itype == InitType.BULK ) { + MatrixBlock mbtmp = DataConverter.convertToMatrixBlock(A); + SparseRow[] srtmp = mbtmp.getSparseBlock(); + switch( btype ) { + case MCSR: sblock = new SparseBlockMCSR(srtmp,true); break; + case CSR: sblock = new SparseBlockCSR(srtmp, (int)mbtmp.getNonZeros()); break; + case COO: sblock = new SparseBlockCOO(srtmp, (int)mbtmp.getNonZeros()); break; + } + } + else if( itype == InitType.SEQ_SET || itype == InitType.RAND_SET ) { + switch( btype ) { + case MCSR: sblock = new SparseBlockMCSR(rows, cols); break; + case CSR: sblock = new SparseBlockCSR(rows, cols); break; + case COO: sblock = new SparseBlockCOO(rows, cols); break; + } + + if(itype == InitType.SEQ_SET) { + for( int i=0; i<rows; i++ ) + for( int j=0; j<cols; j++ ) + sblock.append(i, j, A[i][j]); + } + else if( itype == InitType.RAND_SET ) { + LongLongDoubleHashMap map = new LongLongDoubleHashMap(); + for( int i=0; i<rows; i++ ) + for( int j=0; j<cols; j++ ) + map.addValue(i, j, A[i][j]); + for( LLDoubleEntry e : map.extractValues() ) //random hash order + sblock.set((int)e.key1, (int)e.key2, e.value); + } + } + + //check basic meta data + if( sblock.numRows() != rows ) + Assert.fail("Wrong number of rows: "+sblock.numRows()+", expected: "+rows); + + //check for correct number of non-zeros + int[] rnnz = new int[rows]; int nnz = 0; + for( int i=0; i<rows; i++ ) { + for( int j=0; j<cols; j++ ) + rnnz[i] += (A[i][j]!=0) ? 1 : 0; + nnz += rnnz[i]; + } + if( nnz != sblock.size() ) + Assert.fail("Wrong number of non-zeros: "+sblock.size()+", expected: "+nnz); + + //check correct isEmpty return + for( int i=0; i<rows; i++ ) + if( sblock.isEmpty(i) != (rnnz[i]==0) ) + Assert.fail("Wrong isEmpty(row) result for row nnz: "+rnnz[i]); + + //check correct values + for( int i=0; i<rows; i++ ) + if( !sblock.isEmpty(i) ) + for( int j=0; j<cols; j++ ) { + double tmp = sblock.get(i, j); + if( tmp != A[i][j] ) + Assert.fail("Wrong get value for cell ("+i+","+j+"): "+tmp+", expected: "+A[i][j]); + } + } + catch(Exception ex) { + ex.printStackTrace(); + throw new RuntimeException(ex); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/82d5c5f1/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockIndexRange.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockIndexRange.java b/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockIndexRange.java new file mode 100644 index 0000000..5a4ea4a --- /dev/null +++ b/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockIndexRange.java @@ -0,0 +1,225 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.sysml.test.integration.functions.sparse; + +import java.util.Arrays; +import java.util.Iterator; + +import org.junit.Assert; +import org.junit.Test; +import org.apache.sysml.runtime.matrix.data.IJV; +import org.apache.sysml.runtime.matrix.data.MatrixBlock; +import org.apache.sysml.runtime.matrix.data.SparseBlock; +import org.apache.sysml.runtime.matrix.data.SparseBlockCOO; +import org.apache.sysml.runtime.matrix.data.SparseBlockCSR; +import org.apache.sysml.runtime.matrix.data.SparseBlockMCSR; +import org.apache.sysml.runtime.matrix.data.SparseRow; +import org.apache.sysml.runtime.util.DataConverter; +import org.apache.sysml.test.integration.AutomatedTestBase; +import org.apache.sysml.test.utils.TestUtils; + +/** + * This is a sparse matrix block component test for sparse block deleteIndexRange + * and setIndexRange functionality. In order to achieve broad coverage, we test + * against different update types and sparsity values. + * + */ +public class SparseBlockIndexRange extends AutomatedTestBase +{ + private final static int rows = 662; + private final static int cols = 549; + private final static int cl = 245; + private final static int cu = 425; + private final static double sparsity1 = 0.12; + private final static double sparsity2 = 0.22; + private final static double sparsity3 = 0.32; + + @Override + public void setUp() { + TestUtils.clearAssertionInformation(); + } + + public enum UpdateType { + DELETE, + INSERT, + } + + @Test + public void testSparseBlockMCSR1Delete() { + runSparseBlockIndexRangeTest(SparseBlock.Type.MCSR, sparsity1, UpdateType.DELETE); + } + + @Test + public void testSparseBlockMCSR2Delete() { + runSparseBlockIndexRangeTest(SparseBlock.Type.MCSR, sparsity2, UpdateType.DELETE); + } + + @Test + public void testSparseBlockMCSR3Delete() { + runSparseBlockIndexRangeTest(SparseBlock.Type.MCSR, sparsity3, UpdateType.DELETE); + } + + @Test + public void testSparseBlockMCSR1Insert() { + runSparseBlockIndexRangeTest(SparseBlock.Type.MCSR, sparsity1, UpdateType.INSERT); + } + + @Test + public void testSparseBlockMCSR2Insert() { + runSparseBlockIndexRangeTest(SparseBlock.Type.MCSR, sparsity2, UpdateType.INSERT); + } + + @Test + public void testSparseBlockMCSR3Insert() { + runSparseBlockIndexRangeTest(SparseBlock.Type.MCSR, sparsity3, UpdateType.INSERT); + } + + @Test + public void testSparseBlockCSR1Delete() { + runSparseBlockIndexRangeTest(SparseBlock.Type.CSR, sparsity1, UpdateType.DELETE); + } + + @Test + public void testSparseBlockCSR2Delete() { + runSparseBlockIndexRangeTest(SparseBlock.Type.CSR, sparsity2, UpdateType.DELETE); + } + + @Test + public void testSparseBlockCSR3Delete() { + runSparseBlockIndexRangeTest(SparseBlock.Type.CSR, sparsity3, UpdateType.DELETE); + } + + @Test + public void testSparseBlockCSR1Insert() { + runSparseBlockIndexRangeTest(SparseBlock.Type.CSR, sparsity1, UpdateType.INSERT); + } + + @Test + public void testSparseBlockCSR2Insert() { + runSparseBlockIndexRangeTest(SparseBlock.Type.CSR, sparsity2, UpdateType.INSERT); + } + + @Test + public void testSparseBlockCSR3Insert() { + runSparseBlockIndexRangeTest(SparseBlock.Type.CSR, sparsity3, UpdateType.INSERT); + } + + @Test + public void testSparseBlockCOO1Delete() { + runSparseBlockIndexRangeTest(SparseBlock.Type.COO, sparsity1, UpdateType.DELETE); + } + + @Test + public void testSparseBlockCOO2Delete() { + runSparseBlockIndexRangeTest(SparseBlock.Type.COO, sparsity2, UpdateType.DELETE); + } + + @Test + public void testSparseBlockCOO3Delete() { + runSparseBlockIndexRangeTest(SparseBlock.Type.COO, sparsity3, UpdateType.DELETE); + } + + @Test + public void testSparseBlockCOO1Insert() { + runSparseBlockIndexRangeTest(SparseBlock.Type.COO, sparsity1, UpdateType.INSERT); + } + + @Test + public void testSparseBlockCOO2Insert() { + runSparseBlockIndexRangeTest(SparseBlock.Type.COO, sparsity2, UpdateType.INSERT); + } + + @Test + public void testSparseBlockCOO3Insert() { + runSparseBlockIndexRangeTest(SparseBlock.Type.COO, sparsity3, UpdateType.INSERT); + } + + /** + * + * @param btype + * @param sparsity + */ + private void runSparseBlockIndexRangeTest( SparseBlock.Type btype, double sparsity, UpdateType utype) + { + try + { + //data generation + double[][] A = getRandomMatrix(rows, cols, -10, 10, sparsity, 456); + + //init sparse block + SparseBlock sblock = null; + MatrixBlock mbtmp = DataConverter.convertToMatrixBlock(A); + SparseRow[] srtmp = mbtmp.getSparseBlock(); + switch( btype ) { + case MCSR: sblock = new SparseBlockMCSR(srtmp,true); break; + case CSR: sblock = new SparseBlockCSR(srtmp, (int)mbtmp.getNonZeros()); break; + case COO: sblock = new SparseBlockCOO(srtmp, (int)mbtmp.getNonZeros()); break; + } + + //delete range per row via set + if( utype == UpdateType.DELETE ) { + for( int i=0; i<rows; i++ ) { + sblock.deleteIndexRange(i, cl, cu); + Arrays.fill(A[i], cl, cu, 0); + } + } + else if( utype == UpdateType.INSERT ) { + double[] vals = new double[cu-cl]; + for( int j=cl; j<cu; j++ ) + vals[j-cl] = j; + for( int i=0; i<rows; i++ ) { + sblock.setIndexRange(i, cl, cu, vals, 0, cu-cl); + System.arraycopy(vals, 0, A[i], cl, cu-cl); + } + } + + //check for correct number of non-zeros + int[] rnnz = new int[rows]; int nnz = 0; + for( int i=0; i<rows; i++ ) { + for( int j=0; j<cols; j++ ) + rnnz[i] += (A[i][j]!=0) ? 1 : 0; + nnz += rnnz[i]; + } + if( nnz != sblock.size() ) + Assert.fail("Wrong number of non-zeros: "+sblock.size()+", expected: "+nnz); + + //check correct isEmpty return + for( int i=0; i<rows; i++ ) + if( sblock.isEmpty(i) != (rnnz[i]==0) ) + Assert.fail("Wrong isEmpty(row) result for row nnz: "+rnnz[i]); + + //check correct values + Iterator<IJV> iter = sblock.getIterator(); + int count = 0; + while( iter.hasNext() ) { + IJV cell = iter.next(); + if( cell.v != A[cell.i][cell.j] ) + Assert.fail("Wrong value returned by iterator: "+cell.v+", expected: "+A[cell.i][cell.j]); + count++; + } + if( count != nnz ) + Assert.fail("Wrong number of values returned by iterator: "+count+", expected: "+nnz); + } + catch(Exception ex) { + ex.printStackTrace(); + throw new RuntimeException(ex); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/82d5c5f1/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockIterator.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockIterator.java b/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockIterator.java new file mode 100644 index 0000000..db388c2 --- /dev/null +++ b/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockIterator.java @@ -0,0 +1,205 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.sysml.test.integration.functions.sparse; + +import java.util.Iterator; + +import org.junit.Assert; +import org.junit.Test; +import org.apache.sysml.runtime.matrix.data.IJV; +import org.apache.sysml.runtime.matrix.data.MatrixBlock; +import org.apache.sysml.runtime.matrix.data.SparseBlock; +import org.apache.sysml.runtime.matrix.data.SparseBlockCOO; +import org.apache.sysml.runtime.matrix.data.SparseBlockCSR; +import org.apache.sysml.runtime.matrix.data.SparseBlockMCSR; +import org.apache.sysml.runtime.matrix.data.SparseRow; +import org.apache.sysml.runtime.util.DataConverter; +import org.apache.sysml.test.integration.AutomatedTestBase; +import org.apache.sysml.test.utils.TestUtils; + +/** + * This is a sparse matrix block component test for sparse block iterator + * functionality. In order to achieve broad coverage, we test against + * full and partial iterators as well as different sparsity values. + * + */ +public class SparseBlockIterator extends AutomatedTestBase +{ + private final static int rows = 772; + private final static int cols = 394; + private final static int rlPartial = 134; + private final static double sparsity1 = 0.1; + private final static double sparsity2 = 0.2; + private final static double sparsity3 = 0.3; + + @Override + public void setUp() { + TestUtils.clearAssertionInformation(); + } + + @Test + public void testSparseBlockMCSR1Full() { + runSparseBlockIteratorTest(SparseBlock.Type.MCSR, sparsity1, false); + } + + @Test + public void testSparseBlockMCSR2Full() { + runSparseBlockIteratorTest(SparseBlock.Type.MCSR, sparsity2, false); + } + + @Test + public void testSparseBlockMCSR3Full() { + runSparseBlockIteratorTest(SparseBlock.Type.MCSR, sparsity3, false); + } + + @Test + public void testSparseBlockMCSR1Partial() { + runSparseBlockIteratorTest(SparseBlock.Type.MCSR, sparsity1, true); + } + + @Test + public void testSparseBlockMCSR2Partial() { + runSparseBlockIteratorTest(SparseBlock.Type.MCSR, sparsity2, true); + } + + @Test + public void testSparseBlockMCSR3Partial() { + runSparseBlockIteratorTest(SparseBlock.Type.MCSR, sparsity3, true); + } + + @Test + public void testSparseBlockCSR1Full() { + runSparseBlockIteratorTest(SparseBlock.Type.CSR, sparsity1, false); + } + + @Test + public void testSparseBlockCSR2Full() { + runSparseBlockIteratorTest(SparseBlock.Type.CSR, sparsity2, false); + } + + @Test + public void testSparseBlockCSR3Full() { + runSparseBlockIteratorTest(SparseBlock.Type.CSR, sparsity3, false); + } + + @Test + public void testSparseBlockCSR1Partial() { + runSparseBlockIteratorTest(SparseBlock.Type.CSR, sparsity1, true); + } + + @Test + public void testSparseBlockCSR2Partial() { + runSparseBlockIteratorTest(SparseBlock.Type.CSR, sparsity2, true); + } + + @Test + public void testSparseBlockCSR3Partial() { + runSparseBlockIteratorTest(SparseBlock.Type.CSR, sparsity3, true); + } + + @Test + public void testSparseBlockCOO1Full() { + runSparseBlockIteratorTest(SparseBlock.Type.COO, sparsity1, false); + } + + @Test + public void testSparseBlockCOO2Full() { + runSparseBlockIteratorTest(SparseBlock.Type.COO, sparsity2, false); + } + + @Test + public void testSparseBlockCOO3Full() { + runSparseBlockIteratorTest(SparseBlock.Type.COO, sparsity3, false); + } + + @Test + public void testSparseBlockCOO1Partial() { + runSparseBlockIteratorTest(SparseBlock.Type.COO, sparsity1, true); + } + + @Test + public void testSparseBlockCOO2Partial() { + runSparseBlockIteratorTest(SparseBlock.Type.COO, sparsity2, true); + } + + @Test + public void testSparseBlockCOO3Partial() { + runSparseBlockIteratorTest(SparseBlock.Type.COO, sparsity3, true); + } + + + /** + * + * @param sparseM1 + * @param sparseM2 + * @param instType + */ + private void runSparseBlockIteratorTest( SparseBlock.Type btype, double sparsity, boolean partial) + { + try + { + //data generation + double[][] A = getRandomMatrix(rows, cols, -10, 10, sparsity, 8765432); + + //init sparse block + SparseBlock sblock = null; + MatrixBlock mbtmp = DataConverter.convertToMatrixBlock(A); + SparseRow[] srtmp = mbtmp.getSparseBlock(); + switch( btype ) { + case MCSR: sblock = new SparseBlockMCSR(srtmp,true); break; + case CSR: sblock = new SparseBlockCSR(srtmp, (int)mbtmp.getNonZeros()); break; + case COO: sblock = new SparseBlockCOO(srtmp, (int)mbtmp.getNonZeros()); break; + } + + //check for correct number of non-zeros + int[] rnnz = new int[rows]; int nnz = 0; + int rl = partial ? rlPartial : 0; + for( int i=rl; i<rows; i++ ) { + for( int j=0; j<cols; j++ ) + rnnz[i] += (A[i][j]!=0) ? 1 : 0; + nnz += rnnz[i]; + } + if( !partial && nnz != sblock.size() ) + Assert.fail("Wrong number of non-zeros: "+sblock.size()+", expected: "+nnz); + + //check correct isEmpty return + for( int i=rl; i<rows; i++ ) + if( sblock.isEmpty(i) != (rnnz[i]==0) ) + Assert.fail("Wrong isEmpty(row) result for row nnz: "+rnnz[i]); + + //check correct values + Iterator<IJV> iter = !partial ? sblock.getIterator() : + sblock.getIterator(rl, rows); + int count = 0; + while( iter.hasNext() ) { + IJV cell = iter.next(); + if( cell.v != A[cell.i][cell.j] ) + Assert.fail("Wrong value returned by iterator: "+cell.v+", expected: "+A[cell.i][cell.j]); + count++; + } + if( count != nnz ) + Assert.fail("Wrong number of values returned by iterator: "+count+", expected: "+nnz); + } + catch(Exception ex) { + ex.printStackTrace(); + throw new RuntimeException(ex); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/82d5c5f1/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockScan.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockScan.java b/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockScan.java new file mode 100644 index 0000000..4f89a17 --- /dev/null +++ b/src/test/java/org/apache/sysml/test/integration/functions/sparse/SparseBlockScan.java @@ -0,0 +1,157 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.sysml.test.integration.functions.sparse; + +import org.junit.Assert; +import org.junit.Test; +import org.apache.sysml.runtime.matrix.data.MatrixBlock; +import org.apache.sysml.runtime.matrix.data.SparseBlock; +import org.apache.sysml.runtime.matrix.data.SparseBlockCOO; +import org.apache.sysml.runtime.matrix.data.SparseBlockCSR; +import org.apache.sysml.runtime.matrix.data.SparseBlockMCSR; +import org.apache.sysml.runtime.matrix.data.SparseRow; +import org.apache.sysml.runtime.util.DataConverter; +import org.apache.sysml.test.integration.AutomatedTestBase; +import org.apache.sysml.test.utils.TestUtils; + +/** + * This is a sparse matrix block component test for sparse block scan + * functionality. In order to achieve broad coverage, we test against + * different sparsity values. + * + */ +public class SparseBlockScan extends AutomatedTestBase +{ + private final static int rows = 871; + private final static int cols = 295; + private final static double sparsity1 = 0.09; + private final static double sparsity2 = 0.19; + private final static double sparsity3 = 0.29; + + @Override + public void setUp() { + TestUtils.clearAssertionInformation(); + } + + @Test + public void testSparseBlockMCSR1Full() { + runSparseBlockScanTest(SparseBlock.Type.MCSR, sparsity1); + } + + @Test + public void testSparseBlockMCSR2Full() { + runSparseBlockScanTest(SparseBlock.Type.MCSR, sparsity2); + } + + @Test + public void testSparseBlockMCSR3Full() { + runSparseBlockScanTest(SparseBlock.Type.MCSR, sparsity3); + } + + @Test + public void testSparseBlockCSR1Full() { + runSparseBlockScanTest(SparseBlock.Type.CSR, sparsity1); + } + + @Test + public void testSparseBlockCSR2Full() { + runSparseBlockScanTest(SparseBlock.Type.CSR, sparsity2); + } + + @Test + public void testSparseBlockCSR3Full() { + runSparseBlockScanTest(SparseBlock.Type.CSR, sparsity3); + } + + @Test + public void testSparseBlockCOO1Full() { + runSparseBlockScanTest(SparseBlock.Type.COO, sparsity1); + } + + @Test + public void testSparseBlockCOO2Full() { + runSparseBlockScanTest(SparseBlock.Type.COO, sparsity2); + } + + @Test + public void testSparseBlockCOO3Full() { + runSparseBlockScanTest(SparseBlock.Type.COO, sparsity3); + } + + /** + * + * @param sparseM1 + * @param sparseM2 + * @param instType + */ + private void runSparseBlockScanTest( SparseBlock.Type btype, double sparsity) + { + try + { + //data generation + double[][] A = getRandomMatrix(rows, cols, -10, 10, sparsity, 1234); + + //init sparse block + SparseBlock sblock = null; + MatrixBlock mbtmp = DataConverter.convertToMatrixBlock(A); + SparseRow[] srtmp = mbtmp.getSparseBlock(); + switch( btype ) { + case MCSR: sblock = new SparseBlockMCSR(srtmp,true); break; + case CSR: sblock = new SparseBlockCSR(srtmp, (int)mbtmp.getNonZeros()); break; + case COO: sblock = new SparseBlockCOO(srtmp, (int)mbtmp.getNonZeros()); break; + } + + //check for correct number of non-zeros + int[] rnnz = new int[rows]; int nnz = 0; + for( int i=0; i<rows; i++ ) { + for( int j=0; j<cols; j++ ) + rnnz[i] += (A[i][j]!=0) ? 1 : 0; + nnz += rnnz[i]; + } + if( nnz != sblock.size() ) + Assert.fail("Wrong number of non-zeros: "+sblock.size()+", expected: "+nnz); + + //check correct isEmpty return + for( int i=0; i<rows; i++ ) + if( sblock.isEmpty(i) != (rnnz[i]==0) ) + Assert.fail("Wrong isEmpty(row) result for row nnz: "+rnnz[i]); + + //check correct values + int count = 0; + for( int i=0; i<rows; i++) { + int alen = sblock.size(i); + int apos = sblock.pos(i); + int[] aix = sblock.indexes(i); + double[] avals = sblock.values(i); + for( int j=0; j<alen; j++ ) { + if( avals[apos+j] != A[i][aix[apos+j]] ) + Assert.fail("Wrong value returned by scan: "+avals[apos+j]+", expected: "+A[i][apos+aix[j]]); + count++; + } + } + if( count != nnz ) + Assert.fail("Wrong number of values returned by scan: "+count+", expected: "+nnz); + } + catch(Exception ex) { + ex.printStackTrace(); + throw new RuntimeException(ex); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/82d5c5f1/src/test_suites/java/org/apache/sysml/test/integration/functions/sparse/ZPackageSuite.java ---------------------------------------------------------------------- diff --git a/src/test_suites/java/org/apache/sysml/test/integration/functions/sparse/ZPackageSuite.java b/src/test_suites/java/org/apache/sysml/test/integration/functions/sparse/ZPackageSuite.java new file mode 100644 index 0000000..f4d1411 --- /dev/null +++ b/src/test_suites/java/org/apache/sysml/test/integration/functions/sparse/ZPackageSuite.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.sysml.test.integration.functions.sparse; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +/** Group together the tests in this package into a single suite so that the Maven build + * won't run two of them at once. */ +@RunWith(Suite.class) [email protected]({ + SparseBlockAppendSort.class, + SparseBlockDelete.class, + SparseBlockGetFirstIndex.class, + SparseBlockGetSet.class, + SparseBlockIndexRange.class, + SparseBlockIterator.class, + SparseBlockScan.class, +}) + + +/** This class is just a holder for the above JUnit annotations. */ +public class ZPackageSuite { + +}
