Extend transpose support
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 functionM::transposed()
returning the transposed of the matrix. The result should not just be some wrapper, but a 'real' matrix. This should be implemented forFieldMatrix
,DiagonalMatrix
, andDynamicMatrix
(... andScaledIdentityMatrix
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 ofm
. There's two possibilities for this:- If
m
supportsm.transposed()
the function forwards to this method. - Otherwise
transpose(m)
returns a special wrapper that looks like the transposed ofm
and internally stores a copy ofm
.
- If
-
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
totranspose()
. -
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
andmtv
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 oftranspose(m)
was explicitly discouraged by the documentation. -
The wrapper implements left-multiplication by a FieldMatrix
hence one could useA*transpose(B)
with aFieldMatrix A
and aDiagonalMatrix B
. To make this work iftranspose()
no longer returns the wrapper we need to implementoperator*
forFieldMatrix
andDiagonalMatrix
as proposed in !1106 (closed).
Edited by Carsten Gräser