From b09a3d50f80b1c505f14601722d6dfc7ec185434 Mon Sep 17 00:00:00 2001 From: Lukas Cejka <lukas.ostatek@gmail.com> Date: Thu, 22 Nov 2018 15:22:26 +0100 Subject: [PATCH] Initial commit of just the implemented testing functions. --- .../Matrices/SparseMatrixTest_impl.h | 855 ++++++++++++++++++ 1 file changed, 855 insertions(+) create mode 100644 src/UnitTests/Matrices/SparseMatrixTest_impl.h diff --git a/src/UnitTests/Matrices/SparseMatrixTest_impl.h b/src/UnitTests/Matrices/SparseMatrixTest_impl.h new file mode 100644 index 0000000000..0c1ccbbdd9 --- /dev/null +++ b/src/UnitTests/Matrices/SparseMatrixTest_impl.h @@ -0,0 +1,855 @@ +/*************************************************************************** + SparseMatrixTest_impl.h - description + ------------------- + begin : Nov 22, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +// TODO +/* + * getType() ::HOW? How to test this for each format? edit string how? + * Found the mistake for Cuda instead of Devices::Cuda. Incorrect String in src/TNL/Devices/Cuda.cpp + * MISSING: indexType is missing in CSR_impl.h + * getTypeVirtual() ::TEST? This just calls getType(). + * getSerializationType() ::TEST? This just calls HostType::getType(). + * getSerializationTypeVirtual() ::TEST? This just calls getSerializationType(). + * setDimensions() ::DONE + * setCompressedRowLengths() ::DONE + * getRowLength() ::USED! In test_SetCompressedRowLengths() to verify the test itself. + * getRowLengthFast() ::TEST? How to test __cuda_callable__? ONLY TEST ON CPU FOR NOW + * setLike() ::DONE + * reset() ::DONE + * setElementFast() ::TEST? How to test __cuda_callable__? ONLY TEST ON CPU FOR NOW + * setElement() ::DONE + * addElementFast() ::TEST? How to test __cuda_callable__? ONLY TEST ON CPU FOR NOW + * addElement() ::DONE + * setRowFast() ::TEST? How to test __cuda_callable__? ONLY TEST ON CPU FOR NOW + * setRow() ::DONE + * MISTAKE!!! In SlicedEllpack: addElement(), line 263, "column <= this->rows" shouldn't it be: "column <= this->columns", otherwise test_SetRow causes the assertion to fail. + * addRowFast() ::TEST? How to test __cuda_callable__? ONLY TEST ON CPU FOR NOW + * addRow() ::NOT IMPLEMENTED! This calls addRowFast() which isn't implemented. Implement? Is it supposed to add an extra row to the matrix or add elements of a row to another row in the matrix? + * getElementFast() ::TEST? How to test __cuda_callable__? ONLY TEST ON CPU FOR NOW + * getElement() ::USED! In test_SetElement(), test_AddElement() and test_setRow() to verify the test itself. + * getRowFast() ::TEST? How to test __cuda_callable__? ONLY TEST ON CPU FOR NOW + * MatrixRow getRow() ::TEST? How to test __cuda_callable__? ONLY TEST ON CPU FOR NOW + * ConstMatrixRow getRow() ::TEST? How to test __cuda_callable__? ONLY TEST ON CPU FOR NOW + * rowVectorProduct() ::TEST? How to test __cuda_callable__? ONLY TEST ON CPU FOR NOW + * vectorProduct() ::DONE + * This used to throw illegal memory access, but instead of using ints for vectors, using Types, helped. + * addMatrix() ::NOT IMPLEMENTED! + * getTransposition() ::NOT IMPLMENETED! + * performSORIteration() ::HOW? Throws segmentation fault CUDA. + * operator=() ::HOW? What is this supposed to enable? Overloading operators? + * save( File& file) ::USED! In save( String& fileName ) + * load( File& file ) ::USED! In load( String& fileName ) + * save( String& fileName ) ::DONE + * load( String& fileName ) ::DONE + * print() ::DONE + * setCudaKernelType() ::NOT SUPPOSED TO TEST! via notes from 1.11.2018 supervisor meeting. + * getCudaKernelType() ::NOT SUPPOSED TO TEST! via notes from 1.11.2018 supervisor meeting. + * setCudaWarpSize() ::NOT SUPPOSED TO TEST! via notes from 1.11.2018 supervisor meeting. + * getCudaWarpSize() ::NOT SUPPOSED TO TEST! via notes from 1.11.2018 supervisor meeting. + * setHybridModeSplit() ::NOT SUPPOSED TO TEST! via notes from 1.11.2018 supervisor meeting. + * getHybridModeSplit() ::NOT SUPPOSED TO TEST! via notes from 1.11.2018 supervisor meeting. + * spmvCudaVectorized() ::TEST? How to test __device__? + * vectorProductCuda() ::TEST? How to test __device__? + */ + +// GENERAL TODO +/* + * For every function, EXPECT_EQ needs to be done, even for zeros in matrices. + * Figure out __cuda_callable_. When trying to call __cuda_callable__ functions + * a segmentation fault (core dumped) is thrown. + * ==>__cuda_callable__ works only for CPU at the moment. (for loops vs thread kernel assignment) + */ + +#include <TNL/Containers/Vector.h> +#include <TNL/Containers/VectorView.h> +#include <TNL/Math.h> +#include <iostream> + +#ifdef HAVE_GTEST +#include <gtest/gtest.h> + +template< typename MatrixHostFloat, typename MatrixHostInt > +void host_test_GetType() +{ + MatrixHostFloat mtrxHostFloat; + MatrixHostInt mtrxHostInt; + + + EXPECT_EQ( mtrxHostFloat.getType(), TNL::String( "Matrices::CSR< float, Devices::Host >" ) ); + EXPECT_EQ( mtrxHostInt.getType(), TNL::String( "Matrices::CSR< int, Devices::Host >" ) ); +} + +template< typename MatrixCudaFloat, typename MatrixCudaInt > +void cuda_test_GetType() +{ + MatrixCudaFloat mtrxCudaFloat; + MatrixCudaInt mtrxCudaInt; + + + EXPECT_EQ( mtrxCudaFloat.getType(), TNL::String( "Matrices::CSR< float, Cuda >" ) ); // This is mistakenly labeled in /src/TNL/Devices/Cuda.cpp + EXPECT_EQ( mtrxCudaInt.getType(), TNL::String( "Matrices::CSR< int, Cuda >" ) ); // Should be Devices::Cuda +} + +template< typename Matrix > +void test_SetDimensions() +{ + using RealType = typename Matrix::RealType; + using DeviceType = typename Matrix::DeviceType; + using IndexType = typename Matrix::IndexType; + + const IndexType rows = 9; + const IndexType cols = 8; + + Matrix m; + m.setDimensions( rows, cols ); + + EXPECT_EQ( m.getRows(), 9 ); + EXPECT_EQ( m.getColumns(), 8 ); +} + +template< typename Matrix > +void test_SetCompressedRowLengths() +{ + using RealType = typename Matrix::RealType; + using DeviceType = typename Matrix::DeviceType; + using IndexType = typename Matrix::IndexType; + + const IndexType rows = 10; + const IndexType cols = 11; + + Matrix m; + m.reset(); + m.setDimensions( rows, cols ); + typename Matrix::CompressedRowLengthsVector rowLengths; + rowLengths.setSize( rows ); + rowLengths.setValue( 3 ); + + IndexType value = 1; + for( IndexType i = 2; i < rows; i++ ) + rowLengths.setElement( i, value++ ); + + m.setCompressedRowLengths( rowLengths ); + + + if( m.getType() == TNL::String( TNL::String( "Matrices::CSR< ") + + TNL::String( TNL::getType< RealType >() ) + + TNL::String( ", " ) + + TNL::String( Matrix::DeviceType::getDeviceType() ) + + TNL::String( ", " ) + + TNL::String( TNL::getType< IndexType >() ) + + TNL::String( " >" ) ) + ) + { + EXPECT_EQ( m.getRowLength( 0 ), 3 ); + EXPECT_EQ( m.getRowLength( 1 ), 3 ); + EXPECT_EQ( m.getRowLength( 2 ), 1 ); + EXPECT_EQ( m.getRowLength( 3 ), 2 ); + EXPECT_EQ( m.getRowLength( 4 ), 3 ); + EXPECT_EQ( m.getRowLength( 5 ), 4 ); + EXPECT_EQ( m.getRowLength( 6 ), 5 ); + EXPECT_EQ( m.getRowLength( 7 ), 6 ); + EXPECT_EQ( m.getRowLength( 8 ), 7 ); + EXPECT_EQ( m.getRowLength( 9 ), 8 ); + } + else if( m.getType() == TNL::String( TNL::String( "Matrices::Ellpack< ") + + TNL::String( TNL::getType< RealType >() ) + + TNL::String( ", " ) + + TNL::String( Matrix::DeviceType::getDeviceType() ) + + TNL::String( ", " ) + + TNL::String( TNL::getType< IndexType >() ) + + TNL::String( " >" ) ) + || + m.getType() == TNL::String( TNL::String( "Matrices::SlicedEllpack< ") + + TNL::String( TNL::getType< RealType >() ) + + TNL::String( ", " ) + + TNL::String( Matrix::DeviceType::getDeviceType() ) + + TNL::String( " >" ) ) + ) + { + EXPECT_EQ( m.getRowLength( 0 ), 8 ); + EXPECT_EQ( m.getRowLength( 1 ), 8 ); + EXPECT_EQ( m.getRowLength( 2 ), 8 ); + EXPECT_EQ( m.getRowLength( 3 ), 8 ); + EXPECT_EQ( m.getRowLength( 4 ), 8 ); + EXPECT_EQ( m.getRowLength( 5 ), 8 ); + EXPECT_EQ( m.getRowLength( 6 ), 8 ); + EXPECT_EQ( m.getRowLength( 7 ), 8 ); + EXPECT_EQ( m.getRowLength( 8 ), 8 ); + EXPECT_EQ( m.getRowLength( 9 ), 8 ); + } + else + { + EXPECT_EQ( m.getRowLength( 0 ), 3 ); + EXPECT_EQ( m.getRowLength( 1 ), 3 ); + EXPECT_EQ( m.getRowLength( 2 ), 1 ); + EXPECT_EQ( m.getRowLength( 3 ), 2 ); + EXPECT_EQ( m.getRowLength( 4 ), 3 ); + EXPECT_EQ( m.getRowLength( 5 ), 4 ); + EXPECT_EQ( m.getRowLength( 6 ), 5 ); + EXPECT_EQ( m.getRowLength( 7 ), 6 ); + EXPECT_EQ( m.getRowLength( 8 ), 7 ); + EXPECT_EQ( m.getRowLength( 9 ), 8 ); + } +} + +template< typename Matrix1, typename Matrix2 > +void test_SetLike() +{ + using RealType = typename Matrix1::RealType; + using DeviceType = typename Matrix1::DeviceType; + using IndexType = typename Matrix1::IndexType; + + const IndexType rows = 8; + const IndexType cols = 7; + + Matrix1 m1; + m1.reset(); + m1.setDimensions( rows + 1, cols + 2 ); + + Matrix2 m2; + m2.reset(); + m2.setDimensions( rows, cols ); + + m1.setLike( m2 ); + + + EXPECT_EQ( m1.getRows(), m2.getRows() ); + EXPECT_EQ( m1.getColumns(), m2.getColumns() ); +} + +template< typename Matrix > +void test_Reset() +{ + using RealType = typename Matrix::RealType; + using DeviceType = typename Matrix::DeviceType; + using IndexType = typename Matrix::IndexType; + +/* + * Sets up the following 5x4 sparse matrix: + * + * / 0 0 0 0 \ + * | 0 0 0 0 | + * | 0 0 0 0 | + * | 0 0 0 0 | + * \ 0 0 0 0 / + */ + + const IndexType rows = 5; + const IndexType cols = 4; + + Matrix m; + m.setDimensions( rows, cols ); + + m.reset(); + + + EXPECT_EQ( m.getRows(), 0 ); + EXPECT_EQ( m.getColumns(), 0 ); +} + +template< typename Matrix > +void test_SetElement() +{ + using RealType = typename Matrix::RealType; + using DeviceType = typename Matrix::DeviceType; + using IndexType = typename Matrix::IndexType; + +/* + * Sets up the following 5x5 sparse matrix: + * + * / 1 0 0 0 0 \ + * | 0 2 0 0 0 | + * | 0 0 3 0 0 | + * | 0 0 0 4 0 | + * \ 0 0 0 0 5 / + */ + + const IndexType rows = 5; + const IndexType cols = 5; + + Matrix m; + m.reset(); + m.setDimensions( rows, cols ); + typename Matrix::CompressedRowLengthsVector rowLengths; + rowLengths.setSize( rows ); + rowLengths.setValue( 1 ); + m.setCompressedRowLengths( rowLengths ); + + RealType value = 1; + for( IndexType i = 0; i < rows; i++ ) + m.setElement( i, i, value++ ); + + + EXPECT_EQ( m.getElement( 0, 0 ), 1 ); + EXPECT_EQ( m.getElement( 0, 1 ), 0 ); + EXPECT_EQ( m.getElement( 0, 2 ), 0 ); + EXPECT_EQ( m.getElement( 0, 3 ), 0 ); + EXPECT_EQ( m.getElement( 0, 4 ), 0 ); + + EXPECT_EQ( m.getElement( 1, 0 ), 0 ); + EXPECT_EQ( m.getElement( 1, 1 ), 2 ); + EXPECT_EQ( m.getElement( 1, 2 ), 0 ); + EXPECT_EQ( m.getElement( 1, 3 ), 0 ); + EXPECT_EQ( m.getElement( 1, 4 ), 0 ); + + EXPECT_EQ( m.getElement( 2, 0 ), 0 ); + EXPECT_EQ( m.getElement( 2, 1 ), 0 ); + EXPECT_EQ( m.getElement( 2, 2 ), 3 ); + EXPECT_EQ( m.getElement( 2, 3 ), 0 ); + EXPECT_EQ( m.getElement( 2, 4 ), 0 ); + + EXPECT_EQ( m.getElement( 3, 0 ), 0 ); + EXPECT_EQ( m.getElement( 3, 1 ), 0 ); + EXPECT_EQ( m.getElement( 3, 2 ), 0 ); + EXPECT_EQ( m.getElement( 3, 3 ), 4 ); + EXPECT_EQ( m.getElement( 3, 4 ), 0 ); + + EXPECT_EQ( m.getElement( 4, 0 ), 0 ); + EXPECT_EQ( m.getElement( 4, 1 ), 0 ); + EXPECT_EQ( m.getElement( 4, 2 ), 0 ); + EXPECT_EQ( m.getElement( 4, 3 ), 0 ); + EXPECT_EQ( m.getElement( 4, 4 ), 5 ); +} + +template< typename Matrix > +void test_AddElement() +{ + using RealType = typename Matrix::RealType; + using DeviceType = typename Matrix::DeviceType; + using IndexType = typename Matrix::IndexType; + +/* + * Sets up the following 6x5 sparse matrix: + * + * / 1 2 3 0 0 \ + * | 0 4 5 6 0 | + * | 0 0 7 8 9 | + * | 10 0 0 0 0 | + * | 0 11 0 0 0 | + * \ 0 0 0 12 0 / + */ + + const IndexType rows = 6; + const IndexType cols = 5; + + Matrix m; + m.reset(); + m.setDimensions( rows, cols ); + typename Matrix::CompressedRowLengthsVector rowLengths; + rowLengths.setSize( rows ); + rowLengths.setValue( 3 ); + m.setCompressedRowLengths( rowLengths ); + + RealType value = 1; + for( IndexType i = 0; i < cols - 2; i++ ) // 0th row + m.setElement( 0, i, value++ ); + + for( IndexType i = 1; i < cols - 1; i++ ) // 1st row + m.setElement( 1, i, value++ ); + + for( IndexType i = 2; i < cols; i++ ) // 2nd row + m.setElement( 2, i, value++ ); + + m.setElement( 3, 0, value++ ); // 3rd row + + m.setElement( 4, 1, value++ ); // 4th row + + m.setElement( 5, 3, value++ ); // 5th row + + + // Check the set elements + EXPECT_EQ( m.getElement( 0, 0 ), 1 ); + EXPECT_EQ( m.getElement( 0, 1 ), 2 ); + EXPECT_EQ( m.getElement( 0, 2 ), 3 ); + EXPECT_EQ( m.getElement( 0, 3 ), 0 ); + EXPECT_EQ( m.getElement( 0, 4 ), 0 ); + + EXPECT_EQ( m.getElement( 1, 0 ), 0 ); + EXPECT_EQ( m.getElement( 1, 1 ), 4 ); + EXPECT_EQ( m.getElement( 1, 2 ), 5 ); + EXPECT_EQ( m.getElement( 1, 3 ), 6 ); + EXPECT_EQ( m.getElement( 1, 4 ), 0 ); + + EXPECT_EQ( m.getElement( 2, 0 ), 0 ); + EXPECT_EQ( m.getElement( 2, 1 ), 0 ); + EXPECT_EQ( m.getElement( 2, 2 ), 7 ); + EXPECT_EQ( m.getElement( 2, 3 ), 8 ); + EXPECT_EQ( m.getElement( 2, 4 ), 9 ); + + EXPECT_EQ( m.getElement( 3, 0 ), 10 ); + EXPECT_EQ( m.getElement( 3, 1 ), 0 ); + EXPECT_EQ( m.getElement( 3, 2 ), 0 ); + EXPECT_EQ( m.getElement( 3, 3 ), 0 ); + EXPECT_EQ( m.getElement( 3, 4 ), 0 ); + + EXPECT_EQ( m.getElement( 4, 0 ), 0 ); + EXPECT_EQ( m.getElement( 4, 1 ), 11 ); + EXPECT_EQ( m.getElement( 4, 2 ), 0 ); + EXPECT_EQ( m.getElement( 4, 3 ), 0 ); + EXPECT_EQ( m.getElement( 4, 4 ), 0 ); + + EXPECT_EQ( m.getElement( 5, 0 ), 0 ); + EXPECT_EQ( m.getElement( 5, 1 ), 0 ); + EXPECT_EQ( m.getElement( 5, 2 ), 0 ); + EXPECT_EQ( m.getElement( 5, 3 ), 12 ); + EXPECT_EQ( m.getElement( 5, 4 ), 0 ); + + // Add new elements to the old elements with a multiplying factor applied to the old elements. + +/* + * The following setup results in the following 6x5 sparse matrix: + * + * / 3 6 9 0 0 \ + * | 0 12 15 18 0 | + * | 0 0 21 24 27 | + * | 30 11 12 0 0 | + * | 0 35 14 15 0 | + * \ 0 0 16 41 18 / + */ + + RealType newValue = 1; + for( IndexType i = 0; i < cols - 2; i++ ) // 0th row + m.addElement( 0, i, newValue++, 2.0 ); + + for( IndexType i = 1; i < cols - 1; i++ ) // 1st row + m.addElement( 1, i, newValue++, 2.0 ); + + for( IndexType i = 2; i < cols; i++ ) // 2nd row + m.addElement( 2, i, newValue++, 2.0 ); + + for( IndexType i = 0; i < cols - 2; i++ ) // 3rd row + m.addElement( 3, i, newValue++, 2.0 ); + + for( IndexType i = 1; i < cols - 1; i++ ) // 4th row + m.addElement( 4, i, newValue++, 2.0 ); + + for( IndexType i = 2; i < cols; i++ ) // 5th row + m.addElement( 5, i, newValue++, 2.0 ); + + + EXPECT_EQ( m.getElement( 0, 0 ), 3 ); + EXPECT_EQ( m.getElement( 0, 1 ), 6 ); + EXPECT_EQ( m.getElement( 0, 2 ), 9 ); + EXPECT_EQ( m.getElement( 0, 3 ), 0 ); + EXPECT_EQ( m.getElement( 0, 4 ), 0 ); + + EXPECT_EQ( m.getElement( 1, 0 ), 0 ); + EXPECT_EQ( m.getElement( 1, 1 ), 12 ); + EXPECT_EQ( m.getElement( 1, 2 ), 15 ); + EXPECT_EQ( m.getElement( 1, 3 ), 18 ); + EXPECT_EQ( m.getElement( 1, 4 ), 0 ); + + EXPECT_EQ( m.getElement( 2, 0 ), 0 ); + EXPECT_EQ( m.getElement( 2, 1 ), 0 ); + EXPECT_EQ( m.getElement( 2, 2 ), 21 ); + EXPECT_EQ( m.getElement( 2, 3 ), 24 ); + EXPECT_EQ( m.getElement( 2, 4 ), 27 ); + + EXPECT_EQ( m.getElement( 3, 0 ), 30 ); + EXPECT_EQ( m.getElement( 3, 1 ), 11 ); + EXPECT_EQ( m.getElement( 3, 2 ), 12 ); + EXPECT_EQ( m.getElement( 3, 3 ), 0 ); + EXPECT_EQ( m.getElement( 3, 4 ), 0 ); + + EXPECT_EQ( m.getElement( 4, 0 ), 0 ); + EXPECT_EQ( m.getElement( 4, 1 ), 35 ); + EXPECT_EQ( m.getElement( 4, 2 ), 14 ); + EXPECT_EQ( m.getElement( 4, 3 ), 15 ); + EXPECT_EQ( m.getElement( 4, 4 ), 0 ); + + EXPECT_EQ( m.getElement( 5, 0 ), 0 ); + EXPECT_EQ( m.getElement( 5, 1 ), 0 ); + EXPECT_EQ( m.getElement( 5, 2 ), 16 ); + EXPECT_EQ( m.getElement( 5, 3 ), 41 ); + EXPECT_EQ( m.getElement( 5, 4 ), 18 ); +} + +template< typename Matrix > +void test_SetRow() +{ + using RealType = typename Matrix::RealType; + using DeviceType = typename Matrix::DeviceType; + using IndexType = typename Matrix::IndexType; + +/* + * Sets up the following 3x7 sparse matrix: + * + * / 0 0 0 1 1 1 0 \ + * | 2 2 2 0 0 0 0 | + * \ 3 3 3 0 0 0 0 / + */ + + const IndexType rows = 3; + const IndexType cols = 7; + + Matrix m; + m.reset(); + m.setDimensions( rows, cols ); + typename Matrix::CompressedRowLengthsVector rowLengths; + rowLengths.setSize( rows ); + rowLengths.setValue( 6 ); + rowLengths.setElement( 1, 3 ); + m.setCompressedRowLengths( rowLengths ); + + RealType value = 1; + for( IndexType i = 0; i < 3; i++ ) + { + m.setElement( 0, i + 3, value ); + m.setElement( 1, i, value + 1 ); + m.setElement( 2, i, value + 2 ); + } + + RealType row1 [ 3 ] = { 11, 11, 11 }; IndexType colIndexes1 [ 3 ] = { 0, 1, 2 }; + RealType row2 [ 3 ] = { 22, 22, 22 }; IndexType colIndexes2 [ 3 ] = { 0, 1, 2 }; + RealType row3 [ 3 ] = { 33, 33, 33 }; IndexType colIndexes3 [ 3 ] = { 3, 4, 5 }; + + RealType row = 0; + IndexType elements = 3; + + m.setRow( row++, colIndexes1, row1, elements ); + m.setRow( row++, colIndexes2, row2, elements ); + m.setRow( row++, colIndexes3, row3, elements ); + + + EXPECT_EQ( m.getElement( 0, 0 ), 11 ); + EXPECT_EQ( m.getElement( 0, 1 ), 11 ); + EXPECT_EQ( m.getElement( 0, 2 ), 11 ); + EXPECT_EQ( m.getElement( 0, 3 ), 0 ); + EXPECT_EQ( m.getElement( 0, 4 ), 0 ); + EXPECT_EQ( m.getElement( 0, 5 ), 0 ); + EXPECT_EQ( m.getElement( 0, 6 ), 0 ); + + EXPECT_EQ( m.getElement( 1, 0 ), 22 ); + EXPECT_EQ( m.getElement( 1, 1 ), 22 ); + EXPECT_EQ( m.getElement( 1, 2 ), 22 ); + EXPECT_EQ( m.getElement( 1, 3 ), 0 ); + EXPECT_EQ( m.getElement( 1, 4 ), 0 ); + EXPECT_EQ( m.getElement( 1, 5 ), 0 ); + EXPECT_EQ( m.getElement( 1, 6 ), 0 ); + + EXPECT_EQ( m.getElement( 2, 0 ), 0 ); + EXPECT_EQ( m.getElement( 2, 1 ), 0 ); + EXPECT_EQ( m.getElement( 2, 2 ), 0 ); + EXPECT_EQ( m.getElement( 2, 3 ), 33 ); + EXPECT_EQ( m.getElement( 2, 4 ), 33 ); + EXPECT_EQ( m.getElement( 2, 5 ), 33 ); + EXPECT_EQ( m.getElement( 2, 6 ), 0 ); +} + +template< typename Matrix > +void test_VectorProduct() +{ + using RealType = typename Matrix::RealType; + using DeviceType = typename Matrix::DeviceType; + using IndexType = typename Matrix::IndexType; + +/* + * Sets up the following 5x4 sparse matrix: + * + * / 1 2 3 0 \ + * | 0 0 0 4 | + * | 5 6 7 0 | + * | 0 8 9 10 | + * \ 0 0 11 12 / + */ + + const IndexType m_rows = 5; + const IndexType m_cols = 4; + + Matrix m; + m.reset(); + m.setDimensions( m_rows, m_cols ); + typename Matrix::CompressedRowLengthsVector rowLengths; + rowLengths.setSize( m_rows ); + rowLengths.setValue( 3 ); + m.setCompressedRowLengths( rowLengths ); + + RealType value = 1; + for( IndexType i = 0; i < m_cols - 1; i++ ) // 0th row + m.setElement( 0, i, value++ ); + + m.setElement( 1, 3, value++ ); // 1st row + + for( IndexType i = 0; i < m_cols - 1; i++ ) // 2nd row + m.setElement( 2, i, value++ ); + + for( IndexType i = 1; i < m_cols; i++ ) // 3rd row + m.setElement( 3, i, value++ ); + + for( IndexType i = 2; i < m_cols; i++ ) // 4th row + m.setElement( 4, i, value++ ); + + using VectorType = TNL::Containers::Vector< RealType, DeviceType, IndexType >; + + VectorType inVector; + inVector.setSize( 4 ); + for( IndexType i = 0; i < inVector.getSize(); i++ ) + inVector.setElement( i, 2 ); + + VectorType outVector; + outVector.setSize( 5 ); + for( IndexType j = 0; j < outVector.getSize(); j++ ) + outVector.setElement( j, 0 ); + + + m.vectorProduct( inVector, outVector); + + + EXPECT_EQ( outVector.getElement( 0 ), 12 ); + EXPECT_EQ( outVector.getElement( 1 ), 8 ); + EXPECT_EQ( outVector.getElement( 2 ), 36 ); + EXPECT_EQ( outVector.getElement( 3 ), 54 ); + EXPECT_EQ( outVector.getElement( 4 ), 46 ); +} + +template< typename Matrix > +void test_PerformSORIteration() +{ + using RealType = typename Matrix::RealType; + using DeviceType = typename Matrix::DeviceType; + using IndexType = typename Matrix::IndexType; + +/* + * Sets up the following 4x4 sparse matrix: + * + * / 4 1 0 0 \ + * | 1 4 1 0 | + * | 0 1 4 1 | + * \ 0 0 1 4 / + */ + + const IndexType m_rows = 4; + const IndexType m_cols = 4; + + Matrix m; + m.reset(); + m.setDimensions( m_rows, m_cols ); + typename Matrix::CompressedRowLengthsVector rowLengths; + rowLengths.setSize( m_rows ); + rowLengths.setValue( 3 ); + m.setCompressedRowLengths( rowLengths ); + + m.setElement( 0, 0, 4.0 ); // 0th row + m.setElement( 0, 1, 1.0); + + m.setElement( 1, 0, 1.0 ); // 1st row + m.setElement( 1, 1, 4.0 ); + m.setElement( 1, 2, 1.0 ); + + m.setElement( 2, 1, 1.0 ); // 2nd row + m.setElement( 2, 2, 4.0 ); + m.setElement( 2, 3, 1.0 ); + + m.setElement( 3, 2, 1.0 ); // 3rd row + m.setElement( 3, 3, 4.0 ); + + RealType bVector [ 4 ] = { 1, 1, 1, 1 }; + RealType xVector [ 4 ] = { 1, 1, 1, 1 }; + + IndexType row = 0; + RealType omega = 1; + + + m.performSORIteration( bVector, row++, xVector, omega); + + EXPECT_EQ( xVector[ 0 ], 0.0 ); + EXPECT_EQ( xVector[ 1 ], 1.0 ); + EXPECT_EQ( xVector[ 2 ], 1.0 ); + EXPECT_EQ( xVector[ 3 ], 1.0 ); + + + m.performSORIteration( bVector, row++, xVector, omega); + + EXPECT_EQ( xVector[ 0 ], 0.0 ); + EXPECT_EQ( xVector[ 1 ], 0.0 ); + EXPECT_EQ( xVector[ 2 ], 1.0 ); + EXPECT_EQ( xVector[ 3 ], 1.0 ); + + + m.performSORIteration( bVector, row++, xVector, omega); + + EXPECT_EQ( xVector[ 0 ], 0.0 ); + EXPECT_EQ( xVector[ 1 ], 0.0 ); + EXPECT_EQ( xVector[ 2 ], 0.0 ); + EXPECT_EQ( xVector[ 3 ], 1.0 ); + + + m.performSORIteration( bVector, row++, xVector, omega); + + EXPECT_EQ( xVector[ 0 ], 0.0 ); + EXPECT_EQ( xVector[ 1 ], 0.0 ); + EXPECT_EQ( xVector[ 2 ], 0.0 ); + EXPECT_EQ( xVector[ 3 ], 0.25 ); +} + +template< typename Matrix > +void test_SaveAndLoad() +{ + using RealType = typename Matrix::RealType; + using DeviceType = typename Matrix::DeviceType; + using IndexType = typename Matrix::IndexType; + +/* + * Sets up the following 4x4 sparse matrix: + * + * / 1 2 3 0 \ + * | 0 4 0 5 | + * | 6 7 8 0 | + * \ 0 9 10 11 / + */ + + const IndexType m_rows = 4; + const IndexType m_cols = 4; + + Matrix savedMatrix; + savedMatrix.reset(); + savedMatrix.setDimensions( m_rows, m_cols ); + typename Matrix::CompressedRowLengthsVector rowLengths; + rowLengths.setSize( m_rows ); + rowLengths.setValue( 3 ); + savedMatrix.setCompressedRowLengths( rowLengths ); + + RealType value = 1; + for( IndexType i = 0; i < m_cols - 1; i++ ) // 0th row + savedMatrix.setElement( 0, i, value++ ); + + savedMatrix.setElement( 1, 1, value++ ); + savedMatrix.setElement( 1, 3, value++ ); // 1st row + + for( IndexType i = 0; i < m_cols - 1; i++ ) // 2nd row + savedMatrix.setElement( 2, i, value++ ); + + for( IndexType i = 1; i < m_cols; i++ ) // 3rd row + savedMatrix.setElement( 3, i, value++ ); + + savedMatrix.save( "sparseMatrixFile" ); + + Matrix loadedMatrix; + loadedMatrix.reset(); + loadedMatrix.setDimensions( m_rows, m_cols ); + typename Matrix::CompressedRowLengthsVector rowLengths2; + rowLengths2.setSize( m_rows ); + rowLengths2.setValue( 3 ); + loadedMatrix.setCompressedRowLengths( rowLengths2 ); + + + loadedMatrix.load( "sparseMatrixFile" ); + + + EXPECT_EQ( savedMatrix.getElement( 0, 0 ), loadedMatrix.getElement( 0, 0 ) ); + EXPECT_EQ( savedMatrix.getElement( 0, 1 ), loadedMatrix.getElement( 0, 1 ) ); + EXPECT_EQ( savedMatrix.getElement( 0, 2 ), loadedMatrix.getElement( 0, 2 ) ); + EXPECT_EQ( savedMatrix.getElement( 0, 3 ), loadedMatrix.getElement( 0, 3 ) ); + + EXPECT_EQ( savedMatrix.getElement( 1, 0 ), loadedMatrix.getElement( 1, 0 ) ); + EXPECT_EQ( savedMatrix.getElement( 1, 1 ), loadedMatrix.getElement( 1, 1 ) ); + EXPECT_EQ( savedMatrix.getElement( 1, 2 ), loadedMatrix.getElement( 1, 2 ) ); + EXPECT_EQ( savedMatrix.getElement( 1, 3 ), loadedMatrix.getElement( 1, 3 ) ); + + EXPECT_EQ( savedMatrix.getElement( 2, 0 ), loadedMatrix.getElement( 2, 0 ) ); + EXPECT_EQ( savedMatrix.getElement( 2, 1 ), loadedMatrix.getElement( 2, 1 ) ); + EXPECT_EQ( savedMatrix.getElement( 2, 2 ), loadedMatrix.getElement( 2, 2 ) ); + EXPECT_EQ( savedMatrix.getElement( 2, 3 ), loadedMatrix.getElement( 2, 3 ) ); + + EXPECT_EQ( savedMatrix.getElement( 3, 0 ), loadedMatrix.getElement( 3, 0 ) ); + EXPECT_EQ( savedMatrix.getElement( 3, 1 ), loadedMatrix.getElement( 3, 1 ) ); + EXPECT_EQ( savedMatrix.getElement( 3, 2 ), loadedMatrix.getElement( 3, 2 ) ); + EXPECT_EQ( savedMatrix.getElement( 3, 3 ), loadedMatrix.getElement( 3, 3 ) ); + + EXPECT_EQ( savedMatrix.getElement( 0, 0 ), 1 ); + EXPECT_EQ( savedMatrix.getElement( 0, 1 ), 2 ); + EXPECT_EQ( savedMatrix.getElement( 0, 2 ), 3 ); + EXPECT_EQ( savedMatrix.getElement( 0, 3 ), 0 ); + + EXPECT_EQ( savedMatrix.getElement( 1, 0 ), 0 ); + EXPECT_EQ( savedMatrix.getElement( 1, 1 ), 4 ); + EXPECT_EQ( savedMatrix.getElement( 1, 2 ), 0 ); + EXPECT_EQ( savedMatrix.getElement( 1, 3 ), 5 ); + + EXPECT_EQ( savedMatrix.getElement( 2, 0 ), 6 ); + EXPECT_EQ( savedMatrix.getElement( 2, 1 ), 7 ); + EXPECT_EQ( savedMatrix.getElement( 2, 2 ), 8 ); + EXPECT_EQ( savedMatrix.getElement( 2, 3 ), 0 ); + + EXPECT_EQ( savedMatrix.getElement( 3, 0 ), 0 ); + EXPECT_EQ( savedMatrix.getElement( 3, 1 ), 9 ); + EXPECT_EQ( savedMatrix.getElement( 3, 2 ), 10 ); + EXPECT_EQ( savedMatrix.getElement( 3, 3 ), 11 ); + + std::cout << "\nThis will create a file called 'sparseMatrixFile' (of the matrix created in the test function), in .../tnl-dev/Debug/bin/\n\n"; +} + +template< typename Matrix > +void test_Print() +{ + using RealType = typename Matrix::RealType; + using DeviceType = typename Matrix::DeviceType; + using IndexType = typename Matrix::IndexType; + +/* + * Sets up the following 5x4 sparse matrix: + * + * / 1 2 3 0 \ + * | 0 0 0 4 | + * | 5 6 7 0 | + * | 0 8 9 10 | + * \ 0 0 11 12 / + */ + + const IndexType m_rows = 5; + const IndexType m_cols = 4; + + Matrix m; + m.reset(); + m.setDimensions( m_rows, m_cols ); + typename Matrix::CompressedRowLengthsVector rowLengths; + rowLengths.setSize( m_rows ); + rowLengths.setValue( 3 ); + m.setCompressedRowLengths( rowLengths ); + + RealType value = 1; + for( IndexType i = 0; i < m_cols - 1; i++ ) // 0th row + m.setElement( 0, i, value++ ); + + m.setElement( 1, 3, value++ ); // 1st row + + for( IndexType i = 0; i < m_cols - 1; i++ ) // 2nd row + m.setElement( 2, i, value++ ); + + for( IndexType i = 1; i < m_cols; i++ ) // 3rd row + m.setElement( 3, i, value++ ); + + for( IndexType i = 2; i < m_cols; i++ ) // 4th row + m.setElement( 4, i, value++ ); + + // This is from: https://stackoverflow.com/questions/5193173/getting-cout-output-to-a-stdstring + #include <sstream> + std::stringstream printed; + std::stringstream couted; + + // This is from: https://stackoverflow.com/questions/19485536/redirect-output-of-an-function-printing-to-console-to-string + //change the underlying buffer and save the old buffer + auto old_buf = std::cout.rdbuf(printed.rdbuf()); + + m.print( std::cout ); //all the std::cout goes to ss + + std::cout.rdbuf(old_buf); //reset + + //printed << printed.str() << std::endl; + couted << "Row: 0 -> Col:0->1 Col:1->2 Col:2->3\t\n" + "Row: 1 -> Col:3->4\t\n" + "Row: 2 -> Col:0->5 Col:1->6 Col:2->7\t\n" + "Row: 3 -> Col:1->8 Col:2->9 Col:3->10\t\n" + "Row: 4 -> Col:2->11 Col:3->12\t\n"; + + + EXPECT_EQ( printed.str(), couted.str() ); +} + +#endif \ No newline at end of file -- GitLab