[ 簡単な説明 ] 行列の計算を行う関数ライブラリです。但し、本来2次元の配列であるべき行列を1次元配列で扱うので演算が若干理解しづらくなっています。使い方は使用例をよく見て理解してください。 |
関数名 | 関数の機能 | 機能説明 | 呼び出し例 |
madd( ) | 加算 | m行la列の行列 a とm行lb列の行列 b を加算し m行lc列の行列 c に出力。n は加算処理列数。 |
madd(a, b, c, la, lb, lc, m, n); |
msub( ) | 減算 | m行la列の行列 a からm行lb列の行列 b を減算し m行lc列の行列 c に出力。n は減算処理列数。 |
msub(a, b, c, la, lb, lc, m, n); |
mmul1( ) | 乗算 | m行la列の行列 a とm行lb列の行列 b を乗算し 行列 b に格納する。 |
mmul1(a, b, la, lb, m); |
mmul2( ) | 乗算 | m行la列の行列 a とk行lb列の行列 b を乗算し m行lc列の行列 c に格納する。 n は行列 b の乗算処理対応列数。 |
mmul2(a, b, c, la, lb, lc, m, n, k); |
mtra1( ) | 転置 | m行l列の行列 a を転置する。n は処理列数。 | mtra1(a, l, m, n) |
mtra2( ) | 転置 | m行la列の行列 a を転置し n行lb列の行列 b に格納する。 |
mtra2(a, b, la, lb, m, n); |
minver( ) | 逆行列と 行列式の値 |
m行l列の行列 a の逆行列を a に格納し 行列式の値を返す。epsは収束判定値。 |
d = minver(a, l, m, eps); |
mmove( ) | コピー | m行la列の行列 a を n行lb列の行列 b にコピーする。 | mmove(a, b, la, lb, m, n); |
mswap( ) | 入替え | m行la列の行列 a と n行lb列の行列 b を入替える。 | mswap(a, b, la, lb, m, n); |
jacobi( ) | 固有値と 固有ベクトル ヤコビ法 |
m行l列の行列 a の固有ベクトルを m行l列の行列 v に格納し a の対角要素に固有値を格納する。 nr は回転最大数を与え、処理後回転数が返る。 eps は収束判定値。 |
jacobi(a, v, l, m, &nr, eps); |
/* matrix.c */ #include <stdio.h> #include <stdlib.h> #include "sslib.h" void madd(double a[], double b[], double c[], int la, int lb, int lc, int m, int n) { int i, j, ka, kb, kc; double *p, *q, *r; if(m <= 0 || n <= 0 || la < n || lb < n || lc < n ) { fprintf(stderr, "Error : Illegal parameter in madd()\n"); return; } for(i = 0, ka = kb = kc = 0; i < m; i++, ka += la, kb += lb, kc += lc) for(j = 0, p = a + ka, q = b + kb, r = c + kc; j < n; j++) *r++ = *p++ + *q++; return; } void msub(double a[], double b[], double c[], int la, int lb, int lc, int m, int n) { int i, j, ka, kb, kc; double *p, *q, *r; if(m <= 0 || n <= 0 || la < n || lb < n || lc < n ) { fprintf(stderr, "Error : Illegal parameter in msub()\n"); return; } for(i = 0, ka = kb = kc = 0; i < m; i++, ka += la, kb += lb, kc += lc) for (j = 0, p = a + ka, q = b + kb, r = c + kc; j < n; j++) *r++ = *p++ - *q++; return; } void mmul1(double a[], double b[], int la, int lb, int m) { int i, j, ka, kc, l; double *p, *q, *r, w, *work; if(m <= 0 || la < m || lb < m) { fprintf(stderr, "Error : Illegal parameter in mmul1()\n"); return; } work = (double *)malloc(m * m * sizeof(double)); if(work == NULL) { fprintf(stderr, "Error : Out of memory in mmul1()\n"); return; } for(i = 0, ka = 0, r = work; i < m; i++, ka += la) { for(l = 0; l < m; l++) { w = 0.; for(j = 0, p = a + ka, q = b + l; j < m; j++) { w += *p++ * *q; q += lb; } *r++ = w; } } mmove(work, a, m, la, m, m); free((char *)work); return; } void mmul2(double a[], double b[], double c[], int la, int lb, int lc, int m, int n, int k) { int i, j, ka, kc, l; double *p, *q, *r, w; if(m <= 0 || n <= 0 || k <= 0 || la < n || lb < k || lc < k ) { fprintf(stderr, "Error : Illegal parameter in mmul2()\n"); return; } for(i = 0, ka = kc = 0; i < m; i++, ka += la, kc += lc) { for(l = 0, r = c + kc; l < k; l++) { w = 0.; for(j = 0, p = a + ka, q = b + l; j < n; j++) { w += *p++ * *q; q += lb; } *r++ = w; } } } void mtra1(double a[], int l, int m, int n) { int i, j, ka, mn; double *p, *q; if(m <= 0 || n <= 0 || l < m || l < n || m < n) { fprintf(stderr, "Error : Illegal parameter in mtra1()\n"); return; } mn = m; if(mn < n) mn = n; for(i = 0, ka = 0; i < mn - 1; i++, ka += l) for(j = i + 1, p = a + ka + j, q = p + l - 1; j < mn; j++, q += l) swapd(p++, q); } void mtra2(double a[], double b[], int la, int lb, int m, int n) { int i, j, ka; double *p, *q; if(m <= 0 || n <= 0 || la < n || lb < m) { fprintf(stderr, "Error : Illegal parameter in mtra2()\n"); return; } for(i = 0, ka = 0; i < m; i++, ka += la) for(j = 0, p = a + ka, q = b + i; j < n; j++, q += lb) *q = *p++; } double minver(double a[], int l, int m, double eps) { int i, iw, j, k, *p, r, s, t, u, v, *work; double api, pivot, *q, *q1, w, w1, wmax; if(m < 2 || l < m || eps <= 0.) { fprintf(stderr, "Error : Illegal parameter in minver()\n"); return 0.; } work = (int *)malloc(m * sizeof(int)); if(work == NULL) { fprintf(stderr, "Error : Out of memory in minver()\n"); return 0.; } w1 = 1.; for(i = 0, p = work; i < m; i++) *p++ = i; for(k = 0, u = 0; k < m; k++, u += l) { wmax = 0.; for(i = k; i < m; i++) { w = fabs(*(a + i * l + k)); if(w > wmax) { wmax = w; r = i; } } api = fabs(pivot = *(a + r * l + k)); if(api < eps) { fprintf(stderr, "Error : api < eps in minver()\n"); free((char *)work); return w1; } w1 *= pivot; v = r * l; if(r != k) { w1 = -w1; swapi(work + k, work + r); for(j = 0, q = a + u, q1 = a + v; j < m; j++) swapd(q++, q1++); } for(i = 0, q = a + u; i < m; i++) *q++ /= pivot; for(i = 0, v = 0; i < m; i++, v += l) { if(i != k) { s = v + k; w = *(a + s); if(w != 0.) { for(j = 0, q = a + u, q1 = a + v; j < m; j++, q++, q1++) if (j != k) *q1 -= w * *q; *(a + s) = - w / pivot; } } } *(a + u + k) = 1. / pivot; } for(i = 0; i < m; i++) { for(;;) { k = *(work + i); if(k == i) break; swapi(work + k, work + i); for(j = 0, u = 0; j < m; j++, u += l) swapd(a + u + i, a + u + k); } } free((char *)work); return w1; } void mmove(double a[], double b[], int la, int lb, int m, int n) { int i, j, ka, kb; double *p, *q; if(m <= 0 || n <= 0 || la < n || lb < n) { fprintf(stderr, "Error : Illegal parameter in mmove()\n"); return; } for(i = ka = kb = 0; i < m; i++, ka += la, kb += lb) for(j = 0, p = a + ka, q = b + kb; j < n; j++) *q++ = *p++; return; } void mswap(double a[], double b[], int la, int lb, int m, int n) { int i, j, ka, kb; double *p, *q; if(m <= 0 || n <= 0 || la < n || lb < n) { fprintf(stderr, "Error : Illegal parameter in mswap()\n"); return; } for(i = ka = kb = 0; i < m; i++, ka += la, kb += lb) for(j = 0, p = a + ka, q = b + kb; j < n; j++) swapd(p++, q++); return; } int jacobi(double a[], double v[], int l, int m, int *nr, double eps) { int n, i, j, r, c, k1, k2, s1, s2, s3, s5, s6; double wmax, w, a1, a2, a3, t1, ta, si, co; if(m < 2 || *nr < 1 || eps <= 0.0) return 999; n = 0; for(i = 0; i < m - 1; i++) { k1 = i * l; for(j = i + 1; j < m; j++) if(a[k1 + j] != a[j * l + i]) return 999; } for(i = 0; i < m; i++) { k1 = i * l; for(j = 0; j < m; j++) if(i != j) v[k1 + j] = 0.0; v[k1 + i] = 1.0; } while(1) { wmax = 0.0; for(i = 0; i < m; i++) { k1 = i * l; for(j = i + 1; j < m; j++) { w = fabs(a[k1 + j]); if(w > wmax) { wmax = w; r = i; c = j; } } } if(wmax <= eps) { *nr = n; return 0; } if(n >= *nr) { *nr = n; return 1; } k1 = r * l; k2 = c * l; s1 = k1 + r; s2 = k2 + c; s3 = k1 + c; n++; a1 = a[s1]; a2 = a[s2]; a3 = a[s3]; t1 = fabs(a1 - a2); ta = 2.0 * a3 / (t1 + sqrt(t1 * t1 + 4.0 * a3 * a3)); if(a1 < a2) ta = - ta; co = sqrt(1.0 / (ta * ta + 1.0)); si = ta * co; for(i = 0; i < m; i++) { s5 = i * l + r; s6 = i * l + c; w = v[s5]; v[s5] = w * co + v[s6] * si; v[s6] = - w * si + v[s6] * co; if(i != r && i != c) { w = a[s5]; a[s5] = w * co + a[s6] *si; a[s6] = - w * si + a[s6] * co; a[k1 + i] = a[s5]; a[k2 + i] = a[s6]; } } a[s1] = a1 * co * co + a2 * si * si + 2.0 * a3 * co * si; a[s2] = a1 + a2 - a[s1]; a[s3] = 0.0; a[k2 + r] = 0.0; } } |