#include <stdio.h>
#include <stdlib.h>
#define N1 3
#define N2 4
void make_square_matrix(double ***a, int n)
{
int i;
if ((*a
= (double **)malloc(n
* sizeof(double *))) == NULL
) for (i = 0; i < n; i++)
if (((*a
)[i
] = (double *)malloc(n
* sizeof(double))) == NULL
) }
void free_square_matrix(double **a, int n)
{
int i;
for (i = 0; i < n; i++)
}
/* LU分解(ドゥーリトル法) */
void LU_decomp(double **a, double **l, double **u, int n)
{
int i, j, k;
for (i = 0; i < n; i++)
l[i][i] = 1.0;
for (i = 0; i < n; i++)
u[0][i] = a[0][i];
for (i = 1; i < n; i++) {
if (u[i - 1][i - 1] == 0.0)
for (j = i; j < n; j++) {
// L成分の算出
l[j][i - 1] = a[j][i - 1];
for (k = 0; k < i - 1; k++)
l[j][i - 1] -= l[j][k] * u[k][i - 1];
l[j][i - 1] /= u[i - 1][i - 1];
// U成分の算出
u[i][j] = a[i][j];
for (k = 0; k < i; k++)
u[i][j] -= l[i][k] * u[k][j];
}
}
}
void print_matrix(double **a, int n, char *s)
{
int i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++)
}
}
/* 三角行列の行列式は対角成分の積 */
double det_triangular_matrix(double **a, int n)
{
int i;
double det = 1.0;
for (i = 0; i < n; i++)
det *= a[i][i];
return det;
}
int main(void)
{
double **a, **l, **u, det;
int i, j;
double a1[N1][N1] = {{2.0, 3.0, -1.0}, {4.0, 4.0, -3.0}, {2.0, -3.0, 1.0}};
double a2[N2][N2] = {{1.0, 1.0, 0.0, 3.0}, {2.0, 1.0, -1.0, 1.0}, {3.0, -1.0, -1.0, 2.0}, {-1.0, 2.0, 3.0, -2.0}};
make_square_matrix(&a, N1);
make_square_matrix(&l, N1);
make_square_matrix(&u, N1);
for (i = 0; i < N1; i++)
for (j = 0; j < N1; j++)
a[i][j] = a1[i][j];
LU_decomp(a, l, u, N1);
print_matrix(a, N1, "行列 A");
print_matrix(l, N1, "行列 L");
print_matrix(u, N1, "行列 U");
/* |A| = |L||U| */
det = det_triangular_matrix(l, N1) * det_triangular_matrix(u, N1);
printf("行列式 |A| = %f\n", det
);
free_square_matrix(a, N1);
free_square_matrix(l, N1);
free_square_matrix(u, N1);
make_square_matrix(&a, N2);
make_square_matrix(&l, N2);
make_square_matrix(&u, N2);
for (i = 0; i < N2; i++)
for (j = 0; j < N2; j++)
a[i][j] = a2[i][j];
LU_decomp(a, l, u, N2);
print_matrix(a, N2, "行列 A");
print_matrix(l, N2, "行列 L");
print_matrix(u, N2, "行列 U");
det = det_triangular_matrix(l, N2) * det_triangular_matrix(u, N2);
printf("行列式 |A| = %f\n", det
);
free_square_matrix(a, N2);
free_square_matrix(l, N2);
free_square_matrix(u, N2);
return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KCiNkZWZpbmUgTjEgMwojZGVmaW5lIE4yIDQKCnZvaWQgbWFrZV9zcXVhcmVfbWF0cml4KGRvdWJsZSAqKiphLCBpbnQgbikKewogIGludCBpOwogIAogIGlmICgoKmEgPSAoZG91YmxlICoqKW1hbGxvYyhuICogc2l6ZW9mKGRvdWJsZSAqKSkpID09IE5VTEwpCiAgICBleGl0KDEpOwogIGZvciAoaSA9IDA7IGkgPCBuOyBpKyspCiAgICBpZiAoKCgqYSlbaV0gPSAoZG91YmxlICopbWFsbG9jKG4gKiBzaXplb2YoZG91YmxlKSkpID09IE5VTEwpCiAgICAgIGV4aXQoMSk7Cn0KCnZvaWQgZnJlZV9zcXVhcmVfbWF0cml4KGRvdWJsZSAqKmEsIGludCBuKQp7CiAgaW50IGk7CiAgCiAgZm9yIChpID0gMDsgaSA8IG47IGkrKykKICAgIGZyZWUoYVtpXSk7CiAgZnJlZShhKTsKfQoKLyogTFXliIbop6Mo44OJ44Kl44O844Oq44OI44Or5rOVKSAqLwp2b2lkIExVX2RlY29tcChkb3VibGUgKiphLCBkb3VibGUgKipsLCBkb3VibGUgKip1LCBpbnQgbikKewogIGludCBpLCBqLCBrOwoKICBmb3IgKGkgPSAwOyBpIDwgbjsgaSsrKQogICAgbFtpXVtpXSA9IDEuMDsKICBmb3IgKGkgPSAwOyBpIDwgbjsgaSsrKQogICAgdVswXVtpXSA9IGFbMF1baV07CgogIGZvciAoaSA9IDE7IGkgPCBuOyBpKyspIHsKICAgIGlmICh1W2kgLSAxXVtpIC0gMV0gPT0gMC4wKQogICAgICBleGl0KDEpOwogICAgZm9yIChqID0gaTsgaiA8IG47IGorKykgewogICAgICAvLyBM5oiQ5YiG44Gu566X5Ye6CiAgICAgIGxbal1baSAtIDFdID0gYVtqXVtpIC0gMV07CiAgICAgIGZvciAoayA9IDA7IGsgPCBpIC0gMTsgaysrKQogICAgICAgIGxbal1baSAtIDFdIC09IGxbal1ba10gKiB1W2tdW2kgLSAxXTsKICAgICAgbFtqXVtpIC0gMV0gLz0gdVtpIC0gMV1baSAtIDFdOwogICAgICAvLyBV5oiQ5YiG44Gu566X5Ye6CiAgICAgIHVbaV1bal0gPSBhW2ldW2pdOwogICAgICBmb3IgKGsgPSAwOyBrIDwgaTsgaysrKQogICAgICAgIHVbaV1bal0gLT0gbFtpXVtrXSAqIHVba11bal07CiAgICB9CiAgfQp9Cgp2b2lkIHByaW50X21hdHJpeChkb3VibGUgKiphLCBpbnQgbiwgY2hhciAqcykKewogIGludCBpLCBqOwogIAogIHByaW50ZigiKioqICVzICoqKlxuIiwgcyk7CiAgCiAgZm9yIChpID0gMDsgaSA8IG47IGkrKykgewogICAgZm9yIChqID0gMDsgaiA8IG47IGorKykKICAgICAgcHJpbnRmKCIlIDExLjdmICAiLCBhW2ldW2pdKTsKICAgIHB1dGNoYXIoJ1xuJyk7CiAgfQp9CgovKiDkuInop5LooYzliJfjga7ooYzliJflvI/jga/lr77op5LmiJDliIbjga7nqY0gKi8KZG91YmxlIGRldF90cmlhbmd1bGFyX21hdHJpeChkb3VibGUgKiphLCBpbnQgbikKewogIGludCBpOwogIGRvdWJsZSBkZXQgPSAxLjA7CiAgCiAgZm9yIChpID0gMDsgaSA8IG47IGkrKykKICAgIGRldCAqPSBhW2ldW2ldOwogIAogIHJldHVybiBkZXQ7Cn0KCmludCBtYWluKHZvaWQpCnsKICBkb3VibGUgKiphLCAqKmwsICoqdSwgZGV0OwogIGludCBpLCBqOwogIAogIGRvdWJsZSBhMVtOMV1bTjFdID0ge3syLjAsIDMuMCwgLTEuMH0sIHs0LjAsIDQuMCwgLTMuMH0sIHsyLjAsIC0zLjAsIDEuMH19OwogIGRvdWJsZSBhMltOMl1bTjJdID0ge3sxLjAsIDEuMCwgMC4wLCAzLjB9LCB7Mi4wLCAxLjAsIC0xLjAsIDEuMH0sIHszLjAsIC0xLjAsIC0xLjAsIDIuMH0sIHstMS4wLCAyLjAsIDMuMCwgLTIuMH19OwogIAogIG1ha2Vfc3F1YXJlX21hdHJpeCgmYSwgTjEpOwogIG1ha2Vfc3F1YXJlX21hdHJpeCgmbCwgTjEpOwogIG1ha2Vfc3F1YXJlX21hdHJpeCgmdSwgTjEpOwogIAogIGZvciAoaSA9IDA7IGkgPCBOMTsgaSsrKQogICAgZm9yIChqID0gMDsgaiA8IE4xOyBqKyspCiAgICAgIGFbaV1bal0gPSBhMVtpXVtqXTsKICAKICBMVV9kZWNvbXAoYSwgbCwgdSwgTjEpOwogIAogIHByaW50X21hdHJpeChhLCBOMSwgIuihjOWIlyBBIik7CiAgcHJpbnRfbWF0cml4KGwsIE4xLCAi6KGM5YiXIEwiKTsKICBwcmludF9tYXRyaXgodSwgTjEsICLooYzliJcgVSIpOwoKICAvKiB8QXwgPSB8THx8VXwgKi8KICBkZXQgPSBkZXRfdHJpYW5ndWxhcl9tYXRyaXgobCwgTjEpICogZGV0X3RyaWFuZ3VsYXJfbWF0cml4KHUsIE4xKTsKICBwcmludGYoIuihjOWIl+W8jyB8QXwgPSAlZlxuIiwgZGV0KTsKICAKICBmcmVlX3NxdWFyZV9tYXRyaXgoYSwgTjEpOwogIGZyZWVfc3F1YXJlX21hdHJpeChsLCBOMSk7CiAgZnJlZV9zcXVhcmVfbWF0cml4KHUsIE4xKTsKCiAgcHV0Y2hhcignXG4nKTsKICAKICBtYWtlX3NxdWFyZV9tYXRyaXgoJmEsIE4yKTsKICBtYWtlX3NxdWFyZV9tYXRyaXgoJmwsIE4yKTsKICBtYWtlX3NxdWFyZV9tYXRyaXgoJnUsIE4yKTsKICAKICBmb3IgKGkgPSAwOyBpIDwgTjI7IGkrKykKICAgIGZvciAoaiA9IDA7IGogPCBOMjsgaisrKQogICAgICBhW2ldW2pdID0gYTJbaV1bal07CiAgCiAgTFVfZGVjb21wKGEsIGwsIHUsIE4yKTsKICAKICBwcmludF9tYXRyaXgoYSwgTjIsICLooYzliJcgQSIpOwogIHByaW50X21hdHJpeChsLCBOMiwgIuihjOWIlyBMIik7CiAgcHJpbnRfbWF0cml4KHUsIE4yLCAi6KGM5YiXIFUiKTsKICAKICBkZXQgPSBkZXRfdHJpYW5ndWxhcl9tYXRyaXgobCwgTjIpICogZGV0X3RyaWFuZ3VsYXJfbWF0cml4KHUsIE4yKTsKICBwcmludGYoIuihjOWIl+W8jyB8QXwgPSAlZlxuIiwgZGV0KTsKCiAgZnJlZV9zcXVhcmVfbWF0cml4KGEsIE4yKTsKICBmcmVlX3NxdWFyZV9tYXRyaXgobCwgTjIpOwogIGZyZWVfc3F1YXJlX21hdHJpeCh1LCBOMik7CgogIHJldHVybiAwOwp9