/************************************************/
/* 実対称行列の固有値・固有ベクトル(ヤコビ法) */
/* coded by Y.Suganuma */
/************************************************/
#include <stdio.h>
int Jacobi(int, int, double, double **, double **, double **, double **, double **);
int main()
{
double **A, **A1, **A2, **X1, **X2, eps;
int i1, i2, ind, ct, n;
// データの設定
ct = 1000;
eps = 1.0e-10;
n = 3;
A = new double * [n];
A1 = new double * [n];
A2 = new double * [n];
X1 = new double * [n];
X2 = new double * [n];
for (i1 = 0; i1 < n; i1++) {
A[i1] = new double [n];
A1[i1] = new double [n];
A2[i1] = new double [n];
X1[i1] = new double [n];
X2[i1] = new double [n];
}
A[0][0] = 1.0;
A[0][1] = 0.0;
A[0][2] = -1.0;
A[1][0] = 0.0;
A[1][1] = 1.0;
A[1][2] = -1.0;
A[2][0] = -1.0;
A[2][1] = -1.0;
A[2][2] = 2.0;
// 計算
ind = Jacobi(n, ct, eps, A, A1, A2, X1, X2);
// 出力
if (ind > 0)
printf("収束しませんでした!\n");
else {
printf("固有値\n");
for (i1 = 0; i1 < n; i1++)
printf(" %f", A1[i1][i1]);
printf("\n固有ベクトル(各列が固有ベクトル)\n");
for (i1 = 0; i1 < n; i1++) {
for (i2 = 0; i2 < n; i2++)
printf(" %f", X1[i1][i2]);
printf("\n");
}
}
for (i1 = 0; i1 < n; i1++) {
delete [] A[i1];
delete [] A1[i1];
delete [] A2[i1];
delete [] X1[i1];
delete [] X2[i1];
}
delete [] A;
delete [] A1;
delete [] A2;
delete [] X1;
delete [] X2;
return 0;
}
/*************************************************************/
/* 実対称行列の固有値・固有ベクトル(ヤコビ法) */
/* n : 次数 */
/* ct : 最大繰り返し回数 */
/* eps : 収束判定条件 */
/* A : 対象とする行列 */
/* A1, A2 : 作業域(nxnの行列),A1の対角要素が固有値 */
/* X1, X2 : 作業域(nxnの行列),X1の各列が固有ベクトル */
/* return : =0 : 正常 */
/* =1 : 収束せず */
/* coded by Y.Suganuma */
/*************************************************************/
#include <math.h>
int Jacobi(int n, int ct, double eps, double **A, double **A1, double **A2,
double **X1, double **X2)
{
double max, s, t, v, sn, cs;
int i1, i2, k = 0, ind = 1, p = 0, q = 0;
// 初期設定
for (i1 = 0; i1 < n; i1++) {
for (i2 = 0; i2 < n; i2++) {
A1[i1][i2] = A[i1][i2];
X1[i1][i2] = 0.0;
}
X1[i1][i1] = 1.0;
}
// 計算
while (ind > 0 && k < ct) {
// 最大要素の探索
max = 0.0;
for (i1 = 0; i1 < n; i1++) {
for (i2 = 0; i2 < n; i2++) {
if (i2 != i1) {
if (fabs(A1[i1][i2]) > max) {
max = fabs(A1[i1][i2]);
p = i1;
q = i2;
}
}
}
}
// 収束判定
// 収束した
if (max < eps)
ind = 0;
// 収束しない
else {
// 準備
s = -A1[p][q];
t = 0.5 * (A1[p][p] - A1[q][q]);
v = fabs(t) / sqrt(s * s + t * t);
sn = sqrt(0.5 * (1.0 - v));
if (s*t < 0.0)
sn = -sn;
cs = sqrt(1.0 - sn * sn);
// Akの計算
for (i1 = 0; i1 < n; i1++) {
if (i1 == p) {
for (i2 = 0; i2 < n; i2++) {
if (i2 == p)
A2[p][p] = A1[p][p] * cs * cs + A1[q][q] * sn * sn -
2.0 * A1[p][q] * sn * cs;
else if (i2 == q)
A2[p][q] = 0.0;
else
A2[p][i2] = A1[p][i2] * cs - A1[q][i2] * sn;
}
}
else if (i1 == q) {
for (i2 = 0; i2 < n; i2++) {
if (i2 == q)
A2[q][q] = A1[p][p] * sn * sn + A1[q][q] * cs * cs +
2.0 * A1[p][q] * sn * cs;
else if (i2 == p)
A2[q][p] = 0.0;
else
A2[q][i2] = A1[q][i2] * cs + A1[p][i2] * sn;
}
}
else {
for (i2 = 0; i2 < n; i2++) {
if (i2 == p)
A2[i1][p] = A1[i1][p] * cs - A1[i1][q] * sn;
else if (i2 == q)
A2[i1][q] = A1[i1][q] * cs + A1[i1][p] * sn;
else
A2[i1][i2] = A1[i1][i2];
}
}
}
// Xkの計算
for (i1 = 0; i1 < n; i1++) {
for (i2 = 0; i2 < n; i2++) {
if (i2 == p)
X2[i1][p] = X1[i1][p] * cs - X1[i1][q] * sn;
else if (i2 == q)
X2[i1][q] = X1[i1][q] * cs + X1[i1][p] * sn;
else
X2[i1][i2] = X1[i1][i2];
}
}
// 次のステップへ
k++;
for (i1 = 0; i1 < n; i1++) {
for (i2 = 0; i2 < n; i2++) {
A1[i1][i2] = A2[i1][i2];
X1[i1][i2] = X2[i1][i2];
}
}
}
}
return ind;
}