From acdb69a9f1bcd2763d178609899ece9d6f739dbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carsten=20Gr=C3=A4ser?= <graeser@dune-project.org> Date: Tue, 11 Jul 2017 16:55:48 +0200 Subject: [PATCH] Implement axy using sparseRangeFor() This way it works for multi-type matrices again. This helps to fix the dune-tnnmg test which currently breaks. Notice that this may be slightly less efficient, because we use a new temporary for each loop instance. This is necessary because we may need a different type each time. This may be fixed by adding a specialization for the case that the corresponding vector is a classic dynamic container. --- dune/matrix-vector/axy.hh | 64 ++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/dune/matrix-vector/axy.hh b/dune/matrix-vector/axy.hh index c378c89..c626b12 100644 --- a/dune/matrix-vector/axy.hh +++ b/dune/matrix-vector/axy.hh @@ -5,6 +5,7 @@ #include "axpy.hh" #include "matrixtraits.hh" +#include "algorithm.hh" namespace Dune { namespace MatrixVector { @@ -40,22 +41,23 @@ namespace MatrixVector { static typename VectorType::field_type Axy(const MatrixType &A, const VectorType &x, const VectorType2 &y) { - assert(x.N() == A.M()); - assert(y.N() == A.N()); + assert(x.size() == A.M()); + assert(y.size() == A.N()); - typename VectorType::field_type outer = 0.0; - typename VectorType2::block_type inner; - typename MatrixType::ConstIterator endi = A.end(); - for (typename MatrixType::ConstIterator i = A.begin(); i != endi; ++i) { - inner = 0.0; - const size_t iindex = i.index(); - typename MatrixType::row_type::ConstIterator endj = i->end(); - for (typename MatrixType::row_type::ConstIterator j = i->begin(); - j != endj; ++j) - addProduct(inner, *j, x[j.index()]); - outer += inner * y[iindex]; - } - return outer; + using Result = std::decay_t<decltype(y*y)>; + + Result result = 0; + sparseRangeFor(A, [&](auto&& Ai, auto i) { + // ToDo: Provide a specialization using a single temporary + // for the case that each y[i] has the same type. + auto Aix = y[i]; + Aix = 0; + sparseRangeFor(Ai, [&](auto&& Aij, auto j) { + addProduct(Aix, Aij, x[j]); + }); + result += Aix * y[i]; + }); + return result; } template <class VectorType, class VectorType2> @@ -63,23 +65,23 @@ namespace MatrixVector { const VectorType2 &b, const VectorType &x, const VectorType2 &y) { - assert(x.N() == A.M()); - assert(y.N() == A.N()); - assert(y.N() == b.N()); + assert(x.size() == A.M()); + assert(y.size() == A.N()); + assert(y.size() == b.size()); + + using Result = std::decay_t<decltype(y*y)>; - typename VectorType::field_type outer = 0.0; - typename VectorType2::block_type inner; - typename MatrixType::ConstIterator endi = A.end(); - for (typename MatrixType::ConstIterator i = A.begin(); i != endi; ++i) { - const size_t iindex = i.index(); - inner = b[iindex]; - typename MatrixType::row_type::ConstIterator endj = i->end(); - for (typename MatrixType::row_type::ConstIterator j = i->begin(); - j != endj; ++j) - subtractProduct(inner, *j, x[j.index()]); - outer += inner * y[iindex]; - } - return outer; + Result result = 0; + sparseRangeFor(A, [&](auto&& Ai, auto i) { + // ToDo: Provide a specialization using a single temporary + // for the case that each b[i] has the same type. + auto Aix = b[i]; + sparseRangeFor(Ai, [&](auto&& Aij, auto j) { + subtractProduct(Aix, Aij, x[j]); + }); + result += Aix * y[i]; + }); + return result; } }; -- GitLab