#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define N 4 // Matrix dimension
#define MAX_ITER 100 // Maximum number of sweeps
#define EPSILON 1e-6 // 収束判定条件 (Convergence threshold)
// Function prototypes
void jacobi_method(double A[N][N], double eigenvalues[N], double eigenvectors[N][N]);
void verify_results(double orig_A[N][N], double eigenvalues[N], double eigenvectors[N][N]);
int main() {
// 1. Define the matrix from image_4.png
double A[N][N] = {
{5.0, 4.0, 1.0, 1.0},
{4.0, 5.0, 1.0, 1.0},
{1.0, 1.0, 4.0, 2.0},
{1.0, 1.0, 2.0, 4.0}
};
// Keep a copy of the original matrix for validation later
double orig_A[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
orig_A[i][j] = A[i][j];
}
}
double eigenvalues[N];
double eigenvectors[N][N];
// 2. Run Jacobi Method (Prints detailed iteration step history)
jacobi_method(A, eigenvalues, eigenvectors);
// 3. Print Final Results
printf("\n--- Final Results ---\n"); for (int i = 0; i < N; i++) {
printf("Eigenvalue %d (固有値): %9.6f\n", i
+ 1, eigenvalues
[i
]); printf("Eigenvector %d (固有ベクトル): [ ", i
+ 1); for (int j = 0; j < N; j++) {
printf("%9.6f ", eigenvectors
[j
][i
]); // Columns are eigenvectors }
}
// 4. Verification Check (固有値・固有ベクトルの確認)
verify_results(orig_A, eigenvalues, eigenvectors);
return 0;
}
void jacobi_method(double A[N][N], double eigenvalues[N], double eigenvectors[N][N]) {
// Initialize eigenvector matrix as identity matrix
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
eigenvectors[i][j] = (i == j) ? 1.0 : 0.0;
}
}
printf("--- Iteration Process (収束状況) ---\n");
int step = 0;
for (int iter = 1; iter <= MAX_ITER; iter++) {
double max_off_diag = 0.0;
int p = 0, q = 0;
// Find the largest off-diagonal element |A[p][q]|
for (int i = 0; i < N; i++) {
for (int j = i + 1; j < N; j++) {
if (fabs(A
[i
][j
]) > max_off_diag
) { max_off_diag
= fabs(A
[i
][j
]); p = i;
q = j;
}
}
}
// Check for convergence
if (max_off_diag < EPSILON) {
printf("\n[Convergence Achieved] All remaining off-diagonal elements are below the threshold.\n"); break;
}
step++;
// Print detailed iteration step showing exactly which elements are shrinking
printf("Step %2d | Eliminating A[%d][%d] = %9.6f | Current Diagonals: [%.4f, %.4f, %.4f, %.4f]\n", step, p, q, A[p][q], A[0][0], A[1][1], A[2][2], A[3][3]);
// --- Pure Algebraic Calculation of cos(theta) and sin(theta) ---
double app = A[p][p];
double aqq = A[q][q];
double apq = A[p][q];
double c, s;
c = 1.0;
s = 0.0;
} else {
double phi = 0.5 * (app - aqq) / apq;
double t;
if (phi >= 0.0) {
t
= 1.0 / (phi
+ sqrt(phi
* phi
+ 1.0)); } else {
t
= -1.0 / (-phi
+ sqrt(phi
* phi
+ 1.0)); }
c
= 1.0 / sqrt(1.0 + t
* t
); s = t * c;
}
// Update elements of matrix A
for (int i = 0; i < N; i++) {
if (i != p && i != q) {
double a_ip = A[i][p];
double a_iq = A[i][q];
A[i][p] = A[p][i] = c * a_ip + s * a_iq;
A[i][q] = A[q][i] = -s * a_ip + c * a_iq;
}
}
A[p][p] = c * c * app + 2.0 * s * c * apq + s * s * aqq;
A[q][q] = s * s * app - 2.0 * s * c * apq + c * c * aqq;
A[p][q] = A[q][p] = 0.0;
// Update accumulated eigenvector matrix P
for (int i = 0; i < N; i++) {
double v_ip = eigenvectors[i][p];
double v_iq = eigenvectors[i][q];
eigenvectors[i][p] = c * v_ip + s * v_iq;
eigenvectors[i][q] = -s * v_ip + c * v_iq;
}
}
// Extract eigenvalues from the diagonal elements
for (int i = 0; i < N; i++) {
eigenvalues[i] = A[i][i];
}
}
// Verification function: Explicitly outputs vector equation components and tests vector validity
void verify_results(double orig_A[N][N], double eigenvalues[N], double eigenvectors[N][N]) {
printf("--- Verification Check (Ax = lambda * x & Vector Validity) ---\n");
for (int k = 0; k < N; k++) {
double x[N];
double Ax[N];
double lambda_x[N];
double vector_norm = 0.0;
// Extract the k-th eigenvector
for (int i = 0; i < N; i++) {
x[i] = eigenvectors[i][k];
vector_norm += x[i] * x[i]; // sum of squares
}
vector_norm
= sqrt(vector_norm
); // magnitude of the vector
// Calculate elements of vector Ax and vector lambda*x
for (int i = 0; i < N; i++) {
Ax[i] = 0.0;
for (int j = 0; j < N; j++) {
Ax[i] += orig_A[i][j] * x[j];
}
lambda_x[i] = eigenvalues[k] * x[i];
}
// Print results
printf("Pair %d Verification:\n", k
+ 1); printf(" Eigenvector Norm (Vector Length) = %9.6f (Should be 1.0)\n", vector_norm
); printf(" LHS Vector (Ax) = [ %9.6f %9.6f %9.6f %9.6f ]\n", Ax
[0], Ax
[1], Ax
[2], Ax
[3]); printf(" RHS Vector (lambda * x) = [ %9.6f %9.6f %9.6f %9.6f ]\n\n", lambda_x
[0], lambda_x
[1], lambda_x
[2], lambda_x
[3]); }
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPG1hdGguaD4KCiNkZWZpbmUgTiA0ICAgICAgICAgICAgIC8vIE1hdHJpeCBkaW1lbnNpb24KI2RlZmluZSBNQVhfSVRFUiAxMDAgICAgLy8gTWF4aW11bSBudW1iZXIgb2Ygc3dlZXBzCiNkZWZpbmUgRVBTSUxPTiAxZS02ICAgIC8vIOWPjuadn+WIpOWumuadoeS7tiAoQ29udmVyZ2VuY2UgdGhyZXNob2xkKQoKLy8gRnVuY3Rpb24gcHJvdG90eXBlcwp2b2lkIGphY29iaV9tZXRob2QoZG91YmxlIEFbTl1bTl0sIGRvdWJsZSBlaWdlbnZhbHVlc1tOXSwgZG91YmxlIGVpZ2VudmVjdG9yc1tOXVtOXSk7CnZvaWQgdmVyaWZ5X3Jlc3VsdHMoZG91YmxlIG9yaWdfQVtOXVtOXSwgZG91YmxlIGVpZ2VudmFsdWVzW05dLCBkb3VibGUgZWlnZW52ZWN0b3JzW05dW05dKTsKCmludCBtYWluKCkgewogICAgLy8gMS4gRGVmaW5lIHRoZSBtYXRyaXggZnJvbSBpbWFnZV80LnBuZwogICAgZG91YmxlIEFbTl1bTl0gPSB7CiAgICAgICAgezUuMCwgNC4wLCAxLjAsIDEuMH0sCiAgICAgICAgezQuMCwgNS4wLCAxLjAsIDEuMH0sCiAgICAgICAgezEuMCwgMS4wLCA0LjAsIDIuMH0sCiAgICAgICAgezEuMCwgMS4wLCAyLjAsIDQuMH0KICAgIH07CgogICAgLy8gS2VlcCBhIGNvcHkgb2YgdGhlIG9yaWdpbmFsIG1hdHJpeCBmb3IgdmFsaWRhdGlvbiBsYXRlcgogICAgZG91YmxlIG9yaWdfQVtOXVtOXTsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgTjsgaSsrKSB7CiAgICAgICAgZm9yIChpbnQgaiA9IDA7IGogPCBOOyBqKyspIHsKICAgICAgICAgICAgb3JpZ19BW2ldW2pdID0gQVtpXVtqXTsKICAgICAgICB9CiAgICB9CgogICAgZG91YmxlIGVpZ2VudmFsdWVzW05dOwogICAgZG91YmxlIGVpZ2VudmVjdG9yc1tOXVtOXTsKCiAgICAvLyAyLiBSdW4gSmFjb2JpIE1ldGhvZCAoUHJpbnRzIGRldGFpbGVkIGl0ZXJhdGlvbiBzdGVwIGhpc3RvcnkpCiAgICBqYWNvYmlfbWV0aG9kKEEsIGVpZ2VudmFsdWVzLCBlaWdlbnZlY3RvcnMpOwoKICAgIC8vIDMuIFByaW50IEZpbmFsIFJlc3VsdHMKICAgIHByaW50ZigiXG4tLS0gRmluYWwgUmVzdWx0cyAtLS1cbiIpOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBOOyBpKyspIHsKICAgICAgICBwcmludGYoIkVpZ2VudmFsdWUgJWQgKOWbuuacieWApCk6ICU5LjZmXG4iLCBpICsgMSwgZWlnZW52YWx1ZXNbaV0pOwogICAgICAgIHByaW50ZigiRWlnZW52ZWN0b3IgJWQgKOWbuuacieODmeOCr+ODiOODqyk6IFsgIiwgaSArIDEpOwogICAgICAgIGZvciAoaW50IGogPSAwOyBqIDwgTjsgaisrKSB7CiAgICAgICAgICAgIHByaW50ZigiJTkuNmYgIiwgZWlnZW52ZWN0b3JzW2pdW2ldKTsgLy8gQ29sdW1ucyBhcmUgZWlnZW52ZWN0b3JzCiAgICAgICAgfQogICAgICAgIHByaW50ZigiXVxuXG4iKTsKICAgIH0KCiAgICAvLyA0LiBWZXJpZmljYXRpb24gQ2hlY2sgKOWbuuacieWApOODu+WbuuacieODmeOCr+ODiOODq+OBrueiuuiqjSkKICAgIHZlcmlmeV9yZXN1bHRzKG9yaWdfQSwgZWlnZW52YWx1ZXMsIGVpZ2VudmVjdG9ycyk7CgogICAgcmV0dXJuIDA7Cn0KCnZvaWQgamFjb2JpX21ldGhvZChkb3VibGUgQVtOXVtOXSwgZG91YmxlIGVpZ2VudmFsdWVzW05dLCBkb3VibGUgZWlnZW52ZWN0b3JzW05dW05dKSB7CiAgICAvLyBJbml0aWFsaXplIGVpZ2VudmVjdG9yIG1hdHJpeCBhcyBpZGVudGl0eSBtYXRyaXgKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgTjsgaSsrKSB7CiAgICAgICAgZm9yIChpbnQgaiA9IDA7IGogPCBOOyBqKyspIHsKICAgICAgICAgICAgZWlnZW52ZWN0b3JzW2ldW2pdID0gKGkgPT0gaikgPyAxLjAgOiAwLjA7CiAgICAgICAgfQogICAgfQoKICAgIHByaW50ZigiLS0tIEl0ZXJhdGlvbiBQcm9jZXNzICjlj47mnZ/nirbms4EpIC0tLVxuIik7CgogICAgaW50IHN0ZXAgPSAwOwogICAgZm9yIChpbnQgaXRlciA9IDE7IGl0ZXIgPD0gTUFYX0lURVI7IGl0ZXIrKykgewogICAgICAgIGRvdWJsZSBtYXhfb2ZmX2RpYWcgPSAwLjA7CiAgICAgICAgaW50IHAgPSAwLCBxID0gMDsKCiAgICAgICAgLy8gRmluZCB0aGUgbGFyZ2VzdCBvZmYtZGlhZ29uYWwgZWxlbWVudCB8QVtwXVtxXXwKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IE47IGkrKykgewogICAgICAgICAgICBmb3IgKGludCBqID0gaSArIDE7IGogPCBOOyBqKyspIHsKICAgICAgICAgICAgICAgIGlmIChmYWJzKEFbaV1bal0pID4gbWF4X29mZl9kaWFnKSB7CiAgICAgICAgICAgICAgICAgICAgbWF4X29mZl9kaWFnID0gZmFicyhBW2ldW2pdKTsKICAgICAgICAgICAgICAgICAgICBwID0gaTsKICAgICAgICAgICAgICAgICAgICBxID0gajsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgLy8gQ2hlY2sgZm9yIGNvbnZlcmdlbmNlCiAgICAgICAgaWYgKG1heF9vZmZfZGlhZyA8IEVQU0lMT04pIHsKICAgICAgICAgICAgcHJpbnRmKCJcbltDb252ZXJnZW5jZSBBY2hpZXZlZF0gQWxsIHJlbWFpbmluZyBvZmYtZGlhZ29uYWwgZWxlbWVudHMgYXJlIGJlbG93IHRoZSB0aHJlc2hvbGQuXG4iKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQoKICAgICAgICBzdGVwKys7CiAgICAgICAgLy8gUHJpbnQgZGV0YWlsZWQgaXRlcmF0aW9uIHN0ZXAgc2hvd2luZyBleGFjdGx5IHdoaWNoIGVsZW1lbnRzIGFyZSBzaHJpbmtpbmcKICAgICAgICBwcmludGYoIlN0ZXAgJTJkIHwgRWxpbWluYXRpbmcgQVslZF1bJWRdID0gJTkuNmYgfCBDdXJyZW50IERpYWdvbmFsczogWyUuNGYsICUuNGYsICUuNGYsICUuNGZdXG4iLCAKICAgICAgICAgICAgICAgc3RlcCwgcCwgcSwgQVtwXVtxXSwgQVswXVswXSwgQVsxXVsxXSwgQVsyXVsyXSwgQVszXVszXSk7CgogICAgICAgIC8vIC0tLSBQdXJlIEFsZ2VicmFpYyBDYWxjdWxhdGlvbiBvZiBjb3ModGhldGEpIGFuZCBzaW4odGhldGEpIC0tLQogICAgICAgIGRvdWJsZSBhcHAgPSBBW3BdW3BdOwogICAgICAgIGRvdWJsZSBhcXEgPSBBW3FdW3FdOwogICAgICAgIGRvdWJsZSBhcHEgPSBBW3BdW3FdOwogICAgICAgIAogICAgICAgIGRvdWJsZSBjLCBzOyAKCiAgICAgICAgaWYgKGZhYnMoYXBxKSA8IDFlLTEyKSB7CiAgICAgICAgICAgIGMgPSAxLjA7CiAgICAgICAgICAgIHMgPSAwLjA7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZG91YmxlIHBoaSA9IDAuNSAqIChhcHAgLSBhcXEpIC8gYXBxOwogICAgICAgICAgICBkb3VibGUgdDsKICAgICAgICAgICAgaWYgKHBoaSA+PSAwLjApIHsKICAgICAgICAgICAgICAgIHQgPSAxLjAgLyAocGhpICsgc3FydChwaGkgKiBwaGkgKyAxLjApKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHQgPSAtMS4wIC8gKC1waGkgKyBzcXJ0KHBoaSAqIHBoaSArIDEuMCkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGMgPSAxLjAgLyBzcXJ0KDEuMCArIHQgKiB0KTsKICAgICAgICAgICAgcyA9IHQgKiBjOwogICAgICAgIH0KCiAgICAgICAgLy8gVXBkYXRlIGVsZW1lbnRzIG9mIG1hdHJpeCBBCiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBOOyBpKyspIHsKICAgICAgICAgICAgaWYgKGkgIT0gcCAmJiBpICE9IHEpIHsKICAgICAgICAgICAgICAgIGRvdWJsZSBhX2lwID0gQVtpXVtwXTsKICAgICAgICAgICAgICAgIGRvdWJsZSBhX2lxID0gQVtpXVtxXTsKICAgICAgICAgICAgICAgIEFbaV1bcF0gPSBBW3BdW2ldID0gYyAqIGFfaXAgKyBzICogYV9pcTsKICAgICAgICAgICAgICAgIEFbaV1bcV0gPSBBW3FdW2ldID0gLXMgKiBhX2lwICsgYyAqIGFfaXE7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgQVtwXVtwXSA9IGMgKiBjICogYXBwICsgMi4wICogcyAqIGMgKiBhcHEgKyBzICogcyAqIGFxcTsKICAgICAgICBBW3FdW3FdID0gcyAqIHMgKiBhcHAgLSAyLjAgKiBzICogYyAqIGFwcSArIGMgKiBjICogYXFxOwogICAgICAgIEFbcF1bcV0gPSBBW3FdW3BdID0gMC4wOyAKCiAgICAgICAgLy8gVXBkYXRlIGFjY3VtdWxhdGVkIGVpZ2VudmVjdG9yIG1hdHJpeCBQCiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBOOyBpKyspIHsKICAgICAgICAgICAgZG91YmxlIHZfaXAgPSBlaWdlbnZlY3RvcnNbaV1bcF07CiAgICAgICAgICAgIGRvdWJsZSB2X2lxID0gZWlnZW52ZWN0b3JzW2ldW3FdOwogICAgICAgICAgICBlaWdlbnZlY3RvcnNbaV1bcF0gPSBjICogdl9pcCArIHMgKiB2X2lxOwogICAgICAgICAgICBlaWdlbnZlY3RvcnNbaV1bcV0gPSAtcyAqIHZfaXAgKyBjICogdl9pcTsKICAgICAgICB9CiAgICB9CgogICAgLy8gRXh0cmFjdCBlaWdlbnZhbHVlcyBmcm9tIHRoZSBkaWFnb25hbCBlbGVtZW50cwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBOOyBpKyspIHsKICAgICAgICBlaWdlbnZhbHVlc1tpXSA9IEFbaV1baV07CiAgICB9Cn0KCi8vIFZlcmlmaWNhdGlvbiBmdW5jdGlvbjogRXhwbGljaXRseSBvdXRwdXRzIHZlY3RvciBlcXVhdGlvbiBjb21wb25lbnRzIGFuZCB0ZXN0cyB2ZWN0b3IgdmFsaWRpdHkKdm9pZCB2ZXJpZnlfcmVzdWx0cyhkb3VibGUgb3JpZ19BW05dW05dLCBkb3VibGUgZWlnZW52YWx1ZXNbTl0sIGRvdWJsZSBlaWdlbnZlY3RvcnNbTl1bTl0pIHsKICAgIHByaW50ZigiLS0tIFZlcmlmaWNhdGlvbiBDaGVjayAoQXggPSBsYW1iZGEgKiB4ICYgVmVjdG9yIFZhbGlkaXR5KSAtLS1cbiIpOwogICAgCiAgICBmb3IgKGludCBrID0gMDsgayA8IE47IGsrKykgewogICAgICAgIGRvdWJsZSB4W05dOwogICAgICAgIGRvdWJsZSBBeFtOXTsKICAgICAgICBkb3VibGUgbGFtYmRhX3hbTl07CiAgICAgICAgZG91YmxlIHZlY3Rvcl9ub3JtID0gMC4wOwoKICAgICAgICAvLyBFeHRyYWN0IHRoZSBrLXRoIGVpZ2VudmVjdG9yCiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBOOyBpKyspIHsKICAgICAgICAgICAgeFtpXSA9IGVpZ2VudmVjdG9yc1tpXVtrXTsKICAgICAgICAgICAgdmVjdG9yX25vcm0gKz0geFtpXSAqIHhbaV07IC8vIHN1bSBvZiBzcXVhcmVzCiAgICAgICAgfQogICAgICAgIHZlY3Rvcl9ub3JtID0gc3FydCh2ZWN0b3Jfbm9ybSk7IC8vIG1hZ25pdHVkZSBvZiB0aGUgdmVjdG9yCgogICAgICAgIC8vIENhbGN1bGF0ZSBlbGVtZW50cyBvZiB2ZWN0b3IgQXggYW5kIHZlY3RvciBsYW1iZGEqeAogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgTjsgaSsrKSB7CiAgICAgICAgICAgIEF4W2ldID0gMC4wOwogICAgICAgICAgICBmb3IgKGludCBqID0gMDsgaiA8IE47IGorKykgewogICAgICAgICAgICAgICAgQXhbaV0gKz0gb3JpZ19BW2ldW2pdICogeFtqXTsKICAgICAgICAgICAgfQogICAgICAgICAgICBsYW1iZGFfeFtpXSA9IGVpZ2VudmFsdWVzW2tdICogeFtpXTsKICAgICAgICB9CgogICAgICAgIC8vIFByaW50IHJlc3VsdHMKICAgICAgICBwcmludGYoIlBhaXIgJWQgVmVyaWZpY2F0aW9uOlxuIiwgayArIDEpOwogICAgICAgIHByaW50ZigiICBFaWdlbnZlY3RvciBOb3JtIChWZWN0b3IgTGVuZ3RoKSA9ICU5LjZmIChTaG91bGQgYmUgMS4wKVxuIiwgdmVjdG9yX25vcm0pOwogICAgICAgIHByaW50ZigiICBMSFMgVmVjdG9yIChBeCkgICAgICAgICAgICAgICAgICA9IFsgJTkuNmYgICU5LjZmICAlOS42ZiAgJTkuNmYgXVxuIiwgQXhbMF0sIEF4WzFdLCBBeFsyXSwgQXhbM10pOwogICAgICAgIHByaW50ZigiICBSSFMgVmVjdG9yIChsYW1iZGEgKiB4KSAgICAgICAgICA9IFsgJTkuNmYgICU5LjZmICAlOS42ZiAgJTkuNmYgXVxuXG4iLCBsYW1iZGFfeFswXSwgbGFtYmRhX3hbMV0sIGxhbWJkYV94WzJdLCBsYW1iZGFfeFszXSk7CiAgICB9Cn0K