GaussJordan.h
1/***************************************************************************
2 *
3 * Copyright (C) 2004 by Willem van Straten
4 * Licensed under the Academic Free License version 2.1
5 *
6 ***************************************************************************/
7#include <math.h>
8#include <assert.h>
9
10#include <vector>
11#include <algorithm>
12#include <cmath>
13
14#include "Error.h"
15
16// #define _DEBUG 1
17
18namespace MEAL {
19
34 template <class T, class U>
35 T GaussJordan (std::vector<std::vector<T> >& a,
36 std::vector<std::vector<U> >& b,
37 int nrow = -1, double singular_threshold = 0.0,
38 std::vector<const char*>* names = 0);
39}
40
41inline double inv (double x) { return 1.0/x; }
42
43template <class T, class U>
44T MEAL::GaussJordan (std::vector<std::vector<T> >& a,
45 std::vector<std::vector<U> >& b,
46 int nrow, double singular_threshold,
47 std::vector<const char*>* names)
48{
49 if (nrow < 0)
50 nrow = a.size();
51
52 if (nrow == 0)
53 {
54 std::cerr << "MEAL::GaussJordan nrow=" << nrow << std::endl;
55 return 0.0;
56 }
57
58 int ncol = 0;
59
60 if (b.size())
61 {
62 if (b.size() < unsigned(nrow))
63 throw Error (InvalidState, "MEAL::GaussJordan",
64 "b.size()=%d < nrow=%d", b.size(), nrow);
65
66 ncol = b[0].size();
67 }
68
69#ifdef _DEBUG
70 std::cerr << "MEAL::GaussJordan nrow=" << nrow << " ncol=" << ncol << std::endl;
71#endif
72
73 for (int i=0; i < nrow; i++)
74 if (a[i].size() < unsigned(nrow))
75 throw Error (InvalidState, "MEAL::GaussJordan",
76 "a[%d].size()=%d < nrow=%d", i, a[i].size(), nrow);
77
78 // pivot book-keeping arrays
79 std::vector<int> indxc (nrow);
80 std::vector<int> indxr (nrow);
81 std::vector<bool> ipiv (nrow, false);
82
83#ifdef _DEBUG
84 std::cerr << "MEAL::GaussJordan start loop" << std::endl;
85#endif
86
87 T log_abs_det_a = 0.0;
88
89 for (int i=0; i<nrow; i++)
90 {
91 // search for the pivot element
92
93 int irow = -1;
94 int icol = -1;
95
96#ifdef _DEBUG
97 std::cerr << "MEAL::GaussJordan search for pivot" << std::endl;
98#endif
99
100 double big = 0.0;
101 for (int j=0; j<nrow; j++)
102 {
103 if (ipiv[j])
104 continue;
105
106 for (int k=0; k<nrow; k++)
107 {
108 if (ipiv[k])
109 continue;
110
111 if (fabs(a[j][k]) >= big)
112 {
113 big=fabs(a[j][k]);
114 irow=j;
115 icol=k;
116 }
117 }
118 }
119
120 if (big <= singular_threshold)
121 {
122 if (names)
123 for (int k=i; k<nrow; k++)
124 std::cerr << "MEAL::GaussJordan singular irow=" << k << " name=" << (*names)[k] << std::endl;
125
126 throw Error (InvalidState, "MEAL::GaussJordan",
127 "Singular Matrix. icol=%d nrow=%d pivot=%le", i, nrow, big);
128 }
129
130 assert (irow != -1 && icol != -1);
131
132 ipiv[icol] = true;
133
134#ifdef _DEBUG
135 std::cerr << "MEAL::GaussJordan pivot found" << std::endl;
136#endif
137
138 if (irow != icol)
139 {
140 assert (irow < nrow);
141 assert (icol < nrow);
142#ifdef _DEBUG
143 std::cerr << "MEAL::GaussJordan swap a irow=" << irow << " icol=" << icol << std::endl;
144#endif
145
146 for (int j=0; j<nrow; j++)
147 std::swap (a[irow][j], a[icol][j]);
148
149#ifdef _DEBUG
150 std::cerr << "MEAL::GaussJordan swap b" << std::endl;
151#endif
152
153 for (int j=0; j<ncol; j++)
154 std::swap (b[irow][j], b[icol][j]);
155
156 if (names)
157 std::swap ( (*names)[irow], (*names)[icol] );
158 }
159
160#ifdef _DEBUG
161 std::cerr << "MEAL::GaussJordan swap done" << std::endl;
162#endif
163
164 indxr[i]=irow;
165 indxc[i]=icol;
166
167 T pivinv = inv(a[icol][icol]);
168 log_abs_det_a += std::log(std::fabs(a[icol][icol]));
169
170#ifdef _DEBUG
171 std::cerr << "icol=" << icol << " irow=" << irow << " 1/piv=" << pivinv << std::endl;
172#endif
173
174 a[icol][icol]=1.0;
175
176 for (int j=0; j<nrow; j++)
177 a[icol][j] *= pivinv;
178
179 for (int j=0; j<ncol; j++)
180 b[icol][j] *= pivinv;
181
182 // reduce the rows except for the pivot
183 for (int j=0; j<nrow; j++)
184 {
185 if (j != icol)
186 {
187 T dum = a[j][icol];
188
189 a[j][icol]=0.0;
190
191 for (int k=0; k<nrow; k++)
192 a[j][k] -= a[icol][k]*dum;
193
194 for (int k=0; k<ncol; k++)
195 b[j][k] -= b[icol][k]*dum;
196 }
197 }
198 }
199
200 // unscramble the column interchanges
201 for (int i=nrow-1; i>=0; i--)
202 {
203 if (indxr[i] != indxc[i])
204 {
205 for (int j=0; j<nrow; j++)
206 std::swap(a[j][indxr[i]],a[j][indxc[i]]);
207 }
208 }
209
210 return log_abs_det_a;
211}
Namespace in which all modeling and calibration related code is declared.
Definition ExampleComplex2.h:16
T GaussJordan(std::vector< std::vector< T > > &a, std::vector< std::vector< U > > &b, int nrow=-1, double singular_threshold=0.0, std::vector< const char * > *names=0)
Definition GaussJordan.h:44

Generated using doxygen 1.14.0