Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it

563604 views
1
#include"typedef.h"
2
/**************************************************************************\
3
@---------------------------------------------------------------------------
4
@---------------------------------------------------------------------------
5
@ FILE: dsylv.c
6
@---------------------------------------------------------------------------
7
@---------------------------------------------------------------------------
8
@
9
\**************************************************************************/
10
11
/* changed tilman 2/09/97 because this is far higher than the precision
12
of modern machines (and causes trouble)
13
static double eps = 0.000001; */
14
static double eps = 0.00000000001;
15
16
static double **mat_to_double(M)
17
matrix_TYP *M;
18
{
19
int i,j;
20
double **D;
21
if((D = (double **)malloc(M->rows *sizeof(double *))) == 0)
22
{
23
printf("malloc failed in mat_to_double\n");
24
exit(2);
25
}
26
for(i=0;i<M->rows;i++)
27
{
28
if((D[i] = (double *)malloc((i+1) *sizeof(double))) == 0)
29
{
30
printf("malloc failed in mat_to_double\n");
31
exit(2);
32
}
33
}
34
for(i=0;i<M->rows;i++)
35
for(j=0;j<=i;j++)
36
D[i][j] = ((double) M->array.SZ[i][j]);
37
return(D);
38
}
39
40
41
static int pivot(A, step, n)
42
double **A;
43
int step, n;
44
{
45
int i,j,k, found;
46
double max;
47
int ipos, jpos;
48
double tmp;
49
50
/*****************************************************************************\
51
| search for a nonzero diagonal entry
52
\*****************************************************************************/
53
max = fabs(A[step][step]);
54
if (max < eps){
55
max = A[step][step] = 0.0;
56
}
57
ipos = step;
58
for(i=step+1;i<n;i++)
59
{
60
61
/* inserted tilman 02/09/97, accuracy errors may occur intermediate */
62
if((fabs(A[i][i]) < eps))
63
A[i][i] = 0.0;
64
if((fabs(A[i][i]) > max))
65
{
66
max = fabs(A[i][i]);
67
ipos = i;
68
}
69
}
70
/*****************************************************************************\
71
| if there is a nonzero diagonal entry, swap colum 'step' und colmn 'ipos'
72
| and swap row 'step' and row 'ipos', where A[ipos][ipos] has the maximal
73
| absulute value.
74
\*****************************************************************************/
75
if(max != 0.0)
76
{
77
if (ipos == step)
78
return(1);
79
tmp = A[step][step];
80
A[step][step] = A[ipos][ipos];
81
A[ipos][ipos] = tmp;
82
for(i=step+1;i<ipos;i++)
83
{ tmp = A[i][step]; A[i][step] = A[ipos][i]; A[ipos][i] = tmp;}
84
for(i= ipos+1;i<n;i++)
85
{ tmp = A[i][step]; A[i][step] = A[i][ipos]; A[i][ipos] = tmp;}
86
return(1);
87
}
88
89
/*****************************************************************************\
90
| if all diagonal entries are zero, find an nonzero entry A[ipos][jpos]
91
| if all entries are zero return(0)
92
\*****************************************************************************/
93
ipos = step+1;
94
jpos = step;
95
found = FALSE;
96
for(i=step+1;i<n && found == FALSE;i++)
97
for(j=step;j<i && found == FALSE;j++)
98
{
99
if(A[i][j] != 0.0)
100
{ipos = i; jpos = j; found = TRUE;}
101
}
102
if(found == FALSE)
103
return(0);
104
105
/*****************************************************************************\
106
| swap colum 'step' and column 'jpos' and swap row 'step' and row 'jpos'
107
| Then A[ipos][step] is nonzero.
108
\*****************************************************************************/
109
for(i=step+1;i<jpos;i++)
110
{ tmp = A[i][step]; A[i][step] = A[jpos][i]; A[jpos][i] = tmp;}
111
for(i= jpos+1;i<n;i++)
112
{ tmp = A[i][step]; A[i][step] = A[i][jpos]; A[i][jpos] = tmp;}
113
/*****************************************************************************\
114
| add column 'ipos' to column 'step' and add row 'ipos' to row 'step'
115
| Then A[step][step] is nonzero
116
\*****************************************************************************/
117
A[step][step] = A[ipos][step] * 2.0;
118
for(i=step+1;i<ipos;i++)
119
A[i][step] += A[ipos][i];
120
for(i=ipos+1;i<n;i++)
121
A[i][step] += A[i][ipos];
122
return(1);
123
}
124
125
126
static void col_clear(A, step, n)
127
double **A;
128
int step, n;
129
{
130
int i,j;
131
double f;
132
for(i=step+1; i<n; i++)
133
{
134
/* changed this to a numerically more stable version:
135
if(fabs(A[i][step]) > eps)
136
{
137
f = A[i][step]/A[step][step];
138
for(j=step+1;j<=i;j++)
139
A[i][j] -= A[j][step] * f;
140
for(j=i+1;j<n;j++)
141
A[j][i] -= A[j][step] * f;
142
A[i][step] = 0.0;
143
}
144
else
145
{
146
A[i][step] = 0.0;
147
} */
148
149
for(j=step+1;j<=i;j++)
150
A[i][j] -= (A[j][step] * A[i][step])/A[step][step];
151
for(j=i+1;j<n;j++)
152
A[j][i] -= (A[j][step] * A[i][step])/A[step][step];
153
A[i][step] = 0.0;
154
155
}
156
}
157
158
static void double_symmat_put(D,n)
159
double **D;
160
int n;
161
{
162
int i,j;
163
for(i=0;i<n;i++)
164
{
165
for(j=0;j<=i;j++)
166
printf("%e ", D[i][j]);
167
printf("\n");
168
}
169
}
170
171
172
static int diag_definite_test(D, n)
173
double **D;
174
int n;
175
{
176
int i;
177
int o,u,z;
178
179
o = u = z = 0;
180
for(i=0;i<n;i++)
181
{
182
if(fabs(D[i][i]) > eps)
183
{
184
if(D[i][i] > eps)
185
o = 1;
186
else
187
u = 1;
188
}
189
else
190
z = 1;
191
}
192
if(u == 0)
193
{
194
if(o == 0)
195
return(0);
196
if(z == 0)
197
return(2);
198
return(1);
199
}
200
if(o == 1)
201
return(-3);
202
if(z == 0)
203
return(-2);
204
return(-1);
205
}
206
207
208
209
/**************************************************************************\
210
@---------------------------------------------------------------------------
211
@ matrix_TYP *dsylv(M)
212
@ matrix_TYP *M;
213
@
214
@ The return of 'dsylv' is a diagonal matrix D with diaogonal elements
215
@ D[i][i] in {-1,1,0}.
216
@ The function diagonalizes the symmetric matrix 'M' by simultanous row
217
@ and col-operations.
218
@ If the entry in the diagonalised matrix is positiv it is replaced
219
@ by 1, if negativ by -1, if zero by 0.
220
@ This is done with floating-point arithmetic.
221
@ So rounding errows may occur.
222
@ Therefore a diaogonal entry it is assumed to be zero
223
@ if its absolute value is less then eps.
224
@
225
@---------------------------------------------------------------------------
226
@
227
\**************************************************************************/
228
matrix_TYP *dsylv(M)
229
matrix_TYP *M;
230
{
231
int i,n,step, nonzero;
232
double **D;
233
double eps_new;
234
matrix_TYP *A;
235
int pos, neg;
236
237
extern matrix_TYP *init_mat();
238
239
D = mat_to_double(M);
240
n = M->cols;
241
nonzero = pivot(D, 0, n);
242
for(step = 0;step<n-1 && nonzero == TRUE ;step++)
243
{
244
col_clear(D, step, n);
245
246
if(step+1 != n)
247
nonzero = pivot(D, step+1, n);
248
}
249
pos = neg = 0;
250
for(i=0;i<n;i++)
251
{
252
if(fabs(D[i][i]) > eps)
253
{
254
if(D[i][i] > eps)
255
pos++;
256
else
257
neg++;
258
}
259
}
260
A = init_mat(n,n,"");
261
A->flags.Symmetric = A->flags.Diagonal = TRUE;
262
for(i=0;i<pos;i++)
263
A->array.SZ[i][i] = 1;
264
for(i=pos; i<pos+neg;i++)
265
A->array.SZ[i][i] = -1;
266
for(i=0;i<n;i++)
267
free(D[i]);
268
free(D);
269
return(A);
270
}
271
272
273
274
275
/**************************************************************************\
276
@---------------------------------------------------------------------------
277
@ int definite_test(M)
278
@ matrix_TYP *M;
279
@
280
@ Does the same as 'dsolve' but testes during the Diagonalisation
281
@ if the matrix is indefinite.
282
@ The return is
283
@
284
@ 0: if M is zero
285
@ 1: if M is positiv semidefinite, but not positiv definite.
286
@ 2: if M is positiv definite.
287
@ -1: if M is negativ semidefinite, but not negativ definite.
288
@ -2: if M is negativ definite.
289
@ -3: if M is indefinite.
290
@
291
@---------------------------------------------------------------------------
292
@
293
\**************************************************************************/
294
295
int definite_test(M)
296
matrix_TYP *M;
297
{
298
int i,n,step, nonzero;
299
double **D;
300
int test;
301
302
303
D = mat_to_double(M);
304
n = M->cols;
305
test = diag_definite_test(D, n);
306
if(test == -3)
307
{
308
for(i=0;i<n;i++)
309
free(D[i]);
310
311
/* inserted the next line 15/1/97 tilman */
312
free(D);
313
314
return(-3);
315
}
316
nonzero = pivot(D, 0, n);
317
for(step = 0;step<n-1 && nonzero == TRUE ;step++)
318
{
319
col_clear(D, step, n);
320
test = diag_definite_test(D, n);
321
if(test == -3)
322
{
323
for(i=0;i<n;i++)
324
free(D[i]);
325
326
/* inserted the next line 15/1/97 tilman */
327
free(D);
328
329
return(-3);
330
}
331
if(step+1 != n)
332
nonzero = pivot(D, step+1, n);
333
}
334
for(i=0;i<n;i++)
335
free(D[i]);
336
337
/* inserted the next line 15/1/97 tilman */
338
free(D);
339
340
return(test);
341
}
342
343