| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
/* |
|
2
|
|
|
|
|
|
|
* matrix.c - misc. routines for manipulating matrices and vectors. |
|
3
|
|
|
|
|
|
|
* |
|
4
|
|
|
|
|
|
|
* (C) Copyright 2001 by NetGroup A/S. All rights reserved. |
|
5
|
|
|
|
|
|
|
* |
|
6
|
|
|
|
|
|
|
* $Log$ |
|
7
|
|
|
|
|
|
|
* Revision 1.1 2006/06/20 15:57:22 djburke |
|
8
|
|
|
|
|
|
|
* Hopefully a saner way to build Basic/MatrixOps |
|
9
|
|
|
|
|
|
|
* |
|
10
|
|
|
|
|
|
|
* Revision 1.1 2005/01/08 09:22:57 zowie |
|
11
|
|
|
|
|
|
|
* Added non-symmetric matrices to eigens; updated version to 2.4.2cvs. |
|
12
|
|
|
|
|
|
|
* |
|
13
|
|
|
|
|
|
|
* Revision 1.1.1.1 2001/07/06 13:39:35 kneth |
|
14
|
|
|
|
|
|
|
* Initial import of code. |
|
15
|
|
|
|
|
|
|
* |
|
16
|
|
|
|
|
|
|
* |
|
17
|
|
|
|
|
|
|
* |
|
18
|
|
|
|
|
|
|
* The matrices and vectors are indexed in C-style, i.e. from 0 to |
|
19
|
|
|
|
|
|
|
* N-1. A matrix is assumed to be declared as double **, and it is |
|
20
|
|
|
|
|
|
|
* allocated by MatrixAlloc. |
|
21
|
|
|
|
|
|
|
* |
|
22
|
|
|
|
|
|
|
* |
|
23
|
|
|
|
|
|
|
* References: |
|
24
|
|
|
|
|
|
|
* [1] Numerical Recipes in C, 2nd edition, |
|
25
|
|
|
|
|
|
|
* W.H. Press, S.A. Teukolsky, W.T. Vitterling, and B.P. Flannery, |
|
26
|
|
|
|
|
|
|
* Cambridge University Press, 1992. |
|
27
|
|
|
|
|
|
|
* [2] Numerical Analysis, |
|
28
|
|
|
|
|
|
|
* D. Kincaid and W. Cheney, |
|
29
|
|
|
|
|
|
|
* Brooks/Cole Publishing Company, 1991. |
|
30
|
|
|
|
|
|
|
* [3] The C Programming Language, 2nd edition, |
|
31
|
|
|
|
|
|
|
* B.W. Kernighan and D.M. Ritchie, |
|
32
|
|
|
|
|
|
|
* Prentice Hall, 1988. |
|
33
|
|
|
|
|
|
|
* [4] Advanced Engineering Mathematics, 6th edition, |
|
34
|
|
|
|
|
|
|
* E. Kreyszig, |
|
35
|
|
|
|
|
|
|
* Wiley and Sons, 1988. |
|
36
|
|
|
|
|
|
|
* |
|
37
|
|
|
|
|
|
|
*/ |
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
#include |
|
40
|
|
|
|
|
|
|
#include |
|
41
|
|
|
|
|
|
|
#include |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
#ifndef TINY |
|
44
|
|
|
|
|
|
|
# define TINY 1.0e-18 |
|
45
|
|
|
|
|
|
|
#endif |
|
46
|
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
#include "sslib.h" |
|
48
|
|
|
|
|
|
|
#include "matrix.h" |
|
49
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
/* |
|
52
|
|
|
|
|
|
|
* MatrixAlloc allocates storage for a square matrix with dimension |
|
53
|
|
|
|
|
|
|
* n*n. An error message is printed, if it was impossible to allocate |
|
54
|
|
|
|
|
|
|
* the neccesary space, [3]. |
|
55
|
|
|
|
|
|
|
* |
|
56
|
|
|
|
|
|
|
*/ |
|
57
|
|
|
|
|
|
|
|
|
58
|
20
|
|
|
|
|
|
double **MatrixAlloc(const int n) { |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
double **matrix; |
|
61
|
|
|
|
|
|
|
int i; |
|
62
|
|
|
|
|
|
|
|
|
63
|
20
|
|
|
|
|
|
matrix=(double **)calloc(n, sizeof(double *)); |
|
64
|
20
|
50
|
|
|
|
|
if (matrix==NULL) |
|
65
|
0
|
|
|
|
|
|
SSLerror("No memory available in routine MatrixAlloc"); |
|
66
|
|
|
|
|
|
|
else |
|
67
|
74
|
100
|
|
|
|
|
for(i=0; i
|
|
68
|
54
|
|
|
|
|
|
matrix[i]=(double *)calloc(n, sizeof(double)); |
|
69
|
54
|
50
|
|
|
|
|
if (matrix[i]==NULL) |
|
70
|
0
|
|
|
|
|
|
SSLerror("No memory available in routine MatrixAlloc"); |
|
71
|
|
|
|
|
|
|
} /* for i=1..n */ |
|
72
|
20
|
|
|
|
|
|
return matrix; |
|
73
|
|
|
|
|
|
|
} /* MatrixAlloc */ |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
/* |
|
77
|
|
|
|
|
|
|
* VectorAlloc allocated space for an n-dimensional vector of the type |
|
78
|
|
|
|
|
|
|
* double *, [3]. It can be freed by VectorFree. |
|
79
|
|
|
|
|
|
|
* |
|
80
|
|
|
|
|
|
|
*/ |
|
81
|
|
|
|
|
|
|
|
|
82
|
12
|
|
|
|
|
|
double *VectorAlloc(const int n) { |
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
double *temp; |
|
85
|
|
|
|
|
|
|
|
|
86
|
12
|
|
|
|
|
|
temp=(double *)calloc(n, sizeof(double)); |
|
87
|
12
|
50
|
|
|
|
|
if (temp==NULL) |
|
88
|
0
|
|
|
|
|
|
SSLerror("No memory available in routine VectorAlloc"); |
|
89
|
12
|
|
|
|
|
|
return temp; |
|
90
|
|
|
|
|
|
|
} /* VectorAlloc */ |
|
91
|
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
/* |
|
94
|
|
|
|
|
|
|
* IntVectorAlloc is similar to VectorAlloc, except that the base type is |
|
95
|
|
|
|
|
|
|
* integers (int) instead of reals (double), [3]. |
|
96
|
|
|
|
|
|
|
* |
|
97
|
|
|
|
|
|
|
*/ |
|
98
|
|
|
|
|
|
|
|
|
99
|
7
|
|
|
|
|
|
int *IntVectorAlloc(const int n) { |
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
int *temp; |
|
102
|
|
|
|
|
|
|
|
|
103
|
7
|
|
|
|
|
|
temp=(int *)calloc(n, sizeof(int)); |
|
104
|
7
|
50
|
|
|
|
|
if (temp==NULL) |
|
105
|
0
|
|
|
|
|
|
SSLerror("No memory available in routine IntVectorAlloc"); |
|
106
|
7
|
|
|
|
|
|
return temp; |
|
107
|
|
|
|
|
|
|
} /* IntVectorAlloc */ |
|
108
|
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
/* |
|
111
|
|
|
|
|
|
|
* SSL_ComplexMatrixAlloc allocates space for a nxn matrix with complex elements. |
|
112
|
|
|
|
|
|
|
* |
|
113
|
|
|
|
|
|
|
*/ |
|
114
|
|
|
|
|
|
|
|
|
115
|
0
|
|
|
|
|
|
complex double **SSL_ComplexMatrixAlloc(const int n) { |
|
116
|
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
int i; |
|
118
|
|
|
|
|
|
|
complex double **temp; |
|
119
|
|
|
|
|
|
|
|
|
120
|
0
|
|
|
|
|
|
temp=(complex double **)calloc(n, sizeof(complex double *)); |
|
121
|
0
|
0
|
|
|
|
|
if (temp==NULL) |
|
122
|
0
|
|
|
|
|
|
SSLerror("No memory available in routine SSL_ComplexMatrixAlloc"); |
|
123
|
|
|
|
|
|
|
else { |
|
124
|
0
|
0
|
|
|
|
|
for(i=0; i
|
|
125
|
0
|
|
|
|
|
|
temp[i]=(complex double *)calloc(n, sizeof(complex double)); |
|
126
|
0
|
0
|
|
|
|
|
if (temp[i]==NULL) |
|
127
|
0
|
|
|
|
|
|
SSLerror("No memory available in routine SSL_ComplexMatrixAlloc"); |
|
128
|
|
|
|
|
|
|
} /* for i=1..n */ |
|
129
|
|
|
|
|
|
|
} /* if else */ |
|
130
|
0
|
|
|
|
|
|
return temp; |
|
131
|
|
|
|
|
|
|
} /* SSL_ComplexMatrixAlloc */ |
|
132
|
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
/* |
|
135
|
|
|
|
|
|
|
* SSL_ComplexVectorAlloc allocates a vector of dimension n with complex |
|
136
|
|
|
|
|
|
|
* elements. |
|
137
|
|
|
|
|
|
|
* |
|
138
|
|
|
|
|
|
|
*/ |
|
139
|
|
|
|
|
|
|
|
|
140
|
0
|
|
|
|
|
|
complex double *SSL_ComplexVectorAlloc(const int n) { |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
complex double *temp; |
|
143
|
|
|
|
|
|
|
|
|
144
|
0
|
|
|
|
|
|
temp=(complex double *)calloc(n, sizeof(complex double)); |
|
145
|
0
|
0
|
|
|
|
|
if (temp==NULL) |
|
146
|
0
|
|
|
|
|
|
SSLerror("No memory available in routine SSL_ComplexVectorAlloc"); |
|
147
|
0
|
|
|
|
|
|
return temp; |
|
148
|
|
|
|
|
|
|
} /* SSL_ComplexVectorAlloc */ |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
/* |
|
152
|
|
|
|
|
|
|
* MatrixMul computes the product between two square matrices, [4, pp. |
|
153
|
|
|
|
|
|
|
* 357-358]. Both matrices are assumed to have the dimension n*n. A and B are |
|
154
|
|
|
|
|
|
|
* input, and res is the output, i.e. the routine computes res=A*B. |
|
155
|
|
|
|
|
|
|
* |
|
156
|
|
|
|
|
|
|
*/ |
|
157
|
|
|
|
|
|
|
|
|
158
|
9
|
|
|
|
|
|
void MatrixMul(const int n, double **res, double **A, double **B) { |
|
159
|
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
int i, j, k; |
|
161
|
|
|
|
|
|
|
double x; |
|
162
|
|
|
|
|
|
|
|
|
163
|
33
|
100
|
|
|
|
|
for(i=0; i
|
|
164
|
96
|
100
|
|
|
|
|
for(j=0; j
|
|
165
|
72
|
|
|
|
|
|
x=0.0; |
|
166
|
312
|
100
|
|
|
|
|
for(k=0; k
|
|
167
|
240
|
|
|
|
|
|
x+=A[i][k]*B[k][j]; |
|
168
|
72
|
|
|
|
|
|
res[i][j]=x; |
|
169
|
|
|
|
|
|
|
} /* for j=1..n */ |
|
170
|
9
|
|
|
|
|
|
} /* MatrixMul */ |
|
171
|
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
/* |
|
174
|
|
|
|
|
|
|
* Transpose is simply doing as the name says, i.e. transposing the |
|
175
|
|
|
|
|
|
|
* matrix A, [4, pp. 368-370]. A is assumed to be a square matrix. |
|
176
|
|
|
|
|
|
|
* |
|
177
|
|
|
|
|
|
|
*/ |
|
178
|
|
|
|
|
|
|
|
|
179
|
3
|
|
|
|
|
|
void Transpose(const int n, double **res, double **A) { |
|
180
|
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
int i, j; |
|
182
|
|
|
|
|
|
|
|
|
183
|
11
|
100
|
|
|
|
|
for(i=0; i
|
|
184
|
32
|
100
|
|
|
|
|
for(j=0; j
|
|
185
|
24
|
|
|
|
|
|
res[j][i]=A[i][j]; |
|
186
|
3
|
|
|
|
|
|
} /* Transpose */ |
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
/* |
|
190
|
|
|
|
|
|
|
* MatrixFree, VectorFree, IntVectorFree, SSL_ComplexMatrixFree, and |
|
191
|
|
|
|
|
|
|
* SSL_ComplexVectorFree free the space used by the objects, [3]. |
|
192
|
|
|
|
|
|
|
* |
|
193
|
|
|
|
|
|
|
*/ |
|
194
|
|
|
|
|
|
|
|
|
195
|
18
|
|
|
|
|
|
void MatrixFree(const int n, double **matrix) { |
|
196
|
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
int i; |
|
198
|
|
|
|
|
|
|
|
|
199
|
66
|
100
|
|
|
|
|
for(i=0; i
|
|
200
|
48
|
|
|
|
|
|
free((void *)matrix[i]); |
|
201
|
18
|
|
|
|
|
|
free((void *)matrix); |
|
202
|
18
|
|
|
|
|
|
} /* MatrixFree */ |
|
203
|
|
|
|
|
|
|
|
|
204
|
0
|
|
|
|
|
|
void SSL_ComplexMatrixFree(const int n, complex double **matrix) { |
|
205
|
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
int i; |
|
207
|
|
|
|
|
|
|
|
|
208
|
0
|
0
|
|
|
|
|
for(i=0; i
|
|
209
|
0
|
|
|
|
|
|
free((void *)matrix[i]); |
|
210
|
0
|
|
|
|
|
|
free((void *)matrix); |
|
211
|
0
|
|
|
|
|
|
} /* SSL_ComplexMatrixFree */ |
|
212
|
|
|
|
|
|
|
|
|
213
|
9
|
|
|
|
|
|
void VectorFree(const int n, double *vector) { |
|
214
|
|
|
|
|
|
|
|
|
215
|
9
|
|
|
|
|
|
free((void *)vector); |
|
216
|
9
|
|
|
|
|
|
} /* VectorFree */ |
|
217
|
|
|
|
|
|
|
|
|
218
|
6
|
|
|
|
|
|
void IntVectorFree(const int n, int *vector) { |
|
219
|
|
|
|
|
|
|
|
|
220
|
6
|
|
|
|
|
|
free((void *)vector); |
|
221
|
6
|
|
|
|
|
|
} /* IntVectorFree */ |
|
222
|
|
|
|
|
|
|
|
|
223
|
0
|
|
|
|
|
|
void SSL_ComplexVectorFree(const int n, complex double *vector) { |
|
224
|
|
|
|
|
|
|
|
|
225
|
0
|
|
|
|
|
|
free((void *)vector); |
|
226
|
0
|
|
|
|
|
|
} /* SSL_ComplexVectorFree */ |
|
227
|
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
/* |
|
230
|
|
|
|
|
|
|
* LUfact and LUsubst are plain LU decomposition and substitution routines, |
|
231
|
|
|
|
|
|
|
* [1, pp. 43-50], [2, pp. 145-149]. The version here is Gaussian elimination |
|
232
|
|
|
|
|
|
|
* with scaled row pivoting, and it is based on the algorithm given in [2]. |
|
233
|
|
|
|
|
|
|
* |
|
234
|
|
|
|
|
|
|
* LUfact_fixed and LUsubst_fixed are specialised versions of LUfact and |
|
235
|
|
|
|
|
|
|
* LUsubst. They are used in OEE solvers. |
|
236
|
|
|
|
|
|
|
* |
|
237
|
|
|
|
|
|
|
* The parameters are used: |
|
238
|
|
|
|
|
|
|
* n the dimension of the matrix. |
|
239
|
|
|
|
|
|
|
* a the matrix; it contains both L and U at termination. |
|
240
|
|
|
|
|
|
|
* p permutation index. |
|
241
|
|
|
|
|
|
|
* b the constant vector, and at termination it will contain |
|
242
|
|
|
|
|
|
|
* the solution. |
|
243
|
|
|
|
|
|
|
* |
|
244
|
|
|
|
|
|
|
*/ |
|
245
|
|
|
|
|
|
|
|
|
246
|
0
|
|
|
|
|
|
void LUfact(const int n, double **a, int *p) { |
|
247
|
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
int i, j, k; /* counters */ |
|
249
|
|
|
|
|
|
|
double z; /* temporary real */ |
|
250
|
|
|
|
|
|
|
double *s; /* pivot elements */ |
|
251
|
|
|
|
|
|
|
int not_finished; /* loop control var. */ |
|
252
|
|
|
|
|
|
|
int i_swap; /* swap var. */ |
|
253
|
|
|
|
|
|
|
double temp; /* another temp. real */ |
|
254
|
|
|
|
|
|
|
|
|
255
|
0
|
|
|
|
|
|
s=VectorAlloc(n); |
|
256
|
0
|
0
|
|
|
|
|
for(i=0; i
|
|
257
|
0
|
|
|
|
|
|
p[i]=i; |
|
258
|
0
|
|
|
|
|
|
s[i]=0.0; |
|
259
|
0
|
0
|
|
|
|
|
for(j=0; j
|
|
260
|
0
|
|
|
|
|
|
z=fabs(a[i][j]); |
|
261
|
0
|
0
|
|
|
|
|
if (s[i]
|
|
262
|
0
|
|
|
|
|
|
s[i]=z; |
|
263
|
|
|
|
|
|
|
} /* for j */ |
|
264
|
|
|
|
|
|
|
} /* for i */ |
|
265
|
|
|
|
|
|
|
|
|
266
|
0
|
0
|
|
|
|
|
for(k=0; k<(n-1); k++) { |
|
267
|
0
|
|
|
|
|
|
j=k-1; /* select j>=k so ... */ |
|
268
|
0
|
|
|
|
|
|
not_finished=1; |
|
269
|
0
|
0
|
|
|
|
|
while (not_finished) { |
|
270
|
0
|
|
|
|
|
|
j++; |
|
271
|
0
|
|
|
|
|
|
temp=fabs(a[p[j]][k]/s[p[j]]); |
|
272
|
0
|
0
|
|
|
|
|
for(i=k; i
|
|
273
|
0
|
0
|
|
|
|
|
if (temp>=(fabs(a[p[i]][k])/s[p[i]])) |
|
274
|
0
|
|
|
|
|
|
not_finished=0; /* end loop */ |
|
275
|
|
|
|
|
|
|
} /* while */ |
|
276
|
0
|
|
|
|
|
|
i_swap=p[k]; |
|
277
|
0
|
|
|
|
|
|
p[k]=p[j]; |
|
278
|
0
|
|
|
|
|
|
p[j]=i_swap; |
|
279
|
0
|
|
|
|
|
|
temp=1.0/a[p[k]][k]; |
|
280
|
0
|
0
|
|
|
|
|
for(i=(k+1); i
|
|
281
|
0
|
|
|
|
|
|
z=a[p[i]][k]*temp; |
|
282
|
0
|
|
|
|
|
|
a[p[i]][k]=z; |
|
283
|
0
|
0
|
|
|
|
|
for(j=(k+1); j
|
|
284
|
0
|
|
|
|
|
|
a[p[i]][j]-=z*a[p[k]][j]; |
|
285
|
|
|
|
|
|
|
} /* for i */ |
|
286
|
|
|
|
|
|
|
} /* for k */ |
|
287
|
|
|
|
|
|
|
|
|
288
|
0
|
|
|
|
|
|
VectorFree(n, s); |
|
289
|
0
|
|
|
|
|
|
} /* LUfact */ |
|
290
|
|
|
|
|
|
|
|
|
291
|
0
|
|
|
|
|
|
void LUsubst(const int n, double **a, int *p, double *b) { |
|
292
|
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
int i, j, k; /* counters */ |
|
294
|
|
|
|
|
|
|
double sum; /* temporary sum variable */ |
|
295
|
|
|
|
|
|
|
double *x; /* solution */ |
|
296
|
|
|
|
|
|
|
|
|
297
|
0
|
|
|
|
|
|
x=VectorAlloc(n); |
|
298
|
|
|
|
|
|
|
|
|
299
|
0
|
0
|
|
|
|
|
for(k=0; k<(n-1); k++) /* forward subst */ |
|
300
|
0
|
0
|
|
|
|
|
for(i=(k+1); i
|
|
301
|
0
|
|
|
|
|
|
b[p[i]]-=a[p[i]][k]*b[p[k]]; |
|
302
|
|
|
|
|
|
|
|
|
303
|
0
|
0
|
|
|
|
|
for(i=(n-1); i>=0; i--) { /* back subst */ |
|
304
|
0
|
|
|
|
|
|
sum=b[p[i]]; |
|
305
|
0
|
0
|
|
|
|
|
for(j=(i+1); j
|
|
306
|
0
|
|
|
|
|
|
sum-=a[p[i]][j]*x[j]; |
|
307
|
0
|
|
|
|
|
|
x[i]=sum/a[p[i]][i]; |
|
308
|
|
|
|
|
|
|
} /* for i */ |
|
309
|
|
|
|
|
|
|
|
|
310
|
0
|
0
|
|
|
|
|
for(i=0; i
|
|
311
|
0
|
|
|
|
|
|
b[i]=x[i]; |
|
312
|
|
|
|
|
|
|
|
|
313
|
0
|
|
|
|
|
|
VectorFree(n, x); |
|
314
|
0
|
|
|
|
|
|
} /* LUsubst */ |
|
315
|
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
/* |
|
318
|
|
|
|
|
|
|
* GaussSeidel is an implementation of the Gauss-Seidel method, which is an |
|
319
|
|
|
|
|
|
|
* iterative method, [2, pp. 189-191]. The norm applied is the L1-norm. |
|
320
|
|
|
|
|
|
|
* |
|
321
|
|
|
|
|
|
|
* The parameters are: |
|
322
|
|
|
|
|
|
|
* n the dimension. |
|
323
|
|
|
|
|
|
|
* a the coefficient matrix. |
|
324
|
|
|
|
|
|
|
* b the constant vector. |
|
325
|
|
|
|
|
|
|
* x the initial guess, and at termination the solution. |
|
326
|
|
|
|
|
|
|
* eps the precision. |
|
327
|
|
|
|
|
|
|
* max_iter the maximal number of iterations allowed. |
|
328
|
|
|
|
|
|
|
* |
|
329
|
|
|
|
|
|
|
*/ |
|
330
|
|
|
|
|
|
|
|
|
331
|
0
|
|
|
|
|
|
void GaussSeidel(const int n, double **a, double *b, double *x, double eps, |
|
332
|
|
|
|
|
|
|
int max_iter) { |
|
333
|
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
int iter, i, j; /* counter */ |
|
335
|
|
|
|
|
|
|
double sum; /* temporary real */ |
|
336
|
|
|
|
|
|
|
double *x_old; /* old solution */ |
|
337
|
|
|
|
|
|
|
double norm; /* L1-norm */ |
|
338
|
|
|
|
|
|
|
|
|
339
|
0
|
|
|
|
|
|
x_old=VectorAlloc(n); |
|
340
|
|
|
|
|
|
|
|
|
341
|
0
|
|
|
|
|
|
iter=0; |
|
342
|
|
|
|
|
|
|
do { /* repeat until safisfying sol. */ |
|
343
|
0
|
|
|
|
|
|
iter++; |
|
344
|
0
|
0
|
|
|
|
|
for(i=0; i
|
|
345
|
0
|
|
|
|
|
|
x_old[i]=x[i]; |
|
346
|
0
|
|
|
|
|
|
norm=0.0; /* do an iteration */ |
|
347
|
0
|
0
|
|
|
|
|
for(i=0; i
|
|
348
|
0
|
|
|
|
|
|
sum=-a[i][i]*x[i]; /* don't include term i=j */ |
|
349
|
0
|
0
|
|
|
|
|
for(j=0; j
|
|
350
|
0
|
|
|
|
|
|
sum+=a[i][j]*x[j]; |
|
351
|
0
|
|
|
|
|
|
x[i]=(b[i]-sum)/a[i][i]; |
|
352
|
0
|
|
|
|
|
|
norm+=fabs(x_old[i]-x[i]); |
|
353
|
|
|
|
|
|
|
} /* for i */ |
|
354
|
0
|
0
|
|
|
|
|
} while ((iter<=max_iter) && (norm>=eps)); |
|
|
|
0
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
|
|
356
|
0
|
|
|
|
|
|
VectorFree(n, x_old); |
|
357
|
0
|
|
|
|
|
|
} /* GaussSeidel */ |
|
358
|
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
/* |
|
361
|
|
|
|
|
|
|
* Jacobi is an iterative equation solver, [2, pp. 185-189]. The algorithm |
|
362
|
|
|
|
|
|
|
* can be optimised a bit, which is done in this implementation. The method |
|
363
|
|
|
|
|
|
|
* is suitable for parallel computers. |
|
364
|
|
|
|
|
|
|
* |
|
365
|
|
|
|
|
|
|
* The arguments are the same as in GaussSeidel. |
|
366
|
|
|
|
|
|
|
* |
|
367
|
|
|
|
|
|
|
*/ |
|
368
|
|
|
|
|
|
|
|
|
369
|
0
|
|
|
|
|
|
void Jacobi(const int n, double **a, double *b, double *x, double eps, |
|
370
|
|
|
|
|
|
|
int max_iter) { |
|
371
|
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
double d; /* temporary real */ |
|
373
|
|
|
|
|
|
|
int i, j, iter; /* counters */ |
|
374
|
|
|
|
|
|
|
double **a_new; /* a is altered */ |
|
375
|
|
|
|
|
|
|
double *b_new; /* b is altered */ |
|
376
|
|
|
|
|
|
|
double *u; /* new solution */ |
|
377
|
|
|
|
|
|
|
double norm; /* L1-norm */ |
|
378
|
|
|
|
|
|
|
|
|
379
|
0
|
|
|
|
|
|
a_new=MatrixAlloc(3); |
|
380
|
0
|
|
|
|
|
|
b_new=VectorAlloc(3); |
|
381
|
0
|
|
|
|
|
|
u=VectorAlloc(3); |
|
382
|
|
|
|
|
|
|
|
|
383
|
0
|
0
|
|
|
|
|
for(i=0; i
|
|
384
|
0
|
|
|
|
|
|
d=1.0/a[i][i]; |
|
385
|
0
|
|
|
|
|
|
b_new[i]=d*b[i]; |
|
386
|
0
|
0
|
|
|
|
|
for(j=0; j
|
|
387
|
0
|
|
|
|
|
|
a_new[i][j]=d*a[i][j]; |
|
388
|
|
|
|
|
|
|
} /* for i */ |
|
389
|
|
|
|
|
|
|
|
|
390
|
0
|
|
|
|
|
|
iter=0; |
|
391
|
|
|
|
|
|
|
do { |
|
392
|
0
|
|
|
|
|
|
iter++; |
|
393
|
0
|
|
|
|
|
|
norm=0.0; |
|
394
|
0
|
0
|
|
|
|
|
for(i=0; i
|
|
395
|
0
|
|
|
|
|
|
d=-a_new[i][i]*x[i]; /* don't include term i=j */ |
|
396
|
0
|
0
|
|
|
|
|
for(j=0; j
|
|
397
|
0
|
|
|
|
|
|
d+=a_new[i][j]*x[j]; |
|
398
|
0
|
|
|
|
|
|
u[i]=b_new[i]-d; |
|
399
|
0
|
|
|
|
|
|
norm=fabs(u[i]-x[i]); |
|
400
|
|
|
|
|
|
|
} /* for i */ |
|
401
|
0
|
0
|
|
|
|
|
for(i=0; i
|
|
402
|
0
|
|
|
|
|
|
x[i]=u[i]; |
|
403
|
0
|
0
|
|
|
|
|
} while ((iter<=max_iter) && (norm>=eps)); |
|
|
|
0
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
|
|
405
|
0
|
|
|
|
|
|
MatrixFree(3, a_new); |
|
406
|
0
|
|
|
|
|
|
VectorFree(3, b_new); |
|
407
|
0
|
|
|
|
|
|
VectorFree(3, u); |
|
408
|
0
|
|
|
|
|
|
} /* Jacobi */ |
|
409
|
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
/* |
|
412
|
|
|
|
|
|
|
* DotProd computes the dot product between two vectors. They are assumed to |
|
413
|
|
|
|
|
|
|
* be of the same dimension. |
|
414
|
|
|
|
|
|
|
* |
|
415
|
|
|
|
|
|
|
*/ |
|
416
|
|
|
|
|
|
|
|
|
417
|
0
|
|
|
|
|
|
double DotProd(const int n, double *u, double *v) { |
|
418
|
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
int i; /* counter */ |
|
420
|
0
|
|
|
|
|
|
double sum=0.0; /* temporary real */ |
|
421
|
|
|
|
|
|
|
|
|
422
|
0
|
0
|
|
|
|
|
for(i=0; i
|
|
423
|
0
|
|
|
|
|
|
sum+=u[i]*v[i]; |
|
424
|
0
|
|
|
|
|
|
return sum; |
|
425
|
|
|
|
|
|
|
} /* DotProd */ |
|
426
|
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
/* |
|
429
|
|
|
|
|
|
|
* MatrixVecProd computes the matrix product between a matrix and a vector of |
|
430
|
|
|
|
|
|
|
* the dimension n. The result is found in res. |
|
431
|
|
|
|
|
|
|
* |
|
432
|
|
|
|
|
|
|
*/ |
|
433
|
|
|
|
|
|
|
|
|
434
|
0
|
|
|
|
|
|
void MatrixVecProd(const int n, double **A, double *v, double *res) { |
|
435
|
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
int i, j; /* counters */ |
|
437
|
|
|
|
|
|
|
|
|
438
|
0
|
0
|
|
|
|
|
for(i=0; i
|
|
439
|
0
|
|
|
|
|
|
res[i]=0.0; |
|
440
|
0
|
0
|
|
|
|
|
for(j=0; j
|
|
441
|
0
|
|
|
|
|
|
res[i]+=A[i][j]*v[j]; |
|
442
|
|
|
|
|
|
|
} /* for i */ |
|
443
|
0
|
|
|
|
|
|
} /* MatrixVecProd */ |
|
444
|
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
/* |
|
447
|
|
|
|
|
|
|
* MatrixCopy copies the elements of the matrix A to the B. |
|
448
|
|
|
|
|
|
|
* |
|
449
|
|
|
|
|
|
|
*/ |
|
450
|
|
|
|
|
|
|
|
|
451
|
12
|
|
|
|
|
|
void MatrixCopy(const int n, double **B, double **A) { |
|
452
|
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
int i, j; |
|
454
|
|
|
|
|
|
|
|
|
455
|
44
|
100
|
|
|
|
|
for(i=0; i
|
|
456
|
128
|
100
|
|
|
|
|
for(j=0; j
|
|
457
|
96
|
|
|
|
|
|
B[i][j]=A[i][j]; |
|
458
|
12
|
|
|
|
|
|
} /* MatrixCopy */ |
|
459
|
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
/* |
|
462
|
|
|
|
|
|
|
* L2VectorNorm computes the L2 or Eucleadian norm of a vector. |
|
463
|
|
|
|
|
|
|
* |
|
464
|
|
|
|
|
|
|
*/ |
|
465
|
|
|
|
|
|
|
|
|
466
|
0
|
|
|
|
|
|
double L2VectorNorm(const int n, double *vec) { |
|
467
|
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
int i; |
|
469
|
0
|
|
|
|
|
|
double norm=0.0; |
|
470
|
|
|
|
|
|
|
|
|
471
|
0
|
0
|
|
|
|
|
for(i=0; i
|
|
472
|
0
|
|
|
|
|
|
norm+=vec[i]*vec[i]; |
|
473
|
0
|
|
|
|
|
|
return sqrt(norm); |
|
474
|
|
|
|
|
|
|
} /* L2VectorNorm */ |
|
475
|
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
/* |
|
477
|
|
|
|
|
|
|
* GSR is an implementation of the Gram-Schmidt Reorthonormalisation process, |
|
478
|
|
|
|
|
|
|
* [2, pp. 246-250]. The n vectors are collected in a matrix, and the matrix is |
|
479
|
|
|
|
|
|
|
* both input and output. The implementation is actually the modified algorithm |
|
480
|
|
|
|
|
|
|
* as disucced in [2, p. 248]. Modified by the authors, so the vectors are |
|
481
|
|
|
|
|
|
|
* normalised at the end. |
|
482
|
|
|
|
|
|
|
* |
|
483
|
|
|
|
|
|
|
*/ |
|
484
|
|
|
|
|
|
|
|
|
485
|
0
|
|
|
|
|
|
void GSR(const int n, double **A) { |
|
486
|
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
int i, j, k; /* counters */ |
|
488
|
|
|
|
|
|
|
double dot; |
|
489
|
|
|
|
|
|
|
|
|
490
|
0
|
0
|
|
|
|
|
for(k=0; k
|
|
491
|
0
|
0
|
|
|
|
|
for(j=(k+1); j
|
|
492
|
0
|
|
|
|
|
|
dot=0.0; /* dot product */ |
|
493
|
0
|
0
|
|
|
|
|
for(i=0; i
|
|
494
|
0
|
|
|
|
|
|
dot+=A[i][j]*A[i][k]; |
|
495
|
0
|
0
|
|
|
|
|
for(i=0; i
|
|
496
|
0
|
|
|
|
|
|
A[i][j]-=A[i][k]/dot; |
|
497
|
|
|
|
|
|
|
} /* for j */ |
|
498
|
|
|
|
|
|
|
} /* for k */ |
|
499
|
|
|
|
|
|
|
|
|
500
|
0
|
0
|
|
|
|
|
for(k=0; k
|
|
501
|
0
|
|
|
|
|
|
dot=0.0; /* Compute (L2 norm) */ |
|
502
|
0
|
0
|
|
|
|
|
for(i=0; i
|
|
503
|
0
|
|
|
|
|
|
dot+=A[i][k]*A[i][k]; |
|
504
|
0
|
|
|
|
|
|
dot=sqrt(dot); |
|
505
|
0
|
0
|
|
|
|
|
if (dot==0.0) |
|
506
|
0
|
|
|
|
|
|
SSLerror("Norm = 0 in routine GSR"); |
|
507
|
0
|
0
|
|
|
|
|
for(i=0; i
|
|
508
|
0
|
|
|
|
|
|
A[i][k]/=dot; |
|
509
|
|
|
|
|
|
|
} /* for k */ |
|
510
|
0
|
|
|
|
|
|
} /* GSR */ |
|
511
|
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
/* |
|
514
|
|
|
|
|
|
|
* InversMatrix calculates the inverse matrix. The method is the solution |
|
515
|
|
|
|
|
|
|
* of n linear set of equations which are solved by a LU factorisation. |
|
516
|
|
|
|
|
|
|
* |
|
517
|
|
|
|
|
|
|
*/ |
|
518
|
|
|
|
|
|
|
|
|
519
|
0
|
|
|
|
|
|
void InversMatrix(const int n, double **b, double **ib) { |
|
520
|
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
double **a; |
|
522
|
|
|
|
|
|
|
double *e; |
|
523
|
|
|
|
|
|
|
int i,j; |
|
524
|
|
|
|
|
|
|
int *p; |
|
525
|
|
|
|
|
|
|
|
|
526
|
0
|
|
|
|
|
|
a=MatrixAlloc(n); |
|
527
|
0
|
|
|
|
|
|
e=VectorAlloc(n); |
|
528
|
0
|
|
|
|
|
|
p=IntVectorAlloc(n); |
|
529
|
0
|
|
|
|
|
|
MatrixCopy(n, a, b); |
|
530
|
0
|
|
|
|
|
|
LUfact(n, a, p); |
|
531
|
0
|
0
|
|
|
|
|
for(i=0; i
|
|
532
|
0
|
0
|
|
|
|
|
for(j=0; j
|
|
533
|
0
|
|
|
|
|
|
e[j]=0.0; |
|
534
|
0
|
|
|
|
|
|
e[i]=1.0; |
|
535
|
0
|
|
|
|
|
|
LUsubst(n, a, p, e); |
|
536
|
0
|
0
|
|
|
|
|
for(j=0; j
|
|
537
|
0
|
|
|
|
|
|
ib[j][i]=e[j]; |
|
538
|
|
|
|
|
|
|
} /* for i=1..n */ |
|
539
|
|
|
|
|
|
|
|
|
540
|
0
|
|
|
|
|
|
MatrixFree(n, a); |
|
541
|
0
|
|
|
|
|
|
VectorFree(n, e); |
|
542
|
0
|
|
|
|
|
|
IntVectorFree(n, p); |
|
543
|
0
|
|
|
|
|
|
} /* InversMatrix */ |
|
544
|
|
|
|
|
|
|
|