diff --git a/core/base/iterator_factory.hpp b/core/base/iterator_factory.hpp index ac235dbaa5b..82589b260d5 100644 --- a/core/base/iterator_factory.hpp +++ b/core/base/iterator_factory.hpp @@ -96,6 +96,8 @@ class IteratorFactory { // An empty reference makes no sense, so is is disabled Reference() = delete; + ~Reference() {} + Reference(IteratorFactory &parent, array_index_type array_index) : parent_(parent), arr_index_(array_index) {} @@ -200,6 +202,8 @@ class IteratorFactory { using reference = Reference; using iterator_category = std::random_access_iterator_tag; + ~Iterator() {} + Iterator(IteratorFactory &parent, difference_type array_index) : parent_(parent), arr_index_(array_index) {} diff --git a/core/test/base/iterator_factory.cpp b/core/test/base/iterator_factory.cpp index 3817564e3a1..3f149b167fb 100644 --- a/core/test/base/iterator_factory.cpp +++ b/core/test/base/iterator_factory.cpp @@ -68,14 +68,22 @@ class IteratorFactory : public ::testing::Test { } } - template + // Require that Iterator has a `value_type` specified + template bool is_sorted_iterator(Iterator begin, Iterator end) { - while (begin + 1 < end) { - if (*(begin + 1) < *begin) { + using value_type = typename Iterator::value_type; + for (; begin + 1 < end; ++begin) { + auto curr_ref = *begin; + auto curr_val = static_cast(curr_ref); + auto next_ref = *(begin + 1); + auto next_val = static_cast(next_ref); + + // Test all combinations of the `<` operator + if (*(begin + 1) < *begin || next_ref < curr_ref || + next_ref < curr_val || next_val < curr_ref) { return false; } - ++begin; } return true; } @@ -105,11 +113,9 @@ TEST_F(IteratorFactory, SortingReversedWithIterator) auto test_iter = gko::detail::IteratorFactory( vec1.data(), vec2.data(), vec1.size()); std::sort(test_iter.begin(), test_iter.end()); - auto is_sorted = is_sorted_iterator(test_iter.begin(), test_iter.end()); check_vector_equal(vec1, ordered_int); check_vector_equal(vec2, reversed_double); - ASSERT_TRUE(is_sorted); } @@ -121,10 +127,34 @@ TEST_F(IteratorFactory, SortingAlreadySortedWithIterator) auto test_iter = gko::detail::IteratorFactory( vec1.data(), vec2.data(), vec1.size()); std::sort(test_iter.begin(), test_iter.end()); - auto is_sorted = is_sorted_iterator(test_iter.begin(), test_iter.end()); check_vector_equal(vec1, ordered_int); check_vector_equal(vec2, ordered_double); +} + + +TEST_F(IteratorFactory, IteratorReferenceOperatorSmaller) +{ + std::vector vec1{reversed_int}; + std::vector vec2{ordered_double}; + + auto test_iter = gko::detail::IteratorFactory( + vec1.data(), vec2.data(), vec1.size()); + bool is_sorted = is_sorted_iterator(test_iter.begin(), test_iter.end()); + + ASSERT_FALSE(is_sorted); +} + + +TEST_F(IteratorFactory, IteratorReferenceOperatorSmaller2) +{ + std::vector vec1{ordered_int}; + std::vector vec2{ordered_double}; + + auto test_iter = gko::detail::IteratorFactory( + vec1.data(), vec2.data(), vec1.size()); + bool is_sorted = is_sorted_iterator(test_iter.begin(), test_iter.end()); + ASSERT_TRUE(is_sorted); } diff --git a/doc/conf/Doxyfile-usr.in b/doc/conf/Doxyfile-usr.in index 627ae05c7b2..b29ecac2cca 100644 --- a/doc/conf/Doxyfile-usr.in +++ b/doc/conf/Doxyfile-usr.in @@ -13,3 +13,5 @@ CALL_GRAPH = NO CALLER_GRAPH = NO EXCLUDE_SYMBOLS = *detail::* std::* WARN_LOGFILE = @out@.log +# These are the LaTeX packages we use +EXTRA_PACKAGES = amsmath amsfonts mathtools diff --git a/include/ginkgo/core/factorization/par_ilu.hpp b/include/ginkgo/core/factorization/par_ilu.hpp index 488811317f3..d97e0c40d06 100644 --- a/include/ginkgo/core/factorization/par_ilu.hpp +++ b/include/ginkgo/core/factorization/par_ilu.hpp @@ -55,16 +55,26 @@ namespace factorization { /** * ParILU is an incomplete LU factorization which is computed in parallel. * + * $L$ is a lower unitriangular, while $U$ is an upper triangular matrix, which + * approximate a given matrix $A$ with $A \approx LU$. Here, $L$ and $U$ have + * the same sparsity pattern as $A$, which is also called ILU(0). + * * The ParILU algorithm generates the incomplete factors iteratively, using a * fixed-point iteration of the form - * $F(L, U) = \begin{cases}\frac{1}{u_{jj}}\left(a_{ij}-\sum_{k=1}^{j-1} - * l_{ik}u_{kj}\right), \quad &i>j\\ - * a_{ij}-\sum_{k=1}^{i-1} l_{ik}u_{kj},\quad &i\leq j \end{cases}*$ + * + * $ + * F(L, U) = + * \begin{cases} + * \frac{1}{u_{jj}} + * \left(a_{ij}-\sum_{k=1}^{j-1}l_{ik}u_{kj}\right), \quad & i>j \\ + * a_{ij}-\sum_{k=1}^{i-1}l_{ik}u_{kj}, \quad & i\leq j + * \end{cases} + * $ * * In general, the entries of $L$ and $U$ can be iterated in parallel and in * asynchronous fashion, the algorithm asymptotically converges to the * incomplete factors $L$ and $U$ fulfilling $\left(R = A - L \cdot - * U\right)\vert_\mathcal{S} = 0\vert_\mathcal{S}$ where $\mathcal{S}$ is the + * U\right)\vert_\mathcal{S} = 0$ where $\mathcal{S}$ is the * pre-defined sparsity pattern (in case of ILU(0) the sparsity pattern of the * system matrix $A$). The number of ParILU sweeps needed for convergence * depends on the parallelism level: For sequential execution, a single sweep diff --git a/reference/test/factorization/par_ilu_kernels.cpp b/reference/test/factorization/par_ilu_kernels.cpp index e63948ea50b..4a41c467f1a 100644 --- a/reference/test/factorization/par_ilu_kernels.cpp +++ b/reference/test/factorization/par_ilu_kernels.cpp @@ -238,10 +238,10 @@ TEST_F(ParIlu, LUFactorFunctionsSetProperly) TEST_F(ParIlu, GenerateForCooIdentity) { - auto coo_mtx = Coo::create(exec); + auto coo_mtx = gko::share(Coo::create(exec)); identity->convert_to(coo_mtx.get()); - auto factors = ilu_factory_skip->generate(identity); + auto factors = ilu_factory_skip->generate(coo_mtx); auto l_factor = factors->get_l_factor(); auto u_factor = factors->get_u_factor(); @@ -252,10 +252,10 @@ TEST_F(ParIlu, GenerateForCooIdentity) TEST_F(ParIlu, GenerateForCsrIdentity) { - auto csr_mtx = Csr::create(exec); + auto csr_mtx = gko::share(Csr::create(exec)); identity->convert_to(csr_mtx.get()); - auto factors = ilu_factory_skip->generate(identity); + auto factors = ilu_factory_skip->generate(csr_mtx); auto l_factor = factors->get_l_factor(); auto u_factor = factors->get_u_factor(); @@ -322,6 +322,17 @@ TEST_F(ParIlu, GenerateForDenseSmall) } +TEST_F(ParIlu, GenerateForCsrSmall) +{ + auto factors = ilu_factory_skip->generate(mtx_csr_small); + auto l_factor = factors->get_l_factor(); + auto u_factor = factors->get_u_factor(); + + GKO_ASSERT_MTX_NEAR(l_factor, small_l_expected, 1e-14); + GKO_ASSERT_MTX_NEAR(u_factor, small_u_expected, 1e-14); +} + + TEST_F(ParIlu, GenerateForDenseSmallWithMultipleIterations) { auto multiple_iter_factory = gko::factorization::ParIlu<>::build() @@ -348,11 +359,22 @@ TEST_F(ParIlu, GenerateForDenseBig) } +TEST_F(ParIlu, GenerateForDenseBigSort) +{ + auto factors = ilu_factory_skip->generate(mtx_big); + auto l_factor = factors->get_l_factor(); + auto u_factor = factors->get_u_factor(); + + GKO_ASSERT_MTX_NEAR(l_factor, big_l_expected, 1e-14); + GKO_ASSERT_MTX_NEAR(u_factor, big_u_expected, 1e-14); +} + + TEST_F(ParIlu, GenerateForReverseCooSmall) { const auto size = mtx_small->get_size(); const auto nnz = size[0] * size[1]; - std::shared_ptr reverse_coo = Coo::create(exec, size, nnz); + auto reverse_coo = gko::share(Coo::create(exec, size, nnz)); // Fill the Coo matrix in reversed row order (right to left) for (size_t i = 0; i < size[0]; ++i) { for (size_t j = 0; j < size[1]; ++j) { @@ -377,7 +399,7 @@ TEST_F(ParIlu, GenerateForReverseCsrSmall) { const auto size = mtx_csr_small->get_size(); const auto nnz = size[0] * size[1]; - std::shared_ptr reverse_csr = Csr::create(exec); + auto reverse_csr = gko::share(Csr::create(exec)); reverse_csr->copy_from(mtx_csr_small.get()); // Fill the Csr matrix rows in reverse order for (size_t i = 0; i < size[0]; ++i) {