Skip to content

Extend transpose support

Carsten Gräser requested to merge feature/extend-transpose-support into master

This extends support for transposing matrices. It builds on top of a first experiment in !1101 (closed). More specifically it implements the outcome of a discussion (!1101 (comment 89787)) with @simon.praetorius:

  • (Suitable) matrix implementations M should have dedicated member function M::transposed() returning the transposed of the matrix. The result should not just be some wrapper, but a 'real' matrix. This should be implemented for FieldMatrix, DiagonalMatrix, and DynamicMatrix (... and ScaledIdentityMatrix but this is in dune-istl). Transposing matrices with non-scalar entries is more delicate and should be postponed.
  • The free function transpose(m) returns a transposed version of m. There's two possibilities for this:
    • If m supports m.transposed() the function forwards to this method.
    • Otherwise transpose(m) returns a special wrapper that looks like the transposed of m and internally stores a copy of m.
  • In both cases transpose(m) does not store a reference to the passed matrix, but return an object with independent lifetime.
  • The wrapper supports using the std::reference_wrapper for opt-in capture of references.
  • Cases where you explicitly want a thin wrapper storing a reference to the matrix are supported by passing a std::reference_wrapper to transpose().
  • By-reference-capture could also be provided by an explicit method, e.g. transposedView(m).

Furthermore this adds some more functionality to the wrapper:

  • Add mv and mtv methods.
  • Add conversion to a dense matrix.
  • Make wrapper work for dynamically sized matrices.

The wrapper could potentially be extended by the features proposed in !962.

The major change is that transpose(m) no longer captures by reference. This significantly improves clarity, but also imposes three potential issues. Two of them are no problem in practice, one can be fixed easily:

  • The additional copy involved in transpose(m) should be cheap since it is currently only implemented for statically sized matrices.
  • The different behavior of using auto mt = transpose(m); modifyMatrix(m); useMatrix(m); is also no problem, because storing the result of transpose(m) was explicitly discouraged by the documentation.
  • The wrapper implements left-multiplication by a FieldMatrix hence one could use A*transpose(B) with a FieldMatrix A and a DiagonalMatrix B. To make this work if transpose() no longer returns the wrapper we need to implement operator* for FieldMatrix and DiagonalMatrix as proposed in !1106 (closed).
Edited by Carsten Gräser

Merge request reports