00001 #ifndef LINEAR_SYS_H_IS_INCLUDED
00002 #define LINEAR_SYS_H_IS_INCLUDED
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <cmath>
00017 #include <algorithm>
00018
00019 namespace mlib {
00020
00021 #ifndef likely
00022 # if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
00023 # define likely(x) (x)
00024 # define unlikely(x) (x)
00025 # else
00026 # define likely(x) (__builtin_expect((x), 1))
00027 # define unlikely(x) (__builtin_expect((x), 0))
00028 # endif
00029 #endif
00030
00031
00032 template <class T, int N>
00033 inline bool
00034 ludcmp(T a[N][N], int indx[N], T *d = NULL)
00035 {
00036 int i, j, k;
00037 T vv[N];
00038
00039 if (d)
00040 *d = 1;
00041 for (i = 0; i < N; i++) {
00042 T big = 0.0;
00043 for (j = 0; j < N; j++) {
00044 T tmp = std::fabs(a[i][j]);
00045 if (tmp > big)
00046 big = tmp;
00047 }
00048 if (big == 0.0)
00049 return false;
00050 vv[i] = 1.0 / big;
00051 }
00052 for (j = 0; j < N; j++) {
00053 for (i = 0; i < j; i++) {
00054 T sum = a[i][j];
00055 for (k = 0; k < i; k++)
00056 sum -= a[i][k]*a[k][j];
00057 a[i][j]=sum;
00058 }
00059 T big = 0.0;
00060 int imax = j;
00061 for (i = j; i < N; i++) {
00062 T sum = a[i][j];
00063 for (k = 0; k < j; k++)
00064 sum -= a[i][k]*a[k][j];
00065 a[i][j] = sum;
00066 T tmp = vv[i] * std::fabs(sum);
00067 if (tmp > big) {
00068 big = tmp;
00069 imax = i;
00070 }
00071 }
00072 if (imax != j) {
00073 for (k = 0; k < N; k++)
00074 std::swap(a[imax][k], a[j][k]);
00075 if (d)
00076 *d = -(*d);
00077 vv[imax] = vv[j];
00078 }
00079 indx[j] = imax;
00080 if (a[j][j] == 0.0)
00081 return false;
00082 if (j != N-1) {
00083 T tmp = 1.0/(a[j][j]);
00084 for (i = j+1; i < N; i++)
00085 a[i][j] *= tmp;
00086 }
00087 }
00088 return true;
00089 }
00090
00091
00092
00093 template <class T, int N>
00094 inline void
00095 lubksb(T a[N][N], int indx[N], T b[N])
00096 {
00097 int ii = -1, i, j;
00098 for (i = 0; i < N; i++) {
00099 int ip = indx[i];
00100 T sum = b[ip];
00101 b[ip] = b[i];
00102 if (ii != -1)
00103 for (j = ii; j < i; j++)
00104 sum -= a[i][j] * b[j];
00105 else if (sum)
00106 ii = i;
00107 b[i] = sum;
00108 }
00109 for (i = N-1; i >= 0; i--) {
00110 T sum = b[i];
00111 for (j = i+1; j < N; j++)
00112 sum -= a[i][j] * b[j];
00113 b[i] = sum / a[i][i];
00114 }
00115 }
00116
00117
00118
00119
00120
00121 template <class T, int N>
00122 inline bool
00123 ldltdc(T A[N][N], T rdiag[N])
00124 {
00125 T v[N-1];
00126 for (int i = 0; i < N; i++) {
00127 for (int k = 0; k < i; k++)
00128 v[k] = A[i][k] * rdiag[k];
00129 for (int j = i; j < N; j++) {
00130 T sum = A[i][j];
00131 for (int k = 0; k < i; k++)
00132 sum -= v[k] * A[j][k];
00133 if (i == j) {
00134 if (unlikely(sum <= T(0)))
00135 return false;
00136 rdiag[i] = T(1) / sum;
00137 } else {
00138 A[j][i] = sum;
00139 }
00140 }
00141 }
00142
00143 return true;
00144 }
00145
00146
00147
00148 template <class T, int N>
00149 inline void
00150 ldltsl(T A[N][N], T rdiag[N], T B[N], T x[N])
00151 {
00152 int i;
00153 for (i = 0; i < N; i++) {
00154 T sum = B[i];
00155 for (int k = 0; k < i; k++)
00156 sum -= A[i][k] * x[k];
00157 x[i] = sum * rdiag[i];
00158 }
00159 for (i = N - 1; i >= 0; i--) {
00160 T sum = 0;
00161 for (int k = i + 1; k < N; k++)
00162 sum += A[k][i] * x[k];
00163 x[i] -= sum * rdiag[i];
00164 }
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174 template <int N, class T>
00175 inline void
00176 eigdc(T A[N][N], T d[N])
00177 {
00178
00179 T e[N];
00180 for (int j = 0; j < N; j++) {
00181 d[j] = A[N-1][j];
00182 e[j] = 0.0;
00183 }
00184 for (int i = N-1; i > 0; i--) {
00185 T scale = 0.0;
00186 for (int k = 0; k < i; k++)
00187 scale += std::fabs(d[k]);
00188 if (scale == 0.0) {
00189 e[i] = d[i-1];
00190 for (int j = 0; j < i; j++) {
00191 d[j] = A[i-1][j];
00192 A[i][j] = A[j][i] = 0.0;
00193 }
00194 d[i] = 0.0;
00195 } else {
00196 T h = 0.0;
00197 T invscale = 1.0 / scale;
00198 for (int k = 0; k < i; k++) {
00199 d[k] *= invscale;
00200 h += sqr(d[k]);
00201 }
00202 T f = d[i-1];
00203 T g = (f > 0.0) ? -std::sqrt(h) : std::sqrt(h);
00204 e[i] = scale * g;
00205 h -= f * g;
00206 d[i-1] = f - g;
00207 for (int j = 0; j < i; j++)
00208 e[j] = 0.0;
00209 for (int j = 0; j < i; j++) {
00210 f = d[j];
00211 A[j][i] = f;
00212 g = e[j] + f * A[j][j];
00213 for (int k = j+1; k < i; k++) {
00214 g += A[k][j] * d[k];
00215 e[k] += A[k][j] * f;
00216 }
00217 e[j] = g;
00218 }
00219 f = 0.0;
00220 T invh = 1.0 / h;
00221 for (int j = 0; j < i; j++) {
00222 e[j] *= invh;
00223 f += e[j] * d[j];
00224 }
00225 T hh = f / (h + h);
00226 for (int j = 0; j < i; j++)
00227 e[j] -= hh * d[j];
00228 for (int j = 0; j < i; j++) {
00229 f = d[j];
00230 g = e[j];
00231 for (int k = j; k < i; k++)
00232 A[k][j] -= f * e[k] + g * d[k];
00233 d[j] = A[i-1][j];
00234 A[i][j] = 0.0;
00235 }
00236 d[i] = h;
00237 }
00238 }
00239
00240 for (int i = 0; i < N-1; i++) {
00241 A[N-1][i] = A[i][i];
00242 A[i][i] = 1.0;
00243 T h = d[i+1];
00244 if (h != 0.0) {
00245 T invh = 1.0 / h;
00246 for (int k = 0; k <= i; k++)
00247 d[k] = A[k][i+1] * invh;
00248 for (int j = 0; j <= i; j++) {
00249 T g = 0.0;
00250 for (int k = 0; k <= i; k++)
00251 g += A[k][i+1] * A[k][j];
00252 for (int k = 0; k <= i; k++)
00253 A[k][j] -= g * d[k];
00254 }
00255 }
00256 for (int k = 0; k <= i; k++)
00257 A[k][i+1] = 0.0;
00258 }
00259 for (int j = 0; j < N; j++) {
00260 d[j] = A[N-1][j];
00261 A[N-1][j] = 0.0;
00262 }
00263 A[N-1][N-1] = 1.0;
00264
00265
00266 for (int i = 1; i < N; i++)
00267 e[i-1] = e[i];
00268 e[N-1] = 0.0;
00269 T f = 0.0, tmp = 0.0;
00270 const T eps = pow(2.0, -52.0);
00271 for (int l = 0; l < N; l++) {
00272 tmp = std::max(tmp, std::fabs(d[l]) + std::fabs(e[l]));
00273 int m = l;
00274 while (m < N) {
00275 if (std::fabs(e[m]) <= eps * tmp)
00276 break;
00277 m++;
00278 }
00279 if (m > l) {
00280 do {
00281 T g = d[l];
00282 T p = (d[l+1] - g) / (e[l] + e[l]);
00283 T r = hypot(p, 1.0);
00284 if (p < 0.0)
00285 r = -r;
00286 d[l] = e[l] / (p + r);
00287 d[l+1] = e[l] * (p + r);
00288 T dl1 = d[l+1];
00289 T h = g - d[l];
00290 for (int i = l+2; i < N; i++)
00291 d[i] -= h;
00292 f += h;
00293 p = d[m];
00294 T c = 1.0, c2 = 1.0, c3 = 1.0;
00295 T el1 = e[l+1], s = 0.0, s2 = 0.0;
00296 for (int i = m - 1; i >= l; i--) {
00297 c3 = c2;
00298 c2 = c;
00299 s2 = s;
00300 g = c * e[i];
00301 h = c * p;
00302 r = hypot(p, e[i]);
00303 e[i+1] = s * r;
00304 s = e[i] / r;
00305 c = p / r;
00306 p = c * d[i] - s * g;
00307 d[i+1] = h + s * (c * g + s * d[i]);
00308 for (int k = 0; k < N; k++) {
00309 h = A[k][i+1];
00310 A[k][i+1] = s * A[k][i] + c * h;
00311 A[k][i] = c * A[k][i] - s * h;
00312 }
00313 }
00314 p = -s * s2 * c3 * el1 * e[l] / dl1;
00315 e[l] = s * p;
00316 d[l] = c * p;
00317 } while (std::fabs(e[l]) > eps * tmp);
00318 }
00319 d[l] += f;
00320 e[l] = 0.0;
00321 }
00322
00323
00324 for (int i = 0; i < N-1; i++) {
00325 int k = i;
00326 T p = d[i];
00327 for (int j = i+1; j < N; j++) {
00328 if (d[j] < p) {
00329 k = j;
00330 p = d[j];
00331 }
00332 }
00333 if (k == i)
00334 continue;
00335 d[k] = d[i];
00336 d[i] = p;
00337 for (int j = 0; j < N; j++) {
00338 p = A[j][i];
00339 A[j][i] = A[j][k];
00340 A[j][k] = p;
00341 }
00342 }
00343 }
00344
00345
00346
00347 template <int N, class T>
00348 inline void
00349 eigmult(T A[N][N], T d[N], T b[N], T x[N])
00350 {
00351 T e[N];
00352 for (int i = 0; i < N; i++) {
00353 e[i] = 0.0;
00354 for (int j = 0; j < N; j++)
00355 e[i] += A[j][i] * b[j];
00356 e[i] *= d[i];
00357 }
00358 for (int i = 0; i < N; i++) {
00359 x[i] = 0.0;
00360 for (int j = 0; j < N; j++)
00361 x[i] += A[i][j] * e[j];
00362 }
00363 }
00364
00365 }
00366
00367 #endif // LINEAR_SYS_H_IS_INCLUDED