From ffd5bfce32ce2853a12b1923b4f7ec774be7d513 Mon Sep 17 00:00:00 2001 From: Denis Jelovina Date: Thu, 7 Apr 2022 14:01:29 +0200 Subject: [PATCH 01/22] This is a squashed version of the following commits: - complex type works for real numbers - conjugate_gradient for complex type - works for complex type but real numbers (imaginary part =0) - new test matrix added - parser for complex - not finished - bugfix - works but hermitian format still not functional - randomly generated test added - not good candidate found in the online databases - downloading from my gitlab account - temp test files - fix std:conjugate out-of-place - move conjugate to utils --- .../algorithms/conjugate_gradient.hpp | 51 ++-- include/graphblas/algorithms/hpcg/hpcg.hpp | 24 +- .../algorithms/hpcg/system_building_utils.hpp | 4 +- include/graphblas/utils.hpp | 29 ++ include/graphblas/utils/iscomplex.hpp | 11 + .../utils/parser/MatrixFileIterator.hpp | 2 +- .../utils/parser/MatrixFileProperties.hpp | 3 + .../utils/parser/MatrixFileReader.hpp | 1 + .../utils/parser/MatrixFileReaderBase.hpp | 8 +- tests/smoke/CMakeLists.txt | 6 + tests/smoke/conjugate_gradient.cpp | 40 +-- tests/smoke/hpcg.cpp | 68 +++-- ...te_conjugate_gradient_out_rndHermit256_ref | 256 ++++++++++++++++++ tests/smoke/smoketests.sh | 17 ++ tests/utils/output_verification.hpp | 41 ++- tools/downloadDatasets.sh | 12 +- 16 files changed, 482 insertions(+), 91 deletions(-) create mode 100644 tests/smoke/output_verification/complex_conjugate_conjugate_gradient_out_rndHermit256_ref diff --git a/include/graphblas/algorithms/conjugate_gradient.hpp b/include/graphblas/algorithms/conjugate_gradient.hpp index fcda5d50b..5a622aa77 100644 --- a/include/graphblas/algorithms/conjugate_gradient.hpp +++ b/include/graphblas/algorithms/conjugate_gradient.hpp @@ -23,8 +23,11 @@ #define _H_GRB_ALGORITHMS_CONJUGATE_GRADIENT #include +#include #include +#include + namespace grb { @@ -190,7 +193,8 @@ namespace grb { ); constexpr const Descriptor descr_dense = descr | descriptors::dense; - const ResidualType zero = ring.template getZero< ResidualType >(); + const ResidualType zero_residual = ring.template getZero< ResidualType >(); + const IOType zero = ring.template getZero< IOType >(); const size_t n = grb::ncols( A ); // dynamic checks @@ -223,7 +227,7 @@ namespace grb { } // others - if( tol <= zero ) { + if( tol <= zero_residual ) { std::cerr << "Error: tolerance input to CG must be strictly positive\n"; return ILLEGAL; } @@ -244,7 +248,7 @@ namespace grb { assert( nnz( x ) == n ); } - ResidualType alpha, sigma, bnorm; + IOType sigma, bnorm, alpha, beta; // temp = 0 grb::RC ret = grb::set( temp, 0 ); @@ -269,16 +273,21 @@ namespace grb { // sigma = r' * r; sigma = zero; - ret = ret ? ret : grb::dot< descr_dense >( sigma, r, r, ring ); + grb::set( temp, r ); + grb::eWiseMap( []( IOType a ) { return( grb::utils::conjugate( a ) ); } , temp ); + ret = ret ? ret : grb::dot< descr_dense >( sigma, temp, r, ring ); + assert( ret == SUCCESS ); // bnorm = b' * b; bnorm = zero; - ret = ret ? ret : grb::dot< descr_dense >( bnorm, b, b, ring ); + grb::set( temp, b ); + grb::eWiseMap( []( IOType a ) { return( grb::utils::conjugate( a ) ); } , temp ); + ret = ret ? ret : grb::dot< descr_dense >( bnorm, temp, b, ring ); assert( ret == SUCCESS ); if( ret == SUCCESS ) { - tol *= sqrt( bnorm ); + tol *= sqrt( std::abs( bnorm ) ); } size_t iter = 0; @@ -292,13 +301,15 @@ namespace grb { ret = ret ? ret : grb::mxv< descr_dense >( temp, A, u, ring ); assert( ret == SUCCESS ); - // residual = u' * temp - residual = zero; - ret = ret ? ret : grb::dot< descr_dense >( residual, temp, u, ring ); + // beta = u' * temp + beta = zero; + grb::eWiseMap( []( IOType a ) { return( grb::utils::conjugate( a ) ); } , u ); + ret = ret ? ret : grb::dot< descr_dense >( beta, temp, u, ring ); + grb::eWiseMap( []( IOType a ) { return( grb::utils::conjugate( a ) ); } , u ); assert( ret == SUCCESS ); - // alpha = sigma / residual; - ret = ret ? ret : grb::apply( alpha, sigma, residual, divide ); + // alpha = sigma / beta; + ret = ret ? ret : grb::apply( alpha, sigma, beta, divide ); assert( ret == SUCCESS ); // x = x + alpha * u; @@ -314,19 +325,22 @@ namespace grb { ret = ret ? ret : grb::foldl< descr_dense >( r, temp, minus ); assert( ret == SUCCESS ); - // residual = r' * r; - residual = zero; - ret = ret ? ret : grb::dot< descr_dense >( residual, r, r, ring ); + // beta = r' * r; + beta = zero; + grb::set( temp, r ); + grb::eWiseMap( []( IOType a ) { return( grb::utils::conjugate( a ) ); } , temp ); + ret = ret ? ret : grb::dot< descr_dense >( beta, temp, r, ring ); assert( ret == SUCCESS ); + residual = std::abs( beta ); if( ret == SUCCESS ) { if( sqrt( residual ) < tol ) { break; } } - // alpha = residual / sigma; - ret = ret ? ret : grb::apply( alpha, residual, sigma, divide ); + // alpha = beta / sigma; + ret = ret ? ret : grb::apply( alpha, beta, sigma, divide ); assert( ret == SUCCESS ); // temp = r + alpha * u; @@ -339,8 +353,9 @@ namespace grb { // u = temp std::swap( u, temp ); - // sigma = residual; - sigma = residual; + // sigma = beta; + sigma = beta; + residual = std::abs( beta ); } while( iter++ < max_iterations && ret == SUCCESS ); diff --git a/include/graphblas/algorithms/hpcg/hpcg.hpp b/include/graphblas/algorithms/hpcg/hpcg.hpp index 6caf22a1c..78d05e4fe 100644 --- a/include/graphblas/algorithms/hpcg/hpcg.hpp +++ b/include/graphblas/algorithms/hpcg/hpcg.hpp @@ -105,7 +105,8 @@ namespace grb { const Ring &ring = Ring(), const Minus &minus = Minus() ) { - ResidualType alpha; + IOType alpha; + IOType dotproduct; const grb::Matrix< NonzeroType > &A { data.A }; grb::Vector< IOType > &x { data.x }; @@ -127,8 +128,9 @@ namespace grb { ret = ret ? ret : grb::eWiseApply( r, b, Ap, minus ); // r = b - Ap; assert( ret == SUCCESS ); - norm_residual = ring.template getZero< ResidualType >(); - ret = ret ? ret : grb::dot( norm_residual, r, r, ring ); // norm_residual = r' * r; + dotproduct = static_cast< IOType >( 0.0 ); + ret = ret ? ret : grb::dot( dotproduct, r, r, ring ); // norm_residual = r' * r; + norm_residual = std::abs( dotproduct ); assert( ret == SUCCESS ); // compute sqrt to avoid underflow @@ -136,7 +138,7 @@ namespace grb { // initial norm of residual const ResidualType norm_residual_initial { norm_residual }; - ResidualType old_r_dot_z { 0.0 }, r_dot_z { 0.0 }, beta { 0.0 }; + IOType old_r_dot_z { 0.0 }, r_dot_z { 0.0 }, beta { 0.0 }; size_t iter { 0 }; #ifdef HPCG_PRINT_STEPS @@ -160,7 +162,6 @@ namespace grb { DBG_print_norm( z, "initial z" ); #endif - ResidualType pAp; if( iter == 0 ) { ret = ret ? ret : grb::set( p, z ); // p = z; @@ -171,7 +172,7 @@ namespace grb { } else { old_r_dot_z = r_dot_z; - r_dot_z = ring.template getZero< ResidualType >(); + r_dot_z = static_cast< IOType >( 0.0 );; ret = ret ? ret : grb::dot( r_dot_z, r, z, ring ); // r_dot_z = r' * z; assert( ret == SUCCESS ); @@ -191,11 +192,11 @@ namespace grb { #ifdef HPCG_PRINT_STEPS DBG_print_norm( Ap, "middle Ap" ); #endif - pAp = static_cast< ResidualType >( 0.0 ); - ret = ret ? ret : grb::dot( pAp, Ap, p, ring ); // pAp = p' * Ap + dotproduct = static_cast< IOType >( 0.0 ); + ret = ret ? ret : grb::dot( dotproduct, Ap, p, ring ); // dotproduct = p' * Ap assert( ret == SUCCESS ); - alpha = r_dot_z / pAp; + alpha = r_dot_z / dotproduct; ret = ret ? ret : grb::eWiseMul( x, alpha, p, ring ); // x += alpha * p; assert( ret == SUCCESS ); @@ -209,8 +210,9 @@ namespace grb { DBG_print_norm( r, "end r" ); #endif - norm_residual = static_cast< ResidualType >( 0.0 ); - ret = ret ? ret : grb::dot( norm_residual, r, r, ring ); // residual = r' * r; + dotproduct = static_cast< IOType >( 0.0 ); + ret = ret ? ret : grb::dot( dotproduct, r, r, ring ); // residual = r' * r; + norm_residual = std::abs( dotproduct ); assert( ret == SUCCESS ); norm_residual = std::sqrt( norm_residual ); diff --git a/include/graphblas/algorithms/hpcg/system_building_utils.hpp b/include/graphblas/algorithms/hpcg/system_building_utils.hpp index 11adf82c1..2ac5ddfe5 100644 --- a/include/graphblas/algorithms/hpcg/system_building_utils.hpp +++ b/include/graphblas/algorithms/hpcg/system_building_utils.hpp @@ -80,7 +80,7 @@ namespace grb { * @return grb::SUCCESS if every GraphBLAS operation (to generate vectors and matrices) succeeded, * otherwise the first unsuccessful return value */ - template< std::size_t DIMS, typename T = double > + template< std::size_t DIMS, typename T > grb::RC build_hpcg_system( std::unique_ptr< grb::algorithms::hpcg_data< T, T, T > > & holder, hpcg_system_params< DIMS, T > & params ) { // n is the system matrix size const std::size_t n { std::accumulate( params.physical_sys_sizes.cbegin(), params.physical_sys_sizes.cend(), 1UL, std::multiplies< std::size_t >() ) }; @@ -121,7 +121,7 @@ namespace grb { std::size_t coarser_size { std::accumulate( coarser_sizes.cbegin(), coarser_sizes.cend(), 1UL, std::multiplies< std::size_t >() ) }; std::size_t previous_size { std::accumulate( previous_sizes.cbegin(), previous_sizes.cend(), 1UL, std::multiplies< std::size_t >() ) }; // build data structures for new level - grb::algorithms::multi_grid_data< double, double > * new_coarser { new grb::algorithms::multi_grid_data< double, double >( coarser_size, previous_size ) }; + grb::algorithms::multi_grid_data< T, T > * new_coarser { new grb::algorithms::multi_grid_data< T, T >( coarser_size, previous_size ) }; // install coarser level immediately to cleanup in case of build error *coarser = new_coarser; // initialize coarsener matrix, system matrix and diagonal vector for the coarser level diff --git a/include/graphblas/utils.hpp b/include/graphblas/utils.hpp index 10515f11b..70fdfc415 100644 --- a/include/graphblas/utils.hpp +++ b/include/graphblas/utils.hpp @@ -30,6 +30,7 @@ #include #include +#include namespace grb { @@ -258,6 +259,34 @@ namespace grb { } } + /** Specialisation for complex-valued masks */ + template< Descriptor descriptor, typename T > + static bool interpretMask( const bool & assigned, + const std::complex * const val, const size_t offset ) { + // set default mask to false + bool ret = false; + // if we request a structural mask, decide only on passed assigned variable + if( descriptor & descriptors::structural ) { + ret = assigned; + } else { + // if based on value, if there is a value, cast it to bool + if( assigned ) { + ret = static_cast< bool >( + real( val [ offset ] ) == 0 && + imag( val [ offset ] ) == 0 + ); + } + // otherwise there is no value and false is assumed + } + // check whether we should return the inverted value + if( descriptor & descriptors::invert_mask ) { + return ! ret; + } else { + return ret; + } + } + + /** Specialisation for void-valued masks */ template< Descriptor descriptor > static bool interpretMask( const bool & assigned, const void * const, const size_t ) { diff --git a/include/graphblas/utils/iscomplex.hpp b/include/graphblas/utils/iscomplex.hpp index cfbb949b9..5a4a257c6 100644 --- a/include/graphblas/utils/iscomplex.hpp +++ b/include/graphblas/utils/iscomplex.hpp @@ -63,6 +63,17 @@ namespace grb { static constexpr const bool value = true; }; + + /** \internal Wrapper for the std::conjugate. */ + template X conjugate (X a ) { + return (a); + }; + + template + std::complex conjugate (std::complex a ) { + return (std::conj(a)); + }; + } // end namespace utils } // end namespace grb diff --git a/include/graphblas/utils/parser/MatrixFileIterator.hpp b/include/graphblas/utils/parser/MatrixFileIterator.hpp index baff20fb4..e1b3cb071 100644 --- a/include/graphblas/utils/parser/MatrixFileIterator.hpp +++ b/include/graphblas/utils/parser/MatrixFileIterator.hpp @@ -410,7 +410,7 @@ namespace grb { #endif std::swap( buffer[ pos ].first.first, buffer[ pos ].first.second ); if( properties._symmetric == Hermitian ) { - std::conj( buffer[ pos ].second ); + buffer[ pos ].second = conjugate( buffer[ pos ].second ); } return *this; } else { diff --git a/include/graphblas/utils/parser/MatrixFileProperties.hpp b/include/graphblas/utils/parser/MatrixFileProperties.hpp index ab19fa41c..910f0d260 100644 --- a/include/graphblas/utils/parser/MatrixFileProperties.hpp +++ b/include/graphblas/utils/parser/MatrixFileProperties.hpp @@ -92,6 +92,9 @@ namespace grb { */ bool _complex; + /** Whether the file is hermitian or not. */ + bool _hermitian; + /** * Whether the file has direct indexing or not. * diff --git a/include/graphblas/utils/parser/MatrixFileReader.hpp b/include/graphblas/utils/parser/MatrixFileReader.hpp index dffe52e9d..9f3efea1d 100644 --- a/include/graphblas/utils/parser/MatrixFileReader.hpp +++ b/include/graphblas/utils/parser/MatrixFileReader.hpp @@ -31,6 +31,7 @@ #include "MatrixFileIterator.hpp" #include "MatrixFileProperties.hpp" #include "MatrixFileReaderBase.hpp" +#include "graphblas/utils/iscomplex.hpp" namespace grb { namespace utils { diff --git a/include/graphblas/utils/parser/MatrixFileReaderBase.hpp b/include/graphblas/utils/parser/MatrixFileReaderBase.hpp index 013fdb085..bbb517149 100644 --- a/include/graphblas/utils/parser/MatrixFileReaderBase.hpp +++ b/include/graphblas/utils/parser/MatrixFileReaderBase.hpp @@ -212,9 +212,15 @@ namespace grb { } else { std::cerr << "Type is SNAP"; } - if( properties._symmetric ) { + if( properties._symmetric == internal::Symmetric ) { std::cerr << " and the input is symmetric"; } + if( properties._symmetric == internal::Hermitian ) { + std::cerr << " and the input is hermitian "; + } + if( properties._symmetric == internal::General ) { + std::cerr << " and the input is general "; + } std::cerr << ".\n"; } diff --git a/tests/smoke/CMakeLists.txt b/tests/smoke/CMakeLists.txt index cd2947d19..9d52fa8c5 100644 --- a/tests/smoke/CMakeLists.txt +++ b/tests/smoke/CMakeLists.txt @@ -118,6 +118,12 @@ add_grb_executables( conjugate_gradient conjugate_gradient.cpp ADDITIONAL_LINK_LIBRARIES test_utils_headers ) +add_grb_executables( conjugate_gradient_complex conjugate_gradient.cpp + BACKENDS reference reference_omp bsp1d hybrid + ADDITIONAL_LINK_LIBRARIES test_utils_headers + COMPILE_DEFINITIONS _CG_COMPLEX +) + add_grb_executables( bicgstab bicgstab.cpp BACKENDS reference reference_omp bsp1d hybrid ADDITIONAL_LINK_LIBRARIES test_utils_headers diff --git a/tests/smoke/conjugate_gradient.cpp b/tests/smoke/conjugate_gradient.cpp index a470b5afc..1c43ee15f 100644 --- a/tests/smoke/conjugate_gradient.cpp +++ b/tests/smoke/conjugate_gradient.cpp @@ -18,7 +18,7 @@ #include #include #include - +#include #include #include @@ -28,12 +28,18 @@ #include #include -#define TOL 0.000001 -#define MAX_ITERS 10000 +using hpchscalarbase = double; +#ifdef _CG_COMPLEX +using hpchscalar = std::complex; +#else +using hpchscalar = double; +#endif -#define C1 0.0001 -#define C2 0.0001 +constexpr hpchscalarbase TOL=0.000001; +constexpr size_t MAX_ITERS=10000; +constexpr double C1=0.0001; +constexpr double C2=0.0001; using namespace grb; using namespace algorithms; @@ -50,7 +56,7 @@ struct output { size_t iterations; double residual; grb::utils::TimerResults times; - PinnedVector< double > pinnedVector; + PinnedVector< hpchscalar > pinnedVector; }; void grbProgram( const struct input &data_in, struct output &out ) { @@ -74,7 +80,7 @@ void grbProgram( const struct input &data_in, struct output &out ) { out.error_code = 0; // create local parser - grb::utils::MatrixFileReader< double, + grb::utils::MatrixFileReader< hpchscalar, std::conditional< ( sizeof( grb::config::RowIndexType ) > sizeof( grb::config::ColIndexType ) @@ -88,7 +94,7 @@ void grbProgram( const struct input &data_in, struct output &out ) { timer.reset(); // load into GraphBLAS - Matrix< double > L( n, n ); + Matrix< hpchscalar > L( n, n ); { const RC rc = buildMatrixUnique( L, parser.begin( SEQUENTIAL ), parser.end( SEQUENTIAL), @@ -122,10 +128,10 @@ void grbProgram( const struct input &data_in, struct output &out ) { } // test default pagerank run - Vector< double > x( n ), b( n ), r( n ), u( n ), temp( n ); + Vector< hpchscalar > x( n ), b( n ), r( n ), u( n ), temp( n ); - set( x, static_cast< double >( 1 ) / static_cast< double >( n ) ); - set( b, static_cast< double >( 1 ) ); + set( x, static_cast< hpchscalar >( 1 ) / static_cast< hpchscalar >( n ) ); + set( b, static_cast< hpchscalar >( 1 ) ); out.times.preamble = timer.time(); @@ -141,7 +147,7 @@ void grbProgram( const struct input &data_in, struct output &out ) { out.iterations, out.residual, r, u, temp ); - double single_time = timer.time(); + auto single_time = timer.time(); if( rc != SUCCESS ) { std::cerr << "Failure: call to conjugate_gradient did not succeed (" << toString( rc ) << ")." << std::endl; @@ -166,11 +172,11 @@ void grbProgram( const struct input &data_in, struct output &out ) { } } else { // do benchmark - double time_taken; timer.reset(); for( size_t i = 0; i < out.rep && rc == SUCCESS; ++i ) { - rc = set( x, static_cast< double >( 1 ) / static_cast< double >( n ) ); + rc = set( x, static_cast< hpchscalar >( 1 ) + / static_cast< hpchscalar >( n ) ); if( rc == SUCCESS ) { rc = conjugate_gradient( @@ -181,7 +187,7 @@ void grbProgram( const struct input &data_in, struct output &out ) { ); } } - time_taken = timer.time(); + auto time_taken = timer.time(); if( rc == SUCCESS ) { out.times.useful = time_taken / static_cast< double >( out.rep ); } @@ -212,10 +218,10 @@ void grbProgram( const struct input &data_in, struct output &out ) { } // output - out.pinnedVector = PinnedVector< double >( x, SEQUENTIAL ); + out.pinnedVector = PinnedVector< hpchscalar >( x, SEQUENTIAL ); // finish timing - const double time_taken = timer.time(); + const auto time_taken = timer.time(); out.times.postamble = time_taken; // done diff --git a/tests/smoke/hpcg.cpp b/tests/smoke/hpcg.cpp index 1a219dd51..6829de57c 100644 --- a/tests/smoke/hpcg.cpp +++ b/tests/smoke/hpcg.cpp @@ -33,11 +33,17 @@ #include #include #include +#include #include #include #include +using hpchscalarbase = double ; +using hpchscalar = std::complex ; +//using hpchscalar = double ; + + // here we define a custom macro and do not use NDEBUG since the latter is not defined for smoke tests #ifdef HPCG_PRINT_STEPS @@ -76,13 +82,13 @@ constexpr std::size_t MAX_ITERATIONS_DEF{ 56UL }; constexpr std::size_t SMOOTHER_STEPS_DEF{ 1 }; // internal values -constexpr double SYSTEM_DIAG_VALUE { 26.0 }; -constexpr double SYSTEM_NON_DIAG_VALUE { -1.0 }; +constexpr hpchscalarbase SYSTEM_DIAG_VALUE { 26.0 }; +constexpr hpchscalarbase SYSTEM_NON_DIAG_VALUE { -1.0 }; constexpr std::size_t BAND_WIDTH_3D { 13UL }; constexpr std::size_t HALO_RADIUS { 1U }; //============================================ -constexpr double MAX_NORM { 4.0e-14 }; +constexpr hpchscalarbase MAX_NORM { 4.0e-14 }; using namespace grb; using namespace algorithms; @@ -118,10 +124,10 @@ struct output { RC error_code; size_t test_repetitions; size_t performed_iterations; - double residual; + hpchscalarbase residual; grb::utils::TimerResults times; - std::unique_ptr< PinnedVector< double > > pinnedVector; - double square_norm_diff; + std::unique_ptr< PinnedVector< hpchscalar > > pinnedVector; + hpchscalarbase square_norm_diff; output() { error_code = SUCCESS; @@ -150,19 +156,19 @@ T static next_pow_2( T n ) { * @brief Builds and initializes a 3D system for an HPCG simulation according to the given 3D system sizes. * @return RC grb::SUCCESS if the system initialization within GraphBLAS succeeded */ -static RC build_3d_system( std::unique_ptr< hpcg_data< double, double, double > > & holder, const system_input & in ) { +static RC build_3d_system( std::unique_ptr< hpcg_data< hpchscalar, hpchscalar, hpchscalar > > & holder, const system_input & in ) { const std::array< std::size_t, 3 > physical_sys_sizes { in.nx, in.ny, in.nz }; - struct hpcg_system_params< 3, double > params { + struct hpcg_system_params< 3, hpchscalar > params { physical_sys_sizes, HALO_RADIUS, BAND_WIDTH_3D * 2 + 1, SYSTEM_DIAG_VALUE, SYSTEM_NON_DIAG_VALUE, PHYS_SYSTEM_SIZE_MIN, in.max_coarsening_levels, 2 }; - return build_hpcg_system< 3, double >( holder, params ); + return build_hpcg_system< 3, hpchscalar >( holder, params ); } #ifdef HPCG_PRINT_SYSTEM -static void print_system( const hpcg_data< double, double, double > & data ) { +static void print_system( const hpcg_data< hpchscalar, hpchscalar, hpchscalar > & data ) { print_matrix( data.A, 70, "A" ); - multi_grid_data< double, double > * coarser = data.coarser_level; + multi_grid_data< hpchscalar, hpchscalar > * coarser = data.coarser_level; while( coarser != nullptr ) { print_matrix( coarser->coarsening_matrix, 50, "COARSENING MATRIX" ); print_matrix( coarser->A, 50, "COARSER SYSTEM MATRIX" ); @@ -203,7 +209,7 @@ void grbProgram( const simulation_input & in, struct output & out ) { RC rc { SUCCESS }; // wrap hpcg_data inside a unique_ptr to forget about cleaning chores - std::unique_ptr< hpcg_data< double, double, double > > hpcg_state; + std::unique_ptr< hpcg_data< hpchscalar, hpchscalar, hpchscalar > > hpcg_state; rc = build_3d_system( hpcg_state, in ); if( rc != SUCCESS ) { @@ -217,14 +223,14 @@ void grbProgram( const simulation_input & in, struct output & out ) { } #endif - Matrix< double > & A { hpcg_state->A }; - Vector< double > & x { hpcg_state->x }; - Vector< double > & b { hpcg_state->b }; + Matrix< hpchscalar > & A { hpcg_state->A }; + Vector< hpchscalar > & x { hpcg_state->x }; + Vector< hpchscalar > & b { hpcg_state->b }; // set vectors as from standard HPCG benchmark set( x, 1.0 ); set( b, 0.0 ); - rc = grb::mxv( b, A, x, grb::Semiring< grb::operators::add< double >, grb::operators::mul< double >, grb::identities::zero, grb::identities::one >() ); + rc = grb::mxv( b, A, x, grb::Semiring< grb::operators::add< hpchscalar >, grb::operators::mul< hpchscalar >, grb::identities::zero, grb::identities::one >() ); set( x, 0.0 ); #ifdef HPCG_PRINT_SYSTEM @@ -241,9 +247,9 @@ void grbProgram( const simulation_input & in, struct output & out ) { out.test_repetitions = 0; timer.reset(); rc = hpcg( *hpcg_state, with_preconditioning, in.smoother_steps, in.smoother_steps, in.max_iterations, 0.0, out.performed_iterations, out.residual ); - double single_time = timer.time(); + auto single_time = timer.time(); if( rc == SUCCESS ) { - rc = collectives<>::reduce( single_time, 0, operators::max< double >() ); + rc = collectives<>::reduce( single_time, 0, operators::max< decltype( single_time ) >() ); } out.times.useful = single_time; out.test_repetitions = static_cast< size_t >( 1000.0 / single_time ) + 1; @@ -259,8 +265,8 @@ void grbProgram( const simulation_input & in, struct output & out ) { break; } } - double time_taken { timer.time() }; - out.times.useful = time_taken / static_cast< double >( out.test_repetitions ); + auto time_taken { timer.time() }; + out.times.useful = time_taken / static_cast< decltype( time_taken ) >( out.test_repetitions ); // sleep( 1 ); } @@ -282,28 +288,29 @@ void grbProgram( const simulation_input & in, struct output & out ) { // set error code out.error_code = rc; - Semiring< grb::operators::add< double >, grb::operators::mul< double >, grb::identities::zero, grb::identities::one > ring; + Semiring< grb::operators::add< hpchscalar >, grb::operators::mul< hpchscalar >, grb::identities::zero, grb::identities::one > ring; grb::set( b, 1.0 ); - out.square_norm_diff = 0.0; grb::eWiseMul( b, -1.0, x, ring ); - grb::dot( out.square_norm_diff, b, b, ring ); + hpchscalar dotproduct = 0.0; + grb::dot( dotproduct, b, b, ring ); + out.square_norm_diff = std::norm( dotproduct ); // output - out.pinnedVector = std::unique_ptr< PinnedVector< double > >( new PinnedVector< double >( x, SEQUENTIAL ) ); + out.pinnedVector = std::unique_ptr< PinnedVector< hpchscalar > >( new PinnedVector< hpchscalar >( x, SEQUENTIAL ) ); // finish timing - const double time_taken { timer.time() }; + const auto time_taken { timer.time() }; out.times.postamble = time_taken; } /** * @brief Parser the command-line arguments to extract the simulation information and checks they are valid. */ -static void parse_arguments( simulation_input &, std::size_t &, double &, int, char ** ); +static void parse_arguments( simulation_input &, std::size_t &, hpchscalarbase &, int, char ** ); int main( int argc, char ** argv ) { simulation_input sim_in; size_t test_outer_iterations; - double max_residual_norm; + hpchscalarbase max_residual_norm; parse_arguments( sim_in, test_outer_iterations, max_residual_norm, argc, argv ); thcout << "System size x: " << sim_in.nx << std::endl; @@ -345,7 +352,7 @@ int main( int argc, char ** argv ) { if( ! out.pinnedVector ) { thcerr << "no output vector to inspect" << std::endl; } else { - const PinnedVector< double > &solution { *out.pinnedVector }; + const PinnedVector< hpchscalar > &solution { *out.pinnedVector }; thcout << "Size of x is " << solution.size() << std::endl; if( solution.size() > 0 ) { print_vector( solution, 30, "SOLUTION" ); @@ -356,7 +363,8 @@ int main( int argc, char ** argv ) { ASSERT_RC_SUCCESS( out.error_code ); - double residual_norm { sqrt( out.square_norm_diff ) }; + //hpchscalarbase residual_norm { sqrt( out.square_norm_diff ) }; + auto residual_norm = out.square_norm_diff; thcout << "Residual norm: " << residual_norm << std::endl; ASSERT_LT( residual_norm, max_residual_norm ); @@ -365,7 +373,7 @@ int main( int argc, char ** argv ) { return 0; } -static void parse_arguments( simulation_input & sim_in, std::size_t & outer_iterations, double & max_residual_norm, int argc, char ** argv ) { +static void parse_arguments( simulation_input & sim_in, std::size_t & outer_iterations, hpchscalarbase & max_residual_norm, int argc, char ** argv ) { argument_parser parser; parser.add_optional_argument( "--nx", sim_in.nx, PHYS_SYSTEM_SIZE_DEF, "physical system size along x" ) diff --git a/tests/smoke/output_verification/complex_conjugate_conjugate_gradient_out_rndHermit256_ref b/tests/smoke/output_verification/complex_conjugate_conjugate_gradient_out_rndHermit256_ref new file mode 100644 index 000000000..fc369b863 --- /dev/null +++ b/tests/smoke/output_verification/complex_conjugate_conjugate_gradient_out_rndHermit256_ref @@ -0,0 +1,256 @@ +0.7723776702584036 -0.84712795803166 +-0.6886905967183684 3.117635710723946 +1.2231385630788616 -0.39386697151592265 +-0.42250493862419347 -0.7453222132287582 +0.44709213402163867 -0.6073940113723467 +-2.5189220180032867 0.8615532430627926 +0.5057993183047813 0.45494181456460925 +1.5676239986981222 -0.3886897431472132 +-0.09180930129277204 -0.09514986594888947 +-1.024986551366674 0.0468509237048981 +0.48487864184551277 -2.1848865020402135 +0.6499746994542178 0.6080645006285744 +1.9328544539433712 -0.05152962643037466 +-1.2442555901016015 0.38125919344310333 +-0.4836753519530956 -0.4774053175146954 +0.8296297185128926 0.06208272817665219 +0.28839452926606024 0.616198490991241 +0.9975777185308338 0.4110851552059666 +0.12641377115064228 0.537502289702301 +-0.21051862973591637 -1.5921315469663893 +-0.854597521321234 1.441270192568022 +1.32967279264606 -1.7232932585534653 +0.2355025696667007 -0.6978690323850638 +0.009022941089943934 1.1212394126768797 +0.8228426342506588 -0.24994745561672263 +0.2601611865263779 0.016973907584547903 +0.8751329925383632 -1.3126532414854624 +-0.2571433435102181 0.4640365423631086 +0.7548391438822141 1.244023771006778 +0.15247784247224963 -0.47168436068653524 +0.2991378793619946 0.5218755340344325 +1.4806783085304889 -0.41575202294938424 +-0.9455003879328117 0.5666156817949627 +-0.27078281624373096 0.3408996839850491 +-0.030036531875749607 -0.46215401403154954 +0.30889409333848594 1.3824342799735143 +0.8328074513030241 -0.024870506357607788 +0.21784824635860128 -0.36486351719978966 +-0.4422336707413639 -0.560739186493804 +-0.8100732229157865 -0.024955654911836635 +-0.3532759446058023 0.12334091209165164 +0.36677399827127155 0.3468931203299938 +0.9183438201811326 -0.5886609901662245 +-0.14545178218683896 -0.14332436823546155 +-0.126567663468151 -0.9579698246005053 +-0.8999913041665284 0.62588216981535 +1.0617818244879762 -0.24659536509364316 +0.6072845006836793 -0.1304483529767128 +1.1462452137252834 0.5110669014707554 +0.10993910509956968 -1.0722161861678807 +-0.6809253599482402 0.8635949246697243 +-0.029565813768426253 0.12115006918087091 +0.1765528834191675 -0.04329778410785743 +0.3005647526989962 -0.28730916471966295 +0.23304156420982697 -0.020869135693697305 +0.2572788156544367 0.2511905339893257 +0.038839118487645125 -0.01812136927073703 +0.881350387664376 -0.25588329566880574 +0.0727448119892154 0.06693596815232408 +-0.6337636819910354 -0.11136501931266121 +0.21592064043195877 -0.18402748170544553 +0.42761768932554317 0.7555238348316136 +0.5109906218666478 -0.023873845207600098 +0.17022101099073733 -0.13625844290237563 +-0.22461825778036096 0.12006671243928677 +-0.4795471927171407 -0.20808859456426834 +0.6208882981710478 -0.528516886252354 +0.7023170339852667 0.6760117568141237 +0.14927294807155198 -0.14176770983220502 +0.31380687514991773 -0.7200859124513134 +-1.0637992534373555 0.6533419550793204 +0.6172285271588872 -1.0179275372929768 +0.6804444761699742 1.0191368996803807 +0.7746562960715656 0.15031839101887565 +-0.3896396584709268 -0.46511330135034257 +-0.47721941279975505 0.45536568377762504 +0.9960275092549857 0.03890488737320809 +-1.1721764377706456 2.1667336145033835 +-0.05840926627822804 -1.98818405864798 +0.4251996428667853 -0.2642647710776639 +0.2677484314534049 0.14986837864818772 +0.4251187119804702 -0.025377291216735293 +0.4908182873564492 0.08965985067003496 +-0.3968477373343654 -0.7205134475227902 +0.5532775179569134 0.7165590660275885 +0.10724198766310135 0.001303597456180057 +0.030734647675196586 0.4594269926312774 +0.3612575379213097 -0.14013531901741902 +-0.18461167981015023 -0.5366302626254844 +0.7822150954268913 0.8204433776093175 +-0.6477981887815828 -0.42383670362815934 +1.307159723808943 0.9127919701769127 +0.24771763986530682 -0.1917392104924614 +0.5253565523086161 -0.6091546056997865 +-0.775385289273948 0.2733738759643046 +0.1346321955050716 -0.6173340526165969 +1.2700148280459227 0.08320143750938311 +-0.628969431729404 1.2178922938674765 +0.9026712301882792 -0.6470251015796067 +-0.4541934719676965 0.22077054738358187 +0.616432126227246 -0.6008326976792562 +0.49811250391703826 0.7511153647462188 +-1.2549386308059847 -0.14564166118251257 +0.5422635365724204 -0.526585971079347 +0.5975704657494221 0.15293934040933607 +-0.133451648938522 -0.8030766603728465 +0.8807034617684716 0.05575765827241096 +-0.4614842211176304 -0.42040314818105556 +0.19795805992999696 0.41155012282133646 +0.03076425351990567 0.7164244074558652 +1.1969680081594078 -1.0655162247242396 +0.20121998702307975 -0.12364711570372382 +-0.2675704000852145 -0.5345529140735915 +0.5640981929989356 0.03725910593127368 +0.7927737112675131 0.509390361837525 +-0.04148142366542372 -0.06663279174558119 +0.5162971820439279 0.018110829026078475 +0.09011860686114387 -0.22709036959107576 +0.19386509782589745 0.6896758221403271 +0.9130404164863689 0.13852792729028252 +0.19872098088464177 -0.4815320185777502 +0.229116377308656 0.8549396156058171 +-0.6924671929434297 0.1757037531233293 +-0.8101807478902125 -0.22530552361264397 +1.1463004511585784 0.3965774703871715 +-0.14701239912090042 -0.31684270746489374 +0.2958492269715433 -0.2740224558388744 +-0.12991704996349965 -0.6646113604169919 +0.8033331597322917 -0.6088373031142552 +-0.09428700637797642 0.31685277679497137 +0.5434350543547534 0.4570244690316652 +0.9993999344329718 -0.9802316720712826 +-0.529523440965268 0.23428279171384753 +0.7920048654389736 0.5611819965589694 +0.92428559676361 0.08961552709237758 +-0.5025683635257291 -0.06504551200721112 +0.2485103842224946 0.18120579596220315 +-0.7281848165175798 0.6129880842162474 +3.52077757793993 -0.7984010979909698 +-1.015731405064613 -0.23221692687314952 +-1.4089798029603329 0.019542023808015632 +0.5732935059006081 -1.2193281670566607 +0.25300135272066876 2.549927767942426 +1.8791887549909572 -0.09407782990076 +-0.9778337135482608 -0.5160472914098908 +-0.6628601148168748 1.4498074071117317 +-1.3509189286260863 -0.885717878768758 +-0.20292375666880558 1.041168174370037 +1.3783364997317153 -3.9813759009941694 +1.0081069491660568 1.3254909336825562 +1.2159780208484554 -1.158807677611798 +-0.5072933742374763 0.27491750102136536 +0.7678733188866914 -0.3923545456912674 +-0.05636548830980957 0.6734794491728276 +1.1978229967701928 0.3462656039443953 +-1.2210010135956455 1.7373724043985128 +0.7419894473475313 0.43427838396430196 +-0.19633427353365704 -0.6212467046898682 +0.25236891619817425 -0.8502297070667846 +-0.4675898176991302 -0.18924574505348699 +0.4866969958821393 0.08183186193343761 +0.14462085531673702 -0.18002008335950184 +0.7090758163801251 -0.21669665856233752 +-0.27825374372111283 -0.09671538016122895 +0.49416552828760274 0.4006841853626056 +1.2686999479990222 -0.4364421041254494 +-0.09691663904196725 0.4092349338736431 +-0.2511360695317182 0.09054766797053217 +0.40175538447848025 0.19080370944796352 +-0.04499246037724999 0.799728859892216 +0.0013860204209815955 -0.7129912378781786 +0.37786133854520515 0.1017547473196952 +-0.02327012063652434 0.3318479511307979 +-0.016392725692113967 0.2137592664937556 +0.42020000303174593 -0.6608730676868702 +0.11844480194820341 -0.23247446001595745 +0.35035827538747555 0.6773620404040014 +-0.03725336381925444 -0.22502489752601143 +0.12100664843322943 -0.44489694437325145 +0.697881017583712 0.13217541152003234 +-0.5239484868873787 -0.008569194613447918 +0.9378071228273661 -0.044852243748613595 +0.3625104038566866 -0.22434341381468162 +0.0005302188530878059 0.4597082226120621 +0.6928857184483774 -0.4618770266987219 +0.39233962267325384 0.6844493512506271 +0.555462672865556 0.2900257995517062 +-0.5393986015556983 -0.37946775040187786 +0.5729095251245655 0.44023832877652586 +0.6009412807303678 -0.08805706539338319 +0.00762686812574232 0.02953300279042466 +0.18502057920006992 -0.15129417165252454 +-0.3501099999551211 -0.206155455848976 +0.05948473670853178 0.9088734579902765 +0.33962947222843815 -0.2743872095001304 +0.5979067624492836 0.37637294162057977 +0.2184907269838713 -0.446213514177547 +-0.4976116975781581 -0.32743157912397114 +0.40300102845964764 0.03543690838229253 +0.2694115403092456 0.5337529207112544 +-0.06504258663344696 -0.09287629020116378 +0.0014687421343610961 -0.23558629144421325 +0.7685070195425473 -0.43871531503869676 +0.7265277518243136 0.1025284673440975 +0.49136001703979304 0.23307336226862793 +-0.546504967033296 0.46996616920826806 +-0.4769321088222391 -0.1429531880245315 +0.5097275915944136 0.33222895983446543 +1.1745910414096534 0.06455131556305578 +-0.7428606846176565 -1.2779657410821064 +0.16364937584914216 1.861147512587967 +-0.7744245888096708 -2.2338376354958314 +0.5045409146909483 -0.9232844525094981 +2.770816830925732 0.7865791719817984 +-1.7422186720644406 -0.5944378516379922 +2.711884358770474 0.053597918207951026 +-0.8837430771803491 -2.0337504259078267 +4.096594968630109 1.3307495346991067 +0.14263902100069076 0.658924297755748 +-1.2456666774129734 1.003810367789625 +1.7749546650530499 1.815960592674543 +5.2364869873988455 0.9294290658092762 +-2.99277591903302 -2.2588611244295183 +-2.6145812376191944 -0.6548651270024601 +0.01428780459060174 -0.5036482442796396 +1.0616636070632672 1.7724011090221976 +1.145773683440278 0.17417582538688292 +3.623591504403511 -3.2145385442554244 +0.19958043188489547 -0.6852703432065822 +2.2445252731203613 -0.08483168120655409 +-2.6195055552521054 2.5280847427483724 +1.3021166150895835 -0.8330145583132038 +1.652819241198943 0.7032449701172139 +2.8420333959781554 2.4495567878283326 +-1.021603207801283 -2.228176827757243 +-0.5080549373167023 0.6412950053184773 +-3.054138794581193 2.9022909498027794 +2.209100504655098 -0.29853209381580686 +-0.28799067685473734 -1.2786162145757392 +3.477466999188358 2.078225453879195 +-1.993578255430614 -0.8664646141616699 +-1.8243837772418385 1.156576205952122 +-1.1210469414432285 -1.4820190173925887 +0.11208873456612994 0.30222632107281866 +2.1697698099666494 -1.6235102462830158 +-0.7193150685189091 0.5854720411797895 +-0.3470638992599513 1.211701773535921 +-2.7805605843216963 -1.222760011957959 +3.3506711616036884 -0.8461968199424085 +1.0312361623139503 0.22552092876122182 +0.3105972151328044 0.48823052900482217 +-1.2162925098659427 -2.11422402602363 +0.4657763154584858 0.344661172143587 +1.446873303926675 -1.2122447396323188 +1.2560499484033159 1.16087141271593 +1.472229008366162 0.571754679209421 diff --git a/tests/smoke/smoketests.sh b/tests/smoke/smoketests.sh index 9d2e9e004..513fef682 100755 --- a/tests/smoke/smoketests.sh +++ b/tests/smoke/smoketests.sh @@ -194,6 +194,23 @@ for BACKEND in ${BACKENDS[@]}; do fi echo " " + TESTNAME=rndHermit256 + if [ -f ${INPUT_DIR}/${TESTNAME}.mtx ]; then + n=$(grep -v '^%' ${INPUT_DIR}/${TESTNAME}.mtx | head -1 | awk '{print $1}' ) + m=$(grep -v '^%' ${INPUT_DIR}/${TESTNAME}.mtx | head -1 | awk '{print $2}' ) + echo ">>> [x] [ ] Testing the conjugate gradient complex algorithm for the input" + echo " matrix (${n}x${m}) taken from ${TESTNAME}.mtx. This test" + echo " verifies against a ground-truth solution vector. The test" + echo " employs the grb::Launcher in automatic mode. It uses" + echo " direct-mode file IO." + $runner ${TEST_BIN_DIR}/conjugate_gradient_complex_${BACKEND} ${INPUT_DIR}/${TESTNAME}.mtx direct 1 1 verification ${OUTPUT_VERIFICATION_DIR}/complex_conjugate_conjugate_gradient_out_${TESTNAME}_ref &> ${TEST_OUT_DIR}/conjugate_gradient_complex_${BACKEND}_${P}_${T}.log + head -1 ${TEST_OUT_DIR}/conjugate_gradient_complex_${BACKEND}_${P}_${T}.log + grep 'Test OK' ${TEST_OUT_DIR}/conjugate_gradient_complex_${BACKEND}_${P}_${T}.log || echo "Test FAILED" + else + echo "Test DISABLED: ${TESTNAME}.mtx was not found. To enable, please provide ${INPUT_DIR}/${TESTNAME}.mtx" + fi + echo " " + echo ">>> [x] [ ] Testing the BiCGstab algorithm for the 17361 x 17361 input" echo " matrix gyrom_m.mtx. This test verifies against a ground-" echo " truth solution vector, the same as used for the earlier" diff --git a/tests/utils/output_verification.hpp b/tests/utils/output_verification.hpp index d5d5446ae..d61bf51af 100644 --- a/tests/utils/output_verification.hpp +++ b/tests/utils/output_verification.hpp @@ -29,10 +29,28 @@ #include #include +#include #include + +/** + * internal overload for read of real and complex matrix + */ +template< typename fileType > +int data_fscanf(fileType in, double *truth){ + return( fscanf( in, "%lf", &(*truth) ) ); +}; + +template< typename fileType, typename T > +int data_fscanf(fileType in, std::complex *truth){ + double x,y; + int rc=fscanf( in, "%lf%lf", &x,&y ); + *truth=std::complex( x, y ); + return( rc==2 ); +}; + /** * Verifies a dense vector against a ground-truth output vector. * @@ -88,7 +106,7 @@ int vector_verification( assert( truth_filename != nullptr ); assert( c1 > 0 ); assert( c1 < 1 ); assert( c2 > 0 ); assert( c2 < 1 ); - const constexpr double one = static_cast< double >( 1 ); + const constexpr T one = static_cast< T >( 1 ); // open verification file FILE *in = fopen( truth_filename, "r" ); @@ -101,15 +119,21 @@ int vector_verification( // read the truth output vector from the input verification file const size_t n = output_vector.size(); - double * const truth = new double[ n ]; + T * const truth = new T[ n ]; if( truth == nullptr ) { std::cerr << "Could not allocate necessary buffer" << std::endl; return 20; } + for( size_t i = 0; i < n; i++ ) { - if( fscanf( in, "%lf", &(truth[ i ]) ) != 1 ) { + int rc=data_fscanf(in, truth + i ); + if( rc != 1 ) { std::cerr << "The verification file looks incomplete." - << std::endl; + << " line i= " + << i + << " data= " << truth[ i ] + << " rc= " << rc + << std::endl; delete [] truth; return 30; } @@ -125,7 +149,7 @@ int vector_verification( double magnitude2 = 0; double magnitudeInf = 0; for( size_t i = 0; i < n; ++i ) { - magnitude2 += truth[ i ] * truth[ i ]; + magnitude2 += std::norm( truth[ i ] ); magnitudeInf = fabs( truth[ i ] ) > magnitudeInf ? fabs( truth[ i ] ) : magnitudeInf; @@ -135,7 +159,7 @@ int vector_verification( magnitude2 = sqrt( magnitude2 ); // convert the Pinned Vector into raw data - double * const raw_output_vector = new double[ n ]; + T * const raw_output_vector = new T[ n ]; bool * const written_to = new bool[ n ]; if( raw_output_vector == nullptr || written_to == nullptr ) { std::cerr << "Could not allocate necessary buffers" << std::endl; @@ -147,7 +171,7 @@ int vector_verification( } for( size_t k = 0; k < output_vector.nonzeroes(); k++ ) { - const double value = output_vector.getNonzeroValue( k, one ); + const auto value = output_vector.getNonzeroValue( k, one ); const size_t index = output_vector.getNonzeroIndex( k ); assert( index < n ); assert( !written_to[ index ] ); @@ -216,8 +240,7 @@ int vector_verification( // compute the norm-2 double norm2 = 0; for( size_t i = 0; i < n; i++ ) { - norm2 += ( raw_output_vector[ i ] - truth[ i ] ) * - ( raw_output_vector[ i ] - truth[ i ] ); + norm2 += std::norm( raw_output_vector[ i ] - truth[ i ] ); } // isgreaterequal is used to ensure that the condition norm2 >= 0 diff --git a/tools/downloadDatasets.sh b/tools/downloadDatasets.sh index 2585ae103..d4d2c30ea 100755 --- a/tools/downloadDatasets.sh +++ b/tools/downloadDatasets.sh @@ -22,9 +22,16 @@ downloadSS () { wget ${2} || exit 1 fi if [ ! -f ${1}/${1}.mtx ]; then - tar xf ${1}.tar.gz || exit 1 + if [ -f ${1}.tar.gz ]; then + tar xf ${1}.tar.gz || exit 1 + elif [ -f ${1}.gz ]; then + gzip -d ${1}.gz || exit 1 + elif [ -f ${1}.mtx.gz ]; then + gzip -d ${1}.mtx.gz || exit 1 + fi + else + ln ${1}/${1}.mtx . || exit 1 fi - ln ${1}/${1}.mtx ./ || exit 1 fi } @@ -86,6 +93,7 @@ if [[ "$REPLY" = "yes" ]]; then downloadSS "west0497" "https://suitesparse-collection-website.herokuapp.com/MM/HB/west0497.tar.gz" downloadSS "gyro_m" "https://suitesparse-collection-website.herokuapp.com/MM/Oberwolfach/gyro_m.tar.gz" downloadSS "dwt_59" "https://suitesparse-collection-website.herokuapp.com/MM/HB/dwt_59.tar.gz" + downloadSS "rndHermit256.mtx" "https://gitlab.com/denis.jelovina/hermitian_test_matrix/-/raw/main/rndHermit256.mtx" downloadSN "cit-HepTh" downloadSN "facebook_combined" echo "" From 471ba0c226eb8e3b573a75842b8b4fb4fcf7cb16 Mon Sep 17 00:00:00 2001 From: Denis Jelovina Date: Tue, 26 Apr 2022 11:50:24 +0200 Subject: [PATCH 02/22] revert hpcg to non-complex version --- tests/smoke/hpcg.cpp | 68 +++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 38 deletions(-) diff --git a/tests/smoke/hpcg.cpp b/tests/smoke/hpcg.cpp index 6829de57c..1a219dd51 100644 --- a/tests/smoke/hpcg.cpp +++ b/tests/smoke/hpcg.cpp @@ -33,17 +33,11 @@ #include #include #include -#include #include #include #include -using hpchscalarbase = double ; -using hpchscalar = std::complex ; -//using hpchscalar = double ; - - // here we define a custom macro and do not use NDEBUG since the latter is not defined for smoke tests #ifdef HPCG_PRINT_STEPS @@ -82,13 +76,13 @@ constexpr std::size_t MAX_ITERATIONS_DEF{ 56UL }; constexpr std::size_t SMOOTHER_STEPS_DEF{ 1 }; // internal values -constexpr hpchscalarbase SYSTEM_DIAG_VALUE { 26.0 }; -constexpr hpchscalarbase SYSTEM_NON_DIAG_VALUE { -1.0 }; +constexpr double SYSTEM_DIAG_VALUE { 26.0 }; +constexpr double SYSTEM_NON_DIAG_VALUE { -1.0 }; constexpr std::size_t BAND_WIDTH_3D { 13UL }; constexpr std::size_t HALO_RADIUS { 1U }; //============================================ -constexpr hpchscalarbase MAX_NORM { 4.0e-14 }; +constexpr double MAX_NORM { 4.0e-14 }; using namespace grb; using namespace algorithms; @@ -124,10 +118,10 @@ struct output { RC error_code; size_t test_repetitions; size_t performed_iterations; - hpchscalarbase residual; + double residual; grb::utils::TimerResults times; - std::unique_ptr< PinnedVector< hpchscalar > > pinnedVector; - hpchscalarbase square_norm_diff; + std::unique_ptr< PinnedVector< double > > pinnedVector; + double square_norm_diff; output() { error_code = SUCCESS; @@ -156,19 +150,19 @@ T static next_pow_2( T n ) { * @brief Builds and initializes a 3D system for an HPCG simulation according to the given 3D system sizes. * @return RC grb::SUCCESS if the system initialization within GraphBLAS succeeded */ -static RC build_3d_system( std::unique_ptr< hpcg_data< hpchscalar, hpchscalar, hpchscalar > > & holder, const system_input & in ) { +static RC build_3d_system( std::unique_ptr< hpcg_data< double, double, double > > & holder, const system_input & in ) { const std::array< std::size_t, 3 > physical_sys_sizes { in.nx, in.ny, in.nz }; - struct hpcg_system_params< 3, hpchscalar > params { + struct hpcg_system_params< 3, double > params { physical_sys_sizes, HALO_RADIUS, BAND_WIDTH_3D * 2 + 1, SYSTEM_DIAG_VALUE, SYSTEM_NON_DIAG_VALUE, PHYS_SYSTEM_SIZE_MIN, in.max_coarsening_levels, 2 }; - return build_hpcg_system< 3, hpchscalar >( holder, params ); + return build_hpcg_system< 3, double >( holder, params ); } #ifdef HPCG_PRINT_SYSTEM -static void print_system( const hpcg_data< hpchscalar, hpchscalar, hpchscalar > & data ) { +static void print_system( const hpcg_data< double, double, double > & data ) { print_matrix( data.A, 70, "A" ); - multi_grid_data< hpchscalar, hpchscalar > * coarser = data.coarser_level; + multi_grid_data< double, double > * coarser = data.coarser_level; while( coarser != nullptr ) { print_matrix( coarser->coarsening_matrix, 50, "COARSENING MATRIX" ); print_matrix( coarser->A, 50, "COARSER SYSTEM MATRIX" ); @@ -209,7 +203,7 @@ void grbProgram( const simulation_input & in, struct output & out ) { RC rc { SUCCESS }; // wrap hpcg_data inside a unique_ptr to forget about cleaning chores - std::unique_ptr< hpcg_data< hpchscalar, hpchscalar, hpchscalar > > hpcg_state; + std::unique_ptr< hpcg_data< double, double, double > > hpcg_state; rc = build_3d_system( hpcg_state, in ); if( rc != SUCCESS ) { @@ -223,14 +217,14 @@ void grbProgram( const simulation_input & in, struct output & out ) { } #endif - Matrix< hpchscalar > & A { hpcg_state->A }; - Vector< hpchscalar > & x { hpcg_state->x }; - Vector< hpchscalar > & b { hpcg_state->b }; + Matrix< double > & A { hpcg_state->A }; + Vector< double > & x { hpcg_state->x }; + Vector< double > & b { hpcg_state->b }; // set vectors as from standard HPCG benchmark set( x, 1.0 ); set( b, 0.0 ); - rc = grb::mxv( b, A, x, grb::Semiring< grb::operators::add< hpchscalar >, grb::operators::mul< hpchscalar >, grb::identities::zero, grb::identities::one >() ); + rc = grb::mxv( b, A, x, grb::Semiring< grb::operators::add< double >, grb::operators::mul< double >, grb::identities::zero, grb::identities::one >() ); set( x, 0.0 ); #ifdef HPCG_PRINT_SYSTEM @@ -247,9 +241,9 @@ void grbProgram( const simulation_input & in, struct output & out ) { out.test_repetitions = 0; timer.reset(); rc = hpcg( *hpcg_state, with_preconditioning, in.smoother_steps, in.smoother_steps, in.max_iterations, 0.0, out.performed_iterations, out.residual ); - auto single_time = timer.time(); + double single_time = timer.time(); if( rc == SUCCESS ) { - rc = collectives<>::reduce( single_time, 0, operators::max< decltype( single_time ) >() ); + rc = collectives<>::reduce( single_time, 0, operators::max< double >() ); } out.times.useful = single_time; out.test_repetitions = static_cast< size_t >( 1000.0 / single_time ) + 1; @@ -265,8 +259,8 @@ void grbProgram( const simulation_input & in, struct output & out ) { break; } } - auto time_taken { timer.time() }; - out.times.useful = time_taken / static_cast< decltype( time_taken ) >( out.test_repetitions ); + double time_taken { timer.time() }; + out.times.useful = time_taken / static_cast< double >( out.test_repetitions ); // sleep( 1 ); } @@ -288,29 +282,28 @@ void grbProgram( const simulation_input & in, struct output & out ) { // set error code out.error_code = rc; - Semiring< grb::operators::add< hpchscalar >, grb::operators::mul< hpchscalar >, grb::identities::zero, grb::identities::one > ring; + Semiring< grb::operators::add< double >, grb::operators::mul< double >, grb::identities::zero, grb::identities::one > ring; grb::set( b, 1.0 ); + out.square_norm_diff = 0.0; grb::eWiseMul( b, -1.0, x, ring ); - hpchscalar dotproduct = 0.0; - grb::dot( dotproduct, b, b, ring ); - out.square_norm_diff = std::norm( dotproduct ); + grb::dot( out.square_norm_diff, b, b, ring ); // output - out.pinnedVector = std::unique_ptr< PinnedVector< hpchscalar > >( new PinnedVector< hpchscalar >( x, SEQUENTIAL ) ); + out.pinnedVector = std::unique_ptr< PinnedVector< double > >( new PinnedVector< double >( x, SEQUENTIAL ) ); // finish timing - const auto time_taken { timer.time() }; + const double time_taken { timer.time() }; out.times.postamble = time_taken; } /** * @brief Parser the command-line arguments to extract the simulation information and checks they are valid. */ -static void parse_arguments( simulation_input &, std::size_t &, hpchscalarbase &, int, char ** ); +static void parse_arguments( simulation_input &, std::size_t &, double &, int, char ** ); int main( int argc, char ** argv ) { simulation_input sim_in; size_t test_outer_iterations; - hpchscalarbase max_residual_norm; + double max_residual_norm; parse_arguments( sim_in, test_outer_iterations, max_residual_norm, argc, argv ); thcout << "System size x: " << sim_in.nx << std::endl; @@ -352,7 +345,7 @@ int main( int argc, char ** argv ) { if( ! out.pinnedVector ) { thcerr << "no output vector to inspect" << std::endl; } else { - const PinnedVector< hpchscalar > &solution { *out.pinnedVector }; + const PinnedVector< double > &solution { *out.pinnedVector }; thcout << "Size of x is " << solution.size() << std::endl; if( solution.size() > 0 ) { print_vector( solution, 30, "SOLUTION" ); @@ -363,8 +356,7 @@ int main( int argc, char ** argv ) { ASSERT_RC_SUCCESS( out.error_code ); - //hpchscalarbase residual_norm { sqrt( out.square_norm_diff ) }; - auto residual_norm = out.square_norm_diff; + double residual_norm { sqrt( out.square_norm_diff ) }; thcout << "Residual norm: " << residual_norm << std::endl; ASSERT_LT( residual_norm, max_residual_norm ); @@ -373,7 +365,7 @@ int main( int argc, char ** argv ) { return 0; } -static void parse_arguments( simulation_input & sim_in, std::size_t & outer_iterations, hpchscalarbase & max_residual_norm, int argc, char ** argv ) { +static void parse_arguments( simulation_input & sim_in, std::size_t & outer_iterations, double & max_residual_norm, int argc, char ** argv ) { argument_parser parser; parser.add_optional_argument( "--nx", sim_in.nx, PHYS_SYSTEM_SIZE_DEF, "physical system size along x" ) From f20f46f25ffd11e07d200fb2f57ba25a265ac611 Mon Sep 17 00:00:00 2001 From: "Albert-Jan N. Yzelman" Date: Tue, 26 Apr 2022 15:29:13 +0200 Subject: [PATCH 03/22] Revert HPCG --- include/graphblas/algorithms/hpcg/hpcg.hpp | 24 ++++++++++------------ 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/include/graphblas/algorithms/hpcg/hpcg.hpp b/include/graphblas/algorithms/hpcg/hpcg.hpp index 78d05e4fe..6caf22a1c 100644 --- a/include/graphblas/algorithms/hpcg/hpcg.hpp +++ b/include/graphblas/algorithms/hpcg/hpcg.hpp @@ -105,8 +105,7 @@ namespace grb { const Ring &ring = Ring(), const Minus &minus = Minus() ) { - IOType alpha; - IOType dotproduct; + ResidualType alpha; const grb::Matrix< NonzeroType > &A { data.A }; grb::Vector< IOType > &x { data.x }; @@ -128,9 +127,8 @@ namespace grb { ret = ret ? ret : grb::eWiseApply( r, b, Ap, minus ); // r = b - Ap; assert( ret == SUCCESS ); - dotproduct = static_cast< IOType >( 0.0 ); - ret = ret ? ret : grb::dot( dotproduct, r, r, ring ); // norm_residual = r' * r; - norm_residual = std::abs( dotproduct ); + norm_residual = ring.template getZero< ResidualType >(); + ret = ret ? ret : grb::dot( norm_residual, r, r, ring ); // norm_residual = r' * r; assert( ret == SUCCESS ); // compute sqrt to avoid underflow @@ -138,7 +136,7 @@ namespace grb { // initial norm of residual const ResidualType norm_residual_initial { norm_residual }; - IOType old_r_dot_z { 0.0 }, r_dot_z { 0.0 }, beta { 0.0 }; + ResidualType old_r_dot_z { 0.0 }, r_dot_z { 0.0 }, beta { 0.0 }; size_t iter { 0 }; #ifdef HPCG_PRINT_STEPS @@ -162,6 +160,7 @@ namespace grb { DBG_print_norm( z, "initial z" ); #endif + ResidualType pAp; if( iter == 0 ) { ret = ret ? ret : grb::set( p, z ); // p = z; @@ -172,7 +171,7 @@ namespace grb { } else { old_r_dot_z = r_dot_z; - r_dot_z = static_cast< IOType >( 0.0 );; + r_dot_z = ring.template getZero< ResidualType >(); ret = ret ? ret : grb::dot( r_dot_z, r, z, ring ); // r_dot_z = r' * z; assert( ret == SUCCESS ); @@ -192,11 +191,11 @@ namespace grb { #ifdef HPCG_PRINT_STEPS DBG_print_norm( Ap, "middle Ap" ); #endif - dotproduct = static_cast< IOType >( 0.0 ); - ret = ret ? ret : grb::dot( dotproduct, Ap, p, ring ); // dotproduct = p' * Ap + pAp = static_cast< ResidualType >( 0.0 ); + ret = ret ? ret : grb::dot( pAp, Ap, p, ring ); // pAp = p' * Ap assert( ret == SUCCESS ); - alpha = r_dot_z / dotproduct; + alpha = r_dot_z / pAp; ret = ret ? ret : grb::eWiseMul( x, alpha, p, ring ); // x += alpha * p; assert( ret == SUCCESS ); @@ -210,9 +209,8 @@ namespace grb { DBG_print_norm( r, "end r" ); #endif - dotproduct = static_cast< IOType >( 0.0 ); - ret = ret ? ret : grb::dot( dotproduct, r, r, ring ); // residual = r' * r; - norm_residual = std::abs( dotproduct ); + norm_residual = static_cast< ResidualType >( 0.0 ); + ret = ret ? ret : grb::dot( norm_residual, r, r, ring ); // residual = r' * r; assert( ret == SUCCESS ); norm_residual = std::sqrt( norm_residual ); From d365c0dc58ff1cda7866c42b12df4729445b4698 Mon Sep 17 00:00:00 2001 From: "Albert-Jan N. Yzelman" Date: Tue, 26 Apr 2022 15:29:49 +0200 Subject: [PATCH 04/22] eWiseMap to eWiseLambda, error checking, and (compile-time) conditional execution of lambdas --- .../algorithms/conjugate_gradient.hpp | 38 ++++++++++++++----- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/include/graphblas/algorithms/conjugate_gradient.hpp b/include/graphblas/algorithms/conjugate_gradient.hpp index 5a622aa77..c6dbe5288 100644 --- a/include/graphblas/algorithms/conjugate_gradient.hpp +++ b/include/graphblas/algorithms/conjugate_gradient.hpp @@ -141,7 +141,8 @@ namespace grb { class Minus = operators::subtract< IOType >, class Divide = operators::divide< IOType > > - grb::RC conjugate_gradient( grb::Vector< IOType > &x, + grb::RC conjugate_gradient( + grb::Vector< IOType > &x, const grb::Matrix< NonzeroType > &A, const grb::Vector< InputType > &b, const size_t max_iterations, @@ -273,16 +274,26 @@ namespace grb { // sigma = r' * r; sigma = zero; - grb::set( temp, r ); - grb::eWiseMap( []( IOType a ) { return( grb::utils::conjugate( a ) ); } , temp ); + ret = ret ? ret : grb::set( temp, r ); + if( grb::utils::is_complex< IOType >::value ) { + ret = ret ? ret : grb::eWiseLambda( [&temp]( const size_t i ) { + temp[ i ] = grb::utils::conjugate( temp[ i ] ); + }, temp + ); + } ret = ret ? ret : grb::dot< descr_dense >( sigma, temp, r, ring ); assert( ret == SUCCESS ); // bnorm = b' * b; bnorm = zero; - grb::set( temp, b ); - grb::eWiseMap( []( IOType a ) { return( grb::utils::conjugate( a ) ); } , temp ); + ret = ret ? ret : grb::set( temp, b ); + if( grb::utils::is_complex< IOType >::value ) { + ret = ret ? ret : grb::eWiseLambda( [&temp]( const size_t i ) { + temp[ i ] = grb::utils::conjugate( temp[ i ] ); + }, temp + ); + } ret = ret ? ret : grb::dot< descr_dense >( bnorm, temp, b, ring ); assert( ret == SUCCESS ); @@ -303,9 +314,13 @@ namespace grb { // beta = u' * temp beta = zero; - grb::eWiseMap( []( IOType a ) { return( grb::utils::conjugate( a ) ); } , u ); + if( grb::utils::is_complex< IOType >::value ) { + ret = ret ? ret : grb::eWiseLambda( [&u]( const size_t i ) { u[ i ] = grb::utils::conjugate( u[ i ] ); }, u ); + } ret = ret ? ret : grb::dot< descr_dense >( beta, temp, u, ring ); - grb::eWiseMap( []( IOType a ) { return( grb::utils::conjugate( a ) ); } , u ); + if( grb::utils::is_complex< IOType >::value ) { + ret = ret ? ret : grb::eWiseLambda( [&u]( const size_t i ) { u[ i ] = grb::utils::conjugate( u[ i ] ); }, u ); + } assert( ret == SUCCESS ); // alpha = sigma / beta; @@ -327,8 +342,13 @@ namespace grb { // beta = r' * r; beta = zero; - grb::set( temp, r ); - grb::eWiseMap( []( IOType a ) { return( grb::utils::conjugate( a ) ); } , temp ); + ret = ret ? ret : grb::set( temp, r ); + if( grb::utils::is_complex< IOType >::value ) { + ret = ret ? ret : grb::eWiseLambda( [&temp]( const size_t i ) { + temp[ i ] = grb::utils::conjugate( temp[ i ] ); + }, temp + ); + } ret = ret ? ret : grb::dot< descr_dense >( beta, temp, r, ring ); assert( ret == SUCCESS ); From 87912601d2c2f9594184cbcbf0cfbcf837ea0146 Mon Sep 17 00:00:00 2001 From: "Albert-Jan N. Yzelman" Date: Tue, 26 Apr 2022 18:32:31 +0200 Subject: [PATCH 05/22] Code review: the non-complex CG does not require a (conjugated) copy of a vector, this is now avoided. Removed some redundant statements near the end of the CG iteration loop. std::abs is not necessary to be called in the non-complex case -- used is_complex to translate into a no-op instead. Moved utils::conjugate to is_complex. Documented it. Adapted MatrixFileIterator to cope with this change. --- .../algorithms/conjugate_gradient.hpp | 41 +++++++++++-------- include/graphblas/utils/iscomplex.hpp | 37 ++++++++++++----- .../utils/parser/MatrixFileIterator.hpp | 3 +- 3 files changed, 53 insertions(+), 28 deletions(-) diff --git a/include/graphblas/algorithms/conjugate_gradient.hpp b/include/graphblas/algorithms/conjugate_gradient.hpp index c6dbe5288..d0e26310a 100644 --- a/include/graphblas/algorithms/conjugate_gradient.hpp +++ b/include/graphblas/algorithms/conjugate_gradient.hpp @@ -274,27 +274,29 @@ namespace grb { // sigma = r' * r; sigma = zero; - ret = ret ? ret : grb::set( temp, r ); if( grb::utils::is_complex< IOType >::value ) { - ret = ret ? ret : grb::eWiseLambda( [&temp]( const size_t i ) { - temp[ i ] = grb::utils::conjugate( temp[ i ] ); + ret = ret ? ret : grb::eWiseLambda( [&temp,&r]( const size_t i ) { + temp[ i ] = grb::utils::is_complex< IOType >::conjugate( r[ i ] ); }, temp ); + ret = ret ? ret : grb::dot< descr_dense >( sigma, temp, r, ring ); + } else { + ret = ret ? ret : grb::dot< descr_dense >( sigma, r, r, ring ); } - ret = ret ? ret : grb::dot< descr_dense >( sigma, temp, r, ring ); assert( ret == SUCCESS ); // bnorm = b' * b; bnorm = zero; - ret = ret ? ret : grb::set( temp, b ); if( grb::utils::is_complex< IOType >::value ) { - ret = ret ? ret : grb::eWiseLambda( [&temp]( const size_t i ) { - temp[ i ] = grb::utils::conjugate( temp[ i ] ); + ret = ret ? ret : grb::eWiseLambda( [&temp,&b]( const size_t i ) { + temp[ i ] = grb::utils::is_complex< IOType >::conjugate( b[ i ] ); }, temp ); + ret = ret ? ret : grb::dot< descr_dense >( bnorm, temp, b, ring ); + } else { + ret = ret ? ret : grb::dot< descr_dense >( bnorm, b, b, ring ); } - ret = ret ? ret : grb::dot< descr_dense >( bnorm, temp, b, ring ); assert( ret == SUCCESS ); if( ret == SUCCESS ) { @@ -315,11 +317,17 @@ namespace grb { // beta = u' * temp beta = zero; if( grb::utils::is_complex< IOType >::value ) { - ret = ret ? ret : grb::eWiseLambda( [&u]( const size_t i ) { u[ i ] = grb::utils::conjugate( u[ i ] ); }, u ); + ret = ret ? ret : grb::eWiseLambda( [&u]( const size_t i ) { + u[ i ] = grb::utils::is_complex< IOType >::conjugate( u[ i ] ); + }, u + ); } ret = ret ? ret : grb::dot< descr_dense >( beta, temp, u, ring ); if( grb::utils::is_complex< IOType >::value ) { - ret = ret ? ret : grb::eWiseLambda( [&u]( const size_t i ) { u[ i ] = grb::utils::conjugate( u[ i ] ); }, u ); + ret = ret ? ret : grb::eWiseLambda( [&u]( const size_t i ) { + u[ i ] = grb::utils::is_complex< IOType >::conjugate( u[ i ] ); + }, u + ); } assert( ret == SUCCESS ); @@ -342,17 +350,18 @@ namespace grb { // beta = r' * r; beta = zero; - ret = ret ? ret : grb::set( temp, r ); if( grb::utils::is_complex< IOType >::value ) { - ret = ret ? ret : grb::eWiseLambda( [&temp]( const size_t i ) { - temp[ i ] = grb::utils::conjugate( temp[ i ] ); + ret = ret ? ret : grb::eWiseLambda( [&temp,&r]( const size_t i ) { + temp[ i ] = grb::utils::is_complex< IOType >::conjugate( r[ i ] ); }, temp ); + ret = ret ? ret : grb::dot< descr_dense >( beta, temp, r, ring ); + } else { + ret = ret ? ret : grb::dot< descr_dense >( beta, r, r, ring ); } - ret = ret ? ret : grb::dot< descr_dense >( beta, temp, r, ring ); + residual = grb::utils::is_complex< IOType >::modulus( beta ); assert( ret == SUCCESS ); - residual = std::abs( beta ); if( ret == SUCCESS ) { if( sqrt( residual ) < tol ) { break; @@ -373,9 +382,7 @@ namespace grb { // u = temp std::swap( u, temp ); - // sigma = beta; sigma = beta; - residual = std::abs( beta ); } while( iter++ < max_iterations && ret == SUCCESS ); diff --git a/include/graphblas/utils/iscomplex.hpp b/include/graphblas/utils/iscomplex.hpp index 5a4a257c6..b0cbcbec7 100644 --- a/include/graphblas/utils/iscomplex.hpp +++ b/include/graphblas/utils/iscomplex.hpp @@ -36,6 +36,11 @@ namespace grb { * * @tparam C The type to check. * + * This class also mirrors a couple of standard functions that translate to + * no-ops in case \a C is not complex. The following functions are provided: + * - is_complex::conjugate + * - is_complex::modulus + * * \internal This is the base implementation which assumes \a C is not of * type std::complex. */ @@ -53,6 +58,22 @@ namespace grb { /** Whether the type \a C is std::complex */ static constexpr const bool value = false; + /** + * @returns The conjugate of a given value if \a C is a complex type, or + * the given value if \a C is not complex. + */ + static C conjugate( const C &x ) { + return x; + } + + /** + * @returns The absolute value of a given value if \a C is a complex type, + * or the given value if \a C is not complex. + */ + static C modulus( const C &x ) { + return x; + } + }; /** \internal The specialisation for std::complex types. */ @@ -61,19 +82,15 @@ namespace grb { public: typedef T type; static constexpr const bool value = true; + static std::complex< T > conjugate( const std::complex< T > &x ) { + return std::conj( x ); + } + static T modulus( const std::complex< T > &x ) { + return std::abs( x ); + } }; - /** \internal Wrapper for the std::conjugate. */ - template X conjugate (X a ) { - return (a); - }; - - template - std::complex conjugate (std::complex a ) { - return (std::conj(a)); - }; - } // end namespace utils } // end namespace grb diff --git a/include/graphblas/utils/parser/MatrixFileIterator.hpp b/include/graphblas/utils/parser/MatrixFileIterator.hpp index e1b3cb071..55c262b90 100644 --- a/include/graphblas/utils/parser/MatrixFileIterator.hpp +++ b/include/graphblas/utils/parser/MatrixFileIterator.hpp @@ -410,7 +410,8 @@ namespace grb { #endif std::swap( buffer[ pos ].first.first, buffer[ pos ].first.second ); if( properties._symmetric == Hermitian ) { - buffer[ pos ].second = conjugate( buffer[ pos ].second ); + buffer[ pos ].second = grb::utils::is_complex< T >::conjugate( + buffer[ pos ].second ); } return *this; } else { From 82b36209be1a03d0a725e493d687959b9b5982aa Mon Sep 17 00:00:00 2001 From: "Albert-Jan N. Yzelman" Date: Tue, 26 Apr 2022 18:41:38 +0200 Subject: [PATCH 06/22] Missed one instance where abs was used while modulus (in case of complex values) was intended. By recasting into is_complex::modulus, this operation now translates to no-op in the non-complex case --- include/graphblas/algorithms/conjugate_gradient.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/graphblas/algorithms/conjugate_gradient.hpp b/include/graphblas/algorithms/conjugate_gradient.hpp index d0e26310a..7ed2f3888 100644 --- a/include/graphblas/algorithms/conjugate_gradient.hpp +++ b/include/graphblas/algorithms/conjugate_gradient.hpp @@ -300,7 +300,7 @@ namespace grb { assert( ret == SUCCESS ); if( ret == SUCCESS ) { - tol *= sqrt( std::abs( bnorm ) ); + tol *= sqrt( grb::utils::is_complex< IOType >::modulus( bnorm ) ); } size_t iter = 0; From 1f183c51d32491612ba401ad566e839c8e084aea Mon Sep 17 00:00:00 2001 From: "Albert-Jan N. Yzelman" Date: Tue, 26 Apr 2022 18:56:38 +0200 Subject: [PATCH 07/22] Formatting issues in new code fixed. Bool casting of complex values no longer checks for equality to zero, but rather does a direct cast just as in the non-complex case. Since processing this file anyway, fixed all code style issues here. --- include/graphblas/utils.hpp | 93 ++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 47 deletions(-) diff --git a/include/graphblas/utils.hpp b/include/graphblas/utils.hpp index 70fdfc415..2454aab02 100644 --- a/include/graphblas/utils.hpp +++ b/include/graphblas/utils.hpp @@ -60,7 +60,12 @@ namespace grb { * @returns Whether a == b. */ template< typename T > - static bool equals( const T & a, const T & b, typename std::enable_if< ! std::is_floating_point< T >::value >::type * = NULL ) { + static bool equals( + const T &a, const T &b, + typename std::enable_if< + !std::is_floating_point< T >::value + >::type * = nullptr + ) { // simply do standard compare return a == b; } @@ -84,18 +89,16 @@ namespace grb { */ template< typename T, typename U > static bool equals( const T &a, const T &b, const U epsilons, - typename std::enable_if< std::is_floating_point< T >::value >::type * = NULL + typename std::enable_if< + std::is_floating_point< T >::value + >::type * = nullptr ) { assert( epsilons >= 1 ); // if they are bit-wise equal, it's easy if( a == b ) { #ifdef _DEBUG - #ifndef _GRB_NO_STDIO std::cout << "\t Bit-wise equal\n"; - #else - printf( "\t Bit-wise equal\n" ); - #endif #endif return true; } @@ -107,22 +110,21 @@ namespace grb { const T absPlus = absA + absB; // find the effective epsilon - const T eps = static_cast< T >( epsilons ) * std::numeric_limits< T >::epsilon(); + const T eps = static_cast< T >( epsilons ) * + std::numeric_limits< T >::epsilon(); // find the minimum and maximum *normal* values. const T min = std::numeric_limits< T >::min(); const T max = std::numeric_limits< T >::max(); - // if the difference is a subnormal number, it should be smaller than machine epsilon times min; - // if this is not the case, then we cannot safely conclude anything from this small a difference. + // if the difference is a subnormal number, it should be smaller than + // machine epsilon times min; + // if this is not the case, then we cannot safely conclude anything from this + // small a difference. // The same is true if a or b are zero. if( a == 0 || b == 0 || absPlus < min ) { #ifdef _DEBUG - #ifndef _GRB_NO_STDIO std::cout << "\t Zero or close to zero difference\n"; - #else - printf( "\t Zero or close to zero difference\n" ); - #endif #endif return absDiff < eps * min; } @@ -132,33 +134,21 @@ namespace grb { if( absA > absB ) { if( absB > max - absA ) { #ifdef _DEBUG - #ifndef _GRB_NO_STDIO std::cout << "\t Normalising absolute difference by max (I)\n"; - #else - printf( "\t Normalising absolute difference by max (I)\n" ); - #endif #endif return absDiff / max < eps; } } else { if( absA > max - absB ) { #ifdef _DEBUG - #ifndef _GRB_NO_STDIO std::cout << "\t Normalising absolute difference by max (II)\n"; - #else - printf( "\t Normalising absolute difference by max (II)\n" ); - #endif #endif return absDiff / max < eps; } } // use of relative error should be safe #ifdef _DEBUG - #ifndef _GRB_NO_STDIO std::cout << "\t Using relative error\n"; - #else - printf( "\t Using relative error\n" ); - #endif #endif return absDiff / absPlus < eps; } @@ -177,7 +167,7 @@ namespace grb { * return value is a constexpr. (This was fixed in C++14.) */ template< typename T > - constexpr const T & static_min( const T & a, const T & b ) { + constexpr const T & static_min( const T &a, const T &b ) { return a < b ? a : b; } @@ -187,19 +177,19 @@ namespace grb { */ template< typename T > class SizeOf { - public: - /** - * If \a T is void, this value equals 0 and - * equal to sizeof(T) otherwise. - */ - static constexpr const size_t value = sizeof( T ); + public: + /** + * If \a T is void, this value equals 0 and + * equal to sizeof(T) otherwise. + */ + static constexpr const size_t value = sizeof( T ); }; - // void-specialisation of the above class + /** \internal void-specialisation of the above class */ template<> class SizeOf< void > { - public: - static constexpr const size_t value = 0; + public: + static constexpr const size_t value = 0; }; /** @@ -238,7 +228,11 @@ namespace grb { * compile. */ template< Descriptor descriptor, typename T > - static bool interpretMask( const bool & assigned, const T * const val, const size_t offset ) { + static bool interpretMask( + const bool &assigned, + const T * const val, + const size_t offset + ) { // set default mask to false bool ret = false; // if we request a structural mask, decide only on passed assigned variable @@ -253,7 +247,7 @@ namespace grb { } // check whether we should return the inverted value if( descriptor & descriptors::invert_mask ) { - return ! ret; + return !ret; } else { return ret; } @@ -261,8 +255,11 @@ namespace grb { /** Specialisation for complex-valued masks */ template< Descriptor descriptor, typename T > - static bool interpretMask( const bool & assigned, - const std::complex * const val, const size_t offset ) { + static bool interpretMask( + const bool &assigned, + const std::complex * const val, + const size_t offset + ) { // set default mask to false bool ret = false; // if we request a structural mask, decide only on passed assigned variable @@ -271,30 +268,31 @@ namespace grb { } else { // if based on value, if there is a value, cast it to bool if( assigned ) { - ret = static_cast< bool >( - real( val [ offset ] ) == 0 && - imag( val [ offset ] ) == 0 - ); + ret = static_cast< bool >( real( val [ offset ] ) ) || + static_cast< bool >( imag( val [ offset ] ) ); } // otherwise there is no value and false is assumed } // check whether we should return the inverted value if( descriptor & descriptors::invert_mask ) { - return ! ret; + return !ret; } else { return ret; } } - /** Specialisation for void-valued masks */ template< Descriptor descriptor > - static bool interpretMask( const bool & assigned, const void * const, const size_t ) { + static bool interpretMask( + const bool &assigned, + const void * const, + const size_t + ) { // set default mask to false bool ret = assigned; // check whether we should return the inverted value if( descriptor & descriptors::invert_mask ) { - return ! ret; + return !ret; } else { return ret; } @@ -305,3 +303,4 @@ namespace grb { } // namespace grb #endif + From 83915cbd681b128af07672bc7effa558c85a217d Mon Sep 17 00:00:00 2001 From: "Albert-Jan N. Yzelman" Date: Tue, 26 Apr 2022 18:59:55 +0200 Subject: [PATCH 08/22] Add noexcept to no-op implementations of conjugate and modulus --- include/graphblas/utils/iscomplex.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/graphblas/utils/iscomplex.hpp b/include/graphblas/utils/iscomplex.hpp index b0cbcbec7..85b69235b 100644 --- a/include/graphblas/utils/iscomplex.hpp +++ b/include/graphblas/utils/iscomplex.hpp @@ -62,7 +62,7 @@ namespace grb { * @returns The conjugate of a given value if \a C is a complex type, or * the given value if \a C is not complex. */ - static C conjugate( const C &x ) { + static C conjugate( const C &x ) noexcept { return x; } @@ -70,7 +70,7 @@ namespace grb { * @returns The absolute value of a given value if \a C is a complex type, * or the given value if \a C is not complex. */ - static C modulus( const C &x ) { + static C modulus( const C &x ) noexcept { return x; } From d0ee4a4909d7211c47341b4749c32476b1899266 Mon Sep 17 00:00:00 2001 From: "Albert-Jan N. Yzelman" Date: Tue, 26 Apr 2022 19:07:25 +0200 Subject: [PATCH 09/22] Remove stray (old?) modification --- include/graphblas/utils/parser/MatrixFileProperties.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/graphblas/utils/parser/MatrixFileProperties.hpp b/include/graphblas/utils/parser/MatrixFileProperties.hpp index 910f0d260..ab19fa41c 100644 --- a/include/graphblas/utils/parser/MatrixFileProperties.hpp +++ b/include/graphblas/utils/parser/MatrixFileProperties.hpp @@ -92,9 +92,6 @@ namespace grb { */ bool _complex; - /** Whether the file is hermitian or not. */ - bool _hermitian; - /** * Whether the file has direct indexing or not. * From 4fb775ae600ad072498822bfac2fc36d44aa6b5a Mon Sep 17 00:00:00 2001 From: "Albert-Jan N. Yzelman" Date: Wed, 27 Apr 2022 12:46:12 +0200 Subject: [PATCH 10/22] No need to use auto if the type is known --- tests/smoke/conjugate_gradient.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/smoke/conjugate_gradient.cpp b/tests/smoke/conjugate_gradient.cpp index 1c43ee15f..4865a4234 100644 --- a/tests/smoke/conjugate_gradient.cpp +++ b/tests/smoke/conjugate_gradient.cpp @@ -147,7 +147,7 @@ void grbProgram( const struct input &data_in, struct output &out ) { out.iterations, out.residual, r, u, temp ); - auto single_time = timer.time(); + double single_time = timer.time(); if( rc != SUCCESS ) { std::cerr << "Failure: call to conjugate_gradient did not succeed (" << toString( rc ) << ")." << std::endl; @@ -187,7 +187,7 @@ void grbProgram( const struct input &data_in, struct output &out ) { ); } } - auto time_taken = timer.time(); + double time_taken = timer.time(); if( rc == SUCCESS ) { out.times.useful = time_taken / static_cast< double >( out.rep ); } From a0143423727ae63d2defd84ae615989ec3983748 Mon Sep 17 00:00:00 2001 From: "Albert-Jan N. Yzelman" Date: Wed, 27 Apr 2022 12:48:38 +0200 Subject: [PATCH 11/22] Found two more uses of autos that are avoidable. One const-correctness fix. --- tests/smoke/conjugate_gradient.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/smoke/conjugate_gradient.cpp b/tests/smoke/conjugate_gradient.cpp index 4865a4234..0217e13e8 100644 --- a/tests/smoke/conjugate_gradient.cpp +++ b/tests/smoke/conjugate_gradient.cpp @@ -187,7 +187,7 @@ void grbProgram( const struct input &data_in, struct output &out ) { ); } } - double time_taken = timer.time(); + const double time_taken = timer.time(); if( rc == SUCCESS ) { out.times.useful = time_taken / static_cast< double >( out.rep ); } @@ -221,7 +221,7 @@ void grbProgram( const struct input &data_in, struct output &out ) { out.pinnedVector = PinnedVector< hpchscalar >( x, SEQUENTIAL ); // finish timing - const auto time_taken = timer.time(); + const double time_taken = timer.time(); out.times.postamble = time_taken; // done @@ -348,7 +348,7 @@ int main( int argc, char ** argv ) { if( out.error_code == 0 && out.pinnedVector.size() > 0 ) { std::cout << "First 10 nonzeroes of x are: ( "; for( size_t k = 0; k < out.pinnedVector.nonzeroes() && k < 10; ++k ) { - const auto &nonzeroValue = out.pinnedVector.getNonzeroValue( k ); + const hpchscalar &nonzeroValue = out.pinnedVector.getNonzeroValue( k ); std::cout << nonzeroValue << " "; } std::cout << ")" << std::endl; From 630f76cb9c53f681f1713487ec22c3978e6b13ac Mon Sep 17 00:00:00 2001 From: "Albert-Jan N. Yzelman" Date: Wed, 27 Apr 2022 12:51:46 +0200 Subject: [PATCH 12/22] More descriptive names for hpchscalarbase and hpchscalar --- tests/smoke/conjugate_gradient.cpp | 33 +++++++++++++++--------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/tests/smoke/conjugate_gradient.cpp b/tests/smoke/conjugate_gradient.cpp index 0217e13e8..1117b1a70 100644 --- a/tests/smoke/conjugate_gradient.cpp +++ b/tests/smoke/conjugate_gradient.cpp @@ -28,18 +28,19 @@ #include #include -using hpchscalarbase = double; +using BaseScalarType = double; #ifdef _CG_COMPLEX -using hpchscalar = std::complex; + using ScalarType = std::complex< BaseScalarType >; #else -using hpchscalar = double; + using ScalarType = BaseScalarType; #endif -constexpr hpchscalarbase TOL=0.000001; + +constexpr BaseScalarType TOL=0.000001; constexpr size_t MAX_ITERS=10000; -constexpr double C1=0.0001; -constexpr double C2=0.0001; +constexpr double C1=0.0001; +constexpr double C2=0.0001; using namespace grb; using namespace algorithms; @@ -56,7 +57,7 @@ struct output { size_t iterations; double residual; grb::utils::TimerResults times; - PinnedVector< hpchscalar > pinnedVector; + PinnedVector< ScalarType > pinnedVector; }; void grbProgram( const struct input &data_in, struct output &out ) { @@ -80,7 +81,7 @@ void grbProgram( const struct input &data_in, struct output &out ) { out.error_code = 0; // create local parser - grb::utils::MatrixFileReader< hpchscalar, + grb::utils::MatrixFileReader< ScalarType, std::conditional< ( sizeof( grb::config::RowIndexType ) > sizeof( grb::config::ColIndexType ) @@ -94,7 +95,7 @@ void grbProgram( const struct input &data_in, struct output &out ) { timer.reset(); // load into GraphBLAS - Matrix< hpchscalar > L( n, n ); + Matrix< ScalarType > L( n, n ); { const RC rc = buildMatrixUnique( L, parser.begin( SEQUENTIAL ), parser.end( SEQUENTIAL), @@ -128,10 +129,10 @@ void grbProgram( const struct input &data_in, struct output &out ) { } // test default pagerank run - Vector< hpchscalar > x( n ), b( n ), r( n ), u( n ), temp( n ); + Vector< ScalarType > x( n ), b( n ), r( n ), u( n ), temp( n ); - set( x, static_cast< hpchscalar >( 1 ) / static_cast< hpchscalar >( n ) ); - set( b, static_cast< hpchscalar >( 1 ) ); + set( x, static_cast< ScalarType >( 1 ) / static_cast< ScalarType >( n ) ); + set( b, static_cast< ScalarType >( 1 ) ); out.times.preamble = timer.time(); @@ -175,8 +176,8 @@ void grbProgram( const struct input &data_in, struct output &out ) { timer.reset(); for( size_t i = 0; i < out.rep && rc == SUCCESS; ++i ) { - rc = set( x, static_cast< hpchscalar >( 1 ) - / static_cast< hpchscalar >( n ) ); + rc = set( x, static_cast< ScalarType >( 1 ) + / static_cast< ScalarType >( n ) ); if( rc == SUCCESS ) { rc = conjugate_gradient( @@ -218,7 +219,7 @@ void grbProgram( const struct input &data_in, struct output &out ) { } // output - out.pinnedVector = PinnedVector< hpchscalar >( x, SEQUENTIAL ); + out.pinnedVector = PinnedVector< ScalarType >( x, SEQUENTIAL ); // finish timing const double time_taken = timer.time(); @@ -348,7 +349,7 @@ int main( int argc, char ** argv ) { if( out.error_code == 0 && out.pinnedVector.size() > 0 ) { std::cout << "First 10 nonzeroes of x are: ( "; for( size_t k = 0; k < out.pinnedVector.nonzeroes() && k < 10; ++k ) { - const hpchscalar &nonzeroValue = out.pinnedVector.getNonzeroValue( k ); + const ScalarType &nonzeroValue = out.pinnedVector.getNonzeroValue( k ); std::cout << nonzeroValue << " "; } std::cout << ")" << std::endl; From ca6a351b8f5e796e31a10d5f186a85bcf3d9d18a Mon Sep 17 00:00:00 2001 From: "Albert-Jan N. Yzelman" Date: Wed, 27 Apr 2022 13:12:49 +0200 Subject: [PATCH 13/22] Move original test data rndHermit256.mtx into repository. Adapt CMake and bash scripts to new location. --- tests/parse_env.sh | 8 +- tests/smoke/CMakeLists.txt | 3 +- tests/smoke/smoketests.sh | 2 +- tests/smoke/test_data/rndHermit256.mtx | 1274 ++++++++++++++++++++++++ tests/unit/CMakeLists.txt | 3 +- 5 files changed, 1286 insertions(+), 4 deletions(-) create mode 100644 tests/smoke/test_data/rndHermit256.mtx diff --git a/tests/parse_env.sh b/tests/parse_env.sh index e15a39331..025514e3c 100644 --- a/tests/parse_env.sh +++ b/tests/parse_env.sh @@ -20,7 +20,8 @@ function print_synopsis() { echo " --lpf-args additional arguments for the LPF engine" echo " --gnn-dataset-path " echo " --manual-run-args LPF engine arguments for manual run" - echo " --output-verification-dir directory with golden output for tests verification" + echo " --output-verification-dir directory with golden output for test verification" + echo " --test-data-dir directory with original data used for tests" } function check_dir() { @@ -100,6 +101,10 @@ do fi shift 2 ;; + --test-data-dir) + TEST_DATA_DIR="$(realpath "$2")" + shift 2 + ;; --output-verification-dir) OUTPUT_VERIFICATION_DIR="$(realpath "$2")" shift 2 @@ -227,6 +232,7 @@ echo " INPUT_DIR=${INPUT_DIR}" echo " BACKENDS=${BACKENDS}" echo " GNN_DATASET_PATH=${GNN_DATASET_PATH}" echo " OUTPUT_VERIFICATION_DIR=${OUTPUT_VERIFICATION_DIR}" +echo " TEST_DATA_DIR=${TEST_DATA_DIR}" if [[ ! -z "${LPFRUN}" ]]; then echo " LPFRUN=${LPFRUN}" echo " MANUALRUN=${MANUALRUN}" diff --git a/tests/smoke/CMakeLists.txt b/tests/smoke/CMakeLists.txt index 9d52fa8c5..fac6ceee8 100644 --- a/tests/smoke/CMakeLists.txt +++ b/tests/smoke/CMakeLists.txt @@ -161,10 +161,11 @@ add_custom_target( tests_smoke "--test-bin-dir" "\"${CMAKE_CURRENT_BINARY_DIR}\"" "--test-out-dir" "\"${CMAKE_CURRENT_BINARY_DIR}/output\"" "--output-verification-dir" "\"${CMAKE_CURRENT_SOURCE_DIR}/output_verification\"" + "--test-data-dir" "\"${CMAKE_CURRENT_SOURCE_DIR}/test_data\"" WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" DEPENDS build_tests_category_smoke # add dependency on this target - # to automatically build before running + # to automatically build before running COMMAND_EXPAND_LISTS USES_TERMINAL ) diff --git a/tests/smoke/smoketests.sh b/tests/smoke/smoketests.sh index 513fef682..39e972070 100755 --- a/tests/smoke/smoketests.sh +++ b/tests/smoke/smoketests.sh @@ -203,7 +203,7 @@ for BACKEND in ${BACKENDS[@]}; do echo " verifies against a ground-truth solution vector. The test" echo " employs the grb::Launcher in automatic mode. It uses" echo " direct-mode file IO." - $runner ${TEST_BIN_DIR}/conjugate_gradient_complex_${BACKEND} ${INPUT_DIR}/${TESTNAME}.mtx direct 1 1 verification ${OUTPUT_VERIFICATION_DIR}/complex_conjugate_conjugate_gradient_out_${TESTNAME}_ref &> ${TEST_OUT_DIR}/conjugate_gradient_complex_${BACKEND}_${P}_${T}.log + $runner ${TEST_BIN_DIR}/conjugate_gradient_complex_${BACKEND} ${TEST_DATA_DIR}/${TESTNAME}.mtx direct 1 1 verification ${OUTPUT_VERIFICATION_DIR}/complex_conjugate_conjugate_gradient_out_${TESTNAME}_ref &> ${TEST_OUT_DIR}/conjugate_gradient_complex_${BACKEND}_${P}_${T}.log head -1 ${TEST_OUT_DIR}/conjugate_gradient_complex_${BACKEND}_${P}_${T}.log grep 'Test OK' ${TEST_OUT_DIR}/conjugate_gradient_complex_${BACKEND}_${P}_${T}.log || echo "Test FAILED" else diff --git a/tests/smoke/test_data/rndHermit256.mtx b/tests/smoke/test_data/rndHermit256.mtx new file mode 100644 index 000000000..09fe2b603 --- /dev/null +++ b/tests/smoke/test_data/rndHermit256.mtx @@ -0,0 +1,1274 @@ +%%MatrixMarket matrix coordinate complex hermitian +% randomly generated hermitian and positive definite matrix +% Generated 11-Apr-2022 +256 256 1270 +1 1 1.8654454716290514 0.0 +2 1 0.7416248919438985 -0.42616867839414707 +2 2 0.7861449956654505 0.0 +3 1 0.4287659615116588 -0.43728745566947236 +3 2 0.4894679055006812 -0.28612315365754093 +3 3 1.8114809050878304 0.0 +4 1 0.36193962956574577 -0.38922030266331065 +4 2 0.6911087286316752 -0.7446475835822458 +4 3 0.20421113488499865 -0.7272366069887519 +4 4 1.8487755262383772 0.0 +5 1 0.8390901225979435 -0.31209269652064897 +5 2 0.8146511433467856 -0.3218186456164348 +5 3 0.4748067091192787 -0.8909582536397824 +5 4 0.16263792798344956 -0.40066486247933764 +5 5 0.23830669824672146 0.0 +6 2 0.015531398054373757 -0.19191380089612198 +6 3 0.9984127806893658 -0.45957987759768226 +6 4 0.6720808199075649 -0.8207667104400779 +6 5 0.004074713310305178 -0.8681157381227611 +6 6 0.023287288411028007 0.0 +7 3 0.30021999835700275 -0.3990044990259616 +7 4 0.818914795193084 -0.43204597977514025 +7 5 0.7938787033065059 -0.11075375967438494 +7 6 0.7266973093611347 -0.37272579769241276 +7 7 0.08116563161075496 0.0 +8 4 0.9704295079705486 -0.9452699194193706 +8 5 0.15398060990882723 -0.9476120441756891 +8 6 0.4419660454637322 -0.7955431923583451 +8 7 0.7227098296602295 -0.85013890614888 +8 8 0.6592857701298476 0.0 +9 5 0.5088995103629643 -0.5152139242742844 +9 6 0.7776692546051688 -0.3435201347333464 +9 7 0.5048707662166779 -0.20137097001685633 +9 8 0.15294419239445423 -0.5232555016472138 +9 9 0.5224968191097623 0.0 +10 6 0.29272434769910594 -0.19822298078244271 +10 7 0.38729467871486745 -0.898035520917484 +10 8 0.10881887389204192 -0.5734135778642762 +10 9 0.7975227787966427 -0.7758711048255491 +10 10 0.5497260094163998 0.0 +11 7 0.21081058122186802 -0.7044972145305872 +11 8 0.6813394533112371 -0.4361530202444911 +11 9 0.07538797038878342 -0.6914224924869752 +11 10 0.6214821569707559 -0.5138523301953904 +11 11 0.24976708630535938 0.0 +12 8 0.6329627130135693 -0.5406322700945728 +12 9 0.37925355021085105 -0.18250346468275036 +12 10 0.17183702189177918 -0.6566430511337884 +12 11 0.34226759881781377 -0.9228017489312482 +12 12 1.4378194466925933 0.0 +13 9 0.81832431830782 -0.044509316247739905 +13 10 0.740856539133517 -0.688970569877706 +13 11 0.5075371582696012 -0.7946498370378169 +13 12 0.8054012335112081 -0.900743270762808 +13 13 1.8559115902067718 0.0 +14 10 0.5851536760558084 -0.39586925325205424 +14 11 0.29210635034292853 -0.3535988627021589 +14 12 0.5075276307418575 -0.6036707157683067 +14 13 0.8401698166152574 -0.28421156668985215 +14 14 0.17898283797409142 0.0 +15 11 0.8186504469092792 -0.942163449716619 +15 12 0.6085779050016638 -0.39098019759359226 +15 13 0.9653200838981724 -0.19054148831821172 +15 14 0.700867659602619 -0.15865634947467477 +15 15 1.0542229764149977 0.0 +16 12 0.8440079043463927 -0.0459293416257176 +16 13 0.5081601404338085 -0.8921275935480136 +16 14 0.6721893989180243 -0.6634641185554393 +16 15 0.8623070345101644 -0.9980344709215938 +16 16 0.9565987335621009 0.0 +17 13 0.9854778214795554 -0.7831127533780726 +17 14 0.24242874100414336 -0.5727263580945555 +17 15 0.8202199612712667 -0.020664351532072134 +17 16 0.24416035922727308 -0.02525071898099529 +17 17 1.0829210026464593 0.0 +18 14 0.30850849595356467 -0.3633282988587997 +18 15 0.860027572340404 -0.25337110273449004 +18 16 0.13662911258640542 -0.6064518072814947 +18 17 0.9418885100245534 -0.6770788945337859 +18 18 1.2822108650052586 0.0 +19 15 0.9780177552417991 -0.4854521603021853 +19 16 0.28797194457386843 -0.715036869215492 +19 17 0.4156155086473572 -0.39853434819671407 +19 18 0.6106502612698267 -0.37397039061131865 +19 19 0.16372761489574206 0.0 +20 16 0.5758556416802875 -0.4383512970086868 +20 17 0.864715104793176 -0.5240110553700351 +20 18 0.06806579808275182 -0.2618698436578556 +20 19 0.06146058712076308 -0.3872190535117527 +20 20 0.11467237161686761 0.0 +21 17 0.9452789571372366 -0.8568955914887844 +21 18 0.33113008104205244 -0.929028345462104 +21 19 0.8531492618807637 -0.15527163591684034 +21 20 0.7056256911169826 -0.5769469954010159 +21 21 0.4098014707425772 0.0 +22 18 0.49873268147869854 -0.199237439206141 +22 19 0.20022360793721472 -0.07025416962578845 +22 20 0.4419323720513141 -0.369836160496947 +22 21 0.09986256646498903 -0.27531514004445234 +22 22 0.37048066866778107 0.0 +23 19 0.05755587712940613 -0.3165735526405906 +23 20 0.043744314392563544 -0.2665788155525718 +23 21 0.9717794627300712 -0.22724179144342438 +23 22 0.349464483102893 -0.07718882685222794 +23 23 1.4371111907420158 0.0 +24 20 0.07857088393628464 -0.3852822606551288 +24 21 0.18113741967991792 -0.517433025384594 +24 22 0.4178284432806799 -0.7239785078657528 +24 23 0.17816164648653587 -0.8741389977671347 +24 24 1.6727590202533567 0.0 +25 21 0.11057915501361648 -0.8242874164279995 +25 22 0.7183091534111794 -0.8372839776663494 +25 23 0.5224460363391911 -0.19809832158347662 +25 24 0.9916053440115665 -0.49518942735721083 +25 25 0.22395550008704035 0.0 +26 22 0.41395216244958555 -0.05469436691263019 +26 23 0.4895957759191244 -0.03577186239428187 +26 24 0.6056125979239025 -0.27686748249446036 +26 25 0.02125680874161684 -0.34520650784958584 +26 26 1.932516598108785 0.0 +27 23 0.5782399754603536 -0.7278170131457423 +27 24 0.9455695494854753 -0.5652813844913855 +27 25 0.5416283778353793 -0.41549805375695714 +27 26 0.2775322894376103 -0.6040638567562641 +27 27 1.6182435469667227 0.0 +28 24 0.31676179698117635 -0.639158241043703 +28 25 0.5260454265517205 -0.31712906128343377 +28 26 0.8672360605610955 -0.739974002535723 +28 27 0.9761299314732833 -0.8324790388586634 +28 28 1.7311236572112954 0.0 +29 25 0.16990926008406138 -0.9677407357037292 +29 26 0.03890849365564142 -0.9237982011967315 +29 27 0.9039525838182201 -0.850023143937386 +29 28 0.48277557376132585 -0.5557056195087592 +29 29 1.0227209985698489 0.0 +30 26 0.9989930395228848 -0.4276841519694362 +30 27 0.3168798939785473 -0.019437633213352234 +30 28 0.9422210843640612 -0.250145172480975 +30 29 0.9114523660123175 -0.6180744483256314 +30 30 1.9122384653677604 0.0 +31 27 0.4697265006976825 -0.5684171643960854 +31 28 0.43637161218064024 -0.08859287796816451 +31 29 0.7392061817142784 -0.2876894756256796 +31 30 0.9581430561120569 -0.9549125765327282 +31 31 0.7167795611148171 0.0 +32 28 0.12285791233769261 -0.4122784584603816 +32 29 0.10210678975408549 -0.8000176328561243 +32 30 0.029803130931625232 -0.11522569120525039 +32 31 0.5518982498956251 -0.9279419871660717 +32 32 0.4515896833277133 0.0 +33 29 0.4239602676204667 -0.1573832076027143 +33 30 0.393740504973923 -0.9108660543009574 +33 31 0.31717065583014803 -0.7266804555698003 +33 32 0.5733677935459508 -0.8965344650017577 +33 33 0.41708594268552956 0.0 +34 30 0.10854183086739044 -0.30431589003263904 +34 31 0.31810001212784633 -0.3057593781893535 +34 32 0.19501872738355985 -0.7070955972021369 +34 33 0.17293515780186386 -0.8603947301558645 +34 34 0.5762912188075093 0.0 +35 31 0.506065083394933 -0.6370569805913562 +35 32 0.7078628905268867 -0.9916489413041493 +35 33 0.9631526676141678 -0.947044890874047 +35 34 0.5877355027426846 -0.06406845798639271 +35 35 1.5786276150602747 0.0 +36 32 0.9610429262308964 -0.6439216504139885 +36 33 0.8987309257270211 -0.2977987651566181 +36 34 0.27678079983965054 -0.41544194451235605 +36 35 0.8201002983567145 -0.5536868793241014 +36 36 1.0449259321566577 0.0 +37 33 0.4139214566694186 -0.7454810188830422 +37 34 0.8797228182864173 -0.0007855068560370659 +37 35 0.8199959931168279 -0.21657953765808768 +37 36 0.6197415328577071 -0.8413778702155018 +37 37 0.8320708053780108 0.0 +38 34 0.8969533983645974 -0.7080464314944404 +38 35 0.046342418292541376 -0.07018486859370654 +38 36 0.5157389601545629 -0.9349794875505513 +38 37 0.4315768294403133 -0.39493029878809105 +38 38 0.459751705409855 0.0 +39 35 0.5763103110765366 -0.8597166389925353 +39 36 0.718214012704296 -0.8557817592888228 +39 37 0.6310763514132057 -0.43004625683027664 +39 38 0.06919807514672127 -0.4632240531127104 +39 39 0.6891724136431103 0.0 +40 36 0.932249476918864 -0.7692721940668364 +40 37 0.7468051956479843 -0.8087309655224412 +40 38 0.5804199828530305 -0.6494255665117351 +40 39 0.7857958845316708 -0.06124112658504255 +40 40 1.9784233839064629 0.0 +41 37 0.7002835695793116 -0.6802682133111762 +41 38 0.8312505454726719 -0.27092107904142404 +41 39 0.8161569515189191 -0.771824622450171 +41 40 0.12289554156088767 -0.4872804501511193 +41 41 0.06646230544711873 0.0 +42 38 0.06811770736918066 -0.9782652829959017 +42 39 0.32118241166637984 -0.052759487239052216 +42 40 0.2571932563553785 -0.8956846525872263 +42 41 0.174920513072934 -0.774016560164239 +42 42 1.739502300746691 0.0 +43 39 0.4217222531259982 -0.824458981345402 +43 40 0.8829319166399744 -0.9644580929227882 +43 41 0.04817378737215938 -0.8642308000662755 +43 42 0.6592923967496792 -0.17622345899119973 +43 43 1.046535055755497 0.0 +44 40 0.29314965137679005 -0.8771268153946158 +44 41 0.2188578364094892 -0.32576853850672094 +44 42 0.9336562317828185 -0.7279114841866069 +44 43 0.5252810639824792 -0.7180370706277667 +44 44 0.46544463224074417 0.0 +45 41 0.25367470458393604 -0.9906513253589836 +45 42 0.5535394232134432 -0.6097971702220376 +45 43 0.913274318253074 -0.6062792743283912 +45 44 0.9439850180837487 -0.9527670811958135 +45 45 0.25936641471027544 0.0 +46 42 0.01135501130011285 -0.17394539087084004 +46 43 0.14405598849031176 -0.28257223626675476 +46 44 0.9338798479009681 -0.41204190550549546 +46 45 0.32515293268329915 -0.47424978886750113 +46 46 1.1981484135291687 0.0 +47 43 0.6450433855947336 -0.666729311863175 +47 44 0.15903925735867597 -0.8561079822211161 +47 45 0.28355737837882034 -0.6875312904153125 +47 46 0.8295468803366982 -0.1889445053868133 +47 47 1.3899040243168186 0.0 +48 44 0.9738211833763996 -0.33198833470380795 +48 45 0.5909958565551482 -0.14438902094899908 +48 46 0.5907274495313172 -0.6719409684869163 +48 47 0.8716130202367978 -0.7295220392541589 +48 48 1.682803094314175 0.0 +49 45 0.26254658544608256 -0.3562917153138446 +49 46 0.8571380382657007 -0.014849793400058209 +49 47 0.9478403625842526 -0.26885601120632086 +49 48 0.2471803544288398 -0.4860440415592704 +49 49 1.9276638654253455 0.0 +50 46 0.7775225800297665 -0.2835809977214292 +50 47 0.1874981477554324 -0.15176351479223504 +50 48 0.3023278709894853 -0.1529114159876208 +50 49 0.750085109372675 -0.12478026079886728 +50 50 0.8251864576195791 0.0 +51 47 0.39329751792887824 -0.8059916916392084 +51 48 0.5796426604438759 -0.05132596108519505 +51 49 0.8158879126851893 -0.8356546594014355 +51 50 0.25614737287945477 -0.17786707014092706 +51 51 1.8445722471877015 0.0 +52 48 0.33909692233099775 -0.30657381076888335 +52 49 0.4828397114512415 -0.843374541494705 +52 50 0.5548346548543934 -0.5431371804094698 +52 51 0.7478363926420795 -0.628663132190732 +52 52 1.1913107439056712 0.0 +53 49 0.23249263381997587 -0.846729347088256 +53 50 0.328709515032268 -0.41691984994194 +53 51 0.9447597889417575 -0.7572400284215256 +53 52 0.43964338158116767 -0.06856955432955081 +53 53 1.9745714504767777 0.0 +54 50 0.8459254313537703 -0.9139229816546665 +54 51 0.34780652451179217 -0.7274496476660967 +54 52 0.4223041424809003 -0.886548018336207 +54 53 0.8626927446532839 -0.09562798058710953 +54 54 0.7441027735709556 0.0 +55 51 0.32202628016075263 -0.10678943196317525 +55 52 0.2493520241559226 -0.23605519931797048 +55 53 0.587050653706652 -0.03173282526402532 +55 54 0.7691401753668858 -0.6229689303779087 +55 55 1.8764397308461516 0.0 +56 52 0.082091973750815 -0.6923162476617847 +56 53 0.13165462517590254 -0.548284500266694 +56 54 0.3771550002421915 -0.0358793242824218 +56 55 0.08881460380429218 -0.2740842345684267 +56 56 0.9781830230555151 0.0 +57 53 0.7904830160876023 -0.33162223596041973 +57 54 0.24487036807340912 -0.6063632860367506 +57 55 0.4751268782028001 -0.710089680877007 +57 56 0.4149687210115379 -0.32868197302340973 +57 57 1.7919582042792832 0.0 +58 54 0.7161801275473282 -0.3783830768873835 +58 55 0.5458306868141601 -0.02855094294911653 +58 56 0.7115756506572565 -0.35992619239131496 +58 57 0.21615137836460707 -0.9284138900036318 +58 58 1.2318125526550365 0.0 +59 55 0.9383428858221877 -0.4165459742426917 +59 56 0.4269288023503185 -0.715106797263304 +59 57 0.7404775302227411 -0.1995591494487755 +59 58 0.5792462314709715 -0.7996684720307573 +59 59 0.7532326587603335 0.0 +60 56 0.3245070567855247 -0.27391533956065217 +60 57 0.28779302497170645 -0.35316723345021717 +60 58 0.774550265987423 -0.31601959224901355 +60 59 0.8163225818879617 -0.43271483305663716 +60 60 0.19835584798810713 0.0 +61 57 0.8774821598433868 -0.5738259727663891 +61 58 0.9258247420873669 -0.42906567917044325 +61 59 0.7785952635884134 -0.5381984223269308 +61 60 0.8657234927115102 -0.02295705168652773 +61 61 1.7450567000233324 0.0 +62 58 0.6515654396607243 -0.8924557262792846 +62 59 0.9940566947237828 -0.584873729580744 +62 60 0.2446869670063263 -0.7124096750659655 +62 61 0.47717447132017743 -0.5673996421204329 +62 62 1.1763728643267104 0.0 +63 59 0.6140581323623158 -0.8276124559328547 +63 60 0.7818691060065697 -0.05441609068560582 +63 61 0.8800346571547624 -0.9399730784602619 +63 62 0.8237922690370257 -0.13180064171705286 +63 63 0.5525574180619046 0.0 +64 60 0.031040528651513744 -0.8429044502799431 +64 61 0.5026745073237583 -0.9481926100179887 +64 62 0.11913120540017819 -0.8482958559137334 +64 63 0.07475130549955356 -0.25426571448730106 +64 64 1.9700178464228681 0.0 +65 61 0.17469999872383557 -0.5923601521072165 +65 62 0.6214447855331747 -0.6626459365826635 +65 63 0.060499025589318745 -0.26863564243143334 +65 64 0.36474006177834106 -0.9833366111215626 +65 65 1.2401791041602719 0.0 +66 62 0.3242092791356963 -0.4328184957495429 +66 63 0.05525308037501919 -0.8776476101952363 +66 64 0.7290913107472453 -0.02268560692672117 +66 65 0.8442982932289265 -0.7133505957181019 +66 66 0.9813152509073504 0.0 +67 63 0.1928662669440644 -0.7055053542761212 +67 64 0.789399743245791 -0.2697119921359903 +67 65 0.6637799368649097 -0.4647139621202968 +67 66 0.2853684496198431 -0.2472949080451201 +67 67 1.7534629534038402 0.0 +68 64 0.7558587177612358 -0.7373245717058033 +68 65 0.5314986140055422 -0.5758741636466614 +68 66 0.4130055150696238 -0.5760645755986458 +68 67 0.5519711448428283 -0.6121996035281463 +68 68 0.42332793285286874 0.0 +69 65 0.8747041133920886 -0.8113047592963833 +69 66 0.005402495456489631 -0.4361328086239782 +69 67 0.3283063260682365 -0.023859658498256442 +69 68 0.6702927533152557 -0.779443531539979 +69 69 1.8420252064937683 0.0 +70 66 0.7286059668957396 -0.6677673609867913 +70 67 0.24035323261279828 -0.8042095783070707 +70 68 0.7920944181795526 -0.407080545187286 +70 69 0.6640539438999052 -0.2523447729765832 +70 70 0.7717637211193269 0.0 +71 67 0.6073874052644009 -0.03215704400504671 +71 68 0.4851092953849867 -0.08970196436891553 +71 69 0.9878271191479359 -0.5805528948425617 +71 70 0.3720403040574256 -0.6059430759508189 +71 71 0.8801532040624078 0.0 +72 68 0.05922743684125653 -0.7951073695987577 +72 69 0.5068721158545937 -0.06702567088785694 +72 70 0.5088545639656084 -0.17394831416175538 +72 71 0.5845975756830931 -0.8833495258202692 +72 72 1.4098823083864471 0.0 +73 69 0.7825127607673231 -0.14222134184800705 +73 70 0.9625924748695665 -0.04084540594480901 +73 71 0.137700578008229 -0.29810118021026666 +73 72 0.23911511233646687 -0.8513879283882564 +73 73 1.1487536047044462 0.0 +74 70 0.5597449278472233 -0.7937984302132138 +74 71 0.48336154299785306 -0.1508668332732681 +74 72 0.8082799891124365 -0.349153568729217 +74 73 0.5211852723078526 -0.6935420326919065 +74 74 0.8846792685810463 0.0 +75 71 0.3461408176412073 -0.3493202086217386 +75 72 0.17287594121187 -0.587268716527901 +75 73 0.6149488175139826 -0.5968244120889825 +75 74 0.03509798729701108 -0.9344884622589194 +75 75 0.17071140095284387 0.0 +76 72 0.8753849635919182 -0.3554341033363112 +76 73 0.19038516410974293 -0.7111743960363688 +76 74 0.6908479337238675 -0.07557536138961585 +76 75 0.79357977215732 -0.34918819986457206 +76 76 0.06836290041362392 0.0 +77 73 0.6057586774986071 -0.16194651661529602 +77 74 0.7829390683389087 -0.6596083104635688 +77 75 0.8948417727573921 -0.6475998362428668 +77 76 0.08811039702556456 -0.9699332062652161 +77 77 1.2019645438815225 0.0 +78 74 0.3276524984850877 -0.2333645147899157 +78 75 0.21269751291888817 -0.3639358618651728 +78 76 0.29674320174853497 -0.11574823689851998 +78 77 0.6253832385831407 -0.8658568041495456 +78 78 0.7498564807023109 0.0 +79 75 0.17844305142108263 -0.6152274235201981 +79 76 0.02333164235300944 -0.14494555744939053 +79 77 0.4398043177058276 -0.5242848718514269 +79 78 0.6321543856556305 -0.48259883183829466 +79 79 1.0825043648989223 0.0 +80 76 0.17432011179640972 -0.4258928840459526 +80 77 0.9531371777016018 -0.14714625386647406 +80 78 0.46503560320219794 -0.39846915067220745 +80 79 0.961998012003149 -0.6991970748389792 +80 80 0.09804594589843418 0.0 +81 77 0.17321217307226344 -0.8535206509823803 +81 78 0.37785225490961183 -0.48600942760984733 +81 79 0.38503751558161614 -0.6848945589979483 +81 80 0.9460878725268675 -0.7982590814433657 +81 81 1.4788039299629558 0.0 +82 78 0.025414472438308522 -0.38580491810117634 +82 79 0.021187179941524636 -0.12387387902624658 +82 80 0.7385000852144541 -0.5153629692185729 +82 81 0.5717559192804116 -0.20790439920583115 +82 82 0.9670562010221064 0.0 +83 79 0.04286565521576424 -0.295965053213323 +83 80 0.12617523914521278 -0.30240322627085536 +83 81 0.9891743182140595 -0.6554150503752343 +83 82 0.23315088041040255 -0.10146162423374216 +83 83 1.9005919801688593 0.0 +84 80 0.18802031585447088 -0.8322230626675315 +84 81 0.8622375631026598 -0.5369025659156258 +84 82 0.8709335071057409 -0.461386952096436 +84 83 0.12929491571267626 -0.739739809820747 +84 84 0.3277871553720004 0.0 +85 81 0.9618698614575117 -0.37804204113235906 +85 82 0.23503370216299468 -0.9139765385670922 +85 83 0.1446117085273778 -0.37832973216674404 +85 84 0.8602593837458649 -0.49472971030198376 +85 85 1.2189357449405962 0.0 +86 82 0.9412835277278335 -0.009256124159760848 +86 83 0.913060994867889 -0.6893220795678777 +86 84 0.9067707397991066 -0.4562692917441882 +86 85 0.9118183597635642 -0.560112588848674 +86 86 0.7763310571156046 0.0 +87 83 0.2676470918096636 -0.372429901435787 +87 84 0.07931788107531068 -0.414343893613872 +87 85 0.4303025387270094 -0.7304055685994616 +87 86 0.6169317450855366 -0.5876665743255994 +87 87 1.164540412724615 0.0 +88 84 0.8402907242616839 -0.975213943593378 +88 85 0.7517844282554876 -0.852699889437788 +88 86 0.07775011750473293 -0.6460137633633983 +88 87 0.25179694310781076 -0.30933877858067627 +88 88 0.9166805592562681 0.0 +89 85 0.47530878481391703 -0.8377799996125032 +89 86 0.7390747455759238 -0.7227138478147054 +89 87 0.9481439324582125 -0.4824603436155639 +89 88 0.367534793995383 -0.1996745641443598 +89 89 1.9790442553172936 0.0 +90 86 0.06648056319053108 -0.4648124567357558 +90 87 0.8803000815327402 -0.1426142109615296 +90 88 0.9387314314959471 -0.15617683099649238 +90 89 0.3388856629329313 -0.44977015198801384 +90 90 0.3524717226229388 0.0 +91 87 0.9793776672245442 -0.3439292886620575 +91 88 0.6116608443262402 -0.6304742211297978 +91 89 0.7070581906935722 -0.4988205104212672 +91 90 0.6297711330897506 -0.6822311744630055 +91 91 1.0740005476853183 0.0 +92 88 0.091935992438136 -0.12888444247289965 +92 89 0.496909500476272 -0.4435010271724992 +92 90 0.2376057252942294 -0.14793130872439764 +92 91 0.32020501504622656 -0.35816822574401275 +92 92 1.0514203832468236 0.0 +93 89 0.5829082490846058 -0.1444474161418099 +93 90 0.020707665645135043 -0.13264212689399557 +93 91 0.4823699830613223 -0.8970415223737133 +93 92 0.3000820027910036 -0.48490480551060267 +93 93 1.270084782264005 0.0 +94 90 0.5030045455841144 -0.42533819422394537 +94 91 0.4986119179202523 -0.6199085343418114 +94 92 0.49056076376336466 -0.07763446013771413 +94 93 0.6591869916587586 -0.9522848909318278 +94 94 1.328762804840821 0.0 +95 91 0.233560987978376 -0.441560788632939 +95 92 0.559302459818611 -0.6796428674160507 +95 93 0.9000951034535368 -0.46085835092782435 +95 94 0.1502204659234353 -0.42091674085349784 +95 95 0.9525155922256745 0.0 +96 92 0.5441256749578566 -0.1070794748840328 +96 93 0.17992040111661456 -0.5635096854622406 +96 94 0.8488088580786418 -0.27988253552620657 +96 95 0.8369495655343492 -0.9745551524849219 +96 96 1.2844269845411909 0.0 +97 93 0.13415926571976844 -0.501009733139541 +97 94 0.3819407152443133 -0.2692503803221499 +97 95 0.42019466092808766 -0.6953497164693209 +97 96 0.8725374676633839 -0.38030486722185564 +97 97 0.20586674513477887 0.0 +98 94 0.9745620495846692 -0.37176977456364957 +98 95 0.14407003579798605 -0.7675749801876341 +98 96 0.4833655810462796 -0.9483058422868255 +98 97 0.1880078310976907 -0.2925276463427078 +98 98 0.9583138840241363 0.0 +99 95 0.28209325786662276 -0.5395798672323201 +99 96 0.5626195454635149 -0.17254132532637567 +99 97 0.43170904175993463 -0.6431464906190103 +99 98 0.7206888729859035 -0.733591278261163 +99 99 0.7885819143194335 0.0 +100 96 0.04322715059928439 -0.13020733344109336 +100 97 0.6033475567364367 -0.14342952844055223 +100 98 0.34563576811242525 -0.8565601403542679 +100 99 0.3487727628076014 -0.5026271076896998 +100 100 1.550648568277455 0.0 +101 97 0.8023780509062619 -0.8280951916096284 +101 98 0.9066920773840009 -0.2528014214187676 +101 99 0.36812706647011917 -0.5330199182325384 +101 100 0.4030373766047911 -0.5067672996950776 +101 101 0.04261843595333614 0.0 +102 98 0.24598220827441175 -0.18120980016239874 +102 99 0.328708953212281 -0.14241511014560204 +102 100 0.6234585918271113 -0.3749557099808647 +102 101 0.03975956225133659 -0.806764946561735 +102 102 1.590276480544703 0.0 +103 99 0.8162983720707772 -0.26136809456932564 +103 100 0.9965205469922794 -0.9463140156612857 +103 101 0.24600328573030317 -0.8088647882764974 +103 102 0.23812007215715714 -0.2781550711097268 +103 103 0.2752984351354606 0.0 +104 100 0.5313823577846642 -0.8127805076109698 +104 101 0.5792959260378578 -0.8610329295551807 +104 102 0.5465585621291731 -0.19048279207991048 +104 103 0.46043714261027313 -0.6141825244005374 +104 104 1.2065321075290107 0.0 +105 101 0.6223875690479472 -0.8527833505483746 +105 102 0.008523183901942732 -0.7099148202760116 +105 103 0.1785367068353374 -0.9219440808649026 +105 104 0.20585570732160507 -0.5458145362282749 +105 105 0.8819077904797199 0.0 +106 102 0.9902863122788601 -0.8656643663658935 +106 103 0.0980650977911326 -0.017505802389152447 +106 104 0.6758454563576957 -0.33599364117628117 +106 105 0.4856966146647361 -0.7811610448495679 +106 106 0.4557597256986443 0.0 +107 103 0.5648193656851591 -0.16040347091709528 +107 104 0.40516547128909186 -0.6171081763579211 +107 105 0.6623377721068043 -0.6817667774556455 +107 106 0.2469253776349024 -0.22903547902504917 +107 107 1.5220134172654465 0.0 +108 104 0.024105246264017666 -0.6883207116594794 +108 105 0.6328810561462157 -0.008109239290583048 +108 106 0.2183011191819373 -0.14489849006955224 +108 107 0.04686396401386783 -0.24532363267847057 +108 108 0.4940342123037822 0.0 +109 105 0.8009521800282647 -0.9217901483928821 +109 106 0.1568669242928169 -0.7456319575222928 +109 107 0.2654224694971107 -0.7504672279171579 +109 108 0.5985333448726623 -0.03387317087605635 +109 109 0.9815884972497615 0.0 +110 106 0.9588109106927618 -0.6628357919797991 +110 107 0.14812041006330412 -0.5726404411424243 +110 108 0.6327460827149383 -0.13697463621690853 +110 109 0.5703333852658145 -0.45144970726046885 +110 110 0.48828867780085683 0.0 +111 107 0.13401135337153436 -0.5949264759577297 +111 108 0.42908653905836625 -0.5358659781480499 +111 109 0.01093057397353503 -0.8854403468957582 +111 110 0.21383453501766359 -0.8095901553263329 +111 111 0.020108480999578182 0.0 +112 108 0.6947292409302953 -0.3092959185507129 +112 109 0.5585202697758928 -0.519440843417803 +112 110 0.6767738200626507 -0.3550653242681052 +112 111 0.5311187319181698 -0.5707390952390967 +112 112 1.6330577543491736 0.0 +113 109 0.8623705807382219 -0.41932147273795795 +113 110 0.5971507282624402 -0.09976282059766639 +113 111 0.45537569140337886 -0.21057819478787088 +113 112 0.7676202243499292 -0.37127434958427075 +113 113 1.0884160208322944 0.0 +114 110 0.6613678049876058 -0.8465152675561395 +114 111 0.6472867695013496 -0.18897833302503975 +114 112 0.46564839378895717 -0.6274267190022893 +114 113 0.7269951863575944 -0.5066157415490102 +114 114 0.7306058476065531 0.0 +115 111 0.15676394532276428 -0.6982008836293415 +115 112 0.8568120511916515 -0.9349380304986314 +115 113 0.18448939702787848 -0.4417345845673535 +115 114 0.12289539567939545 -0.9175395111391826 +115 115 1.460824804549494 0.0 +116 112 0.03069877393535847 -0.912317844871185 +116 113 0.3135144206155551 -0.20507476400100566 +116 114 0.5212219281247908 -0.042887345850015746 +116 115 0.2221136786549054 -0.48093334536852894 +116 116 1.508299547984554 0.0 +117 113 0.22824365065277297 -0.11675644201441593 +117 114 0.040916530464566114 -0.46394433829311976 +117 115 0.776473165262423 -0.8802501349657843 +117 116 0.6889486679020098 -0.5921708119672516 +117 117 0.13630193957293835 0.0 +118 114 0.7625917447428994 -0.6346607543302488 +118 115 0.13716302968078364 -0.8778043335309903 +118 116 0.9122667957285763 -0.4675877428693408 +118 117 0.6158826844033379 -0.3371889045561064 +118 118 1.0293118564104995 0.0 +119 115 0.7221062876016048 -0.34233110186199334 +119 116 0.4974278902715743 -0.19068701210903993 +119 117 0.4668734950626683 -0.983373600614326 +119 118 0.7417277488715047 -0.9175832043221345 +119 119 1.703119817396758 0.0 +120 116 0.1809364646294136 -0.12618573199069683 +120 117 0.4128238681238564 -0.6377232420650405 +120 118 0.4059912933310098 -0.24960841699975855 +120 119 0.5579063844398665 -0.16903045302846031 +120 120 0.919671722555633 0.0 +121 117 0.7920505900255965 -0.0549634704562032 +121 118 0.7275703378213108 -0.7497248173592641 +121 119 0.5720155611076302 -0.14540587020364848 +121 120 0.4567801353926346 -0.9178426785618685 +121 121 1.8132452768346963 0.0 +122 118 0.470509577885843 -0.9568217066097526 +122 119 0.04229567714266014 -0.19462850941886312 +122 120 0.6170302134017117 -0.38276313044576427 +122 121 0.5723868416061685 -0.08138248757207467 +122 122 1.61698549816695 0.0 +123 119 0.7211990409520624 -0.9934898811516958 +123 120 0.06821808719854705 -0.24862866405458584 +123 121 0.8165701983381113 -0.12523044105278858 +123 122 0.28029398221682145 -0.24310209213248168 +123 123 0.6944025850716753 0.0 +124 120 0.7277471112349233 -0.35748721699946884 +124 121 0.2939234153086592 -0.3117336142834166 +124 122 0.8870271463161544 -0.6346168376640444 +124 123 0.8950429530858941 -0.21553072444027888 +124 124 1.5522400890437635 0.0 +125 121 0.5582354475346526 -0.9256143241790638 +125 122 0.80809815736524 -0.18097662695321093 +125 123 0.7246354177924306 -0.30992167231116474 +125 124 0.909537138193965 -0.17666377094700014 +125 125 0.7776010153027206 0.0 +126 122 0.9162001610314571 -0.2008569454798652 +126 123 0.7418588310390559 -0.34662842664876303 +126 124 0.9272270007020594 -0.6954243878726861 +126 125 0.8763057015052477 -0.8744617076579352 +126 126 0.2791325008184036 0.0 +127 123 0.2035842770754499 -0.33919481783498473 +127 124 0.7185692502081841 -0.7787770818496196 +127 125 0.24919003542959872 -0.6760184759798807 +127 126 0.33359633343620243 -0.0917725477807263 +127 127 1.7496229611911909 0.0 +128 124 0.49786136944975357 -0.08058874156090423 +128 125 0.3208261349771081 -0.3412749115307272 +128 126 0.6512525058008939 -0.6292103707598153 +128 127 0.21673396814309698 -0.18567858633636325 +128 128 1.1519986578804282 0.0 +129 125 0.7329970233581237 -0.24043589654209452 +129 126 0.5412482122540726 -0.1372981627292188 +129 127 0.6488540579363825 -0.5521557360248008 +129 128 0.28809826281780904 -0.6528100028518327 +129 129 0.643997512189513 0.0 +130 126 0.4945597744615273 -0.821728446388199 +130 127 0.8850039155698731 -0.3207707047944438 +130 128 0.941608297056527 -0.29066746505756236 +130 129 0.6126826277666017 -0.18153379227648525 +130 130 1.397974641698471 0.0 +131 127 0.4264617587775763 -0.3360252633678529 +131 128 0.0033363266820084503 -0.5592357489701156 +131 129 0.9853683747640947 -0.9302449691181528 +131 130 0.27826573330215787 -0.10660722775980602 +131 131 0.9195278254752934 0.0 +132 128 0.3996862943773556 -0.7714987846565742 +132 129 0.3591140902381539 -0.4078757789308659 +132 130 0.2393127470149895 -0.5474466497342776 +132 131 0.7113023089879781 -0.1623239759723304 +132 132 0.8006074277047366 0.0 +133 129 0.8828945077781878 -0.7916685500623826 +133 130 0.4147888038221089 -0.27836142232783145 +133 131 0.268923974481472 -0.26830998270852724 +133 132 0.9708635125142245 -0.3206915750268289 +133 133 1.9533372168409306 0.0 +134 130 0.882022833767019 -0.11975953654026861 +134 131 0.33521585008719823 -0.6156009697480285 +134 132 0.8667664998253183 -0.38558475402824877 +134 133 0.7290451542500201 -0.992857109948996 +134 134 0.7578973707295131 0.0 +135 131 0.11717988968976312 -0.9764335340554672 +135 132 0.4770344140793592 -0.34021739261283124 +135 133 0.9042889700565341 -0.685724914397548 +135 134 0.11455405639781979 -0.07179569087128046 +135 135 0.17280056342156458 0.0 +136 132 0.3682673058653323 -0.10052589617211005 +136 133 0.08040337785489138 -0.5636910729447281 +136 134 0.17085862473698377 -0.15110116263329765 +136 135 0.8881437877653356 -0.8064700042872907 +136 136 1.2369290826428994 0.0 +137 133 0.5549118644885229 -0.526868690818574 +137 134 0.8938902172074976 -0.6300671735346811 +137 135 0.2614424673056497 -0.7786444365710196 +137 136 0.2179273481348578 -0.5862927134973999 +137 137 0.8697102659124938 0.0 +138 134 0.18365614873723357 -0.5726724102971295 +138 135 0.6088764833485558 -0.8951295235804742 +138 136 0.35166885342268916 -0.543163796379584 +138 137 0.9035716571716049 -0.3685139067746005 +138 138 1.2578320042004358 0.0 +139 135 0.4233179632065087 -0.43330748781836326 +139 136 0.2730890947045779 -0.6406535810454228 +139 137 0.5935063357465243 -0.4267741812102609 +139 138 0.38324862035585416 -0.3768740323953421 +139 139 0.5382584783258479 0.0 +140 136 0.8799720002640277 -0.9099477143480363 +140 137 0.894904114391044 -0.9234695483166161 +140 138 0.9468526289521482 -0.4768153759007754 +140 139 0.9435918428461353 -0.525592581417447 +140 140 1.4607812517991485 0.0 +141 137 0.7936997476342991 -0.23945149077799566 +141 138 0.5978601771523774 -0.4266370460521224 +141 139 0.3549075068851413 -0.34628403716333034 +141 140 0.05955072762078506 -0.11381549124903434 +141 141 0.9430013262849475 0.0 +142 138 0.0424755017474332 -0.6183798732427491 +142 139 0.8281918400993277 -0.8529696877722415 +142 140 0.9455099345388985 -0.8586562695021603 +142 141 0.7159341187287382 -0.8594778015680503 +142 142 1.1669275719624588 0.0 +143 139 0.6150363356156271 -0.6471875499752754 +143 140 0.3147983658837584 -0.7567115778687746 +143 141 0.7577574486780273 -0.3821926194122427 +143 142 0.5227608589097142 -0.07345745879929066 +143 143 0.9615280865382474 0.0 +144 140 0.19195074563375514 -0.8122848800384328 +144 141 0.37718356410449305 -0.07077539224531704 +144 142 0.17129034008549404 -0.6998898864150572 +144 143 0.8352855075090803 -0.5298278627396142 +144 144 1.2241006440065407 0.0 +145 141 0.4873066079007081 -0.8936747359533808 +145 142 0.03839989427831059 -0.7444033998792031 +145 143 0.9753887490273612 -0.6453600190278753 +145 144 0.21818695317785608 -0.9408415482386808 +145 145 1.9426514216957633 0.0 +146 142 0.6770251570676932 -0.22815032940118896 +146 143 0.9212135580162176 -0.39689490895563007 +146 144 0.21917190063550784 -0.7515013939527599 +146 145 0.6991358217280597 -0.9098196583479755 +146 146 0.4623036031533907 0.0 +147 143 0.04384190121715692 -0.7904252502571679 +147 144 0.1994127436251799 -0.9909693572422021 +147 145 0.3724396400443184 -0.4474515681128667 +147 146 0.678479194950521 -0.8713469570476392 +147 147 1.5725465800344645 0.0 +148 144 0.6789339585569081 -0.6739799166205283 +148 145 0.8782354823081819 -0.10142455990206756 +148 146 0.9019715054834491 -0.805278852224366 +148 147 0.6192838707375561 -0.5227568908127305 +148 148 0.6970042701169141 0.0 +149 145 0.4992486985933726 -0.9357280197770583 +149 146 0.27003272084960606 -0.43179968139602476 +149 147 0.10513216682216742 -0.006221590295067525 +149 148 0.6454222089071346 -0.06716970333619032 +149 149 0.923929685525045 0.0 +150 146 0.14373113173858776 -0.23132892992779952 +150 147 0.33320379683355594 -0.40683708671729857 +150 148 0.9451159433747368 -0.2665410678284622 +150 149 0.7594611804709795 -0.871716104759459 +150 150 1.6828929827507904 0.0 +151 147 0.32475664618117805 -0.7822898597604998 +151 148 0.12166425243692969 -0.2509275145501979 +151 149 0.32293247011118664 -0.2977157071070502 +151 150 0.9265353665885427 -0.9497013132324565 +151 151 0.6447537567485628 0.0 +152 148 0.746988046816112 -0.8954876430382117 +152 149 0.5755183085919507 -0.4545841865430882 +152 150 0.6364438966825933 -0.528264543909257 +152 151 0.21397031108282027 -0.12057380625248748 +152 152 1.1124957489709721 0.0 +153 149 0.5762424972261545 -0.21848607617754445 +153 150 0.9598736493131119 -0.4611815172850897 +153 151 0.7607500701724561 -0.16962939231582252 +153 152 0.7333137534903986 -0.9882194379107622 +153 153 0.755904049364982 0.0 +154 150 0.6097544393624361 -0.6396270057203716 +154 151 0.5301496020923899 -0.7810671746698181 +154 152 0.02412797384113441 -0.15029161057066565 +154 153 0.009909902633485346 -0.41427848028773107 +154 154 0.12549148409940547 0.0 +155 151 0.014195694896510513 -0.9002809280129562 +155 152 0.7468297839668843 -0.2913515712079059 +155 153 0.4658653207451444 -0.9071628178026384 +155 154 0.9603699538444433 -0.2297174766718042 +155 155 1.6919455728741275 0.0 +156 152 0.6033946108352839 -0.3265031529665351 +156 153 0.6022806967427293 -0.5742241409359844 +156 154 0.45432005980767654 -0.15765155549931353 +156 155 0.0017216384212606073 -0.11381033591333412 +156 156 0.6333041771618231 0.0 +157 153 0.5816412037321393 -0.8630666275117039 +157 154 0.20450232788018763 -0.8455836303384253 +157 155 0.04052168777534049 -0.8745040275211656 +157 156 0.6861983460874012 -0.14306969333663844 +157 157 0.4694927264212918 0.0 +158 154 0.5791730599999566 -0.02877334674332177 +158 155 0.04362791798372079 -0.6213652173373273 +158 156 0.44504227469614777 -0.2932798879219227 +158 157 0.08273378031714118 -0.0035333383935305385 +158 158 0.25824978686103006 0.0 +159 155 0.10674348142088208 -0.4009265696308064 +159 156 0.9006401795390097 -0.8277414050275793 +159 157 0.034693778247471885 -0.08816535313108631 +159 158 0.8791887876590557 -0.06326574309926669 +159 159 1.6801741970389188 0.0 +160 156 0.04300882503904757 -0.9384229075609192 +160 157 0.028927088734996498 -0.18243393271032005 +160 158 0.2577897373328337 -0.01683637459354148 +160 159 0.5176850799602043 -0.8907154486896454 +160 160 1.749150397031889 0.0 +161 157 0.37262979544961305 -0.5914960490646378 +161 158 0.8776156439390561 -0.11299023062195968 +161 159 0.0482623572849713 -0.546097115928831 +161 160 0.28628546047502124 -0.7541039917743643 +161 161 1.1450604548310621 0.0 +162 158 0.5366379029429603 -0.6314889440901055 +162 159 0.17762629792702522 -0.8731356738766557 +162 160 0.4067157189177305 -0.26029772860409417 +162 161 0.052854820459053764 -0.27362804187082435 +162 162 1.986762393593932 0.0 +163 159 0.02726334281447418 -0.05196961904125852 +163 160 0.8661827757491732 -0.17138603708636335 +163 161 0.7507470071320658 -0.6795397958855713 +163 162 0.329934364780765 -0.18499728011627214 +163 163 1.0489221831666775 0.0 +164 160 0.2846745004561977 -0.7406924286557516 +164 161 0.08773980159370587 -0.21846521969557198 +164 162 0.781997387024433 -0.46337419661327106 +164 163 0.8434218596717227 -0.4593751440611461 +164 164 0.1725969410415047 0.0 +165 161 0.48367047341695135 -0.22879878501168383 +165 162 0.9696234096866566 -0.09057454913266005 +165 163 0.49867842257691286 -0.9736096085614357 +165 164 0.30473999573291344 -0.9213584133034587 +165 165 1.3979809199531616 0.0 +166 162 0.9180232290432898 -0.8944726044119619 +166 163 0.7003084494872227 -0.16860601399075537 +166 164 0.9413577407242378 -0.22988509118611233 +166 165 0.22304634535536771 -0.3018480966614866 +166 166 1.1100180680810698 0.0 +167 163 0.929613413360145 -0.5924468180927738 +167 164 0.4252736652356277 -0.7182222003096786 +167 165 0.34786762851943986 -0.4589227912262689 +167 166 0.7038231806105234 -0.43486659263167804 +167 167 1.8122509656717718 0.0 +168 164 0.0002731204800967557 -0.09162068310673022 +168 165 0.7802656254108445 -0.9579058806573759 +168 166 0.3351441415783438 -0.7020859452425232 +168 167 0.959386796083041 -0.7441996753873933 +168 168 1.9388396481082444 0.0 +169 165 0.16059450656754026 -0.06617386647146295 +169 166 0.5138424677208988 -0.8276824959061955 +169 167 0.32656674318497503 -0.286012588109646 +169 168 0.24582189488263362 -0.19254225812494818 +169 169 1.2179789032664894 0.0 +170 166 0.7873089215384826 -0.5079630526827389 +170 167 0.9884747160511719 -0.689466816909966 +170 168 0.5885178404568352 -0.35821406346086593 +170 169 0.9576335242633973 -0.3749405899859687 +170 170 0.3845044540697562 0.0 +171 167 0.23896404491273027 -0.8428424995895104 +171 168 0.5068513405678098 -0.8278772982555949 +171 169 0.6041315514397166 -0.7746075347646033 +171 170 0.05426011302152789 -0.01998783569540996 +171 171 1.0676279251500058 0.0 +172 168 0.3465839521597025 -0.7360817336365418 +172 169 0.6347512254945581 -0.8566819462132942 +172 170 0.4276219395904194 -0.015152107101262913 +172 171 0.28919674605718926 -0.267744017815684 +172 172 0.9613106896598731 0.0 +173 169 0.273013715803856 -0.8542745243521114 +173 170 0.16376782724728667 -0.9697372188024054 +173 171 0.3063870032336996 -0.7135904317554295 +173 172 0.16070449024830613 -0.8064993255395443 +173 173 0.20630051458529342 0.0 +174 170 0.009094172824022806 -0.6349653454625096 +174 171 0.7856235764645817 -0.29534633612584416 +174 172 0.051219875047730956 -0.7714082704979962 +174 173 0.422377519658795 -0.25660494734485373 +174 174 1.61038919744527 0.0 +175 171 0.27706096864012586 -0.6756555241965368 +175 172 0.7780037946420097 -0.6593098226571062 +175 173 0.6576143903030159 -0.7609229953393394 +175 174 0.03299898992435357 -0.3987592726816154 +175 175 0.7494668694242168 0.0 +176 172 0.2707176309721363 -0.3385423155150048 +176 173 0.41216697720501894 -0.13366166499040688 +176 174 0.61651193089303 -0.8671003123674387 +176 175 0.7692111978972381 -0.0812204226220059 +176 176 1.409381930183114 0.0 +177 173 0.49231816232686487 -0.9452531856944582 +177 174 0.35794245709414274 -0.2298780445171419 +177 175 0.9245870053615033 -0.7892585949802454 +177 176 0.7987235761143049 -0.9089176966920663 +177 177 1.719289954557862 0.0 +178 174 0.4409635368342625 -0.22245473776811764 +178 175 0.32514648747492325 -0.6240451312334732 +178 176 0.3672159167901172 -0.42271903349433626 +178 177 0.7955076014032216 -0.8533128058012102 +178 178 0.1338891732024623 0.0 +179 175 0.30754956823171753 -0.9409222340297945 +179 176 0.6705937898879455 -0.1866132598570548 +179 177 0.9612486582328194 -0.07990321919812426 +179 178 0.6821059974028082 -0.08865011586912563 +179 179 0.17565333507570657 0.0 +180 176 0.4768584187268917 -0.1952442532934645 +180 177 0.24847255099531151 -0.7803582112091312 +180 178 0.5912236877176812 -0.14823401327533958 +180 179 0.7084675197253462 -0.30725767775774704 +180 180 0.168578006761549 0.0 +181 177 0.16203901338698157 -0.2700247215991207 +181 178 0.7705553984517582 -0.41836214127406024 +181 179 0.8576179579954122 -0.631683754547175 +181 180 0.20798640181948425 -0.584688404667923 +181 181 1.2449686584431363 0.0 +182 178 0.3116904883154983 -0.6993012937350634 +182 179 0.7412739167563813 -0.26197974445750805 +182 180 0.4368662830393518 -0.8819157035127577 +182 181 0.9491478369155502 -0.8089498838841338 +182 182 0.7452869758608838 0.0 +183 179 0.49744455301836 -0.8585979701594267 +183 180 0.5818048979010404 -0.8978750540196364 +183 181 0.5719771825456769 -0.9990790980576674 +183 182 0.02590797494147734 -0.7533975382646999 +183 183 1.4087284139851117 0.0 +184 180 0.004195186136556672 -0.8606808507495943 +184 181 0.5076733523062059 -0.7081990628367129 +184 182 0.30194055597264924 -0.568061259363668 +184 183 0.42903901771126995 -0.48500450931014816 +184 184 1.2348767729222696 0.0 +185 181 0.5851196614272848 -0.11320287093064396 +185 182 0.9701193799631554 -0.5470059415713405 +185 183 0.6095629367572198 -0.7407989114014119 +185 184 0.7814424904812002 -0.4470378904283555 +185 185 0.1609189356510241 0.0 +186 182 0.10244696687079458 -0.44236308699251636 +186 183 0.43157526384709244 -0.8801840694872071 +186 184 0.151968236570442 -0.23668068832380662 +186 185 0.12963339269234708 -0.3630876137869029 +186 186 1.0201524303122922 0.0 +187 183 0.9300079516859646 -0.07275132250766159 +187 184 0.6056495456763444 -0.4488539646161621 +187 185 0.6500111867479561 -0.6200940539758171 +187 186 0.6161303088491767 -0.5137574100444764 +187 187 0.17619720966356578 0.0 +188 184 0.07739769667150453 -0.10612483115156357 +188 185 0.5492774988980446 -0.9981381041594186 +188 186 0.5721374558402195 -0.6140129633814377 +188 187 0.5752383256693927 -0.19854323476577207 +188 188 1.3197528724059413 0.0 +189 185 0.4931332581851504 -0.6779702106658042 +189 186 0.14587863985640492 -0.2439666382863973 +189 187 0.15555548906332373 -0.9033726897325975 +189 188 0.5506064150182317 -0.8104524525622544 +189 189 1.0771554877966987 0.0 +190 186 0.6545189959288845 -0.5270055727845838 +190 187 0.2438943084159786 -0.23964805784880394 +190 188 0.9985472460763201 -0.7125465743935153 +190 189 0.17532570735140163 -0.8403895115079539 +190 190 1.62841818623123 0.0 +191 187 0.9683479152547773 -0.48190272017069413 +191 188 0.9777448549607803 -0.9186178990389479 +191 189 0.3679980246131044 -0.19008411784532275 +191 190 0.8140342804748611 -0.12029907335817425 +191 191 0.9508356093426604 0.0 +192 188 0.06911570956313884 -0.7075816215510936 +192 189 0.4112523427492428 -0.9763304696345245 +192 190 0.8569056582620475 -0.41952158214311497 +192 191 0.6500356793800913 -0.05412327079618573 +192 192 0.02297972933940362 0.0 +193 189 0.24556489507406654 -0.3486231496131763 +193 190 0.8133191234723702 -0.8445499841749384 +193 191 0.4381171163712121 -0.6741890846391995 +193 192 0.5984501298154358 -0.6543959884300408 +193 193 0.148103288181346 0.0 +194 190 0.8940901844702204 -0.6928276013953941 +194 191 0.32493266699624257 -0.15039921822385982 +194 192 0.17164129326071953 -0.040419972827835826 +194 193 0.891242992499248 -0.6781161779195456 +194 194 0.5374399877263876 0.0 +195 191 0.6993526483528509 -0.6697279826168506 +195 192 0.947294011503979 -0.08518665997905528 +195 193 0.5297172877236285 -0.3720028655476485 +195 194 0.1356862430344905 -0.38174921128628236 +195 195 0.8975762927622626 0.0 +196 192 0.4624990644084328 -0.9802801394706416 +196 193 0.595338809286565 -0.06634765970713818 +196 194 0.9891102135802824 -0.5461271722459785 +196 195 0.3442417514553864 -0.8742556964440076 +196 196 0.7584694394086051 0.0 +197 193 0.5723765946904772 -0.29943080918163356 +197 194 0.752177967195544 -0.17631358565406274 +197 195 0.2971244892645162 -0.03114259992505297 +197 196 0.7052567891043953 -0.8449940164949857 +197 197 1.1752058439510915 0.0 +198 194 0.29217546936224637 -0.8450802806636108 +198 195 0.13063616034690428 -0.7658449417493394 +198 196 0.989633953921644 -0.7806799421392245 +198 197 0.3760044127174874 -0.2573020582876151 +198 198 1.3157104992764783 0.0 +199 195 0.70911975014929 -0.34837695387818524 +199 196 0.7842601342730408 -0.6250986490993942 +199 197 0.629518708719504 -0.9332440366249888 +199 198 0.3681104104666356 -0.9723328401665458 +199 199 1.702651562563625 0.0 +200 196 0.08616554303453261 -0.3977428616436699 +200 197 0.10041014935152714 -0.34732320504678416 +200 198 0.9333145100235151 -0.3901331883302015 +200 199 0.24077392413479193 -0.7885386587631377 +200 200 0.8915986810598029 0.0 +201 197 0.6640483007411703 -0.5603083650271078 +201 198 0.6480182930753631 -0.1481691037355216 +201 199 0.619345258667704 -0.7212757104268469 +201 200 0.15441430556084235 -0.4799892904601355 +201 201 0.691322505428128 0.0 +202 198 0.4622360981465612 -0.2239507666490066 +202 199 0.9602176115443224 -0.8996380278212781 +202 200 0.7959069215789315 -0.13464745240202403 +202 201 0.35597506713989147 -0.2235502731955341 +202 202 0.3194350182127481 0.0 +203 199 0.10700777710329845 -0.6349239712888919 +203 200 0.9219947667931351 -0.32270750615040344 +203 201 0.41804861984082375 -0.6523557668283779 +203 202 0.9704746809068672 -0.11950950953081929 +203 203 0.4861958018109087 0.0 +204 200 0.4513159608491666 -0.8450850247157548 +204 201 0.12715952796151964 -0.2905965661708034 +204 202 0.006694203620821848 -0.23861959087852413 +204 203 0.7856005932488713 -0.38330161373556093 +204 204 1.2825015120297971 0.0 +205 201 0.7502941534989611 -0.6178199530805359 +205 202 0.8879443490716686 -0.06840168737905528 +205 203 0.5448257906171682 -0.3218874958441734 +205 204 0.13148486227070966 -0.6991427745228912 +205 205 0.6083325687627119 0.0 +206 202 0.5799344865530641 -0.5115701520075645 +206 203 0.2588163719389165 -0.4354266755605084 +206 204 0.7407058428959631 -0.7841585584883181 +206 205 0.5557472032250792 -0.46364358290465246 +206 206 0.4086526048313166 0.0 +207 203 0.37733564285313526 -0.3952203092643788 +207 204 0.5820982120394068 -0.011344286532620984 +207 205 0.19497076057380802 -0.9311232748399925 +207 206 0.7212621172437771 -0.1721835854704178 +207 207 0.30711685840191705 0.0 +208 204 0.6669595318339196 -0.12292138921318585 +208 205 0.5774455887247618 -0.6034261487494782 +208 206 0.8183188669026702 -0.48650954999730833 +208 207 0.9331147666654892 -0.16493262326183533 +208 208 1.4250293187981131 0.0 +209 205 0.6979790457965266 -0.8492628566947531 +209 206 0.3612088949137141 -0.6115240550479821 +209 207 0.8067851141877224 -0.6825563208961806 +209 208 0.5343187862545039 -0.09545428419905388 +209 209 0.4515508808622428 0.0 +210 206 0.04809453860861268 -0.039334654823574344 +210 207 0.602496844161274 -0.689712936874958 +210 208 0.5614804846923404 -0.5978842727615469 +210 209 0.5368765297723577 -0.4686828528350713 +210 210 1.1585029413522885 0.0 +211 207 0.1993524802973189 -0.6365252665638161 +211 208 0.31375848663141714 -0.9014998613577916 +211 209 0.7314721166988827 -0.9760291027706104 +211 210 0.744559504558346 -0.8430541591428505 +211 211 0.6971824057221596 0.0 +212 208 0.14425823564006113 -0.36217428726372825 +212 209 0.024020197653021103 -0.49943210959482465 +212 210 0.7140469236114727 -0.18517434488655615 +212 211 0.8294461679109169 -0.04030286261049454 +212 212 1.087141486765332 0.0 +213 209 0.7436503593282836 -0.044891767935308025 +213 210 0.7099807022601214 -0.5398393037179197 +213 211 0.5609227254854033 -0.49912698266310473 +213 212 0.8024756536743102 -0.81540989911118 +213 213 1.5770696173504086 0.0 +214 210 0.8440286525141186 -0.6358048484288431 +214 211 0.8700516775676086 -0.7819648590068102 +214 212 0.8561826263121601 -0.7094676554002729 +214 213 0.5379148281967305 -0.8183323440538263 +214 214 0.10019274739171413 0.0 +215 211 0.42921576551406193 -0.1369957461148288 +215 212 0.7447791626756664 -0.8090246726821765 +215 213 0.46097107780567126 -0.6497757917241167 +215 214 0.7966057870274879 -0.7851132655625916 +215 215 0.912475713415061 0.0 +216 212 0.009854360636042059 -0.7116975849787684 +216 213 0.086402522965071 -0.9120852884268816 +216 214 0.3442928709475913 -0.8275991163772098 +216 215 0.4226154279024462 -0.7660693738606329 +216 216 0.9686244888285958 0.0 +217 213 0.4173643529522716 -0.8461885676004474 +217 214 0.9844738139074288 -0.4975843896982868 +217 215 0.09397908479890982 -0.40258152180528495 +217 216 0.5107620825891448 -0.9093137255543525 +217 217 1.186385927857351 0.0 +218 214 0.9423139931012381 -0.506605038462582 +218 215 0.20778303909101992 -0.27154056108198765 +218 216 0.2932819426654757 -0.5402016824402337 +218 217 0.24660035136498715 -0.5564998165264144 +218 218 0.07549962507607932 0.0 +219 215 0.19296769763050148 -0.2534780854454268 +219 216 0.7729526171585032 -0.09446785495594956 +219 217 0.7462315481232763 -0.9555487835235406 +219 218 0.0579517571014353 -0.21321117910060505 +219 219 1.327915584406355 0.0 +220 216 0.6140569238538748 -0.804653002745385 +220 217 0.15756935137944716 -0.9129275566774085 +220 218 0.7675568289864155 -0.2291581204810813 +220 219 0.49250156656693744 -0.5661053570828795 +220 220 0.2813769292366415 0.0 +221 217 0.9025174853024794 -0.972798387130392 +221 218 0.2511092775490581 -0.24295919432900082 +221 219 0.4378889684795856 -0.9182179293748185 +221 220 0.5480500138487386 -0.7035768236235377 +221 221 1.5155095266325624 0.0 +222 218 0.01571216554281607 -0.04124076137095134 +222 219 0.9311818829890874 -0.04975460253838593 +222 220 0.29681880286122597 -0.8458698492054821 +222 221 0.1228843631533677 -0.06446090724778075 +222 222 0.26083079698256406 0.0 +223 219 0.7742066261117062 -0.37055943876916975 +223 220 0.7362520455919758 -0.7829019209770768 +223 221 0.23644911232887356 -0.3216248008057949 +223 222 0.1936727053041879 -0.03811480335038642 +223 223 0.7895016544767088 0.0 +224 220 0.9918522715830876 -0.474127370717885 +224 221 0.7911807951082197 -0.3390450927706754 +224 222 0.43597888111004957 -0.8111477971122 +224 223 0.27789800430811973 -0.6560834281984724 +224 224 1.6578105018431026 0.0 +225 221 0.5117843776342615 -0.5555727592182546 +225 222 0.24244584129513236 -0.8084133892884261 +225 223 0.7735954111407108 -0.8243626487749044 +225 224 0.06737239917062943 -0.2620319451660278 +225 225 1.0424117953153202 0.0 +226 222 0.18428046159770028 -0.546857783926701 +226 223 0.778971913153303 -0.3030125828879684 +226 224 0.99031409342351 -0.4835139096292077 +226 225 0.80981198632922 -0.5150163736653425 +226 226 0.930609258884888 0.0 +227 223 0.613702213855341 -0.20844899225694324 +227 224 0.5954705405873149 -0.6384831173077667 +227 225 0.15425104946340384 -0.788223880855468 +227 226 0.04097762052361864 -0.34240208244705284 +227 227 1.1319511454232007 0.0 +228 224 0.63940292541202 -0.04215572715482585 +228 225 0.04956596821750825 -0.2924841419253531 +228 226 0.39020638003885366 -0.5100166093061168 +228 227 0.6150665908172694 -0.29787175420096446 +228 228 0.013858609711130843 0.0 +229 225 0.9675284563099948 -0.3978918565771561 +229 226 0.6487170435108344 -0.28764033794777377 +229 227 0.5425903807626946 -0.7698969362663014 +229 228 0.6939643050865641 -0.8329226522777419 +229 229 1.8445364263571207 0.0 +230 226 0.5782466888781557 -0.5071015226063968 +230 227 0.7997215436546495 -0.06549051469065814 +230 228 0.22408849344769965 -0.7595708914999824 +230 229 0.2242444825709854 -0.9804914428821401 +230 230 0.5085641241566539 0.0 +231 227 0.508102456609791 -0.2221916942673402 +231 228 0.012370578617593608 -0.6701672541081738 +231 229 0.9637492147716347 -0.3316491581626897 +231 230 0.6352642877383251 -0.2171922174301495 +231 231 1.0959836030066565 0.0 +232 228 0.35432611254974 -0.8517411226133322 +232 229 0.04125058481450272 -0.9329492933623766 +232 230 0.7383027110723812 -0.30339944775094585 +232 231 0.4822301678117965 -0.4342849104675972 +232 232 0.6403547582739058 0.0 +233 229 0.938367967067255 -0.8224716168250998 +233 230 0.3361121437498674 -0.5321513853204334 +233 231 0.5905530293987428 -0.6982112571174223 +233 232 0.37767918038118753 -0.027129769876907406 +233 233 0.9399545541977272 0.0 +234 230 0.33984140266793483 -0.1931553860535321 +234 231 0.6348628986182779 -0.24476138619669008 +234 232 0.7824465154320783 -0.8450695685301535 +234 233 0.4085962868024664 -0.09702527101219649 +234 234 1.0166046625995757 0.0 +235 231 0.8354496064913401 -0.969852401535629 +235 232 0.461916881991673 -0.4870279714839232 +235 233 0.30277458914054045 -0.8429253886897715 +235 234 0.48676670899617225 -0.868689150701947 +235 235 1.0283672335812726 0.0 +236 232 0.6927757628050983 -0.36641682563176436 +236 233 0.44532049064714885 -0.5373937324405126 +236 234 0.29730427177830887 -0.41492358931713813 +236 235 0.756294478770047 -0.8599969346748849 +236 236 0.6701856477266075 0.0 +237 233 0.3796492005051839 -0.8048612937873454 +237 234 0.40312668677954555 -0.8865984713029962 +237 235 0.9755129099545143 -0.31284544199866005 +237 236 0.20036066641734274 -0.6452649975333866 +237 237 0.8498562809400683 0.0 +238 234 0.006353619400054633 -0.3997521957971374 +238 235 0.672987324087051 -0.004281048819168798 +238 236 0.8322566285420399 -0.8596557145975647 +238 237 0.740661117270127 -0.13955557647515127 +238 238 1.9854688747577542 0.0 +239 235 0.4059487922414161 -0.34325505616950047 +239 236 0.877197909591441 -0.21196578717877224 +239 237 0.31130093587959273 -0.9633314726629482 +239 238 0.9801248523162966 -0.9049166157751136 +239 239 1.2382332256020419 0.0 +240 236 0.6033033214967016 -0.6109246222667429 +240 237 0.05530350219855529 -0.8741855378454231 +240 238 0.648492594751345 -0.49793702834270215 +240 239 0.7583168062494149 -0.4823566502469623 +240 240 0.07878976288335093 0.0 +241 237 0.4983635315266943 -0.305009856798405 +241 238 0.9682295863025027 -0.3224729903786313 +241 239 0.9082183571989882 -0.256979153302931 +241 240 0.3742136580129243 -0.18394376901128806 +241 241 0.8929899262277587 0.0 +242 238 0.8346569442055333 -0.7601867790166676 +242 239 0.2249203805732224 -0.6950437158464685 +242 240 0.7526020003423356 -0.12988001277611694 +242 241 0.3238225335845246 -0.33322240937126235 +242 242 1.727462813090923 0.0 +243 239 0.35476118390075295 -0.4527640838763639 +243 240 0.7591699608366617 -0.6518493447013197 +243 241 0.7381432563005063 -0.377359540466662 +243 242 0.3113880497577056 -0.7959375078207093 +243 243 0.531278682457007 0.0 +244 240 0.8112403536511108 -0.9010433665322264 +244 241 0.4418415442497895 -0.7082072548451943 +244 242 0.14658174040007943 -0.7516685039470177 +244 243 0.28193254686785474 -0.8030590577554527 +244 244 1.7743791981454913 0.0 +245 241 0.08281699640983498 -0.930217588337888 +245 242 0.5151832957574115 -0.3816625277571414 +245 243 0.5865189093580937 -0.1634201952724399 +245 244 0.36833850129505585 -0.6345734184486139 +245 245 1.4416475711558738 0.0 +246 242 0.5207530846763655 -0.7640005115265305 +246 243 0.510097710141314 -0.9260055692475522 +246 244 0.9903864428247324 -0.13581257859643237 +246 245 0.6678713255054962 -0.33813700714897976 +246 246 0.26014953776378036 0.0 +247 243 0.6575219839361002 -0.38088122090870913 +247 244 0.14465447842282242 -0.7244255723058278 +247 245 0.27270588118695405 -0.6662716653751457 +247 246 0.6689420154590588 -0.2924592017814922 +247 247 0.1751799322447083 0.0 +248 244 0.9239624017462322 -0.7898712913797656 +248 245 0.0672982303529982 -0.40254574820962374 +248 246 0.012298264706943618 -0.819406674114885 +248 247 0.4564126806111377 -0.5905669800477813 +248 248 1.3977189874459135 0.0 +249 245 0.2987032649145036 -0.3339264313461311 +249 246 0.3916955622909284 -0.12665599196113664 +249 247 0.5558248637544468 -0.9574715021052913 +249 248 0.5468682792664002 -0.8766853151072082 +249 249 0.5626258755752966 0.0 +250 246 0.4394000863541182 -0.480677425258906 +250 247 0.8467905172465797 -0.4742851990515846 +250 248 0.9543722544832562 -0.8238185314056322 +250 249 0.8373528601325193 -0.28973919973497064 +250 250 0.6890929682768423 0.0 +251 247 0.6762494267374438 -0.35799011156101246 +251 248 0.8477843762535774 -0.3599440476622128 +251 249 0.24578259890998744 -0.23618602032714253 +251 250 0.95176076178918 -0.8362223111365733 +251 251 0.717422166183068 0.0 +252 248 0.9220735254000207 -0.7969356213476989 +252 249 0.9014902542860653 -0.6091056369683769 +252 250 0.621878295796954 -0.5527799286447672 +252 251 0.6485205294113717 -0.42915266284119735 +252 252 0.9637262565477243 0.0 +253 249 0.42009203167605036 -0.8832384930272423 +253 250 0.43313086331037165 -0.057737468526309565 +253 251 0.28839698079237597 -0.20161200702865067 +253 252 0.636238973928563 -0.6750159725758995 +253 253 1.4619937492824968 0.0 +254 250 0.37332423128382664 -0.1007010286648724 +254 251 0.1503742507841347 -0.5177554705801335 +254 252 0.5007613732699555 -0.7950637586601362 +254 253 0.43241927465809127 -0.50129190694347 +254 254 1.0233379748533198 0.0 +255 251 0.8414705965735798 -0.4339319173160615 +255 252 0.5299661878658627 -0.5179794390400045 +255 253 0.16393286954320963 -0.9586945237509589 +255 254 0.7274070749516975 -0.34544215348979734 +255 255 0.4926722499080729 0.0 +256 252 0.5048315563058061 -0.9290824713378029 +256 253 0.8949059731248792 -0.7550413092139174 +256 254 0.18336149538396185 -0.0954832590509248 +256 255 0.6825209153098727 -0.6954609779793235 +256 256 0.7383898735649581 0.0 diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index ab8ac9802..9cceed8bc 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -257,10 +257,11 @@ add_custom_target( tests_unit "--test-bin-dir" "\"${CMAKE_CURRENT_BINARY_DIR}\"" "--test-out-dir" "\"${CMAKE_CURRENT_BINARY_DIR}/output\"" "--output-verification-dir" "\"${CMAKE_CURRENT_SOURCE_DIR}/output_verification\"" + "--test-data-dir" "\"${CMAKE_CURRENT_SOURCE_DIR}/test_data\"" WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" DEPENDS build_tests_category_unit # add dependency on this target - # to automatically build before running + # to automatically build before running COMMAND_EXPAND_LISTS USES_TERMINAL ) From 086e4de47ad06d1251196f1899acea1098b06272 Mon Sep 17 00:00:00 2001 From: "Albert-Jan N. Yzelman" Date: Wed, 27 Apr 2022 13:14:09 +0200 Subject: [PATCH 14/22] Remove external data location after having moved associated original data to repo --- tools/downloadDatasets.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/downloadDatasets.sh b/tools/downloadDatasets.sh index d4d2c30ea..81ca2e131 100755 --- a/tools/downloadDatasets.sh +++ b/tools/downloadDatasets.sh @@ -93,7 +93,6 @@ if [[ "$REPLY" = "yes" ]]; then downloadSS "west0497" "https://suitesparse-collection-website.herokuapp.com/MM/HB/west0497.tar.gz" downloadSS "gyro_m" "https://suitesparse-collection-website.herokuapp.com/MM/Oberwolfach/gyro_m.tar.gz" downloadSS "dwt_59" "https://suitesparse-collection-website.herokuapp.com/MM/HB/dwt_59.tar.gz" - downloadSS "rndHermit256.mtx" "https://gitlab.com/denis.jelovina/hermitian_test_matrix/-/raw/main/rndHermit256.mtx" downloadSN "cit-HepTh" downloadSN "facebook_combined" echo "" From 1e0fda3592d9604a52a40119b9e169b21f2cae1d Mon Sep 17 00:00:00 2001 From: "Albert-Jan N. Yzelman" Date: Wed, 27 Apr 2022 14:12:14 +0200 Subject: [PATCH 15/22] Revert tools/downloadDatasets.sh to target branch version at head --- tools/downloadDatasets.sh | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/tools/downloadDatasets.sh b/tools/downloadDatasets.sh index 81ca2e131..2585ae103 100755 --- a/tools/downloadDatasets.sh +++ b/tools/downloadDatasets.sh @@ -22,16 +22,9 @@ downloadSS () { wget ${2} || exit 1 fi if [ ! -f ${1}/${1}.mtx ]; then - if [ -f ${1}.tar.gz ]; then - tar xf ${1}.tar.gz || exit 1 - elif [ -f ${1}.gz ]; then - gzip -d ${1}.gz || exit 1 - elif [ -f ${1}.mtx.gz ]; then - gzip -d ${1}.mtx.gz || exit 1 - fi - else - ln ${1}/${1}.mtx . || exit 1 + tar xf ${1}.tar.gz || exit 1 fi + ln ${1}/${1}.mtx ./ || exit 1 fi } From 7a40721fa1ec361bbc03c133f807b2aae7712f1c Mon Sep 17 00:00:00 2001 From: "Albert-Jan N. Yzelman" Date: Wed, 27 Apr 2022 16:07:35 +0200 Subject: [PATCH 16/22] Revert hpcg/system_building_utils.hpp to latest state in develop --- include/graphblas/algorithms/hpcg/system_building_utils.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/graphblas/algorithms/hpcg/system_building_utils.hpp b/include/graphblas/algorithms/hpcg/system_building_utils.hpp index 2ac5ddfe5..11adf82c1 100644 --- a/include/graphblas/algorithms/hpcg/system_building_utils.hpp +++ b/include/graphblas/algorithms/hpcg/system_building_utils.hpp @@ -80,7 +80,7 @@ namespace grb { * @return grb::SUCCESS if every GraphBLAS operation (to generate vectors and matrices) succeeded, * otherwise the first unsuccessful return value */ - template< std::size_t DIMS, typename T > + template< std::size_t DIMS, typename T = double > grb::RC build_hpcg_system( std::unique_ptr< grb::algorithms::hpcg_data< T, T, T > > & holder, hpcg_system_params< DIMS, T > & params ) { // n is the system matrix size const std::size_t n { std::accumulate( params.physical_sys_sizes.cbegin(), params.physical_sys_sizes.cend(), 1UL, std::multiplies< std::size_t >() ) }; @@ -121,7 +121,7 @@ namespace grb { std::size_t coarser_size { std::accumulate( coarser_sizes.cbegin(), coarser_sizes.cend(), 1UL, std::multiplies< std::size_t >() ) }; std::size_t previous_size { std::accumulate( previous_sizes.cbegin(), previous_sizes.cend(), 1UL, std::multiplies< std::size_t >() ) }; // build data structures for new level - grb::algorithms::multi_grid_data< T, T > * new_coarser { new grb::algorithms::multi_grid_data< T, T >( coarser_size, previous_size ) }; + grb::algorithms::multi_grid_data< double, double > * new_coarser { new grb::algorithms::multi_grid_data< double, double >( coarser_size, previous_size ) }; // install coarser level immediately to cleanup in case of build error *coarser = new_coarser; // initialize coarsener matrix, system matrix and diagonal vector for the coarser level From ebeae927ae30b7b9315b7daab47057c6cf3b67e3 Mon Sep 17 00:00:00 2001 From: "Albert-Jan N. Yzelman" Date: Wed, 27 Apr 2022 16:21:38 +0200 Subject: [PATCH 17/22] Various small code style fixes and removing one superfluous include --- .../utils/parser/MatrixFileIterator.hpp | 24 ++++-- .../utils/parser/MatrixFileReader.hpp | 81 ++++++++++++------- 2 files changed, 71 insertions(+), 34 deletions(-) diff --git a/include/graphblas/utils/parser/MatrixFileIterator.hpp b/include/graphblas/utils/parser/MatrixFileIterator.hpp index 55c262b90..7dd125d56 100644 --- a/include/graphblas/utils/parser/MatrixFileIterator.hpp +++ b/include/graphblas/utils/parser/MatrixFileIterator.hpp @@ -51,6 +51,7 @@ #include #endif + namespace grb { namespace utils { @@ -69,14 +70,18 @@ namespace grb { class MatrixFileIterator { template< typename X1, typename X2 > - friend std::ostream & operator<<( std::ostream &, const MatrixFileIterator< X1, X2 > & ); + friend std::ostream & operator<<( + std::ostream &, const MatrixFileIterator< X1, X2 > & ); private: /** The output type of the base iterator. */ typedef std::pair< std::pair< S, S >, T > OutputType; - /** Iterators will retrieve this many lines at a time from the input file. */ + /** + * Iterators will retrieve this many lines at a time from the input + * file. + */ static constexpr size_t buffer_size = grb::config::PARSER::bsize(); /** The nonzero buffer. */ @@ -97,7 +102,10 @@ namespace grb { /** Whether the \a infile stream \em and \a buffer have been depleted. */ bool ended; - /** Whether the first fill of the buffer is held until the first dereference of this iterator is taking place. */ + /** + * Whether the first fill of the buffer is held until the first + * dereference of this iterator is taking place. + */ bool started; /** Whether the smmetric counterpart of the current nonzero was output. */ @@ -106,10 +114,16 @@ namespace grb { /** A function to apply to convert input values on the fly. */ std::function< void( T & ) > converter; - /** In case we are reading from a pattern matrix, which value should substitute a nonzero. */ + /** + * In case we are reading from a pattern matrix, which value should + * substitute a nonzero. + */ const T patternValue; - /** Strips comments and possible MatrixMarket header from input stream start. */ + /** + * Strips comments and possible MatrixMarket header from input stream + * start. + */ void preprocess() { #ifdef _DEBUG std::cout << "\t In MatrixFileIterator::preprocess()\n"; diff --git a/include/graphblas/utils/parser/MatrixFileReader.hpp b/include/graphblas/utils/parser/MatrixFileReader.hpp index 9f3efea1d..9e7cc6ea1 100644 --- a/include/graphblas/utils/parser/MatrixFileReader.hpp +++ b/include/graphblas/utils/parser/MatrixFileReader.hpp @@ -31,22 +31,28 @@ #include "MatrixFileIterator.hpp" #include "MatrixFileProperties.hpp" #include "MatrixFileReaderBase.hpp" -#include "graphblas/utils/iscomplex.hpp" + namespace grb { + namespace utils { template< typename T, typename S = size_t > class MatrixFileReader : public internal::MatrixFileReaderBase< T, S > { - static_assert( std::is_integral< S >::value, "The template parameter S to MatrixFileReader must be integral." ); + static_assert( std::is_integral< S >::value, + "The template parameter S to MatrixFileReader must be integral." ); template< typename U, typename V > - friend std::ostream & operator<<( std::ostream & out, const MatrixFileReader< U, V > & A ); + friend std::ostream & operator<<( + std::ostream &out, const MatrixFileReader< U, V > &A ); private: - /** In case we are reading pattern matrices, which value to substitute for nonzeroes. */ + /** + * In case we are reading pattern matrices, which value to substitute for + * nonzeroes. + */ const T patternValue; @@ -55,15 +61,19 @@ namespace grb { /** * Constructs a matrix reader using minimal information. * - * This constructor will parse the file in its entirety once. The use of an iterator will parse the file \em again. + * This constructor will parse the file in its entirety once. The use of an + * iterator will parse the file \em again. * * @param[in] filename Which file to read. * @param[in] direct (Optional) Whether the file uses direct indexing. * If not, new indices will be automatically inferred. * Default value is \a true. - * @param[in] symmetricmap (Optional) In case \a direct is \a false, whether - * the row map should equal the column map. - * @param[in] patternValueSub (Optional) Which value to substitute for nonzeroes when reading in from a pattern + * + * @param[in] symmetricmap (Optional) In case \a direct is \a false, + * whether the row map should equal the column + * map. + * @param[in] patternValueSub (Optional) Which value to substitute for + * nonzeroes when reading in from a pattern * matrix. * * Defaults for \a direct and \a symmetricmap are true. @@ -71,14 +81,15 @@ namespace grb { * * @throws std::runtime_error If the given file does not exist. * - * \note Auto-detecting the correct value for \a pattern only can happen successfully in case of MatrixMarket. + * \note Auto-detecting the correct value for \a pattern only can happen + * successfully in case of MatrixMarket. */ MatrixFileReader( const std::string filename, const bool direct = true, const bool symmetricmap = true, const T patternValueSub = 1 ) : patternValue( patternValueSub ) { - internal::MatrixFileProperties & properties = this->properties; + internal::MatrixFileProperties &properties = this->properties; // set properties properties._fn = filename; properties._direct = direct; @@ -88,11 +99,11 @@ namespace grb { // open up file stream to infer remainder properties std::ifstream infile( properties._fn ); // try and find header - if( ! this->findHeader( infile ) ) { + if( !this->findHeader( infile ) ) { #ifdef _DEBUG - std::cout << "MatrixFileReader: couldn't parse header, " - "inferring SNAP-based defaults; i.e., no " - "pattern matrix, not symmetric, 0-based.\n"; + std::cout << "MatrixFileReader: couldn't parse header, inferring SNAP-" + << "based defaults; i.e., no pattern matrix, not symmetric, and" + << "0-based.\n"; #endif // not found, so we have to infer matrix properties // we assume the input is not pattern, since \a T is not \a void @@ -110,14 +121,14 @@ namespace grb { S row, col; T val; // read until we drop - while( ( infile >> row >> col >> val ) ) { - ++properties._entries; - ++properties._nz; + while( (infile >> row >> col >> val) ) { + (void) ++properties._entries; + (void) ++properties._nz; // if symmetric, count non-diagonal entries twice if( properties._symmetric && row != col ) { (void) ++properties._nz; } - (void)val; + (void) val; if( !direct ) { const auto row_it = properties._row_map.find( row ); if( row_it != properties._row_map.end() ) { @@ -165,8 +176,8 @@ namespace grb { properties._n = properties._m; } if( properties._nz > 0 ) { - ++properties._m; - ++properties._n; + (void) ++properties._m; + (void) ++properties._n; } } // print info to stdout @@ -216,41 +227,53 @@ namespace grb { internal::MatrixFileIterator< S, T > cbegin( const IOMode mode = SEQUENTIAL, const std::function< void( T & ) > valueConverter = []( T & ) {} ) { - return internal::MatrixFileIterator< S, T >( internal::MatrixFileReaderBase< T, S >::properties, mode, valueConverter, patternValue, false ); + return internal::MatrixFileIterator< S, T >( + internal::MatrixFileReaderBase< T, S >::properties, mode, + valueConverter, patternValue, false + ); } /** Matching end iterator to cbegin(). */ internal::MatrixFileIterator< S, T > cend( const IOMode mode = SEQUENTIAL, const std::function< void( T & ) > valueConverter = []( T & ) {} ) { - return internal::MatrixFileIterator< S, T >( internal::MatrixFileReaderBase< T, S >::properties, mode, valueConverter, patternValue, true ); + return internal::MatrixFileIterator< S, T >( + internal::MatrixFileReaderBase< T, S >::properties, mode, + valueConverter, patternValue, true + ); } }; template< typename S > - class MatrixFileReader< void, S > : public internal::MatrixFileReaderBase< void, S > { - - static_assert( std::is_integral< S >::value, "The template parameter S to MatrixFileReader must be integral." ); + class MatrixFileReader< void, S > : + public internal::MatrixFileReaderBase< void, S > + { + static_assert( std::is_integral< S >::value, + "The template parameter S to MatrixFileReader must be integral." ); template< typename U, typename V > - friend std::ostream & operator<<( std::ostream & out, const MatrixFileReader< U, V > & A ); + friend std::ostream & operator<<( + std::ostream &out, const MatrixFileReader< U, V > &A ); public: /** * Constructs a matrix reader using minimal information. * - * This constructor will parse the file in its entirety once. The use of an iterator will parse the file \em again. + * This constructor will parse the file in its entirety once. The use of an + * iterator will parse the file \em again. * * @param[in] filename Which file to read. * @param[in] direct (Optional) Whether the file uses direct indexing. - * If not, new indices will be automatically inferred. Default value is \a true. + * If not, new indices will be automatically inferred. + * Default value is \a true. * @param[in] symmetricmap (Optional) In case \a direct is \a false, whether * the row map should equal the column map. * * @throws std::runtime_error If the given file does not exist. * - * \note Auto-detecting the correct value for \a pattern only can happen successfully in case of MatrixMarket. + * \note Auto-detecting the correct value for \a pattern only can happen + * successfully in case of MatrixMarket. */ MatrixFileReader( const std::string filename, From 1d8caec1404022279679838f74279b132d9e5d9d Mon Sep 17 00:00:00 2001 From: "Albert-Jan N. Yzelman" Date: Wed, 27 Apr 2022 16:29:19 +0200 Subject: [PATCH 18/22] Else-if instead of sequence of ifs. Also catch unrecognised symmetry modes, and a small code style fix --- .../utils/parser/MatrixFileReaderBase.hpp | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/include/graphblas/utils/parser/MatrixFileReaderBase.hpp b/include/graphblas/utils/parser/MatrixFileReaderBase.hpp index bbb517149..b9612e5fa 100644 --- a/include/graphblas/utils/parser/MatrixFileReaderBase.hpp +++ b/include/graphblas/utils/parser/MatrixFileReaderBase.hpp @@ -44,8 +44,10 @@ namespace grb { /** * Parses SNAP files & Matrix Market files. * - * @tparam T The type a nonzero value iterator should return. Can be set to \a void in case the values are not of interest. - * @tparam S (Optional) The type an nonzero index iterator should return. Default value: \a size_t. + * @tparam T The type a nonzero value iterator should return. Can be set to + * \a void in case the values are not of interest. + * @tparam S (Optional) The type an nonzero index iterator should return. + * Default value: \a size_t. */ template< typename T, typename S > class MatrixFileReaderBase { @@ -214,13 +216,17 @@ namespace grb { } if( properties._symmetric == internal::Symmetric ) { std::cerr << " and the input is symmetric"; + } else if( properties._symmetric == internal::Hermitian ) { + std::cerr << " and the input is hermitian"; + } else if( properties._symmetric == internal::General ) { + std::cerr << " and the input is general"; + } else { + std::cerr << " and the input has unknown symmetry(!)"; +#ifndef NDEBUG + const bool unknown_symmetry_type_encountered = false; + assert( unknown_symmetry_type_encountered ); +#endif } - if( properties._symmetric == internal::Hermitian ) { - std::cerr << " and the input is hermitian "; - } - if( properties._symmetric == internal::General ) { - std::cerr << " and the input is general "; - } std::cerr << ".\n"; } From 822f374041ec7ff8c1b591d481464207403bf8fd Mon Sep 17 00:00:00 2001 From: "Albert-Jan N. Yzelman" Date: Wed, 27 Apr 2022 16:32:34 +0200 Subject: [PATCH 19/22] Remove superfluous spaces --- tests/smoke/smoketests.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/smoke/smoketests.sh b/tests/smoke/smoketests.sh index 39e972070..9fdbe4166 100755 --- a/tests/smoke/smoketests.sh +++ b/tests/smoke/smoketests.sh @@ -196,8 +196,8 @@ for BACKEND in ${BACKENDS[@]}; do TESTNAME=rndHermit256 if [ -f ${INPUT_DIR}/${TESTNAME}.mtx ]; then - n=$(grep -v '^%' ${INPUT_DIR}/${TESTNAME}.mtx | head -1 | awk '{print $1}' ) - m=$(grep -v '^%' ${INPUT_DIR}/${TESTNAME}.mtx | head -1 | awk '{print $2}' ) + n=$(grep -v '^%' ${INPUT_DIR}/${TESTNAME}.mtx | head -1 | awk '{print $1}' ) + m=$(grep -v '^%' ${INPUT_DIR}/${TESTNAME}.mtx | head -1 | awk '{print $2}' ) echo ">>> [x] [ ] Testing the conjugate gradient complex algorithm for the input" echo " matrix (${n}x${m}) taken from ${TESTNAME}.mtx. This test" echo " verifies against a ground-truth solution vector. The test" From 7fa9ca8b833f800f5a509a998cd89d83384aeeea Mon Sep 17 00:00:00 2001 From: "Albert-Jan N. Yzelman" Date: Wed, 27 Apr 2022 16:34:33 +0200 Subject: [PATCH 20/22] No need to always include complex header --- tests/smoke/conjugate_gradient.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/smoke/conjugate_gradient.cpp b/tests/smoke/conjugate_gradient.cpp index 1117b1a70..3b28da4ee 100644 --- a/tests/smoke/conjugate_gradient.cpp +++ b/tests/smoke/conjugate_gradient.cpp @@ -18,7 +18,11 @@ #include #include #include -#include + +#ifdef _CG_COMPLEX + #include +#endif + #include #include From 3b833391a705055d4856376a9b712cf066ba1139 Mon Sep 17 00:00:00 2001 From: "Albert-Jan N. Yzelman" Date: Wed, 27 Apr 2022 16:36:45 +0200 Subject: [PATCH 21/22] Did not correctly update smoketests.sh -- herewith fixed --- tests/smoke/smoketests.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/smoke/smoketests.sh b/tests/smoke/smoketests.sh index 9fdbe4166..e1f7e5f4c 100755 --- a/tests/smoke/smoketests.sh +++ b/tests/smoke/smoketests.sh @@ -195,9 +195,9 @@ for BACKEND in ${BACKENDS[@]}; do echo " " TESTNAME=rndHermit256 - if [ -f ${INPUT_DIR}/${TESTNAME}.mtx ]; then - n=$(grep -v '^%' ${INPUT_DIR}/${TESTNAME}.mtx | head -1 | awk '{print $1}' ) - m=$(grep -v '^%' ${INPUT_DIR}/${TESTNAME}.mtx | head -1 | awk '{print $2}' ) + if [ -f ${TEST_DATA_DIR}/${TESTNAME}.mtx ]; then + n=$(grep -v '^%' ${TEST_DATA_DIR}/${TESTNAME}.mtx | head -1 | awk '{print $1}' ) + m=$(grep -v '^%' ${TEST_DATA_DIR}/${TESTNAME}.mtx | head -1 | awk '{print $2}' ) echo ">>> [x] [ ] Testing the conjugate gradient complex algorithm for the input" echo " matrix (${n}x${m}) taken from ${TESTNAME}.mtx. This test" echo " verifies against a ground-truth solution vector. The test" @@ -207,7 +207,7 @@ for BACKEND in ${BACKENDS[@]}; do head -1 ${TEST_OUT_DIR}/conjugate_gradient_complex_${BACKEND}_${P}_${T}.log grep 'Test OK' ${TEST_OUT_DIR}/conjugate_gradient_complex_${BACKEND}_${P}_${T}.log || echo "Test FAILED" else - echo "Test DISABLED: ${TESTNAME}.mtx was not found. To enable, please provide ${INPUT_DIR}/${TESTNAME}.mtx" + echo "Test DISABLED: ${TESTNAME}.mtx was not found. To enable, please provide ${TEST_DATA_DIR}/${TESTNAME}.mtx" fi echo " " From c35004a696ddd84bc0c10aa5524e16ae2048fcb7 Mon Sep 17 00:00:00 2001 From: "Albert-Jan N. Yzelman" Date: Wed, 27 Apr 2022 17:00:04 +0200 Subject: [PATCH 22/22] Do not use auto unnecessarily, use const-reference when reading out pinned vectors, rely on std::abs instead of fabs due to possible complex numbers, minor code style fixes, standard error handling of new data_fscanf functions, add documentation and const-correctness to those new functions --- tests/utils/output_verification.hpp | 71 ++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 22 deletions(-) diff --git a/tests/utils/output_verification.hpp b/tests/utils/output_verification.hpp index d61bf51af..8f212dedb 100644 --- a/tests/utils/output_verification.hpp +++ b/tests/utils/output_verification.hpp @@ -36,19 +36,51 @@ /** - * internal overload for read of real and complex matrix + * Attempts to read in a double value from a given file into a given memory + * location. + * + * @param[in] in The input file + * @param[out] out Where to store the read value. + * + * @returns 0 on success and 1 on failure. + * + * If the function fails, \a out shall not be assigned. + * + * \internal This is the overload for reading double data. */ template< typename fileType > -int data_fscanf(fileType in, double *truth){ - return( fscanf( in, "%lf", &(*truth) ) ); +int data_fscanf( const fileType in, double * const out ) { + const int rc = fscanf( in, "%lf", out ); + if( rc == 1 ) { + return 0; + } else { + return 1; + } }; +/** + * Attempts to read in a complex value from a given file into a given memory + * location. + * + * @param[in] in The input file + * @param[out] out Where to store the read value. + * + * @returns 0 on success and 1 on failure. + * + * If the function fails, \a out shall not be assigned. + * + * \internal This is the overload for reading complex data. + */ template< typename fileType, typename T > -int data_fscanf(fileType in, std::complex *truth){ - double x,y; - int rc=fscanf( in, "%lf%lf", &x,&y ); - *truth=std::complex( x, y ); - return( rc==2 ); +int data_fscanf( const fileType in, std::complex< T > * const out ) { + double x, y; + const int rc = fscanf( in, "%lf%lf", &x, &y ); + if( rc == 2 ) { + *out = std::complex< T >( x, y ); + return 0; + } else { + return 1; + } }; /** @@ -109,7 +141,7 @@ int vector_verification( const constexpr T one = static_cast< T >( 1 ); // open verification file - FILE *in = fopen( truth_filename, "r" ); + FILE * const in = fopen( truth_filename, "r" ); if( in == nullptr ) { std::cerr << "Could not open the file \"" << truth_filename << "\"." @@ -126,14 +158,10 @@ int vector_verification( } for( size_t i = 0; i < n; i++ ) { - int rc=data_fscanf(in, truth + i ); - if( rc != 1 ) { - std::cerr << "The verification file looks incomplete." - << " line i= " - << i - << " data= " << truth[ i ] - << " rc= " << rc - << std::endl; + const int rc = data_fscanf( in, truth + i ); + if( rc != 0 ) { + std::cerr << "The verification file looks incomplete. " << "Line i = " << i + << ", data = " << truth[ i ] << ", rc = " << rc << std::endl; delete [] truth; return 30; } @@ -141,8 +169,7 @@ int vector_verification( // close verification file if( fclose( in ) != 0 ) { - std::cerr << "I/O warning: closing verification file failed." - << std::endl; + std::cerr << "I/O warning: closing verification file failed." << std::endl; } // compute magnitudes @@ -150,8 +177,8 @@ int vector_verification( double magnitudeInf = 0; for( size_t i = 0; i < n; ++i ) { magnitude2 += std::norm( truth[ i ] ); - magnitudeInf = fabs( truth[ i ] ) > magnitudeInf ? - fabs( truth[ i ] ) : + magnitudeInf = std::abs( truth[ i ] ) > magnitudeInf ? + std::abs( truth[ i ] ) : magnitudeInf; } // we assume the ground truth should have a properly computable 2-norm @@ -171,7 +198,7 @@ int vector_verification( } for( size_t k = 0; k < output_vector.nonzeroes(); k++ ) { - const auto value = output_vector.getNonzeroValue( k, one ); + const T &value = output_vector.getNonzeroValue( k, one ); const size_t index = output_vector.getNonzeroIndex( k ); assert( index < n ); assert( !written_to[ index ] );