householder_QR_decomp.c

/*--------------------------------------------------------------------------------

ハウスホルダー変換を用いたQR分解

QR decomposition using the Householder transformation


householder_QR_decomp.c

--------------------------------------------------------------------------------*/


#include "lorenz_lyap.h"


void householder_QR_decomp( double X[DIM][DIM], double Q[DIM][DIM], double R[DIM][DIM] )

{

int i;

int j;

int k;

double alpha;

double norm;

double v[DIM][DIM];  // Householder vector, ハウスホルダー変換ベクトル

double u[DIM][DIM];  // temporary matrix


// initialize Q as an identity matrix

for (i = 0; i < DIM; i++) {

for (j = 0; j < DIM; j++) {

Q[i][j] = (i == j) ? 1.0 : 0.0;

}

}


for (i = 0; i < DIM; i++) {

for (j = 0; j < DIM; j++) {

R[i][j] = X[i][j];

}

}


// perform QR decomposition

// QR分解を実行

for (k = 0; k < DIM; k++) {

// compute the norm of the k-th column of R

// Rのk列のノルムを計算

norm = 0.0;

for (i = k; i < DIM; i++) {

norm += R[i][k] * R[i][k];

}

norm = sqrt(norm);


// compute alpha and update the k-th column of R

// alphaを計算し、Rのk列を更新

alpha = (R[k][k] > 0) ? -norm : norm;

u[k][k] = R[k][k] - alpha;

for (i = k+1; i < DIM; i++) {

u[i][k] = R[i][k];

}


// compute the Householder vector v

// ハウスホルダー変換ベクトルvを計算

norm = 0.0;

for (i = k; i < DIM; i++) {

norm += u[i][k] * u[i][k];

}

norm = sqrt(norm);

for (i = k; i < DIM; i++) {

v[i][k] = u[i][k] / norm;

}


// update R and Q using the Householder transformation

// ハウスホルダー変換を使ってRとQを更新

for (j = k; j < DIM; j++) {

alpha = 0.0;

for (i = k; i < DIM; i++) {

alpha += v[i][k] * R[i][j];

}

alpha *= 2.0;

for (i = k; i < DIM; i++) {

R[i][j] -= alpha * v[i][k];

}

}


for (j = 0; j < DIM; j++) {

alpha = 0.0;

for (i = k; i < DIM; i++) {

alpha += v[i][k] * Q[j][i];

}

alpha *= 2.0;

for (i = k; i < DIM; i++) {

Q[j][i] -= alpha * v[i][k];

}

}

}

}