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 59<br />

dense vector inline unit vector(unsigned k, unsigned n)<br />

{<br />

dense vector v(n, 0.0);<br />

v[k]= 1;<br />

return v;<br />

}<br />

As the function returns the unit vector we can just take it as argument of the triangular solver<br />

res k= upper trisolve(A, unit vector(k, n));<br />

For a dense matrix, MTL4 allows us to access a matrix column as column vector (instead of a<br />

sub-matrix). Then we can assign the result vector directly without a loop.<br />

Inv[irange(0, n)][k]= res k;<br />

As short explanation, the bracket operator is implemented in a manner that integer indices<br />

<strong>for</strong> rows and columns returns the matrix entry while ranges <strong>for</strong> rows and columns returns a<br />

sub-matrix. Likewise, a range of rows and a single column gives you a column of the according<br />

matrix — or part of this column. Vice versa, a row vector can be extracted from a matrix with<br />

an integer as row index and a range <strong>for</strong> the columns.<br />

This is an interesting example how to deal with the limitations as well as possibilities of C ++.<br />

Other languages have ranges as part of their intrinsic notation, e.g. Python has a symbol ‘:’<br />

<strong>for</strong> expressing ranges of indices. C ++ does not have this symbol but we can introduce a new<br />

type — like MTL4’s irange — and define the behavior of operator[] <strong>for</strong> this type. This leads to<br />

an extremely powerful mechanism!<br />

Extending Operator Functionality<br />

Since we cannot introduce new operators into C ++— not now (in 2010), not<br />

in the next standard (C ++0x), maybe in that afterwards — we define new<br />

types and give operators the desired behavior when applied to those types.<br />

This technique allows us providing a very broad functionality with a limited<br />

number of operators.<br />

The operator semantics on user types shall be intuitive and must be consistent with the operator<br />

priority (see example in § 2.3.7).<br />

Back to our algorithm. We store the result of the solver in a vector and then we assign it to a<br />

matrix column. In fact, we can assign the triangular solver’s result directly.<br />

Inv[irange(0, n)][k]= upper trisolve(A, unit vector(k, n));<br />

The range of all indices is predefined as iall:<br />

Inv[iall][k]= upper trisolve(A, unit vector(k, n));<br />

Next, we explore some mathematical back-ground. The inverse of an upper triangular matrix<br />

is also upper triangular. Thus, we only need to compute the upper part of the result and set<br />

the remainder to 0 — or the whole matrix to zero be<strong>for</strong>e computing the upper part. Of course,

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

Saved successfully!

Ooh no, something went wrong!