1 // 菊地文雄, 山本昌宏「微分方程式と計算機演習」, 山海堂 (1991), p. 104
2 /* ** SHIFT METHOD **
3 N : ORDER OF MATRIX
4 A : COEFFICIENT MATRIX
5 SHIFT : SHIFT PARAMETER
6 EPS : THRESHOLD VALUE FOR ERROR
7 M : MAXIMUM NO. OF ITERATIONS
8 EVAL : EIGENVALUE
9 X : EIGENVECTOR
10 NITER : NO.OF ITERATIONS
11 NPIVOT : NO.OF NEGATIVE PIVOTS
12 */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <math.h>
17
18 void gauss(int ndim, double a[][ndim], double f[], int n, int id);
19 void inpr(double x[], double y[], int n, double *s);
20
21 #define NDIM (100)
22
23 int main(void)
24 {
25 int n, m, i, j, niter, npivot;
26 double shift, eps, eval, s, t, enew, error;
27 double a[NDIM][NDIM], x[NDIM], y[NDIM];
28 // INPUT
29 printf("INPUT : N=\n");
30 scanf("%d", &n);
31 if (n <= 1) exit(1);
32 printf("INPUT : SHIFT=\n");
33 scanf("%lf", &shift);
34 printf("INPUT : EPS=\n");
35 scanf("%lf", &eps);
36 printf("INPUT : M=\n");
37 scanf("%d", &m);
38 for (i=0; i<n; i++) {
39 for (j=0; j<n; j++) {
40 printf("INPUT : A(%3d,%3d)=\n", i+1, j+1);
41 scanf("%lf", &a[i][j]);
42 if (j == i) a[i][i] -= shift;
43 }
44 }
45 for (i=0; i<n; i++) {
46 printf("INPUT : X(%3d)=\n", i+1);
47 scanf("%lf", &x[i]);
48 }
49 // ITERATION
50 niter = 0;
51 eval=shift;
52 do {
53 for (i=0; i<n; i++)
54 y[i] = x[i];
55 gauss(NDIM,a,y,n,niter);
56 inpr(x,y,n,&s);
57 inpr(y,y,n,&t);
58 enew=s/t+shift;
59 t=sqrt(t);
60 for (i=0; i<n; i++)
61 x[i] = y[i] / t;
62 error=fabs((enew-eval)/enew);
63 eval=enew;
64 niter++;
65 printf("(NITER,EVAL,ERROR)=%d %g %g\n", niter, eval, error);
66 if (niter == m) break;
67 }
68 while (error > eps);
69 npivot=0;
70 for (i=0; i<n; i++)
71 if (a[i][i] < 0.0) npivot++;
72 // OUTPUT
73 printf("NO. OF ITERATIONS=%3d EPS=%12.4e SHIFT=%12.4e NPIVOT=%3d\n",
74 niter, eps, shift, npivot);
75 printf("EIGENVALUE=%12.4e\n", eval);
76 printf("** EIGENVECTOR **\n");
77 for (i = 0; i < 5; i++)
78 printf(" I X(I) ");
79 printf("\n");
80 for (i=0; i<n; i++) {
81 printf("%3d%12.4e ", i+1, x[i]);
82 if ((i+1) % 5 == 0 || (i+1) == n)
83 printf("\n");
84 }
85 }
86
87 void gauss(int ndim, double a[][ndim], double f[], int n, int id)
88 {
89 int i, j, k;
90 double aa;
91 //FORWARD ELIMINATION
92 for (i=0; i<n-1; i++) {
93 for (j=i+1; j<n; j++) {
94 aa = a[j][i] / a[i][i];
95 if (id == 0) {
96 for (k=i+1; k<n; k++)
97 a[j][k] -= aa * a[i][k];
98 }
99 f[j] -= aa * f[i];
100 }
101 }
102 // BACKWARD SUBSTITUTION
103 f[n-1] /= a[n-1][n-1];
104 for (i=n-2; i>=0; i--) {
105 for (j=i+1; j<n; j++)
106 f[i] -= a[i][j] * f[j];
107 f[i] /= a[i][i];
108 }
109 }
110
111 void inpr(double x[], double y[], int n, double *s)
112 {
113 int i;
114 // INNER PRODUCT
115 *s = 0.0;
116 for (i=0; i<n; i++)
117 *s += x[i] * y[i];
118 }
桂田 祐史
2018-06-08