Triangular systems of equations are of the form
where
Most introductory courses on numerical analysis introduce two algorithms for solving triangular systems of equations. Usually these algorithms are implemented using two nested (uncompiled) for-loops. A significant performance improvement can be made by rewriting the inner of these two loops in terms of a vector operation (i.e., a compiled for-loop).
Commonly, the standard forward and backward substitution algorithms (for solving lower and upper triangular systems respectively) are treated as two completely different entities. Below, my aim is to demonstrate that a vectorized implementation of these algorithms happens to yield the exact same code up to one little difference in the indexing.
Let me write a lower triangular system in an explicit (pythonic) notation:
Suppose
Introduce a helper vector
which allows us to rewrite the above equation in terms of a dot product (denoted by
Here, I have employed the numpy indexing notation
Some rearranging then yields
Hence, starting with
An almost identical study can be conducted for the case of an upper triangular matrix, where the only difference is that one starts from the last component of
Inputs: Lower triangular matrix
- Let
$x$ be the zero vector - For
$i = 0, 1, \dots, n-1$ let$x[i] = (b[i] - \langle A[i,:], x \rangle) / A[i,i]$
Inputs: Lower triangular matrix
- Let
$x$ be the zero vector - For
$i = n-1, n-2, \dots, 0$ let$x[i] = (b[i] - \langle A[i,:], x \rangle) / A[i,i]$
One sees immediately that the two algorithms are basically the same, except that the order of the loop is inverted. This motivated me to combine the algorithms.