diff --git a/CMakeLists.txt b/CMakeLists.txt index 7141a566a49..fafa54390b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -234,7 +234,7 @@ endif() set(GINKGO_HAVE_GPU_AWARE_MPI OFF) set(GINKGO_FORCE_SPMV_BLOCKING_COMM OFF) if(GINKGO_BUILD_MPI) - find_package(MPI REQUIRED) + find_package(MPI 3.1 COMPONENTS CXX REQUIRED) if(GINKGO_FORCE_GPU_AWARE_MPI) set(GINKGO_HAVE_GPU_AWARE_MPI ON) else() diff --git a/README.md b/README.md index 38bd1096d39..9ed29271cbd 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,10 @@ The Ginkgo DPC++ module has the following __additional__ requirements: * oneMKL * oneDPL +The Ginkgo MPI module has the following __additional__ requirements: + +* MPI 3.1+, ideally with GPUDirect support for best performance + In addition, if you want to contribute code to Ginkgo, you will also need the following: diff --git a/cmake/GinkgoConfig.cmake.in b/cmake/GinkgoConfig.cmake.in index bc1828c80d0..1d0bc291ce0 100644 --- a/cmake/GinkgoConfig.cmake.in +++ b/cmake/GinkgoConfig.cmake.in @@ -161,7 +161,7 @@ endif() # Check for MPI if it is enabled if(GINKGO_BUILD_MPI) - find_package(MPI REQUIRED) + find_package(MPI 3.1 COMPONENTS CXX REQUIRED) endif() # HIP and OpenMP depend on Threads::Threads in some circumstances, but don't find it diff --git a/cmake/autodetect_executors.cmake b/cmake/autodetect_executors.cmake index 3a5ba36b559..315e0eb3e38 100644 --- a/cmake/autodetect_executors.cmake +++ b/cmake/autodetect_executors.cmake @@ -15,7 +15,7 @@ if (NOT DEFINED GINKGO_BUILD_OMP) endif() if (NOT DEFINED GINKGO_BUILD_MPI) - find_package(MPI 3.1) + find_package(MPI 3.1 COMPONENTS CXX) if(MPI_FOUND) message(STATUS "Enabling MPI support") set(GINKGO_HAS_MPI ON) diff --git a/cmake/create_test.cmake b/cmake/create_test.cmake index d38c2781b74..458ecbf07c0 100644 --- a/cmake/create_test.cmake +++ b/cmake/create_test.cmake @@ -14,7 +14,7 @@ function(ginkgo_create_gtest_mpi_main) target_sources(gtest_mpi_main PRIVATE ${PROJECT_SOURCE_DIR}/core/test/mpi/gtest/mpi_listener.cpp) - find_package(MPI REQUIRED) + find_package(MPI 3.1 COMPONENTS CXX REQUIRED) target_link_libraries(gtest_mpi_main PRIVATE GTest::GTest MPI::MPI_CXX) endfunction(ginkgo_create_gtest_mpi_main) diff --git a/core/distributed/matrix.cpp b/core/distributed/matrix.cpp index 7fcade79886..0a8451bed9e 100644 --- a/core/distributed/matrix.cpp +++ b/core/distributed/matrix.cpp @@ -66,15 +66,16 @@ Matrix::Matrix( template Matrix::Matrix( std::shared_ptr exec, mpi::communicator comm, - const LinOp* local_matrix_type) - : Matrix(exec, comm, local_matrix_type, local_matrix_type) + ptr_param local_matrix_template) + : Matrix(exec, comm, local_matrix_template, local_matrix_template) {} template Matrix::Matrix( std::shared_ptr exec, mpi::communicator comm, - const LinOp* local_matrix_template, const LinOp* non_local_matrix_template) + ptr_param local_matrix_template, + ptr_param non_local_matrix_template) : EnableDistributedLinOp< Matrix>{exec}, DistributedBase{comm}, @@ -141,8 +142,10 @@ void Matrix::move_to( template void Matrix::read_distributed( const device_matrix_data& data, - const Partition* row_partition, - const Partition* col_partition) + ptr_param> + row_partition, + ptr_param> + col_partition) { const auto comm = this->get_communicator(); GKO_ASSERT_EQ(data.get_size()[0], row_partition->get_size()); @@ -228,8 +231,10 @@ void Matrix::read_distributed( template void Matrix::read_distributed( const matrix_data& data, - const Partition* row_partition, - const Partition* col_partition) + ptr_param> + row_partition, + ptr_param> + col_partition) { this->read_distributed( device_matrix_data::create_from_host( @@ -241,7 +246,7 @@ void Matrix::read_distributed( template void Matrix::read_distributed( const matrix_data& data, - const Partition* partition) + ptr_param> partition) { this->read_distributed( device_matrix_data::create_from_host( @@ -253,7 +258,7 @@ void Matrix::read_distributed( template void Matrix::read_distributed( const device_matrix_data& data, - const Partition* partition) + ptr_param> partition) { this->read_distributed(data, partition, partition); } diff --git a/core/distributed/vector.cpp b/core/distributed/vector.cpp index 07e43135488..cafc347d5ed 100644 --- a/core/distributed/vector.cpp +++ b/core/distributed/vector.cpp @@ -102,7 +102,7 @@ Vector::Vector(std::shared_ptr exec, template Vector::Vector(std::shared_ptr exec, mpi::communicator comm, dim<2> global_size, - local_vector_type* local_vector) + ptr_param local_vector) : EnableDistributedLinOp>{exec, global_size}, DistributedBase{comm}, local_{exec} @@ -114,7 +114,7 @@ Vector::Vector(std::shared_ptr exec, template Vector::Vector(std::shared_ptr exec, mpi::communicator comm, - local_vector_type* local_vector) + ptr_param local_vector) : EnableDistributedLinOp>{exec, {}}, DistributedBase{comm}, local_{exec} @@ -126,7 +126,7 @@ Vector::Vector(std::shared_ptr exec, template std::unique_ptr> Vector::create_with_config_of( - const Vector* other) + ptr_param other) { // De-referencing `other` before calling the functions (instead of // using operator `->`) is currently required to be compatible with @@ -138,7 +138,8 @@ std::unique_ptr> Vector::create_with_config_of( template std::unique_ptr> Vector::create_with_type_of( - const Vector* other, std::shared_ptr exec) + ptr_param> other, + std::shared_ptr exec) { return (*other).create_with_type_of_impl(exec, {}, {}, 0); } @@ -146,8 +147,9 @@ std::unique_ptr> Vector::create_with_type_of( template std::unique_ptr> Vector::create_with_type_of( - const Vector* other, std::shared_ptr exec, - const dim<2>& global_size, const dim<2>& local_size, size_type stride) + ptr_param> other, + std::shared_ptr exec, const dim<2>& global_size, + const dim<2>& local_size, size_type stride) { return (*other).create_with_type_of_impl(exec, global_size, local_size, stride); @@ -156,7 +158,7 @@ std::unique_ptr> Vector::create_with_type_of( template template -void Vector::read_distributed( +void Vector::read_distributed_impl( const device_matrix_data& data, const Partition* partition) { @@ -175,16 +177,65 @@ void Vector::read_distributed( template -template void Vector::read_distributed( - const matrix_data& data, - const Partition* partition) + const device_matrix_data& data, + ptr_param> partition) +{ + this->read_distributed_impl(data, partition.get()); +} + + +template +void Vector::read_distributed( + const device_matrix_data& data, + ptr_param> partition) +{ + this->read_distributed_impl(data, partition.get()); +} + + +template +void Vector::read_distributed( + const device_matrix_data& data, + ptr_param> partition) +{ + this->read_distributed_impl(data, partition.get()); +} + + +template +void Vector::read_distributed( + const matrix_data& data, + ptr_param> partition) +{ + this->read_distributed( + device_matrix_data::create_from_host( + this->get_executor(), data), + partition); +} + + +template +void Vector::read_distributed( + const matrix_data& data, + ptr_param> partition) +{ + this->read_distributed( + device_matrix_data::create_from_host( + this->get_executor(), data), + partition); +} + +template +void Vector::read_distributed( + const matrix_data& data, + ptr_param> partition) { this->read_distributed( - device_matrix_data::create_from_host( + device_matrix_data::create_from_host( this->get_executor(), data), - std::move(partition)); + partition); } @@ -259,7 +310,8 @@ Vector::make_complex() const template -void Vector::make_complex(Vector::complex_type* result) const +void Vector::make_complex( + ptr_param result) const { this->get_local_vector()->make_complex(&result->local_); } @@ -279,7 +331,7 @@ Vector::get_real() const template -void Vector::get_real(Vector::real_type* result) const +void Vector::get_real(ptr_param result) const { this->get_local_vector()->get_real(&result->local_); } @@ -299,28 +351,29 @@ Vector::get_imag() const template -void Vector::get_imag(Vector::real_type* result) const +void Vector::get_imag(ptr_param result) const { this->get_local_vector()->get_imag(&result->local_); } template -void Vector::scale(const LinOp* alpha) +void Vector::scale(ptr_param alpha) { local_.scale(alpha); } template -void Vector::inv_scale(const LinOp* alpha) +void Vector::inv_scale(ptr_param alpha) { local_.inv_scale(alpha); } template -void Vector::add_scaled(const LinOp* alpha, const LinOp* b) +void Vector::add_scaled(ptr_param alpha, + ptr_param b) { auto dense_b = as>(b); local_.add_scaled(alpha, dense_b->get_local_vector()); @@ -328,7 +381,8 @@ void Vector::add_scaled(const LinOp* alpha, const LinOp* b) template -void Vector::sub_scaled(const LinOp* alpha, const LinOp* b) +void Vector::sub_scaled(ptr_param alpha, + ptr_param b) { auto dense_b = as>(b); local_.sub_scaled(alpha, dense_b->get_local_vector()); @@ -336,7 +390,8 @@ void Vector::sub_scaled(const LinOp* alpha, const LinOp* b) template -void Vector::compute_dot(const LinOp* b, LinOp* result) const +void Vector::compute_dot(ptr_param b, + ptr_param result) const { array tmp{this->get_executor()}; this->compute_dot(b, result, tmp); @@ -344,7 +399,8 @@ void Vector::compute_dot(const LinOp* b, LinOp* result) const template -void Vector::compute_dot(const LinOp* b, LinOp* result, +void Vector::compute_dot(ptr_param b, + ptr_param result, array& tmp) const { GKO_ASSERT_EQUAL_DIMENSIONS(result, dim<2>(1, this->get_size()[1])); @@ -370,7 +426,8 @@ void Vector::compute_dot(const LinOp* b, LinOp* result, template -void Vector::compute_conj_dot(const LinOp* b, LinOp* result) const +void Vector::compute_conj_dot(ptr_param b, + ptr_param result) const { array tmp{this->get_executor()}; this->compute_conj_dot(b, result, tmp); @@ -378,7 +435,8 @@ void Vector::compute_conj_dot(const LinOp* b, LinOp* result) const template -void Vector::compute_conj_dot(const LinOp* b, LinOp* result, +void Vector::compute_conj_dot(ptr_param b, + ptr_param result, array& tmp) const { GKO_ASSERT_EQUAL_DIMENSIONS(result, dim<2>(1, this->get_size()[1])); @@ -404,7 +462,7 @@ void Vector::compute_conj_dot(const LinOp* b, LinOp* result, template -void Vector::compute_norm2(LinOp* result) const +void Vector::compute_norm2(ptr_param result) const { array tmp{this->get_executor()}; this->compute_norm2(result, tmp); @@ -412,7 +470,8 @@ void Vector::compute_norm2(LinOp* result) const template -void Vector::compute_norm2(LinOp* result, array& tmp) const +void Vector::compute_norm2(ptr_param result, + array& tmp) const { using NormVector = typename local_vector_type::absolute_type; GKO_ASSERT_EQUAL_DIMENSIONS(result, dim<2>(1, this->get_size()[1])); @@ -437,7 +496,7 @@ void Vector::compute_norm2(LinOp* result, array& tmp) const template -void Vector::compute_norm1(LinOp* result) const +void Vector::compute_norm1(ptr_param result) const { array tmp{this->get_executor()}; this->compute_norm1(result, tmp); @@ -445,7 +504,8 @@ void Vector::compute_norm1(LinOp* result) const template -void Vector::compute_norm1(LinOp* result, array& tmp) const +void Vector::compute_norm1(ptr_param result, + array& tmp) const { using NormVector = typename local_vector_type::absolute_type; GKO_ASSERT_EQUAL_DIMENSIONS(result, dim<2>(1, this->get_size()[1])); @@ -570,20 +630,6 @@ std::unique_ptr> Vector::create_with_type_of_impl( GKO_INSTANTIATE_FOR_EACH_VALUE_TYPE(GKO_DECLARE_DISTRIBUTED_VECTOR); -#define GKO_DECLARE_DISTRIBUTED_VECTOR_READ_DISTRIBUTED( \ - ValueType, LocalIndexType, GlobalIndexType) \ - void Vector::read_distributed( \ - const device_matrix_data& data, \ - const Partition* partition); \ - template void \ - Vector::read_distributed( \ - const matrix_data& data, \ - const Partition* partition) - -GKO_INSTANTIATE_FOR_EACH_VALUE_AND_LOCAL_GLOBAL_INDEX_TYPE( - GKO_DECLARE_DISTRIBUTED_VECTOR_READ_DISTRIBUTED); - - } // namespace distributed } // namespace experimental } // namespace gko diff --git a/core/matrix/dense.cpp b/core/matrix/dense.cpp index b7dfecdc018..78fea8e2898 100644 --- a/core/matrix/dense.cpp +++ b/core/matrix/dense.cpp @@ -153,7 +153,7 @@ void Dense::fill(const ValueType value) template -void Dense::scale(const LinOp* alpha) +void Dense::scale(ptr_param alpha) { auto exec = this->get_executor(); this->scale_impl(make_temporary_clone(exec, alpha).get()); @@ -161,7 +161,7 @@ void Dense::scale(const LinOp* alpha) template -void Dense::inv_scale(const LinOp* alpha) +void Dense::inv_scale(ptr_param alpha) { auto exec = this->get_executor(); this->inv_scale_impl(make_temporary_clone(exec, alpha).get()); @@ -169,7 +169,8 @@ void Dense::inv_scale(const LinOp* alpha) template -void Dense::add_scaled(const LinOp* alpha, const LinOp* b) +void Dense::add_scaled(ptr_param alpha, + ptr_param b) { auto exec = this->get_executor(); this->add_scaled_impl(make_temporary_clone(exec, alpha).get(), @@ -178,7 +179,8 @@ void Dense::add_scaled(const LinOp* alpha, const LinOp* b) template -void Dense::sub_scaled(const LinOp* alpha, const LinOp* b) +void Dense::sub_scaled(ptr_param alpha, + ptr_param b) { auto exec = this->get_executor(); this->sub_scaled_impl(make_temporary_clone(exec, alpha).get(), @@ -187,7 +189,8 @@ void Dense::sub_scaled(const LinOp* alpha, const LinOp* b) template -void Dense::compute_dot(const LinOp* b, LinOp* result) const +void Dense::compute_dot(ptr_param b, + ptr_param result) const { auto exec = this->get_executor(); this->compute_dot_impl(make_temporary_clone(exec, b).get(), @@ -196,7 +199,8 @@ void Dense::compute_dot(const LinOp* b, LinOp* result) const template -void Dense::compute_conj_dot(const LinOp* b, LinOp* result) const +void Dense::compute_conj_dot(ptr_param b, + ptr_param result) const { auto exec = this->get_executor(); this->compute_conj_dot_impl( @@ -206,7 +210,7 @@ void Dense::compute_conj_dot(const LinOp* b, LinOp* result) const template -void Dense::compute_norm2(LinOp* result) const +void Dense::compute_norm2(ptr_param result) const { auto exec = this->get_executor(); this->compute_norm2_impl(make_temporary_output_clone(exec, result).get()); @@ -214,7 +218,7 @@ void Dense::compute_norm2(LinOp* result) const template -void Dense::compute_norm1(LinOp* result) const +void Dense::compute_norm1(ptr_param result) const { auto exec = this->get_executor(); this->compute_norm1_impl(make_temporary_output_clone(exec, result).get()); @@ -337,7 +341,8 @@ void Dense::sub_scaled_impl(const LinOp* alpha, const LinOp* b) template -void Dense::compute_dot(const LinOp* b, LinOp* result, +void Dense::compute_dot(ptr_param b, + ptr_param result, array& tmp) const { GKO_ASSERT_EQUAL_DIMENSIONS(this, b); @@ -371,7 +376,8 @@ void Dense::compute_dot_impl(const LinOp* b, LinOp* result) const template -void Dense::compute_conj_dot(const LinOp* b, LinOp* result, +void Dense::compute_conj_dot(ptr_param b, + ptr_param result, array& tmp) const { GKO_ASSERT_EQUAL_DIMENSIONS(this, b); @@ -406,7 +412,8 @@ void Dense::compute_conj_dot_impl(const LinOp* b, template -void Dense::compute_norm2(LinOp* result, array& tmp) const +void Dense::compute_norm2(ptr_param result, + array& tmp) const { GKO_ASSERT_EQUAL_DIMENSIONS(result, dim<2>(1, this->get_size()[1])); auto exec = this->get_executor(); @@ -434,7 +441,8 @@ void Dense::compute_norm2_impl(LinOp* result) const template -void Dense::compute_norm1(LinOp* result, array& tmp) const +void Dense::compute_norm1(ptr_param result, + array& tmp) const { GKO_ASSERT_EQUAL_DIMENSIONS(result, dim<2>(1, this->get_size()[1])); auto exec = this->get_executor(); @@ -1010,7 +1018,7 @@ std::unique_ptr Dense::conj_transpose() const template -void Dense::transpose(Dense* output) const +void Dense::transpose(ptr_param> output) const { GKO_ASSERT_EQUAL_DIMENSIONS(output, gko::transpose(this->get_size())); auto exec = this->get_executor(); @@ -1020,7 +1028,7 @@ void Dense::transpose(Dense* output) const template -void Dense::conj_transpose(Dense* output) const +void Dense::conj_transpose(ptr_param> output) const { GKO_ASSERT_EQUAL_DIMENSIONS(output, gko::transpose(this->get_size())); auto exec = this->get_executor(); @@ -1176,17 +1184,17 @@ std::unique_ptr Dense::permute( template void Dense::permute(const array* permutation_indices, - Dense* output) const + ptr_param> output) const { - this->permute_impl(permutation_indices, output); + this->permute_impl(permutation_indices, output.get()); } template void Dense::permute(const array* permutation_indices, - Dense* output) const + ptr_param> output) const { - this->permute_impl(permutation_indices, output); + this->permute_impl(permutation_indices, output.get()); } @@ -1212,17 +1220,17 @@ std::unique_ptr Dense::inverse_permute( template void Dense::inverse_permute(const array* permutation_indices, - Dense* output) const + ptr_param> output) const { - this->inverse_permute_impl(permutation_indices, output); + this->inverse_permute_impl(permutation_indices, output.get()); } template void Dense::inverse_permute(const array* permutation_indices, - Dense* output) const + ptr_param> output) const { - this->inverse_permute_impl(permutation_indices, output); + this->inverse_permute_impl(permutation_indices, output.get()); } @@ -1248,17 +1256,17 @@ std::unique_ptr Dense::row_permute( template void Dense::row_permute(const array* permutation_indices, - Dense* output) const + ptr_param> output) const { - this->row_permute_impl(permutation_indices, output); + this->row_permute_impl(permutation_indices, output.get()); } template void Dense::row_permute(const array* permutation_indices, - Dense* output) const + ptr_param> output) const { - this->row_permute_impl(permutation_indices, output); + this->row_permute_impl(permutation_indices, output.get()); } @@ -1284,20 +1292,6 @@ std::unique_ptr> Dense::row_gather( return result; } -template -void Dense::row_gather(const array* row_idxs, - Dense* row_collection) const -{ - this->row_gather_impl(row_idxs, row_collection); -} - -template -void Dense::row_gather(const array* row_idxs, - Dense* row_collection) const -{ - this->row_gather_impl(row_idxs, row_collection); -} - namespace { @@ -1320,28 +1314,29 @@ void gather_mixed_real_complex(Function fn, LinOp* out) template void Dense::row_gather(const array* row_idxs, - LinOp* row_collection) const + ptr_param row_collection) const { gather_mixed_real_complex( [&](auto dense) { this->row_gather_impl(row_idxs, dense); }, - row_collection); + row_collection.get()); } template void Dense::row_gather(const array* row_idxs, - LinOp* row_collection) const + ptr_param row_collection) const { gather_mixed_real_complex( [&](auto dense) { this->row_gather_impl(row_idxs, dense); }, - row_collection); + row_collection.get()); } template -void Dense::row_gather(const LinOp* alpha, +void Dense::row_gather(ptr_param alpha, const array* gather_indices, - const LinOp* beta, LinOp* out) const + ptr_param beta, + ptr_param out) const { auto dense_alpha = make_temporary_conversion(alpha); auto dense_beta = make_temporary_conversion(beta); @@ -1352,13 +1347,14 @@ void Dense::row_gather(const LinOp* alpha, this->row_gather_impl(dense_alpha.get(), gather_indices, dense_beta.get(), dense); }, - out); + out.get()); } template -void Dense::row_gather(const LinOp* alpha, +void Dense::row_gather(ptr_param alpha, const array* gather_indices, - const LinOp* beta, LinOp* out) const + ptr_param beta, + ptr_param out) const { auto dense_alpha = make_temporary_conversion(alpha); auto dense_beta = make_temporary_conversion(beta); @@ -1369,7 +1365,7 @@ void Dense::row_gather(const LinOp* alpha, this->row_gather_impl(dense_alpha.get(), gather_indices, dense_beta.get(), dense); }, - out); + out.get()); } @@ -1395,17 +1391,17 @@ std::unique_ptr Dense::column_permute( template void Dense::column_permute(const array* permutation_indices, - Dense* output) const + ptr_param> output) const { - this->column_permute_impl(permutation_indices, output); + this->column_permute_impl(permutation_indices, output.get()); } template void Dense::column_permute(const array* permutation_indices, - Dense* output) const + ptr_param> output) const { - this->column_permute_impl(permutation_indices, output); + this->column_permute_impl(permutation_indices, output.get()); } @@ -1431,17 +1427,19 @@ std::unique_ptr Dense::inverse_row_permute( template void Dense::inverse_row_permute( - const array* permutation_indices, Dense* output) const + const array* permutation_indices, + ptr_param> output) const { - this->inverse_row_permute_impl(permutation_indices, output); + this->inverse_row_permute_impl(permutation_indices, output.get()); } template void Dense::inverse_row_permute( - const array* permutation_indices, Dense* output) const + const array* permutation_indices, + ptr_param> output) const { - this->inverse_row_permute_impl(permutation_indices, output); + this->inverse_row_permute_impl(permutation_indices, output.get()); } @@ -1467,22 +1465,25 @@ std::unique_ptr Dense::inverse_column_permute( template void Dense::inverse_column_permute( - const array* permutation_indices, Dense* output) const + const array* permutation_indices, + ptr_param> output) const { - this->inverse_column_permute_impl(permutation_indices, output); + this->inverse_column_permute_impl(permutation_indices, output.get()); } template void Dense::inverse_column_permute( - const array* permutation_indices, Dense* output) const + const array* permutation_indices, + ptr_param> output) const { - this->inverse_column_permute_impl(permutation_indices, output); + this->inverse_column_permute_impl(permutation_indices, output.get()); } template -void Dense::extract_diagonal(Diagonal* output) const +void Dense::extract_diagonal( + ptr_param> output) const { auto exec = this->get_executor(); const auto diag_size = std::min(this->get_size()[0], this->get_size()[1]); @@ -1522,8 +1523,7 @@ Dense::compute_absolute() const template -void Dense::compute_absolute( - Dense::absolute_type* output) const +void Dense::compute_absolute(ptr_param output) const { GKO_ASSERT_EQUAL_DIMENSIONS(this, output); auto exec = this->get_executor(); @@ -1544,8 +1544,7 @@ Dense::make_complex() const template -void Dense::make_complex( - typename Dense::complex_type* result) const +void Dense::make_complex(ptr_param result) const { GKO_ASSERT_EQUAL_DIMENSIONS(this, result); auto exec = this->get_executor(); @@ -1566,8 +1565,7 @@ Dense::get_real() const template -void Dense::get_real( - typename Dense::real_type* result) const +void Dense::get_real(ptr_param result) const { GKO_ASSERT_EQUAL_DIMENSIONS(this, result); auto exec = this->get_executor(); @@ -1588,8 +1586,7 @@ Dense::get_imag() const template -void Dense::get_imag( - typename Dense::real_type* result) const +void Dense::get_imag(ptr_param result) const { GKO_ASSERT_EQUAL_DIMENSIONS(this, result); auto exec = this->get_executor(); diff --git a/core/test/base/mtx_io.cpp b/core/test/base/mtx_io.cpp index 2575dd79bfd..e04542e7964 100644 --- a/core/test/base/mtx_io.cpp +++ b/core/test/base/mtx_io.cpp @@ -1087,12 +1087,16 @@ TYPED_TEST(RealDummyLinOpTest, WritesLinOpToStreamDefault) auto lin_op = gko::read>( iss, gko::ReferenceExecutor::create()); std::ostringstream oss{}; + std::ostringstream oss_const{}; - write(oss, lend(lin_op)); + write(oss, lin_op); + write(oss_const, std::unique_ptr>{ + std::move(lin_op)}); ASSERT_EQ(oss.str(), "%%MatrixMarket matrix coordinate real general\n2 3 6\n1 1 1\n1 " "2 3\n1 3 2\n2 1 0\n2 2 5\n2 3 0\n"); + ASSERT_EQ(oss_const.str(), oss.str()); } diff --git a/core/test/base/utils.cpp b/core/test/base/utils.cpp index 200f47e45d0..66bd3ed588d 100644 --- a/core/test/base/utils.cpp +++ b/core/test/base/utils.cpp @@ -61,6 +61,59 @@ struct Base2 { struct MultipleDerived : Base, Base2 {}; +TEST(PointerParam, WorksForRawPointers) +{ + auto obj = std::make_unique(); + auto ptr = obj.get(); + + gko::ptr_param param(ptr); + gko::ptr_param param2(ptr); + + ASSERT_EQ(param.get(), static_cast(ptr)); + ASSERT_EQ(param2.get(), ptr); +} + + +TEST(PointerParam, WorksForSharedPointers) +{ + auto obj = std::make_shared(); + auto ptr = obj.get(); + + // no difference whether we use lvalue or rvalue + gko::ptr_param param1(obj); + gko::ptr_param param2(std::move(obj)); + gko::ptr_param param3(obj); + gko::ptr_param param4(std::move(obj)); + + ASSERT_EQ(param1.get(), static_cast(ptr)); + ASSERT_EQ(param2.get(), static_cast(ptr)); + ASSERT_EQ(param3.get(), ptr); + ASSERT_EQ(param4.get(), ptr); + // shared_ptr was unmodified + ASSERT_EQ(obj.get(), ptr); +} + + +TEST(PointerParam, WorksForUniquePointers) +{ + auto obj = std::make_unique(); + auto ptr = obj.get(); + + // no difference whether we use lvalue or rvalue + gko::ptr_param param1(obj); + gko::ptr_param param2(std::move(obj)); + gko::ptr_param param3(obj); + gko::ptr_param param4(std::move(obj)); + + ASSERT_EQ(param1.get(), static_cast(ptr)); + ASSERT_EQ(param2.get(), static_cast(ptr)); + ASSERT_EQ(param3.get(), ptr); + ASSERT_EQ(param4.get(), ptr); + // shared_ptr was unmodified + ASSERT_EQ(obj.get(), ptr); +} + + struct ClonableDerived : Base { ClonableDerived(std::shared_ptr exec = nullptr) : executor(exec) diff --git a/include/ginkgo/core/base/executor.hpp b/include/ginkgo/core/base/executor.hpp index 1b9e44c82b8..4a4e4ec55fa 100644 --- a/include/ginkgo/core/base/executor.hpp +++ b/include/ginkgo/core/base/executor.hpp @@ -756,19 +756,19 @@ class Executor : public log::EnableLogging { * where the data will be copied to */ template - void copy_from(const Executor* src_exec, size_type num_elems, + void copy_from(ptr_param src_exec, size_type num_elems, const T* src_ptr, T* dest_ptr) const { const auto src_loc = reinterpret_cast(src_ptr); const auto dest_loc = reinterpret_cast(dest_ptr); this->template log( - src_exec, this, src_loc, dest_loc, num_elems * sizeof(T)); - if (this != src_exec) { + src_exec.get(), this, src_loc, dest_loc, num_elems * sizeof(T)); + if (this != src_exec.get()) { src_exec->template log( - src_exec, this, src_loc, dest_loc, num_elems * sizeof(T)); + src_exec.get(), this, src_loc, dest_loc, num_elems * sizeof(T)); } try { - this->raw_copy_from(src_exec, num_elems * sizeof(T), src_ptr, + this->raw_copy_from(src_exec.get(), num_elems * sizeof(T), src_ptr, dest_ptr); } catch (NotSupported&) { #if (GKO_VERBOSE_LEVEL >= 1) && !defined(NDEBUG) @@ -778,7 +778,7 @@ class Executor : public log::EnableLogging { << std::endl; #endif auto src_master = src_exec->get_master().get(); - if (num_elems > 0 && src_master != src_exec) { + if (num_elems > 0 && src_master != src_exec.get()) { auto* master_ptr = src_exec->get_master()->alloc(num_elems); src_master->copy_from(src_exec, num_elems, src_ptr, master_ptr); @@ -787,10 +787,10 @@ class Executor : public log::EnableLogging { } } this->template log( - src_exec, this, src_loc, dest_loc, num_elems * sizeof(T)); - if (this != src_exec) { + src_exec.get(), this, src_loc, dest_loc, num_elems * sizeof(T)); + if (this != src_exec.get()) { src_exec->template log( - src_exec, this, src_loc, dest_loc, num_elems * sizeof(T)); + src_exec.get(), this, src_loc, dest_loc, num_elems * sizeof(T)); } } @@ -870,6 +870,8 @@ class Executor : public log::EnableLogging { this->EnableLogging::remove_logger(logger); } + using EnableLogging::remove_logger; + /** * Sets the logger event propagation mode for the executor. * This controls whether events that happen at objects created on this diff --git a/include/ginkgo/core/base/lin_op.hpp b/include/ginkgo/core/base/lin_op.hpp index 947ca18680c..95abf7d2a84 100644 --- a/include/ginkgo/core/base/lin_op.hpp +++ b/include/ginkgo/core/base/lin_op.hpp @@ -124,9 +124,9 @@ class Diagonal; * auto tmp = gko::clone(x0); * auto one = Dense<>::create(L->get_executor(), {1.0,}); * for (int i = 0; i < iters; ++i) { - * L->apply(gko::lend(tmp), gko::lend(x)); - * x->add_scaled(gko::lend(one), gko::lend(b)); - * tmp->copy_from(gko::lend(x)); + * L->apply(tmp, x); + * x->add_scaled(one, b); + * tmp->copy_from(x); * } * return x; * } @@ -155,28 +155,32 @@ class LinOp : public EnableAbstractPolymorphicObject { * * @return this */ - LinOp* apply(const LinOp* b, LinOp* x) + LinOp* apply(ptr_param b, ptr_param x) { - this->template log(this, b, x); - this->validate_application_parameters(b, x); + this->template log(this, b.get(), + x.get()); + this->validate_application_parameters(b.get(), x.get()); auto exec = this->get_executor(); this->apply_impl(make_temporary_clone(exec, b).get(), make_temporary_clone(exec, x).get()); - this->template log(this, b, x); + this->template log(this, b.get(), + x.get()); return this; } /** * @copydoc apply(const LinOp *, LinOp *) */ - const LinOp* apply(const LinOp* b, LinOp* x) const + const LinOp* apply(ptr_param b, ptr_param x) const { - this->template log(this, b, x); - this->validate_application_parameters(b, x); + this->template log(this, b.get(), + x.get()); + this->validate_application_parameters(b.get(), x.get()); auto exec = this->get_executor(); this->apply_impl(make_temporary_clone(exec, b).get(), make_temporary_clone(exec, x).get()); - this->template log(this, b, x); + this->template log(this, b.get(), + x.get()); return this; } @@ -190,38 +194,40 @@ class LinOp : public EnableAbstractPolymorphicObject { * * @return this */ - LinOp* apply(const LinOp* alpha, const LinOp* b, const LinOp* beta, - LinOp* x) + LinOp* apply(ptr_param alpha, ptr_param b, + ptr_param beta, ptr_param x) { this->template log( - this, alpha, b, beta, x); - this->validate_application_parameters(alpha, b, beta, x); + this, alpha.get(), b.get(), beta.get(), x.get()); + this->validate_application_parameters(alpha.get(), b.get(), beta.get(), + x.get()); auto exec = this->get_executor(); this->apply_impl(make_temporary_clone(exec, alpha).get(), make_temporary_clone(exec, b).get(), make_temporary_clone(exec, beta).get(), make_temporary_clone(exec, x).get()); this->template log( - this, alpha, b, beta, x); + this, alpha.get(), b.get(), beta.get(), x.get()); return this; } /** * @copydoc apply(const LinOp *, const LinOp *, const LinOp *, LinOp *) */ - const LinOp* apply(const LinOp* alpha, const LinOp* b, const LinOp* beta, - LinOp* x) const + const LinOp* apply(ptr_param alpha, ptr_param b, + ptr_param beta, ptr_param x) const { this->template log( - this, alpha, b, beta, x); - this->validate_application_parameters(alpha, b, beta, x); + this, alpha.get(), b.get(), beta.get(), x.get()); + this->validate_application_parameters(alpha.get(), b.get(), beta.get(), + x.get()); auto exec = this->get_executor(); this->apply_impl(make_temporary_clone(exec, alpha).get(), make_temporary_clone(exec, b).get(), make_temporary_clone(exec, beta).get(), make_temporary_clone(exec, x).get()); this->template log( - this, alpha, b, beta, x); + this, alpha.get(), b.get(), beta.get(), x.get()); return this; } @@ -399,7 +405,7 @@ class LinOp : public EnableAbstractPolymorphicObject { * // create a linear operator which represents the solver * auto cg = cg_factory->generate(A); * // solve the system - * cg->apply(gko::lend(b), gko::lend(x)); + * cg->apply(b, x); * ``` * * @ingroup LinOp @@ -829,7 +835,8 @@ class ScaledIdentityAddable { * @param b Scalar to multiply this before adding the scaled identity to * it. */ - void add_scaled_identity(const LinOp* const a, const LinOp* const b) + void add_scaled_identity(ptr_param const a, + ptr_param const b) { GKO_ASSERT_IS_SCALAR(a); GKO_ASSERT_IS_SCALAR(b); @@ -885,27 +892,30 @@ class EnableLinOp using EnablePolymorphicObject::EnablePolymorphicObject; - const ConcreteLinOp* apply(const LinOp* b, LinOp* x) const + const ConcreteLinOp* apply(ptr_param b, + ptr_param x) const { PolymorphicBase::apply(b, x); return self(); } - ConcreteLinOp* apply(const LinOp* b, LinOp* x) + ConcreteLinOp* apply(ptr_param b, ptr_param x) { PolymorphicBase::apply(b, x); return self(); } - const ConcreteLinOp* apply(const LinOp* alpha, const LinOp* b, - const LinOp* beta, LinOp* x) const + const ConcreteLinOp* apply(ptr_param alpha, + ptr_param b, + ptr_param beta, + ptr_param x) const { PolymorphicBase::apply(alpha, b, beta, x); return self(); } - ConcreteLinOp* apply(const LinOp* alpha, const LinOp* b, const LinOp* beta, - LinOp* x) + ConcreteLinOp* apply(ptr_param alpha, ptr_param b, + ptr_param beta, ptr_param x) { PolymorphicBase::apply(alpha, b, beta, x); return self(); diff --git a/include/ginkgo/core/base/mtx_io.hpp b/include/ginkgo/core/base/mtx_io.hpp index c1a19e4401b..2e1a4191bf5 100644 --- a/include/ginkgo/core/base/mtx_io.hpp +++ b/include/ginkgo/core/base/mtx_io.hpp @@ -312,20 +312,21 @@ struct mtx_io_traits { /** * Writes a matrix into an output stream in matrix market format. * - * @tparam MatrixType a WritableToMatrixData object providing data to be - * written. + * @tparam MatrixPtrType a (smart or raw) pointer to a WritableToMatrixData + * object providing data to be written. * @tparam StreamType type of stream used to write the data to * * @param os output stream where the data is to be written * @param matrix the matrix to write * @param layout the layout used in the output */ -template +template inline void write( - StreamType&& os, MatrixType* matrix, - layout_type layout = - detail::mtx_io_traits>::default_layout) + StreamType&& os, MatrixPtrType&& matrix, + layout_type layout = detail::mtx_io_traits< + std::remove_cv_t>>::default_layout) { + using MatrixType = detail::pointee; matrix_data data{}; @@ -340,16 +341,17 @@ inline void write( * so files from a big endian processor can't be read from a little endian * processor and vice-versa. * - * @tparam MatrixType a WritableToMatrixData object providing data to be - * written. + * @tparam MatrixPtrType a (smart or raw) pointer to a WritableToMatrixData + * object providing data to be written. * @tparam StreamType type of stream used to write the data to * * @param os output stream where the data is to be written * @param matrix the matrix to write */ -template -inline void write_binary(StreamType&& os, MatrixType* matrix) +template +inline void write_binary(StreamType&& os, MatrixPtrType&& matrix) { + using MatrixType = detail::pointee; matrix_data data{}; diff --git a/include/ginkgo/core/base/perturbation.hpp b/include/ginkgo/core/base/perturbation.hpp index 7a0b6d64ef3..4e9adc4e94e 100644 --- a/include/ginkgo/core/base/perturbation.hpp +++ b/include/ginkgo/core/base/perturbation.hpp @@ -135,7 +135,7 @@ class Perturbation : public EnableLinOp>, // basis can not be std::move(basis). Otherwise, Program deletes // basis before applying conjugate transpose basis, - std::move((as(lend(basis)))->conj_transpose())) + std::move((as(basis))->conj_transpose())) {} /** diff --git a/include/ginkgo/core/base/polymorphic_object.hpp b/include/ginkgo/core/base/polymorphic_object.hpp index 06a34c8aebe..8c3bb3bd96c 100644 --- a/include/ginkgo/core/base/polymorphic_object.hpp +++ b/include/ginkgo/core/base/polymorphic_object.hpp @@ -175,8 +175,20 @@ class PolymorphicObject : public log::EnableLogging { * @param other the object to move from * * @return this + * + * @tparam Derived the actual pointee type of the parameter, it needs to be + * derived from PolymorphicObject. + * @tparam Deleter the deleter of the unique_ptr parameter */ - PolymorphicObject* copy_from(std::unique_ptr other) + template + [[deprecated( + "This function will be removed in a future release, the replacement " + "will copy instead of move. If a move in intended, use move_to " + "instead.")]] std:: + enable_if_t< + std::is_base_of>::value, + PolymorphicObject>* + copy_from(std::unique_ptr&& other) { this->template log( exec_.get(), other.get(), this); @@ -187,24 +199,28 @@ class PolymorphicObject : public log::EnableLogging { } /** - * Moves another object into this object. - * - * This is the polymorphic equivalent of the move assignment operator. - * - * @see move_from_impl(PolymorphicObject *) - * - * @param other the object to move from + * @copydoc copy_from(const PolymorphicObject*) * - * @return this + * @tparam Derived the actual pointee type of the parameter, it needs to be + * derived from PolymorphicObject. + * @tparam Deleter the deleter of the unique_ptr parameter */ - PolymorphicObject* move_from(PolymorphicObject* other) + template + std::enable_if_t< + std::is_base_of>::value, + PolymorphicObject>* + copy_from(const std::unique_ptr& other) { - this->template log( - exec_.get(), other, this); - auto moved = this->move_from_impl(other); - this->template log( - exec_.get(), other, this); - return moved; + return this->copy_from(other.get()); + } + + /** + * @copydoc copy_from(const PolymorphicObject*) + */ + PolymorphicObject* copy_from( + const std::shared_ptr& other) + { + return this->copy_from(other.get()); } /** @@ -212,20 +228,20 @@ class PolymorphicObject : public log::EnableLogging { * * This is the polymorphic equivalent of the move assignment operator. * - * @see move_from_impl(std::unique_ptr) + * @see move_from_impl(PolymorphicObject *) * * @param other the object to move from * * @return this */ - PolymorphicObject* move_from(std::unique_ptr other) + PolymorphicObject* move_from(ptr_param other) { this->template log( exec_.get(), other.get(), this); - auto copied = this->copy_from_impl(std::move(other)); + auto moved = this->move_from_impl(other.get()); this->template log( exec_.get(), other.get(), this); - return copied; + return moved; } /** @@ -391,22 +407,39 @@ class EnableAbstractPolymorphicObject : public PolymorphicBase { this->PolymorphicBase::copy_from(other)); } - AbstractObject* copy_from(std::unique_ptr other) + template + [[deprecated( + "This function will be removed in a future release, the replacement " + "will copy instead of move. If a move in intended, use move_to " + "instead.")]] std:: + enable_if_t< + std::is_base_of>::value, + AbstractObject>* + copy_from(std::unique_ptr&& other) { return static_cast( this->PolymorphicBase::copy_from(std::move(other))); } - AbstractObject* move_from(PolymorphicObject* other) + template + std::enable_if_t< + std::is_base_of>::value, + AbstractObject>* + copy_from(const std::unique_ptr& other) { - return static_cast( - this->PolymorphicBase::move_from(other)); + return copy_from(other.get()); } - AbstractObject* move_from(std::unique_ptr other) + AbstractObject* copy_from( + const std::shared_ptr& other) + { + return copy_from(other.get()); + } + + AbstractObject* move_from(ptr_param other) { return static_cast( - this->PolymorphicBase::move_from(std::move(other))); + this->PolymorphicBase::move_from(other.get())); } AbstractObject* clear() @@ -477,6 +510,11 @@ class ConvertibleTo { */ virtual void convert_to(result_type* result) const = 0; + void convert_to(ptr_param result) const + { + convert_to(result.get()); + } + /** * Converts the implementer to an object of type result_type by moving data * from this object. @@ -492,6 +530,8 @@ class ConvertibleTo { * moved to the result. */ virtual void move_to(result_type* result) = 0; + + void move_to(ptr_param result) { move_to(result.get()); } }; @@ -504,10 +544,11 @@ std::unique_ptr> copy_and_convert_to_impl( { auto obj_as_r = dynamic_cast(obj); if (obj_as_r != nullptr && obj->get_executor() == exec) { + // FIXME: this breaks lifetimes return {obj_as_r, [](R*) {}}; } else { auto copy = R::create(exec); - as>>(obj)->convert_to(lend(copy)); + as>>(obj)->convert_to(copy); return {copy.release(), std::default_delete{}}; } } @@ -522,7 +563,7 @@ std::shared_ptr copy_and_convert_to_impl( return obj_as_r; } else { auto copy = R::create(exec); - as>>(obj.get())->convert_to(lend(copy)); + as>>(obj.get())->convert_to(copy); return {std::move(copy)}; } } @@ -712,6 +753,8 @@ template class EnablePolymorphicAssignment : public ConvertibleTo { public: using result_type = ResultType; + using ConvertibleTo::convert_to; + using ConvertibleTo::move_to; void convert_to(result_type* result) const override { *result = *self(); } diff --git a/include/ginkgo/core/base/precision_dispatch.hpp b/include/ginkgo/core/base/precision_dispatch.hpp index ad6d0cd36bf..d9542db44db 100644 --- a/include/ginkgo/core/base/precision_dispatch.hpp +++ b/include/ginkgo/core/base/precision_dispatch.hpp @@ -68,27 +68,19 @@ namespace gko { * @tparam ValueType the value type into whose associated matrix::Dense type to * convert the input LinOp. */ -template -detail::temporary_conversion> -make_temporary_conversion(LinOp* matrix) +template +detail::temporary_conversion>::value, const matrix::Dense, + matrix::Dense>> +make_temporary_conversion(Ptr&& matrix) { - auto result = - detail::temporary_conversion>::template create< - matrix::Dense>>(matrix); - if (!result) { - GKO_NOT_SUPPORTED(matrix); - } - return result; -} - - -/** @copydoc make_temporary_conversion(LinOp*) */ -template -detail::temporary_conversion> -make_temporary_conversion(const LinOp* matrix) -{ - auto result = detail::temporary_conversion>:: - template create>>(matrix); + using Pointee = detail::pointee; + using Dense = matrix::Dense; + using NextDense = matrix::Dense>; + using MaybeConstDense = + std::conditional_t::value, const Dense, Dense>; + auto result = detail::temporary_conversion< + MaybeConstDense>::template create(matrix); if (!result) { GKO_NOT_SUPPORTED(matrix); } diff --git a/include/ginkgo/core/base/temporary_clone.hpp b/include/ginkgo/core/base/temporary_clone.hpp index 87ba89fb0f2..8a9f5a9b152 100644 --- a/include/ginkgo/core/base/temporary_clone.hpp +++ b/include/ginkgo/core/base/temporary_clone.hpp @@ -140,19 +140,19 @@ class temporary_clone { * @param copy_data should the data be copied to the executor, or should * only the result be copied back afterwards? */ - explicit temporary_clone(std::shared_ptr exec, pointer ptr, - bool copy_data = true) + explicit temporary_clone(std::shared_ptr exec, + ptr_param ptr, bool copy_data = true) { if (ptr->get_executor()->memory_accessible(exec)) { // just use the object we already have - handle_ = handle_type(ptr, null_deleter()); + handle_ = handle_type(ptr.get(), null_deleter()); } else { // clone the object to the new executor and make sure it's copied // back before we delete it handle_ = handle_type(temporary_clone_helper::create( - std::move(exec), ptr, copy_data) + std::move(exec), ptr.get(), copy_data) .release(), - copy_back_deleter(ptr)); + copy_back_deleter(ptr.get())); } } @@ -188,6 +188,9 @@ class temporary_clone { } // namespace detail +template +struct err {}; + /** * Creates a temporary_clone. * @@ -197,12 +200,15 @@ class temporary_clone { * * @param exec the executor where the clone will be created * @param ptr a pointer to the object of which the clone will be created + * + * @tparam Ptr the (raw or smart) pointer type to be temporarily cloned */ -template -detail::temporary_clone make_temporary_clone( - std::shared_ptr exec, T* ptr) +template +detail::temporary_clone> make_temporary_clone( + std::shared_ptr exec, Ptr&& ptr) { - return detail::temporary_clone(std::move(exec), ptr); + using T = detail::pointee; + return detail::temporary_clone(std::move(exec), std::forward(ptr)); } @@ -217,15 +223,19 @@ detail::temporary_clone make_temporary_clone( * * @param exec the executor where the uninitialized clone will be created * @param ptr a pointer to the object of which the clone will be created + * + * @tparam Ptr the (raw or smart) pointer type to be temporarily cloned */ -template -detail::temporary_clone make_temporary_output_clone( - std::shared_ptr exec, T* ptr) +template +detail::temporary_clone> make_temporary_output_clone( + std::shared_ptr exec, Ptr&& ptr) { + using T = detail::pointee; static_assert( !std::is_const::value, "make_temporary_output_clone should only be used on non-const objects"); - return detail::temporary_clone(std::move(exec), ptr, false); + return detail::temporary_clone(std::move(exec), std::forward(ptr), + false); } diff --git a/include/ginkgo/core/base/temporary_conversion.hpp b/include/ginkgo/core/base/temporary_conversion.hpp index e94974fce58..64506a95e98 100644 --- a/include/ginkgo/core/base/temporary_conversion.hpp +++ b/include/ginkgo/core/base/temporary_conversion.hpp @@ -234,14 +234,14 @@ class temporary_conversion { * try out for converting ptr to type T. */ template - static temporary_conversion create(lin_op_type* ptr) + static temporary_conversion create(ptr_param ptr) { T* cast_ptr{}; - if ((cast_ptr = dynamic_cast(ptr))) { + if ((cast_ptr = dynamic_cast(ptr.get()))) { return handle_type{cast_ptr, null_deleter{}}; } else { return conversion_helper::template convert< - T>(ptr); + T>(ptr.get()); } } diff --git a/include/ginkgo/core/base/utils_helper.hpp b/include/ginkgo/core/base/utils_helper.hpp index 237d64c0ef6..3f26d5d7659 100644 --- a/include/ginkgo/core/base/utils_helper.hpp +++ b/include/ginkgo/core/base/utils_helper.hpp @@ -56,29 +56,72 @@ namespace gko { class Executor; -namespace detail { +/** + * This class is used for function parameters in the place of raw pointers. + * Pointer parameters should be used for everything that does not involve + * transfer of ownership. It can be converted to from raw pointers, shared + * pointers and unique pointers of the specified type or any derived type. This + * allows functions to be called without having to use gko::lend or calling + * .get() for every pointer argument. It probably has no use outside of function + * parameters, as it is immutable. + * + * @tparam T the pointed-to type + */ +template +class ptr_param { +public: + /** Initializes the ptr_param from a raw pointer. */ + ptr_param(T* ptr) : ptr_{ptr} {} + /** Initializes the ptr_param from a shared_ptr. */ + template ::value>* = nullptr> + ptr_param(const std::shared_ptr& ptr) : ptr_param{ptr.get()} + {} -template -struct pointee_impl {}; + /** Initializes the ptr_param from a unique_ptr. */ + template ::value>* = nullptr> + ptr_param(const std::unique_ptr& ptr) : ptr_param{ptr.get()} + {} -template -struct pointee_impl { - using type = T; -}; + /** Initializes the ptr_param from a ptr_param of a derived type. */ + template ::value>* = nullptr> + ptr_param(const ptr_param& ptr) : ptr_param{ptr.get()} + {} -template -struct pointee_impl> { - using type = T; -}; + ptr_param(const ptr_param&) = default; -template -struct pointee_impl> { - using type = T; + ptr_param(ptr_param&&) = default; + + /** @return a reference to the underlying pointee. */ + T& operator*() const { return *ptr_; } + + /** @return the underlying pointer. */ + T* operator->() const { return ptr_; } + + /** @return the underlying pointer. */ + T* get() const { return ptr_; } + + /** @return true iff the underlying pointer is non-null. */ + explicit operator bool() const { return ptr_; } + + ptr_param& operator=(const ptr_param&) = delete; + + ptr_param& operator=(ptr_param&&) = delete; + +private: + T* ptr_; }; + +namespace detail { + + template -using pointee = typename pointee_impl::type>::type; +using pointee = + std::remove_reference_t>())>; template @@ -91,7 +134,7 @@ struct is_clonable_impl().clone())>> template constexpr bool is_clonable() { - return is_clonable_impl::type>::value; + return is_clonable_impl>::value; } @@ -107,7 +150,7 @@ struct is_clonable_to_impl< template constexpr bool is_clonable_to() { - return is_clonable_to_impl::type>::value; + return is_clonable_to_impl>::value; } @@ -121,7 +164,7 @@ template struct have_ownership_impl> : std::true_type {}; template -using have_ownership_s = have_ownership_impl::type>; +using have_ownership_s = have_ownership_impl>; template constexpr bool have_ownership() @@ -251,9 +294,10 @@ inline typename std::remove_reference::type&& give( * same as calling .get() on the smart pointer. */ template -inline typename std::enable_if::value, - detail::pointee*>::type -lend(const Pointer& p) +[[deprecated("no longer necessary, just pass the object without lend")]] inline + typename std::enable_if::value, + detail::pointee*>::type + lend(const Pointer& p) { return p.get(); } @@ -269,9 +313,10 @@ lend(const Pointer& p) * returns `p`. */ template -inline typename std::enable_if::value, - detail::pointee*>::type -lend(const Pointer& p) +[[deprecated("no longer necessary, just pass the object without lend")]] inline + typename std::enable_if::value, + detail::pointee*>::type + lend(const Pointer& p) { return p; } @@ -289,9 +334,9 @@ lend(const Pointer& p) * NotSupported. */ template -inline typename std::decay::type* as(U* obj) +inline std::decay_t* as(U* obj) { - if (auto p = dynamic_cast::type*>(obj)) { + if (auto p = dynamic_cast*>(obj)) { return p; } else { throw NotSupported(__FILE__, __LINE__, @@ -315,9 +360,9 @@ inline typename std::decay::type* as(U* obj) * NotSupported. */ template -inline const typename std::decay::type* as(const U* obj) +inline const std::decay_t* as(const U* obj) { - if (auto p = dynamic_cast::type*>(obj)) { + if (auto p = dynamic_cast*>(obj)) { return p; } else { throw NotSupported(__FILE__, __LINE__, @@ -328,6 +373,43 @@ inline const typename std::decay::type* as(const U* obj) } +/** + * Performs polymorphic type conversion on a ptr_param. + * + * @tparam T requested result type + * @tparam U static type of the passed object + * + * @param obj the object which should be converted + * + * @return If successful, returns a pointer to the subtype, otherwise throws + * NotSupported. + */ +template +inline std::decay_t* as(ptr_param obj) +{ + return as(obj.get()); +} + +/** + * Performs polymorphic type conversion. + * + * This is the constant version of the function. + * + * @tparam T requested result type + * @tparam U static type of the passed object + * + * @param obj the object which should be converted + * + * @return If successful, returns a pointer to the subtype, otherwise throws + * NotSupported. + */ +template +inline const std::decay_t* as(ptr_param obj) +{ + return as(obj.get()); +} + + /** * Performs polymorphic type conversion of a unique_ptr. * @@ -341,12 +423,11 @@ inline const typename std::decay::type* as(const U* obj) * NotSupported. */ template -inline std::unique_ptr::type> as( - std::unique_ptr&& obj) +inline std::unique_ptr> as(std::unique_ptr&& obj) { - if (auto p = dynamic_cast::type*>(obj.get())) { + if (auto p = dynamic_cast*>(obj.get())) { obj.release(); - return std::unique_ptr::type>{p}; + return std::unique_ptr>{p}; } else { throw NotSupported(__FILE__, __LINE__, __func__, name_demangling::get_type_name(typeid(*obj))); @@ -366,9 +447,9 @@ inline std::unique_ptr::type> as( * NotSupported. This pointer shares ownership with the input pointer. */ template -inline std::shared_ptr::type> as(std::shared_ptr obj) +inline std::shared_ptr> as(std::shared_ptr obj) { - auto ptr = std::dynamic_pointer_cast::type>(obj); + auto ptr = std::dynamic_pointer_cast>(obj); if (ptr) { return ptr; } else { @@ -392,11 +473,9 @@ inline std::shared_ptr::type> as(std::shared_ptr obj) * NotSupported. This pointer shares ownership with the input pointer. */ template -inline std::shared_ptr::type> as( - std::shared_ptr obj) +inline std::shared_ptr> as(std::shared_ptr obj) { - auto ptr = - std::dynamic_pointer_cast::type>(obj); + auto ptr = std::dynamic_pointer_cast>(obj); if (ptr) { return ptr; } else { diff --git a/include/ginkgo/core/distributed/lin_op.hpp b/include/ginkgo/core/distributed/lin_op.hpp index 0b27957f68b..e7fe8b1b4f9 100644 --- a/include/ginkgo/core/distributed/lin_op.hpp +++ b/include/ginkgo/core/distributed/lin_op.hpp @@ -75,27 +75,30 @@ class EnableDistributedLinOp using EnableDistributedPolymorphicObject< ConcreteLinOp, PolymorphicBase>::EnableDistributedPolymorphicObject; - const ConcreteLinOp* apply(const LinOp* b, LinOp* x) const + const ConcreteLinOp* apply(ptr_param b, + ptr_param x) const { PolymorphicBase::apply(b, x); return self(); } - ConcreteLinOp* apply(const LinOp* b, LinOp* x) + ConcreteLinOp* apply(ptr_param b, ptr_param x) { PolymorphicBase::apply(b, x); return self(); } - const ConcreteLinOp* apply(const LinOp* alpha, const LinOp* b, - const LinOp* beta, LinOp* x) const + const ConcreteLinOp* apply(ptr_param alpha, + ptr_param b, + ptr_param beta, + ptr_param x) const { PolymorphicBase::apply(alpha, b, beta, x); return self(); } - ConcreteLinOp* apply(const LinOp* alpha, const LinOp* b, const LinOp* beta, - LinOp* x) + ConcreteLinOp* apply(ptr_param alpha, ptr_param b, + ptr_param beta, ptr_param x) { PolymorphicBase::apply(alpha, b, beta, x); return self(); diff --git a/include/ginkgo/core/distributed/matrix.hpp b/include/ginkgo/core/distributed/matrix.hpp index 06be1aa6812..215c446cceb 100644 --- a/include/ginkgo/core/distributed/matrix.hpp +++ b/include/ginkgo/core/distributed/matrix.hpp @@ -285,6 +285,10 @@ class Matrix using EnableDistributedLinOp::convert_to; using EnableDistributedLinOp::move_to; + using ConvertibleTo, LocalIndexType, + GlobalIndexType>>::convert_to; + using ConvertibleTo, LocalIndexType, + GlobalIndexType>>::move_to; void convert_to(Matrix, local_index_type, global_index_type>* result) const override; @@ -308,7 +312,8 @@ class Matrix */ void read_distributed( const device_matrix_data& data, - const Partition* partition); + ptr_param> + partition); /** * Reads a square matrix from the matrix_data structure and a global @@ -321,7 +326,8 @@ class Matrix */ void read_distributed( const matrix_data& data, - const Partition* partition); + ptr_param> + partition); /** * Reads a matrix from the device_matrix_data structure, a global row @@ -340,8 +346,10 @@ class Matrix */ void read_distributed( const device_matrix_data& data, - const Partition* row_partition, - const Partition* col_partition); + ptr_param> + row_partition, + ptr_param> + col_partition); /** * Reads a matrix from the matrix_data structure, a global row partition, @@ -354,8 +362,10 @@ class Matrix */ void read_distributed( const matrix_data& data, - const Partition* row_partition, - const Partition* col_partition); + ptr_param> + row_partition, + ptr_param> + col_partition); /** * Get read access to the stored local matrix. @@ -506,7 +516,8 @@ class Matrix * same runtime type. */ explicit Matrix(std::shared_ptr exec, - mpi::communicator comm, const LinOp* matrix_template); + mpi::communicator comm, + ptr_param matrix_template); /** * Creates an empty distributed matrix with specified types for the local @@ -523,8 +534,9 @@ class Matrix * constructed with the same runtime type. */ explicit Matrix(std::shared_ptr exec, - mpi::communicator comm, const LinOp* local_matrix_template, - const LinOp* non_local_matrix_template); + mpi::communicator comm, + ptr_param local_matrix_template, + ptr_param non_local_matrix_template); /** * Starts a non-blocking communication of the values of b that are shared diff --git a/include/ginkgo/core/distributed/vector.hpp b/include/ginkgo/core/distributed/vector.hpp index 2469e4b61ac..6cb96ca892b 100644 --- a/include/ginkgo/core/distributed/vector.hpp +++ b/include/ginkgo/core/distributed/vector.hpp @@ -99,6 +99,8 @@ class Vector public: using EnableDistributedLinOp::convert_to; using EnableDistributedLinOp::move_to; + using ConvertibleTo>>::convert_to; + using ConvertibleTo>>::move_to; using value_type = ValueType; using absolute_type = remove_complex; @@ -112,7 +114,8 @@ class Vector * * @param other The other vector whose configuration needs to copied. */ - static std::unique_ptr create_with_config_of(const Vector* other); + static std::unique_ptr create_with_config_of( + ptr_param other); /** @@ -127,7 +130,7 @@ class Vector * @returns an empty Vector with the type of other. */ static std::unique_ptr create_with_type_of( - const Vector* other, std::shared_ptr exec); + ptr_param other, std::shared_ptr exec); /** * Creates an Vector with the same type as another Vector, but on a @@ -142,7 +145,7 @@ class Vector * @returns a Vector of specified size with the type of other. */ static std::unique_ptr create_with_type_of( - const Vector* other, std::shared_ptr exec, + ptr_param other, std::shared_ptr exec, const dim<2>& global_size, const dim<2>& local_size, size_type stride); /** @@ -159,10 +162,14 @@ class Vector * @param data The device_matrix_data structure * @param partition The global row partition */ - template - void read_distributed( - const device_matrix_data& data, - const Partition* partition); + void read_distributed(const device_matrix_data& data, + ptr_param> partition); + + void read_distributed(const device_matrix_data& data, + ptr_param> partition); + + void read_distributed(const device_matrix_data& data, + ptr_param> partition); /** * Reads a vector from the matrix_data structure and a global row @@ -173,10 +180,14 @@ class Vector * @note For efficiency it is advised to use the device_matrix_data * overload. */ - template - void read_distributed( - const matrix_data& data, - const Partition* partition); + void read_distributed(const matrix_data& data, + ptr_param> partition); + + void read_distributed(const matrix_data& data, + ptr_param> partition); + + void read_distributed(const matrix_data& data, + ptr_param> partition); void convert_to(Vector>* result) const override; @@ -197,7 +208,7 @@ class Vector * If the original vectors were real, the imaginary part of the result will * be zero. */ - void make_complex(complex_type* result) const; + void make_complex(ptr_param result) const; /** * Creates new real vectors and extracts the real part of the original @@ -208,7 +219,7 @@ class Vector /** * Extracts the real part of the original vectors into given real vectors. */ - void get_real(real_type* result) const; + void get_real(ptr_param result) const; /** * Creates new real vectors and extracts the imaginary part of the @@ -220,7 +231,7 @@ class Vector * Extracts the imaginary part of the original vectors into given real * vectors. */ - void get_imag(real_type* result) const; + void get_imag(ptr_param result) const; /** * Fill the distributed vectors with a given value. @@ -238,7 +249,7 @@ class Vector * element of alpha (the number of columns of alpha has to * match the number of vectors). */ - void scale(const LinOp* alpha); + void scale(ptr_param alpha); /** * Scales the vectors with the inverse of a scalar. @@ -249,7 +260,7 @@ class Vector * of the i-th element of alpha (the number of columns of * alpha has to match the number of vectors). */ - void inv_scale(const LinOp* alpha); + void inv_scale(ptr_param alpha); /** * Adds `b` scaled by `alpha` to the vectors (aka: BLAS axpy). @@ -260,7 +271,7 @@ class Vector * columns of alpha has to match the number of vectors). * @param b a (multi-)vector of the same dimension as this */ - void add_scaled(const LinOp* alpha, const LinOp* b); + void add_scaled(ptr_param alpha, ptr_param b); /** * Subtracts `b` scaled by `alpha` from the vectors (aka: BLAS axpy). @@ -270,7 +281,7 @@ class Vector * vector of b is scaled with the i-th element of alpha (the number of c * @param b a (multi-)vector of the same dimension as this */ - void sub_scaled(const LinOp* alpha, const LinOp* b); + void sub_scaled(ptr_param alpha, ptr_param b); /** * Computes the column-wise dot product of this (multi-)vector and `b` using @@ -281,7 +292,7 @@ class Vector * (the number of column in result must match the number * of columns of this) */ - void compute_dot(const LinOp* b, LinOp* result) const; + void compute_dot(ptr_param b, ptr_param result) const; /** * Computes the column-wise dot product of this (multi-)vector and `b` using @@ -295,7 +306,8 @@ class Vector * reduction computation. It may be resized and/or reset to the * correct executor. */ - void compute_dot(const LinOp* b, LinOp* result, array& tmp) const; + void compute_dot(ptr_param b, ptr_param result, + array& tmp) const; /** * Computes the column-wise dot product of this (multi-)vector and `conj(b)` @@ -306,7 +318,8 @@ class Vector * (the number of column in result must match the number * of columns of this) */ - void compute_conj_dot(const LinOp* b, LinOp* result) const; + void compute_conj_dot(ptr_param b, + ptr_param result) const; /** * Computes the column-wise dot product of this (multi-)vector and `conj(b)` @@ -320,7 +333,7 @@ class Vector * reduction computation. It may be resized and/or reset to the * correct executor. */ - void compute_conj_dot(const LinOp* b, LinOp* result, + void compute_conj_dot(ptr_param b, ptr_param result, array& tmp) const; /** @@ -331,7 +344,7 @@ class Vector * (the number of columns in result must match the number * of columns of this) */ - void compute_norm2(LinOp* result) const; + void compute_norm2(ptr_param result) const; /** * Computes the Euclidian (L^2) norm of this (multi-)vector using a global @@ -344,7 +357,7 @@ class Vector * reduction computation. It may be resized and/or reset to the * correct executor. */ - void compute_norm2(LinOp* result, array& tmp) const; + void compute_norm2(ptr_param result, array& tmp) const; /** * Computes the column-wise (L^1) norm of this (multi-)vector. @@ -353,7 +366,7 @@ class Vector * (the number of columns in result must match the number * of columns of this) */ - void compute_norm1(LinOp* result) const; + void compute_norm1(ptr_param result) const; /** * Computes the column-wise (L^1) norm of this (multi-)vector using a global @@ -366,7 +379,7 @@ class Vector * reduction computation. It may be resized and/or reset to the * correct executor. */ - void compute_norm1(LinOp* result, array& tmp) const; + void compute_norm1(ptr_param result, array& tmp) const; /** * Returns a single element of the multi-vector. @@ -485,7 +498,7 @@ class Vector * into this */ Vector(std::shared_ptr exec, mpi::communicator comm, - dim<2> global_size, local_vector_type* local_vector); + dim<2> global_size, ptr_param local_vector); /** * Creates a distributed vector from local vectors. The global size will @@ -502,10 +515,15 @@ class Vector * into this */ Vector(std::shared_ptr exec, mpi::communicator comm, - local_vector_type* local_vector); + ptr_param local_vector); void resize(dim<2> global_size, dim<2> local_size); + template + void read_distributed_impl( + const device_matrix_data& data, + const Partition* partition); + void apply_impl(const LinOp*, LinOp*) const override; void apply_impl(const LinOp*, const LinOp*, const LinOp*, diff --git a/include/ginkgo/core/log/logger.hpp b/include/ginkgo/core/log/logger.hpp index 465b4367280..65a30b74948 100644 --- a/include/ginkgo/core/log/logger.hpp +++ b/include/ginkgo/core/log/logger.hpp @@ -610,6 +610,11 @@ class Loggable { */ virtual void remove_logger(const Logger* logger) = 0; + void remove_logger(ptr_param logger) + { + remove_logger(logger.get()); + } + /** * Returns the vector containing all loggers registered at this object. * @@ -647,7 +652,7 @@ class EnableLogging : public PolymorphicBase { { auto idx = find_if(begin(loggers_), end(loggers_), - [&logger](const auto& l) { return lend(l) == logger; }); + [&logger](const auto& l) { return l.get() == logger; }); if (idx != end(loggers_)) { loggers_.erase(idx); } else { @@ -656,6 +661,11 @@ class EnableLogging : public PolymorphicBase { } } + void remove_logger(ptr_param logger) + { + remove_logger(logger.get()); + } + const std::vector>& get_loggers() const override { diff --git a/include/ginkgo/core/matrix/coo.hpp b/include/ginkgo/core/matrix/coo.hpp index 0cfd50fbbc4..9ccd02d48db 100644 --- a/include/ginkgo/core/matrix/coo.hpp +++ b/include/ginkgo/core/matrix/coo.hpp @@ -96,6 +96,12 @@ class Coo : public EnableLinOp>, public: using EnableLinOp::convert_to; using EnableLinOp::move_to; + using ConvertibleTo, IndexType>>::convert_to; + using ConvertibleTo, IndexType>>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; using ReadableFromMatrixData::read; using value_type = ValueType; @@ -210,9 +216,9 @@ class Coo : public EnableLinOp>, * * @return this */ - LinOp* apply2(const LinOp* b, LinOp* x) + LinOp* apply2(ptr_param b, ptr_param x) { - this->validate_application_parameters(b, x); + this->validate_application_parameters(b.get(), x.get()); auto exec = this->get_executor(); this->apply2_impl(make_temporary_clone(exec, b).get(), make_temporary_clone(exec, x).get()); @@ -222,9 +228,9 @@ class Coo : public EnableLinOp>, /** * @copydoc apply2(cost LinOp *, LinOp *) */ - const LinOp* apply2(const LinOp* b, LinOp* x) const + const LinOp* apply2(ptr_param b, ptr_param x) const { - this->validate_application_parameters(b, x); + this->validate_application_parameters(b.get(), x.get()); auto exec = this->get_executor(); this->apply2_impl(make_temporary_clone(exec, b).get(), make_temporary_clone(exec, x).get()); @@ -240,9 +246,10 @@ class Coo : public EnableLinOp>, * * @return this */ - LinOp* apply2(const LinOp* alpha, const LinOp* b, LinOp* x) + LinOp* apply2(ptr_param alpha, ptr_param b, + ptr_param x) { - this->validate_application_parameters(b, x); + this->validate_application_parameters(b.get(), x.get()); GKO_ASSERT_EQUAL_DIMENSIONS(alpha, dim<2>(1, 1)); auto exec = this->get_executor(); this->apply2_impl(make_temporary_clone(exec, alpha).get(), @@ -254,9 +261,10 @@ class Coo : public EnableLinOp>, /** * @copydoc apply2(const LinOp *, const LinOp *, LinOp *) */ - const LinOp* apply2(const LinOp* alpha, const LinOp* b, LinOp* x) const + const LinOp* apply2(ptr_param alpha, ptr_param b, + ptr_param x) const { - this->validate_application_parameters(b, x); + this->validate_application_parameters(b.get(), x.get()); GKO_ASSERT_EQUAL_DIMENSIONS(alpha, dim<2>(1, 1)); auto exec = this->get_executor(); this->apply2_impl(make_temporary_clone(exec, alpha).get(), diff --git a/include/ginkgo/core/matrix/csr.hpp b/include/ginkgo/core/matrix/csr.hpp index 31214dcaed1..d0bd515f586 100644 --- a/include/ginkgo/core/matrix/csr.hpp +++ b/include/ginkgo/core/matrix/csr.hpp @@ -158,6 +158,22 @@ class Csr : public EnableLinOp>, public: using EnableLinOp::convert_to; using EnableLinOp::move_to; + using ConvertibleTo, IndexType>>::convert_to; + using ConvertibleTo, IndexType>>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; using ReadableFromMatrixData::read; using value_type = ValueType; @@ -910,7 +926,7 @@ class Csr : public EnableLinOp>, * @param alpha The entire matrix is scaled by alpha. alpha has to be a 1x1 * Dense matrix. */ - void scale(const LinOp* alpha) + void scale(ptr_param alpha) { auto exec = this->get_executor(); GKO_ASSERT_EQUAL_DIMENSIONS(alpha, dim<2>(1, 1)); @@ -923,7 +939,7 @@ class Csr : public EnableLinOp>, * @param alpha The entire matrix is scaled by 1 / alpha. alpha has to be a * 1x1 Dense matrix. */ - void inv_scale(const LinOp* alpha) + void inv_scale(ptr_param alpha) { auto exec = this->get_executor(); GKO_ASSERT_EQUAL_DIMENSIONS(alpha, dim<2>(1, 1)); diff --git a/include/ginkgo/core/matrix/dense.hpp b/include/ginkgo/core/matrix/dense.hpp index c4bef828eb2..3a0eb374b07 100644 --- a/include/ginkgo/core/matrix/dense.hpp +++ b/include/ginkgo/core/matrix/dense.hpp @@ -35,6 +35,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include #include @@ -154,6 +155,36 @@ class Dense public: using EnableLinOp::convert_to; using EnableLinOp::move_to; + using ConvertibleTo>>::convert_to; + using ConvertibleTo>>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; using ReadableFromMatrixData::read; using ReadableFromMatrixData::read; @@ -176,7 +207,8 @@ class Dense * * @param other The other matrix whose configuration needs to copied. */ - static std::unique_ptr create_with_config_of(const Dense* other) + static std::unique_ptr create_with_config_of( + ptr_param other) { // De-referencing `other` before calling the functions (instead of // using operator `->`) is currently required to be compatible with @@ -197,7 +229,7 @@ class Dense * @returns a Dense matrix with the type of other. */ static std::unique_ptr create_with_type_of( - const Dense* other, std::shared_ptr exec, + ptr_param other, std::shared_ptr exec, const dim<2>& size = dim<2>{}) { // See create_with_config_of() @@ -213,7 +245,7 @@ class Dense * @note This is an overload which allows full parameter specification. */ static std::unique_ptr create_with_type_of( - const Dense* other, std::shared_ptr exec, + ptr_param other, std::shared_ptr exec, const dim<2>& size, size_type stride) { // See create_with_config_of() @@ -231,7 +263,7 @@ class Dense * gko::experimental::distributed::Vector */ static std::unique_ptr create_with_type_of( - const Dense* other, std::shared_ptr exec, + ptr_param other, std::shared_ptr exec, const dim<2>& size, const dim<2>& local_size, size_type stride) { // See create_with_config_of() @@ -246,7 +278,7 @@ class Dense * * @return A Dense matrix that is a view of other */ - static std::unique_ptr create_view_of(Dense* other) + static std::unique_ptr create_view_of(ptr_param other) { return other->create_view_of_impl(); } @@ -258,7 +290,8 @@ class Dense * @param other The other matrix on which to create the view * @return A immutable Dense matrix that is a view of other */ - static std::unique_ptr create_const_view_of(const Dense* other) + static std::unique_ptr create_const_view_of( + ptr_param other) { return other->create_const_view_of_impl(); } @@ -351,7 +384,7 @@ class Dense * @param output The output matrix. It must have the dimensions * `gko::transpose(this->get_size())` */ - void transpose(Dense* output) const; + void transpose(ptr_param output) const; /** * Writes the conjugate-transposed matrix into the given output matrix. @@ -359,7 +392,7 @@ class Dense * @param output The output matrix. It must have the dimensions * `gko::transpose(this->get_size())` */ - void conj_transpose(Dense* output) const; + void conj_transpose(ptr_param output) const; /** * Fill the dense matrix with a given value. @@ -383,12 +416,14 @@ class Dense * `this->get_size()` * @see Dense::permute(const array*) */ - void permute(const array* permutation_indices, Dense* output) const; + void permute(const array* permutation_indices, + ptr_param output) const; /** * @copydoc Dense::permute(const array*, Dense*) */ - void permute(const array* permutation_indices, Dense* output) const; + void permute(const array* permutation_indices, + ptr_param output) const; std::unique_ptr inverse_permute( const array* permutation_indices) const override; @@ -407,13 +442,13 @@ class Dense * @see Dense::inverse_permute(const array*) */ void inverse_permute(const array* permutation_indices, - Dense* output) const; + ptr_param output) const; /** * @copydoc Dense::inverse_permute(const array*, Dense*) */ void inverse_permute(const array* permutation_indices, - Dense* output) const; + ptr_param output) const; std::unique_ptr row_permute( const array* permutation_indices) const override; @@ -431,13 +466,13 @@ class Dense * @see Dense::row_permute(const array*) */ void row_permute(const array* permutation_indices, - Dense* output) const; + ptr_param output) const; /** * @copydoc Dense::row_permute(const array*, Dense*) */ void row_permute(const array* permutation_indices, - Dense* output) const; + ptr_param output) const; /** * Create a Dense matrix consisting of the given rows from this matrix. @@ -456,26 +491,6 @@ class Dense */ std::unique_ptr row_gather(const array* gather_indices) const; - /** - * Copies the given rows from this matrix into `row_collection` - * - * @param gather_indices pointer to an array containing row indices - * from this matrix. It may contain duplicates. - * @param row_collection pointer to a Dense matrix that will store the - * gathered rows: - * `row_collection(i,j) = input(gather_indices(i), j)` - * It must have the same number of columns as this - * matrix and `gather_indices->get_num_elems()` rows. - */ - void row_gather(const array* gather_indices, - Dense* row_collection) const; - - /** - * @copydoc row_gather(const array*, Dense*) const - */ - void row_gather(const array* gather_indices, - Dense* row_collection) const; - /** * Copies the given rows from this matrix into `row_collection` * @@ -489,13 +504,13 @@ class Dense * matrix and `gather_indices->get_num_elems()` rows. */ void row_gather(const array* gather_indices, - LinOp* row_collection) const; + ptr_param row_collection) const; /** * @copydoc row_gather(const array*, LinOp*) const */ void row_gather(const array* gather_indices, - LinOp* row_collection) const; + ptr_param row_collection) const; /** * Copies the given rows from this matrix into `row_collection` with scaling @@ -510,15 +525,19 @@ class Dense * It must have the same number of columns as this * matrix and `gather_indices->get_num_elems()` rows. */ - void row_gather(const LinOp* alpha, const array* gather_indices, - const LinOp* beta, LinOp* row_collection) const; + void row_gather(ptr_param alpha, + const array* gather_indices, + ptr_param beta, + ptr_param row_collection) const; /** * @copydoc row_gather(const LinOp*, const array*, const LinOp*, * LinOp*) const */ - void row_gather(const LinOp* alpha, const array* gather_indices, - const LinOp* beta, LinOp* row_collection) const; + void row_gather(ptr_param alpha, + const array* gather_indices, + ptr_param beta, + ptr_param row_collection) const; std::unique_ptr column_permute( const array* permutation_indices) const override; @@ -536,13 +555,13 @@ class Dense * @see Dense::column_permute(const array*) */ void column_permute(const array* permutation_indices, - Dense* output) const; + ptr_param output) const; /** * @copydoc Dense::column_permute(const array*, Dense*) */ void column_permute(const array* permutation_indices, - Dense* output) const; + ptr_param output) const; std::unique_ptr inverse_row_permute( const array* permutation_indices) const override; @@ -560,13 +579,13 @@ class Dense * @see Dense::inverse_row_permute(const array*) */ void inverse_row_permute(const array* permutation_indices, - Dense* output) const; + ptr_param output) const; /** * @copydoc Dense::inverse_row_permute(const array*, Dense*) */ void inverse_row_permute(const array* permutation_indices, - Dense* output) const; + ptr_param output) const; std::unique_ptr inverse_column_permute( const array* permutation_indices) const override; @@ -584,13 +603,13 @@ class Dense * @see Dense::inverse_column_permute(const array*) */ void inverse_column_permute(const array* permutation_indices, - Dense* output) const; + ptr_param output) const; /** * @copydoc Dense::inverse_column_permute(const array*, Dense*) */ void inverse_column_permute(const array* permutation_indices, - Dense* output) const; + ptr_param output) const; std::unique_ptr> extract_diagonal() const override; @@ -601,7 +620,7 @@ class Dense * matrix's diagonal. * @see Dense::extract_diagonal() */ - void extract_diagonal(Diagonal* output) const; + void extract_diagonal(ptr_param> output) const; std::unique_ptr compute_absolute() const override; @@ -612,7 +631,7 @@ class Dense * matrix. * @see Dense::compute_absolute() */ - void compute_absolute(absolute_type* output) const; + void compute_absolute(ptr_param output) const; void compute_absolute_inplace() override; @@ -627,7 +646,7 @@ class Dense * If the original matrix was real, the imaginary part of the result will * be zero. */ - void make_complex(complex_type* result) const; + void make_complex(ptr_param result) const; /** * Creates a new real matrix and extracts the real part of the original @@ -638,7 +657,7 @@ class Dense /** * Extracts the real part of the original matrix into a given real matrix. */ - void get_real(real_type* result) const; + void get_real(ptr_param result) const; /** * Creates a new real matrix and extracts the imaginary part of the @@ -650,7 +669,7 @@ class Dense * Extracts the imaginary part of the original matrix into a given real * matrix. */ - void get_imag(real_type* result) const; + void get_imag(ptr_param result) const; /** * Returns a pointer to the array of values of the matrix. @@ -747,7 +766,7 @@ class Dense * element of alpha (the number of columns of alpha has to * match the number of columns of the matrix). */ - void scale(const LinOp* alpha); + void scale(ptr_param alpha); /** * Scales the matrix with the inverse of a scalar. @@ -758,7 +777,7 @@ class Dense * of the i-th element of alpha (the number of columns of * alpha has to match the number of columns of the matrix). */ - void inv_scale(const LinOp* alpha); + void inv_scale(ptr_param alpha); /** * Adds `b` scaled by `alpha` to the matrix (aka: BLAS axpy). @@ -770,7 +789,7 @@ class Dense * match the number of columns of the matrix). * @param b a matrix of the same dimension as this */ - void add_scaled(const LinOp* alpha, const LinOp* b); + void add_scaled(ptr_param alpha, ptr_param b); /** * Subtracts `b` scaled by `alpha` fron the matrix (aka: BLAS axpy). @@ -782,7 +801,7 @@ class Dense * match the number of columns of the matrix). * @param b a matrix of the same dimension as this */ - void sub_scaled(const LinOp* alpha, const LinOp* b); + void sub_scaled(ptr_param alpha, ptr_param b); /** * Computes the column-wise dot product of this matrix and `b`. @@ -792,7 +811,7 @@ class Dense * (the number of column in the vector must match the number * of columns of this) */ - void compute_dot(const LinOp* b, LinOp* result) const; + void compute_dot(ptr_param b, ptr_param result) const; /** * Computes the column-wise dot product of this matrix and `b`. @@ -805,7 +824,8 @@ class Dense * reduction computation. It may be resized and/or reset to the * correct executor. */ - void compute_dot(const LinOp* b, LinOp* result, array& tmp) const; + void compute_dot(ptr_param b, ptr_param result, + array& tmp) const; /** * Computes the column-wise dot product of `conj(this matrix)` and `b`. @@ -815,7 +835,8 @@ class Dense * (the number of column in the vector must match the number * of columns of this) */ - void compute_conj_dot(const LinOp* b, LinOp* result) const; + void compute_conj_dot(ptr_param b, + ptr_param result) const; /** * Computes the column-wise dot product of `conj(this matrix)` and `b`. @@ -828,7 +849,7 @@ class Dense * reduction computation. It may be resized and/or reset to the * correct executor. */ - void compute_conj_dot(const LinOp* b, LinOp* result, + void compute_conj_dot(ptr_param b, ptr_param result, array& tmp) const; /** @@ -838,7 +859,7 @@ class Dense * (the number of columns in the vector must match the number * of columns of this) */ - void compute_norm2(LinOp* result) const; + void compute_norm2(ptr_param result) const; /** * Computes the column-wise Euclidian (L^2) norm of this matrix. @@ -850,7 +871,7 @@ class Dense * reduction computation. It may be resized and/or reset to the * correct executor. */ - void compute_norm2(LinOp* result, array& tmp) const; + void compute_norm2(ptr_param result, array& tmp) const; /** * Computes the column-wise (L^1) norm of this matrix. @@ -859,7 +880,7 @@ class Dense * (the number of columns in the vector must match the number * of columns of this) */ - void compute_norm1(LinOp* result) const; + void compute_norm1(ptr_param result) const; /** * Computes the column-wise (L^1) norm of this matrix. @@ -871,7 +892,7 @@ class Dense * reduction computation. It may be resized and/or reset to the * correct executor. */ - void compute_norm1(LinOp* result, array& tmp) const; + void compute_norm1(ptr_param result, array& tmp) const; /** * Create a submatrix from the original matrix. @@ -1267,30 +1288,33 @@ struct temporary_clone_helper> { /** * Creates a view of a given Dense vector. * - * @tparam ValueType the underlying value type of the vector + * @tparam VecPtr a (smart or raw) pointer to the vector. * * @param vector the vector on which to create the view */ -template -std::unique_ptr> make_dense_view( - matrix::Dense* vector) +template +std::unique_ptr::value_type>> +make_dense_view(VecPtr&& vector) { - return matrix::Dense::create_view_of(vector); + using value_type = typename detail::pointee::value_type; + return matrix::Dense::create_view_of(vector); } /** * Creates a view of a given Dense vector. * - * @tparam ValueType the underlying value type of the vector + * @tparam VecPtr a (smart or raw) pointer to the vector. * * @param vector the vector on which to create the view */ -template -std::unique_ptr> make_const_dense_view( - const matrix::Dense* vector) +template +std::unique_ptr< + const matrix::Dense::value_type>> +make_const_dense_view(VecPtr&& vector) { - return matrix::Dense::create_const_view_of(vector); + using value_type = typename detail::pointee::value_type; + return matrix::Dense::create_const_view_of(vector); } diff --git a/include/ginkgo/core/matrix/diagonal.hpp b/include/ginkgo/core/matrix/diagonal.hpp index a2212acd0b0..50febffcfad 100644 --- a/include/ginkgo/core/matrix/diagonal.hpp +++ b/include/ginkgo/core/matrix/diagonal.hpp @@ -86,6 +86,12 @@ class Diagonal public: using EnableLinOp::convert_to; using EnableLinOp::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>>::convert_to; + using ConvertibleTo>>::move_to; using value_type = ValueType; using index_type = int64; @@ -143,13 +149,13 @@ class Diagonal * @param b the input vector(s) on which the diagonal matrix is applied * @param x the output vector(s) where the result is stored */ - void rapply(const LinOp* b, LinOp* x) const + void rapply(ptr_param b, ptr_param x) const { GKO_ASSERT_REVERSE_CONFORMANT(this, b); GKO_ASSERT_EQUAL_ROWS(b, x); GKO_ASSERT_EQUAL_COLS(this, x); - this->rapply_impl(b, x); + this->rapply_impl(b.get(), x.get()); } /** @@ -161,13 +167,13 @@ class Diagonal * is applied * @param x the output vector(s) where the result is stored */ - void inverse_apply(const LinOp* b, LinOp* x) const + void inverse_apply(ptr_param b, ptr_param x) const { GKO_ASSERT_CONFORMANT(this, b); GKO_ASSERT_EQUAL_ROWS(b, x); GKO_ASSERT_EQUAL_ROWS(this, x); - this->inverse_apply_impl(b, x); + this->inverse_apply_impl(b.get(), x.get()); } void read(const mat_data& data) override; diff --git a/include/ginkgo/core/matrix/ell.hpp b/include/ginkgo/core/matrix/ell.hpp index 58a3f8f9300..afa19f49407 100644 --- a/include/ginkgo/core/matrix/ell.hpp +++ b/include/ginkgo/core/matrix/ell.hpp @@ -99,6 +99,12 @@ class Ell : public EnableLinOp>, public: using EnableLinOp::convert_to; using EnableLinOp::move_to; + using ConvertibleTo, IndexType>>::convert_to; + using ConvertibleTo, IndexType>>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; using ReadableFromMatrixData::read; using value_type = ValueType; diff --git a/include/ginkgo/core/matrix/fbcsr.hpp b/include/ginkgo/core/matrix/fbcsr.hpp index 564b3a21ec9..b8833d59b7f 100644 --- a/include/ginkgo/core/matrix/fbcsr.hpp +++ b/include/ginkgo/core/matrix/fbcsr.hpp @@ -165,6 +165,16 @@ class Fbcsr : public EnableLinOp>, */ using EnableLinOp>::convert_to; + using ConvertibleTo< + Fbcsr, IndexType>>::convert_to; + using ConvertibleTo, IndexType>>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + friend class Fbcsr, IndexType>; void convert_to( diff --git a/include/ginkgo/core/matrix/hybrid.hpp b/include/ginkgo/core/matrix/hybrid.hpp index f85e1d11e43..a923e7b9079 100644 --- a/include/ginkgo/core/matrix/hybrid.hpp +++ b/include/ginkgo/core/matrix/hybrid.hpp @@ -89,6 +89,13 @@ class Hybrid public: using EnableLinOp::convert_to; using EnableLinOp::move_to; + using ConvertibleTo< + Hybrid, IndexType>>::convert_to; + using ConvertibleTo, IndexType>>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; using ReadableFromMatrixData::read; using value_type = ValueType; diff --git a/include/ginkgo/core/matrix/sellp.hpp b/include/ginkgo/core/matrix/sellp.hpp index ada0711a6da..1a0e68500f5 100644 --- a/include/ginkgo/core/matrix/sellp.hpp +++ b/include/ginkgo/core/matrix/sellp.hpp @@ -87,6 +87,13 @@ class Sellp : public EnableLinOp>, public: using EnableLinOp::convert_to; using EnableLinOp::move_to; + using ConvertibleTo< + Sellp, IndexType>>::convert_to; + using ConvertibleTo, IndexType>>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; using ReadableFromMatrixData::read; using value_type = ValueType; diff --git a/include/ginkgo/core/matrix/sparsity_csr.hpp b/include/ginkgo/core/matrix/sparsity_csr.hpp index 4caf24d8d68..3b1868cbb7c 100644 --- a/include/ginkgo/core/matrix/sparsity_csr.hpp +++ b/include/ginkgo/core/matrix/sparsity_csr.hpp @@ -94,6 +94,10 @@ class SparsityCsr public: using EnableLinOp::convert_to; using EnableLinOp::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; using ReadableFromMatrixData::read; using value_type = ValueType; diff --git a/include/ginkgo/core/preconditioner/jacobi.hpp b/include/ginkgo/core/preconditioner/jacobi.hpp index 35a4605755f..34ade339138 100644 --- a/include/ginkgo/core/preconditioner/jacobi.hpp +++ b/include/ginkgo/core/preconditioner/jacobi.hpp @@ -220,6 +220,8 @@ class Jacobi : public EnableLinOp>, public: using EnableLinOp::convert_to; using EnableLinOp::move_to; + using ConvertibleTo>::convert_to; + using ConvertibleTo>::move_to; using value_type = ValueType; using index_type = IndexType; using mat_data = matrix_data; @@ -564,7 +566,7 @@ class Jacobi : public EnableLinOp>, parameters_.block_pointers.set_executor(this->get_executor()); parameters_.storage_optimization.block_wise.set_executor( this->get_executor()); - this->generate(lend(system_matrix), parameters_.skip_sorting); + this->generate(system_matrix.get(), parameters_.skip_sorting); } /** diff --git a/include/ginkgo/core/solver/solver_base.hpp b/include/ginkgo/core/solver/solver_base.hpp index 29ca133180c..df9388f4014 100644 --- a/include/ginkgo/core/solver/solver_base.hpp +++ b/include/ginkgo/core/solver/solver_base.hpp @@ -106,6 +106,12 @@ class ApplyWithInitialGuess { virtual void apply_with_initial_guess(const LinOp* b, LinOp* x, initial_guess_mode guess) const = 0; + void apply_with_initial_guess(ptr_param b, ptr_param x, + initial_guess_mode guess) const + { + apply_with_initial_guess(b.get(), x.get(), guess); + } + /** * Performs the operation x = alpha * op(b) + beta * x with a initial guess * statement, where op is this linear operator and the initial guess @@ -122,6 +128,17 @@ class ApplyWithInitialGuess { const LinOp* beta, LinOp* x, initial_guess_mode guess) const = 0; + + void apply_with_initial_guess(ptr_param alpha, + ptr_param b, + ptr_param beta, + ptr_param x, + initial_guess_mode guess) const + { + apply_with_initial_guess(alpha.get(), b.get(), beta.get(), x.get(), + guess); + } + /** * Get the default initial guess * diff --git a/include/ginkgo/core/stop/criterion.hpp b/include/ginkgo/core/stop/criterion.hpp index d5df4378ad9..bc6bb000957 100644 --- a/include/ginkgo/core/stop/criterion.hpp +++ b/include/ginkgo/core/stop/criterion.hpp @@ -114,13 +114,22 @@ class Criterion : public EnableAbstractPolymorphicObject { return *this; \ } \ mutable _type _name##_ {} +#define GKO_UPDATER_REGISTER_PTR_PARAMETER(_type, _name) \ + const Updater& _name(ptr_param<_type> value) const \ + { \ + _name##_ = value.get(); \ + return *this; \ + } \ + mutable _type* _name##_ {} GKO_UPDATER_REGISTER_PARAMETER(size_type, num_iterations); - GKO_UPDATER_REGISTER_PARAMETER(const LinOp*, residual); - GKO_UPDATER_REGISTER_PARAMETER(const LinOp*, residual_norm); - GKO_UPDATER_REGISTER_PARAMETER(const LinOp*, implicit_sq_residual_norm); - GKO_UPDATER_REGISTER_PARAMETER(const LinOp*, solution); + GKO_UPDATER_REGISTER_PTR_PARAMETER(const LinOp, residual); + GKO_UPDATER_REGISTER_PTR_PARAMETER(const LinOp, residual_norm); + GKO_UPDATER_REGISTER_PTR_PARAMETER(const LinOp, + implicit_sq_residual_norm); + GKO_UPDATER_REGISTER_PTR_PARAMETER(const LinOp, solution); +#undef GKO_UPDATER_REGISTER_PTR_PARAMETER #undef GKO_UPDATER_REGISTER_PARAMETER private: