最大固有値と固有ベクトル(べき乗法)

/****************************************/
/* 最大固有値と固有ベクトル(べき乗法) */
/*      coded by Y.Suganuma             */
/****************************************/
#include <stdio.h>

int power(int, int, int, int, double, double **, double **, double **,
          double *, double **, double *, double *, double *);

int main()
{
	double **A, **B, **C, *r, **v, *v0, *v1, *v2, eps;
	int i1, i2, ind, ct, m, n;
					// データの設定
	ct  = 200;
	eps = 1.0e-10;
	n   = 3;
	m   = 15;

	A   = new double * [n];
	B   = new double * [n];
	C   = new double * [n];
	v   = new double * [n];
	for (i1 = 0; i1 < n; i1++) {
		A[i1] = new double [n];
		B[i1] = new double [n];
		C[i1] = new double [n];
		v[i1] = new double [n];
	}

	r  = new double [n];
	v0 = new double [n];
	v1 = new double [n];
	v2 = new double [n];

	A[0][0] = 11.0;
	A[0][1] = 6.0;
	A[0][2] = -2.0;

	A[1][0] = -2.0;
	A[1][1] = 18.0;
	A[1][2] = 1.0;

	A[2][0] = -12.0;
	A[2][1] = 24.0;
	A[2][2] = 13.0;

	for (i1 = 0; i1 < n; i1++) {
		for (i2 = 0; i2 < n; i2++)
			B[i1][i2] = 0.0;
		B[i1][i1] = 1.0;
		v0[i1]    = 1.0;
	}
					// 計算
	ind = power(0, n, m, ct, eps, A, B, C, r, v, v0, v1, v2);
					// 出力
	if (ind == 0)
		printf("固有値が求まりませんでした!\n");
	else {
		for (i1 = 0; i1 < ind; i1++) {
			printf("固有値 %f", r[i1]);
			printf(" 固有ベクトル ");
			for (i2 = 0; i2 < n; i2++)
				printf(" %f", v[i1][i2]);
			printf("\n");
		}
	}

	for (i1 = 0; i1 < n; i1++) {
		delete [] A[i1];
		delete [] B[i1];
		delete [] C[i1];
		delete [] v[i1];
	}
	delete [] A;
	delete [] B;
	delete [] C;
	delete [] v;
	delete [] r;
	delete [] v0;
	delete [] v1;
	delete [] v2;

	return 0;
}

/****************************************/
/* 最大固有値と固有ベクトル(べき乗法) */
/*      i : 何番目の固有値かを示す      */
/*      n : 次数                        */
/*      m : 丸め誤差の修正回数          */
/*      ct : 最大繰り返し回数           */
/*      eps : 収束判定条件              */
/*      A : 対象とする行列              */
/*      B : nxnの行列,最初は,単位行列 */
/*      C : 作業域,nxnの行列           */
/*      r : 固有値                      */
/*      v : 各行が固有ベクトル(nxn)   */
/*      v0 : 固有ベクトルの初期値       */
/*      v1,v2 : 作業域(n次元ベクトル) */
/*      return : 求まった固有値の数     */
/*      coded by Y.Suganuma             */
/****************************************/
#include <math.h>

int power(int i, int n, int m, int ct, double eps, double **A, double **B,
          double **C, double *r, double **v, double *v0, double *v1, double *v2)
{
	double l1, l2, x;
	int i1, i2, i3, ind, k, k1;
					// 初期設定
	ind = i;
	k   = 0;
	l1  = 0.0;
	for (i1 = 0; i1 < n; i1++) {
		l1     += v0[i1] * v0[i1];
		v1[i1]  = v0[i1];
	}
	l1 = sqrt(l1);
					// 繰り返し計算
	while (k < ct) {
						// 丸め誤差の修正
		if (k%m == 0) {
			l2 = 0.0;
			for (i1 = 0; i1 < n; i1++) {
				v2[i1] = 0.0;
				for (i2 = 0; i2 < n; i2++)
					v2[i1] += B[i1][i2] * v1[i2];
				l2 += v2[i1] * v2[i1];
			}
			l2 = sqrt(l2);
			for (i1 = 0; i1 < n; i1++)
				v1[i1] = v2[i1] / l2;
		}
						// 次の近似
		l2 = 0.0;
		for (i1 = 0; i1 < n; i1++) {
			v2[i1] = 0.0;
			for (i2 = 0; i2 < n; i2++)
				v2[i1] += A[i1][i2] * v1[i2];
			l2 += v2[i1] * v2[i1];
		}
		l2 = sqrt(l2);
		for (i1 = 0; i1 < n; i1++)
			v2[i1] /= l2;
						// 収束判定
							// 収束した場合
		if (fabs((l2-l1)/l1) < eps) {
			k1 = -1;
			for (i1 = 0; i1 < n && k1 < 0; i1++) {
				if (fabs(v2[i1]) > 0.001) {
					k1 = i1;
					if (v2[k1]*v1[k1] < 0.0)
						l2 = -l2;
				}
			}
			k    = ct;
			r[i] = l2;
			for (i1 = 0; i1 < n; i1++)
				v[i][i1] = v2[i1];
			if (i == n-1)
				ind = i + 1;
			else {
				for (i1 = 0; i1 < n; i1++) {
					for (i2 = 0; i2 < n; i2++) {
						C[i1][i2] = 0.0;
						for (i3 = 0; i3 < n; i3++) {
							x          = (i1 == i3) ? A[i1][i3] - l2 : A[i1][i3];
							C[i1][i2] += x * B[i3][i2];
						}
					}
				}
				for (i1 = 0; i1 < n; i1++) {
					for (i2 = 0; i2 < n; i2++)
						B[i1][i2] = C[i1][i2];
				}
				for (i1 = 0; i1 < n; i1++) {
					v1[i1] = 0.0;
					for (i2 = 0; i2 < n; i2++)
						v1[i1] += B[i1][i2] * v0[i2];
				}
				for (i1 = 0; i1 < n; i1++)
					v0[i1] = v1[i1];
				ind = power(i+1, n, m, ct, eps, A, B, C, r, v, v0, v1, v2);
			}
		}
							// 収束しない場合
		else {
			for (i1 = 0; i1 < n; i1++)
				v1[i1] = v2[i1];
			l1 = l2;
			k++;
		}
	}

	return ind;
}