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

/****************************************/
/* 最大固有値と固有ベクトル(べき乗法) */
/*      coded by Y.Suganuma             */
/****************************************/
import java.io.*;

public class Test {
	public static void main(String args[]) throws IOException
	{
		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][n];
		B   = new double [n][n];
		C   = new double [n][n];
		v   = new double [n][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)
			System.out.println("固有値が求まりませんでした!");
		else {
			for (i1 = 0; i1 < ind; i1++) {
				System.out.print("固有値 " + r[i1]);
				System.out.print(" 固有ベクトル ");
				for (i2 = 0; i2 < n; i2++)
					System.out.print(" " + v[i1][i2]);
				System.out.println();
			}
		}
	}

	/****************************************/
	/* 最大固有値と固有ベクトル(べき乗法) */
	/*      i : 何番目の固有値かを示す      */
	/*      n : 次数                        */
	/*      m : 丸め誤差の修正回数          */
	/*      ct : 最大繰り返し回数           */
	/*      eps : 収束判定条件              */
	/*      A : 対象とする行列              */
	/*      B : nxnの行列,最初は,単位行列 */
	/*      C : 作業域,nxnの行列           */
	/*      r : 固有値                      */
	/*      v : 各行が固有ベクトル(nxn)   */
	/*      v0 : 固有ベクトルの初期値       */
	/*      v1,v2 : 作業域(n次元ベクトル) */
	/*      return : 求まった固有値の数     */
	/*      coded by Y.Suganuma             */
	/****************************************/
	static 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 = Math.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 = Math.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 = Math.sqrt(l2);
			for (i1 = 0; i1 < n; i1++)
				v2[i1] /= l2;
						// 収束判定
							// 収束した場合
			if (Math.abs((l2-l1)/l1) < eps) {
				k1 = -1;
				for (i1 = 0; i1 < n && k1 < 0; i1++) {
					if (Math.abs(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;
	}
}