1
#ifndef _RHEO_TINY_LU_H
2
#define _RHEO_TINY_LU_H
4
/// This file is part of Rheolef.
6
/// Copyright (C) 2000-2009 Pierre Saramito <Pierre.Saramito@imag.fr>
8
/// Rheolef is free software; you can redistribute it and/or modify
9
/// it under the terms of the GNU General Public License as published by
10
/// the Free Software Foundation; either version 2 of the License, or
11
/// (at your option) any later version.
13
/// Rheolef is distributed in the hope that it will be useful,
14
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
15
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
/// GNU General Public License for more details.
18
/// You should have received a copy of the GNU General Public License
19
/// along with Rheolef; if not, write to the Free Software
20
/// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
/// =========================================================================
24
#include "rheolef/tiny_matvec.h"
26
// first step: LU factorization
27
// ----------------------------
28
// with partial pivoting
31
// P. Lascaux, R. Theodor
32
// "Analyse numerique matricielle
33
// appliquee a l'art de l'ingenieur",
41
lu (tiny_matrix<T>& a, tiny_vector<size_t>& piv)
43
typedef size_t size_type;
44
const size_type n = a.nrow();
47
// initialize permutation table
48
for (size_type i = 0; i < n; i++)
51
// factorize in 'n' steps
52
for (size_type k = 0; k < n-1; k++) {
54
// we search the largest element of th k-th
55
// line, that has not yet been pivot-line
56
T amax = abs(a(piv[k],k));
59
for (size_type i = k+1; i < n; i++) {
60
if (abs(a(piv[i],k)) > amax) {
61
amax = abs(a(piv[i],k));
65
// largest element is in piv[jmax] line
67
size_type i = piv [k];
71
// and invert the pivot
72
if (1 + a(piv[k],k) == 1) { // a (piv[k],k) < zero machine
73
error_macro ("lu: unisolvence failed on pivot " << k);
75
T pivinv = 1./a(piv[k],k);
77
// modify lines that has not yet been
79
for (size_type i = k+1; i < n; i++) {
81
T c = a(piv[i],k) * pivinv;
83
for (size_type j = k+1; j < n; j++)
84
a(piv [i],j) -= c * a(piv[k],j);
88
// second step: one-column resolution
89
// ----------------------------------
92
solve (tiny_matrix<T>& a, tiny_vector<size_t>& piv,
93
const tiny_vector<T>& b, tiny_vector<T>& x)
95
typedef size_t size_type;
96
const size_type n = a.nrow();
99
// solve Ly = piv(b); y is stored in x
100
for (size_type i = 0; i < n; i++) {
103
for (size_type j = 0; j < i; j++)
105
c += a(piv[i],j) * x [j];
107
x [i] = b [piv[i]] - c;
109
// solve Ux = y; x contains y as input and x as output
110
for (int i = n-1; i >= 0; i--) {
113
for (size_type j = i+1; j < n; j++)
115
c += a(piv[i],j) * x [j];
117
x [i] = (x [i] - c) / a(piv[i],i);
120
// ---------------------------------
121
// third step : matrix inversion
122
// NOTE: the a matrix is destroyed !
123
// ---------------------------------
127
invert (tiny_matrix<T>& a, tiny_matrix<T>& inv_a)
129
typedef size_t size_type;
130
const size_type n = a.nrow();
132
// performs the gauss factorization: M = L.U
133
tiny_vector<size_t> piv (n);
136
// invert M in B, column by colomn
137
tiny_vector<T> column (n);
138
tiny_vector<T> x (n);
141
for (size_type j = 0; j < n; j++) {
143
for (size_type i = 0; i < n; i++)
147
solve (a, piv, column, x);
149
for (size_type i = 0; i < n; i++)
155
put (std::ostream& out, std::string name, const tiny_matrix<T>& a)
157
typedef size_t size_type;
158
out << name << "(" << a.nrow() << "," << a.ncol() << ")" << std::endl;
160
for (size_type i = 0; i < a.nrow(); i++) {
161
for (size_type j = 0; j < a.ncol(); j++) {
162
out << name << "(" << i << "," << j << ") = " << a(i,j) << std::endl;
166
}// namespace rheolef
167
#endif // _RHEO_TINY_LU_H