diff --git a/include/ginkgo/core/base/lin_op.hpp b/include/ginkgo/core/base/lin_op.hpp index b3cee5f9da4..86e43a8c9a4 100644 --- a/include/ginkgo/core/base/lin_op.hpp +++ b/include/ginkgo/core/base/lin_op.hpp @@ -520,8 +520,8 @@ class Permutable { * In the resulting LinOp, the entry at location `(i,j)` contains the input * value `(perm[i],perm[j])`. * - * From the linear algebra perspective, with \f$P_{ij} = \delta_{i - * \pi(i)}\f$, this represents the operation \f$P A P^{-1}\f$. + * From the linear algebra perspective, with $P_{ij} = \delta_{i + * \pi(i)}$, this represents the operation $P A P^T$. * * @param permutation_indices the array of indices containing the * permutation order. @@ -533,7 +533,7 @@ class Permutable { { return as(this->row_permute(permutation_indices)) ->column_permute(permutation_indices); - }; + } /** * Returns a LinOp representing the symmetric inverse row and column @@ -541,8 +541,8 @@ class Permutable { * In the resulting LinOp, the entry at location `(perm[i],perm[j])` * contains the input value `(i,j)`. * - * From the linear algebra perspective, with \f$P_{ij} = \delta_{i - * \pi(i)}\f$, this represents the operation \f$P^{-1} A P\f$. + * From the linear algebra perspective, with $P_{ij} = \delta_{i + * \pi(i)}$, this represents the operation $P^{-1} A P^{-T}$. * * @param permutation_indices the array of indices containing the * permutation order. @@ -554,15 +554,15 @@ class Permutable { { return as(this->inverse_row_permute(permutation_indices)) ->inverse_column_permute(permutation_indices); - }; + } /** * Returns a LinOp representing the row permutation of the Permutable * object. * In the resulting LinOp, the row `i` contains the input row `perm[i]`. * - * From the linear algebra perspective, with \f$P_{ij} = \delta_{i - * \pi(i)}\f$, this represents the operation \f$P A\f$. + * From the linear algebra perspective, with $P_{ij} = \delta_{i + * \pi(i)}$, this represents the operation $P A$. * * @param permutation_indices the array of indices containing the * permutation order. @@ -578,8 +578,8 @@ class Permutable { * In the resulting LinOp, the column `i` contains the input column * `perm[i]`. * - * From the linear algebra perspective, with \f$P_{ij} = \delta_{i - * \pi(i)}\f$, this represents the operation \f$A P^{-1}\f$. + * From the linear algebra perspective, with $P_{ij} = \delta_{i + * \pi(i)}$, this represents the operation $A P^T$. * * @param permutation_indices the array of indices containing the * permutation order `perm`. @@ -594,8 +594,8 @@ class Permutable { * object. * In the resulting LinOp, the row `perm[i]` contains the input row `i`. * - * From the linear algebra perspective, with \f$P_{ij} = \delta_{i - * \pi(i)}\f$, this represents the operation \f$P^{-1} A\f$. + * From the linear algebra perspective, with $P_{ij} = \delta_{i + * \pi(i)}$, this represents the operation $P^{-1} A$. * * @param permutation_indices the array of indices containing the * permutation order `perm`. @@ -611,8 +611,8 @@ class Permutable { * In the resulting LinOp, the column `perm[i]` contains the input column * `i`. * - * From the linear algebra perspective, with \f$P_{ij} = \delta_{i - * \pi(i)}\f$, this represents the operation \f$A P\f$. + * From the linear algebra perspective, with $P_{ij} = \delta_{i + * \pi(i)}$, this represents the operation $A P^{-T}$. * * @param permutation_indices the array of indices containing the * permutation order `perm`. diff --git a/include/ginkgo/core/matrix/csr.hpp b/include/ginkgo/core/matrix/csr.hpp index 611e5d33c64..834208c4322 100644 --- a/include/ginkgo/core/matrix/csr.hpp +++ b/include/ginkgo/core/matrix/csr.hpp @@ -59,6 +59,12 @@ class Ell; template class Hybrid; +template +class Permutation; + +template +class ScaledPermutation; + template class Sellp; @@ -763,6 +769,84 @@ class Csr : public EnableLinOp>, std::unique_ptr conj_transpose() const override; + /** + * Creates a permuted copy $A'$ of this matrix $A$ with the given + * permutation $P$. By default, this computes a symmetric permutation + * (permute_mode::symmetric). For the effect of the different permutation + * modes, see the following table. + * + * mode | entry mapping | matrix representation + * ------------------|----------------------------|---------------------- + * none | $A'(i, j) = A(i, j)$ | $A' = A$ + * rows | $A'(i, j) = A(p[i], j)$ | $A' = P A$ + * columns | $A'(i, j) = A(i, p[j])$ | $A' = A P^T$ + * inverse_rows | $A'(p[i], j) = A(i, j)$ | $A' = P^{-1} A$ + * inverse_columns | $A'(p[i], j) = A(i, j)$ | $A' = A P^{-T}$ + * symmetric | $A'(i, j) = A(p[i], p[j])$ | $A' = P A P^T$ + * inverse_symmetric | $A'(p[i], p[j]) = A(i, j)$ | $A' = P^{-1} A P^{-T}$ + * + * @param permutation The input permutation. + * @param mode The permutation mode. If permute_mode::inverse is set, we + * use the inverse permutation $P^{-1}$ instead of $P$. + * If permute_mode::rows is set, the rows will be permuted. + * If permute_mode::columns is set, the columns will be + * permuted. + * @return The permuted matrix. + */ + std::unique_ptr permute( + ptr_param> permutation, + permute_mode mode = permute_mode::symmetric) const; + + /** + * Creates a non-symmetrically permuted copy $A'$ of this matrix $A$ with + * the given row and column permutations $P$ and $Q$. The operation will + * compute $A'(i, j) = A(p[i], q[j])$, or $A' = P A Q^T$ if `invert` is + * `false`, and $A'(p[i], q[j]) = A(i,j)$, or $A' = P^{-1} A Q^{-T}$ if + * `invert` is `true`. + * + * @param row_permutation The permutation $P$ to apply to the rows + * @param column_permutation The permutation $Q$ to apply to the columns + * @param invert If set to `false`, uses the input permutations, otherwise + * uses their inverses $P^{-1}, Q^{-1}$ + * @return The permuted matrix. + */ + std::unique_ptr permute( + ptr_param> row_permutation, + ptr_param> column_permutation, + bool invert = false) const; + + /** + * Creates a scaled and permuted copy of this matrix. + * For an explanation of the permutation modes, see + * @ref permute(ptr_param>, permute_mode) + * + * @param permutation The scaled permutation. + * @param mode The permutation mode. + * @return The permuted matrix. + */ + std::unique_ptr scale_permute( + ptr_param> permutation, + permute_mode = permute_mode::symmetric) const; + + /** + * Creates a scaled and permuted copy of this matrix. + * For an explanation of the parameters, see + * @ref permute(ptr_param>, ptr_param>, permute_mode) + * + * @param row_permutation The scaled row permutation. + * @param column_permutation The scaled column permutation. + * @param invert If set to `false`, uses the input permutations, otherwise + * uses their inverses $P^{-1}, Q^{-1}$ + * @return The permuted matrix. + */ + std::unique_ptr scale_permute( + ptr_param> + row_permutation, + ptr_param> + column_permutation, + bool invert = false) const; + std::unique_ptr permute( const array* permutation_indices) const override; diff --git a/include/ginkgo/core/matrix/dense.hpp b/include/ginkgo/core/matrix/dense.hpp index ae738d49b93..4af7bac9432 100644 --- a/include/ginkgo/core/matrix/dense.hpp +++ b/include/ginkgo/core/matrix/dense.hpp @@ -81,6 +81,12 @@ class Fbcsr; template class Hybrid; +template +class Permutation; + +template +class ScaledPermutation; + template class Sellp; @@ -401,6 +407,191 @@ class Dense */ void fill(const ValueType value); + /** + * Creates a permuted copy $A'$ of this matrix $A$ with the given + * permutation $P$. By default, this computes a symmetric permutation + * (permute_mode::symmetric). For the effect of the different permutation + * modes, see the following table. + * + * mode | entry mapping | matrix representation + * ------------------|----------------------------|---------------------- + * none | $A'(i, j) = A(i, j)$ | $A' = A$ + * rows | $A'(i, j) = A(p[i], j)$ | $A' = P A$ + * columns | $A'(i, j) = A(i, p[j])$ | $A' = A P^T$ + * inverse_rows | $A'(p[i], j) = A(i, j)$ | $A' = P^{-1} A$ + * inverse_columns | $A'(p[i], j) = A(i, j)$ | $A' = A P^{-T}$ + * symmetric | $A'(i, j) = A(p[i], p[j])$ | $A' = P A P^T$ + * inverse_symmetric | $A'(p[i], p[j]) = A(i, j)$ | $A' = P^{-1} A P^{-T}$ + * + * @param permutation The input permutation. + * @param mode The permutation mode. If permute_mode::inverse is set, we + * use the inverse permutation $P^{-1}$ instead of $P$. + * If permute_mode::rows is set, the rows will be permuted. + * If permute_mode::columns is set, the columns will be + * permuted. + * @return The permuted matrix. + */ + std::unique_ptr permute( + ptr_param> permutation, + permute_mode mode = permute_mode::symmetric) const; + + /** + * @copydoc permute(ptr_param>, permute_mode) + */ + std::unique_ptr permute( + ptr_param> permutation, + permute_mode mode = permute_mode::symmetric) const; + + /** + * Overload of permute(ptr_param>, permute_mode) + * that writes the permuted copy into an existing Dense matrix. + * @param output the output matrix. + */ + void permute(ptr_param> permutation, + ptr_param output, permute_mode mode) const; + + /** + * @copydoc permute(ptr_param>, ptr_param, + * permute_mode) + */ + void permute(ptr_param> permutation, + ptr_param output, permute_mode mode) const; + + /** + * Creates a non-symmetrically permuted copy $A'$ of this matrix $A$ with + * the given row and column permutations $P$ and $Q$. The operation will + * compute $A'(i, j) = A(p[i], q[j])$, or $A' = P A Q^T$ if `invert` is + * `false`, and $A'(p[i], q[j]) = A(i,j)$, or $A' = P^{-1} A Q^{-T}$ if + * `invert` is `true`. + * + * @param row_permutation The permutation $P$ to apply to the rows + * @param column_permutation The permutation $Q$ to apply to the columns + * @param invert If set to `false`, uses the input permutations, otherwise + * uses their inverses $P^{-1}, Q^{-1}$ + * @return The permuted matrix. + */ + std::unique_ptr permute( + ptr_param> row_permutation, + ptr_param> column_permutation, + bool invert = false) const; + + /** + * @copydoc permute(ptr_param>, ptr_param>, permute_mode) + */ + std::unique_ptr permute( + ptr_param> row_permutation, + ptr_param> column_permutation, + bool invert = false) const; + + /** + * Overload of permute(ptr_param>, ptr_param>, permute_mode) that writes the permuted copy into an + * existing Dense matrix. + * @param output the output matrix. + */ + void permute(ptr_param> row_permutation, + ptr_param> column_permutation, + ptr_param output, bool invert) const; + + /** + * @copydoc permute(ptr_param>, ptr_param>, ptr_param, permute_mode) + */ + void permute(ptr_param> row_permutation, + ptr_param> column_permutation, + ptr_param output, bool invert) const; + + /** + * Creates a scaled and permuted copy of this matrix. + * For an explanation of the permutation modes, see + * @ref permute(ptr_param>, permute_mode) + * + * @param permutation The scaled permutation. + * @param mode The permutation mode. + * @return The permuted matrix. + */ + std::unique_ptr scale_permute( + ptr_param> permutation, + permute_mode mode = permute_mode::symmetric) const; + + /** + * @copydoc scale_permute(ptr_param>, permute_mode) + */ + std::unique_ptr scale_permute( + ptr_param> permutation, + permute_mode mode = permute_mode::symmetric) const; + + /** + * Overload of scale_permute(ptr_param>, permute_mode) that writes the permuted copy into an + * existing Dense matrix. + * @param output the output matrix. + */ + void scale_permute( + ptr_param> permutation, + ptr_param output, permute_mode mode) const; + + /** + * @copydoc scale_permute(ptr_param>, ptr_param, permute_mode) + */ + std::unique_ptr scale_permute( + ptr_param> permutation, + ptr_param output, permute_mode mode) const; + + /** + * Creates a scaled and permuted copy of this matrix. + * For an explanation of the parameters, see + * @ref permute(ptr_param>, ptr_param>, permute_mode) + * + * @param row_permutation The scaled row permutation. + * @param column_permutation The scaled column permutation. + * @param invert If set to `false`, uses the input permutations, otherwise + * uses their inverses $P^{-1}, Q^{-1}$ + * @return The permuted matrix. + */ + std::unique_ptr scale_permute( + ptr_param> row_permutation, + ptr_param> + column_permutation, + bool invert = false) const; + + /** + * @copydoc scale_permute(ptr_param>, ptr_param>, bool) + */ + std::unique_ptr scale_permute( + ptr_param> row_permutation, + ptr_param> + column_permutation, + bool invert = false) const; + + /** + * Overload of scale_permute(ptr_param>, ptr_param>, bool) + * that writes the permuted copy into an existing Dense matrix. + * @param output the output matrix. + */ + std::unique_ptr scale_permute( + ptr_param> row_permutation, + ptr_param> + column_permutation, + ptr_param output, bool invert) const; + + /** + * @copydoc scale_permute(ptr_param>, ptr_param>, + * ptr_param, bool) + */ + std::unique_ptr scale_permute( + ptr_param> row_permutation, + ptr_param> + column_permutation, + ptr_param output, bool invert) const; + std::unique_ptr permute( const array* permutation_indices) const override;