03.12.2012 Views

C++ for Scientists - Technische Universität Dresden

C++ for Scientists - Technische Universität Dresden

C++ for Scientists - Technische Universität Dresden

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

2.11. REAL-WORLD EXAMPLE: MATRIX INVERSION 61<br />

This does not work yet <strong>for</strong> technical reasons but will in the future.<br />

You may argue that the transpostions and passing the matrix and the vector once more takes<br />

more time. More importantly, we know that the lower matrix has a unit diagonal and we did<br />

not explore this property, e.g. <strong>for</strong> avoiding the divisions in the triangular solver. We could<br />

even ignore or omit the diagonal and treat this implicitly in the algorithms. This is all true.<br />

However, we prioritized the simplicity and clarity of the implementation and the reusability<br />

aspect higher than per<strong>for</strong>mance here. 28<br />

We have now all we need to put the matrix inversion together. As above we start we checking<br />

the squareness.<br />

dense2D inline inverse(dense2D const& A)<br />

{<br />

const unsigned n= num rows(A);<br />

assert(num cols(A) == n); // Matrix must be square<br />

Then we per<strong>for</strong>m the LU factorization. For per<strong>for</strong>mance reasons this function does not return<br />

the result but takes its arguments as mutable references and factorizes in place. Thus, we need<br />

a copy of a matrix to pass and a permutation vector of appropriate size.<br />

dense2D PLU(A);<br />

dense vector Pv(n);<br />

lu(PLU, Pv);<br />

The upper triangular factor PU of the permuted A is stored in the upper triangle of PLU. The<br />

lower triangular factor PL is partly stored in the strict lower triangle of PLU while the unit<br />

diagonal is omitted. We there<strong>for</strong>e need to add it be<strong>for</strong>e inversion (or alternatively handle the<br />

unit diagonal implicitly in the inversion).<br />

dense2D PU(upper(PLU)), PL(strict lower(PLU) + matrix::identity(n, n));<br />

The inversion of a square matrix according to Equation (2.1) can then be per<strong>for</strong>med in one<br />

single line: 29<br />

return dense2D(inverse upper(PU) ∗ inverse lower(PL) ∗ permutation(Pv));<br />

During this section you have seen that you have always alternatives to implement the same<br />

behavior, most likely you already made this experience be<strong>for</strong>e. Despite we suggested <strong>for</strong> every<br />

choice we made that it is the most appropriate, there is not always THE single best solution and<br />

even while trading off pro and cons of the alternatives, one might not come to a final conclusion<br />

and just pick one. We also illustrated that the choices depend on the goals, <strong>for</strong> instance the<br />

implementation would look different if per<strong>for</strong>mance were the primary goal.<br />

The section shall show as well that that non-trivial programs are not written in a single sweep<br />

by an ingenious mind — exceptions might prove the rule — but are the result of a gradually<br />

improving development. Experience will make this journey shorter and directer but we will not<br />

write the perfect program at the first glance.<br />

28 People that care about per<strong>for</strong>mance do not use matrix inversion in the first place.<br />

29 The explicit conversion can probably be omitted in later versions of MTL4.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!