diff --git a/include/alp/structures.hpp b/include/alp/structures.hpp index f6b2b2ff5..ad8eb4edb 100644 --- a/include/alp/structures.hpp +++ b/include/alp/structures.hpp @@ -109,6 +109,65 @@ namespace alp { typedef OpenInterval type; }; + /** + * Checks if a given diagonal belongs to the given interval. + */ + template< typename Interval > + bool is_within_interval( const std::ptrdiff_t diag_offset ) { + return ( ( diag_offset >= Interval::left ) && ( diag_offset < Interval::right ) ); + } + + namespace internal { + + /** + * Checks if a pair of coordinates (i, j) belong to non-zero structure + * of the band defined by the band_index and the union of bands. + * \note Does not check for matrix dimensions. + */ + + /** Specialization for out-of-bounds band index */ + template< + size_t band_index, typename Bands, + std::enable_if_t< + band_index >= std::tuple_size< Bands >::value + > * = nullptr + > + bool is_non_zero( const size_t i, const size_t j ) { + (void)i; + (void)j; + return false; + } + + /** Specialization for within-the-bounds band index */ + template< + size_t band_index, typename Bands, + std::enable_if_t< + band_index < std::tuple_size< Bands >::value + > * = nullptr + > + bool is_non_zero( const size_t i, const size_t j ) { + + using band_interval = typename std::tuple_element< band_index, Bands >::type; + + if( is_within_interval< band_interval >( static_cast< std::ptrdiff_t >( j ) - static_cast< std::ptrdiff_t >( i ) ) ) { + return true; + } else { + return is_non_zero< band_index + 1, Bands >( i, j ); + } + } + + } // namespace internal + + /** + * Checks if a pair of coordinates (i, j) belong to non-zero structure + * of the band defined by the band_index and the union of bands. + * \note Does not check for matrix dimensions. + */ + template< typename Structure > + bool is_non_zero( const size_t i, const size_t j ) { + return internal::is_non_zero< 0, typename Structure::band_intervals >( i, j ); + } + namespace internal { /** * @internal Compile-time check if a tuple of intervals is sorted and non-overlapping. diff --git a/tests/unit/alp_views.cpp b/tests/unit/alp_views.cpp index 453fbd110..dc5ac6a81 100644 --- a/tests/unit/alp_views.cpp +++ b/tests/unit/alp_views.cpp @@ -18,45 +18,8 @@ #include #include -#include "alp.hpp" - -template< typename MatrixType > -void print_matrix( std::string name, const MatrixType &A ) { - - if( ! alp::internal::getInitialized( A ) ) { - std::cout << "Matrix " << name << " uninitialized.\n"; - return; - } - - std::cout << "Matrix " << name << " of size " << alp::dims( A ).first << " x " << alp::dims( A ).second << " contains the following elements:\n"; - - for( size_t row = 0; row < alp::nrows( A ); ++row ) { - std::cout << "[\t"; - for( size_t col = 0; col < alp::ncols( A ); ++col ) { - auto pos = alp::internal::getStorageIndex( A, row, col ); - // std::cout << "(" << pos << "): "; - std::cout << alp::internal::access( A, pos ) << "\t"; - } - std::cout << "]\n"; - } -} - -template< typename VectorType > -void print_vector( std::string name, const VectorType &v ) { - - if( ! alp::internal::getInitialized( v ) ) { - std::cout << "Vector " << name << " uninitialized.\n"; - return; - } - - std::cout << "Vector " << name << " of size " << alp::getLength( v ) << " contains the following elements:\n"; - - std::cout << "[\t"; - for( size_t i = 0; i < alp::getLength( v ); ++i ) { - std::cout << v[ i ] << "\t"; - } - std::cout << "]\n"; -} +#include +#include "../utils/print_alp_containers.hpp" template< typename T > void init_matrix( std::vector< T > &A, const size_t rows, const size_t cols ) { diff --git a/tests/unit/dense_dot_norm2.cpp b/tests/unit/dense_dot_norm2.cpp index 1ece45e16..aecf15f9f 100644 --- a/tests/unit/dense_dot_norm2.cpp +++ b/tests/unit/dense_dot_norm2.cpp @@ -31,23 +31,6 @@ const T1 testval1 = 1.5; const T1 testval2 = -1; const T1 testval3 = 2.; -template< typename VectorType > -void print_vector( std::string name, const VectorType &v ) { - - if( ! alp::internal::getInitialized( v ) ) { - std::cout << "Vector " << name << " uninitialized.\n"; - return; - } - - std::cout << "Vector " << name << " of size " << alp::getLength( v ) << " contains the following elements:\n"; - - std::cout << "[\t"; - for( size_t i = 0; i < alp::getLength( v ); ++i ) { - std::cout << v[ i ] << "\t"; - } - std::cout << "]\n"; -} - void alp_program( const size_t &n, alp::RC &rc ) { { diff --git a/tests/unit/dense_fold.cpp b/tests/unit/dense_fold.cpp index ffab496ab..47ff89206 100644 --- a/tests/unit/dense_fold.cpp +++ b/tests/unit/dense_fold.cpp @@ -28,23 +28,6 @@ const T1 testval1 = 1.5; const T1 testval2 = -1; const T1 testval3 = 2.; -template< typename VectorType > -void print_vector( std::string name, const VectorType &v ) { - - if( ! alp::internal::getInitialized( v ) ) { - std::cout << "Vector " << name << " uninitialized.\n"; - return; - } - - std::cout << "Vector " << name << " of size " << alp::getLength( v ) << " contains the following elements:\n"; - - std::cout << "[\t"; - for( size_t i = 0; i < alp::getLength( v ); ++i ) { - std::cout << v[ i ] << "\t"; - } - std::cout << "]\n"; -} - void alp_program( const size_t &n, alp::RC &rc ) { // test 1 foldl( vector, scalar, mul_op) diff --git a/tests/unit/dense_matrix_eWiseApply.cpp b/tests/unit/dense_matrix_eWiseApply.cpp index a2c7ea0d2..6e2cb61f5 100644 --- a/tests/unit/dense_matrix_eWiseApply.cpp +++ b/tests/unit/dense_matrix_eWiseApply.cpp @@ -23,22 +23,6 @@ using namespace alp; -template< typename Structure > -void print_matrix( const alp::Matrix< double, Structure > & A) { - (void)A; - // if( ! alp::internal::getInitialized< double >( A ) ) { - // std::cout << "Matrix is uninitialized, nothing to print.\n"; - // return; - // } - // const double * Araw = alp::getRaw( internal::getContainer( A ) ); - // for( size_t row = 0; row < alp::nrows( A ); ++row ) { - // for( size_t col = 0; col < alp::ncols( A ); ++col ) { - // std::cout << Araw[row * alp::ncols( A ) + col] << " "; - // } - // std::cout << "\n"; - // } -} - void alp_program( const size_t & n, alp::RC & rc ) { alp::Semiring< alp::operators::add< double >, alp::operators::mul< double >, alp::identities::zero, alp::identities::one > ring; diff --git a/tests/unit/dense_mxm.cpp b/tests/unit/dense_mxm.cpp index b9ad38a76..2474807da 100644 --- a/tests/unit/dense_mxm.cpp +++ b/tests/unit/dense_mxm.cpp @@ -20,29 +20,10 @@ #include #include +#include "../utils/print_alp_containers.hpp" using namespace alp; -template< typename T, typename Structure > -void print_matrix( std::string name, const alp::Matrix< T, Structure > & A) { - - if( ! alp::internal::getInitialized( A ) ) { - std::cout << "Matrix " << name << " uninitialized.\n"; - return; - } - - std::cout << name << ":" << std::endl; - for( size_t row = 0; row < alp::nrows( A ); ++row ) { - std::cout << "[\t"; - for( size_t col = 0; col < alp::ncols( A ); ++col ) { - auto pos = internal::getStorageIndex( A, row, col ); - // std::cout << "(" << pos << "): "; - std::cout << internal::access(A, pos ) << "\t"; - } - std::cout << "]" << std::endl; - } -} - template< typename T > void print_stdvec_as_matrix( std::string name, const std::vector< T > & vA, const size_t m, const size_t n, const size_t lda ) { diff --git a/tests/unit/dense_outer.cpp b/tests/unit/dense_outer.cpp index 6640e26e4..eecaf4077 100644 --- a/tests/unit/dense_outer.cpp +++ b/tests/unit/dense_outer.cpp @@ -19,26 +19,7 @@ #include #include "alp.hpp" - -template< typename MatrixType > -void print_matrix( std::string name, const MatrixType &A) { - - if( ! alp::internal::getInitialized( A ) ) { - std::cout << "Matrix " << name << " uninitialized.\n"; - return; - } - - std::cout << name << ":" << std::endl; - for( size_t row = 0; row < alp::nrows( A ); ++row ) { - std::cout << "[\t"; - for( size_t col = 0; col < alp::ncols( A ); ++col ) { - auto pos = alp::internal::getStorageIndex( A, row, col ); - // std::cout << "(" << pos << "): "; - std::cout << alp::internal::access( A, pos ) << "\t"; - } - std::cout << "]" << std::endl; - } -} +#include "../utils/print_alp_containers.hpp" template< typename T > void print_stdvec_as_matrix( std::string name, const std::vector< T > &vA, const size_t m, const size_t n, const size_t lda ) { diff --git a/tests/utils/print_alp_containers.hpp b/tests/utils/print_alp_containers.hpp new file mode 100644 index 000000000..0c58714a2 --- /dev/null +++ b/tests/utils/print_alp_containers.hpp @@ -0,0 +1,76 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * Licensed 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. + */ + +#ifndef _H_TEST_UTILS_PRINT_ALP_CONTAINERS +#define _H_TEST_UTILS_PRINT_ALP_CONTAINERS + +#include + +#include + +template< + typename MatrixType, + std::enable_if_t< alp::is_matrix< MatrixType >::value > * = nullptr +> +void print_matrix( std::string name, const MatrixType &A ) { + + if( ! alp::internal::getInitialized( A ) ) { + std::cout << "Matrix " << name << " uninitialized. Nothing to print.\n"; + return; + } + + constexpr bool is_sym { alp::structures::is_a< typename alp::inspect_structure< MatrixType >::type, alp::structures::Symmetric >::value }; + // Temporary until adding multiple symmetry directions + constexpr bool sym_up { is_sym }; + + std::cout << name << ":" << std::endl; + for( size_t row = 0; row < alp::nrows( A ); ++row ) { + std::cout << "|"; + for( size_t col = 0; col < alp::ncols( A ); ++col ) { + if( alp::is_non_zero< typename alp::inspect_structure< MatrixType >::type >( row, col ) ) { + const auto k = ( !is_sym || ( is_sym && ( sym_up == ( row > col ) ) ) ) ? + alp::internal::getStorageIndex( A, row, col ) : + alp::internal::getStorageIndex( A, col, row ); + std::cout << std::setprecision( 3 ) << "\t" << alp::internal::access( A, k ); + } else { + std::cout << std::setprecision( 0 ) << "\t" << 0; + } + } + std::cout << "\t" << "|" << "\n"; + } +} + +template< + typename VectorType, + std::enable_if_t< alp::is_vector< VectorType >::value > * = nullptr +> +void print_vector( std::string name, const VectorType &v ) { + + if( ! alp::internal::getInitialized( v ) ) { + std::cout << "Vector " << name << " uninitialized. Nothing to print.\n"; + return; + } + + std::cout << name << ":" << std::endl; + std::cout << "["; + for( size_t i = 0; i < alp::nrows( v ); ++i ) { + std::cout << std::setprecision( 3 ) << "\t" << v[ i ]; + } + std::cout << "\t" << "]" << "\n"; +} + +#endif // _H_TEST_UTILS_PRINT_ALP_CONTAINERS