C++ for Scientists - Technische Universität Dresden
C++ for Scientists - Technische Universität Dresden
C++ for Scientists - Technische Universität Dresden
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,