/* vi: set tabstop=4 nocindent noautoindent: */ /** マトリックス&ベクトルライブラリ matrix.c ヘッダ #include "matrix.h" */ #include "matrix.h" /** vector unit_vector(vector a) 機能: ベクトル aの単位ベクトルを返す。 引数: a -- 対象ベクトル。 戻り値: aの単位ベクトル。 */ vector unit_vector(vector a) { vector c; double r; r = a.x*a.x+a.y*a.y+a.z*a.z; if (Xabs(r)sz!=NULL) free(a->sz); if(a->mx!=NULL) free(a->mx); a->sz = NULL; a->mx = NULL; a->n = a->r = 0; } /** void free_imatrix(imatrix* a) 機能: 整数マトリックスのバッファ部を開放する。 引数: 開放するバッファ部を持った整数マトリックスへのポインタ。 戻り値: なし。 */ void free_imatrix(imatrix* a) { if(a->sz!=NULL) free(a->sz); if(a->mx!=NULL) free(a->mx); a->sz = NULL; a->mx = NULL; a->n = a->r = 0; } /** double* get_matrix(matrix mtx, ...) Matrix の要素を返す.次元数に制限はない.インデックスは1から数える(0からではない). 参考:1次元配列へのアクセスインデックス 1次元: (i) (i-1) 2次元: (i,j) (j-1) + sz[1]*(i-1) 3次元: (i,j,k) (k-1) + sz[2]*(j-1) + sz[1]*sz[2]*(i-1) 4次元: (i,j,k,l) (l-1) + sz[3]*(k-1) + sz[2]*sz[3]*(j-1) + sz[1]*sz[2]*sz[3]*(i-1) ................... */ double* get_matrix(matrix mtx, ...) { int m, d; int* args; va_list argsptr; args = (int*)malloc(mtx.n*sizeof(int)); if (args==NULL) return NULL; va_start(argsptr, mtx); for (m=0; m=mtx.r || dx<0) return NULL; return &mtx.mx[dx]; } /** int* get_imatrix(imatrix mtx, ...) Matrix の要素を返す.次元数に制限はない.インデックスは1から数える(0からではない). 参考:1次元配列へのアクセスインデックス 1次元: (i) (i-1) 2次元: (i,j) (j-1) + sz[1]*(i-1) 3次元: (i,j,k) (k-1) + sz[2]*(j-1) + sz[1]*sz[2]*(i-1) 4次元: (i,j,k,l) (l-1) + sz[3]*(k-1) + sz[2]*sz[3]*(j-1) + sz[1]*sz[2]*sz[3]*(i-1) ................... */ int* get_imatrix(imatrix mtx, ...) { int m, d; int* args; va_list argsptr; args = (int*)malloc(mtx.n*sizeof(int)); if (args==NULL) return NULL; va_start(argsptr, mtx); for (m=0; m=mtx.r || dx<0) return NULL; return &mtx.mx[dx]; } /** void copy_matrix(matrix src, matrix dst) 機能: マトリックスのコピー。srcの内容を dstへコピーする。 マトリックス全体のサイズが合わない場合は何もしない。 全体のサイズが合っていればコピーする。 引数: src -- コピー元マトリックス。 dst -- コピー先マトリックス。 戻り値: なし。 */ void copy_matrix(matrix src, matrix dst) { int i; if (src.mx==NULL || dst.mx==NULL) return; if ((src.r!=dst.r)||(dst.n!=dst.n)) return; for (i=0; i=0; i--) sa[i] = sa[i+1]*a.sz[i+1]; for (i=b.n-2; i>=0; i--) sb[i] = sb[i+1]*b.sz[i+1]; for (i=n-2; i>=0; i--) sc[i] = sc[i+1]*sz[i+1]; c = make_matrix(n, sz); for (i=0; i=0; i--) sa[i] = sa[i+1]*a.sz[i+1]; for (i=b.n-2; i>=0; i--) sb[i] = sb[i+1]*b.sz[i+1]; for (i=n-2; i>=0; i--) sc[i] = sc[i+1]*sz[i+1]; c = make_imatrix(n, sz); for (i=0; iu) { u = t; j = i; } } i = Vt(col,j); Vt(col,j) = Vt(col,r); Vt(col,r) = i; t = Vt(nsq,j); Vt(nsq,j) = Vt(nsq,r); Vt(nsq,r) = t; t = Vt(isq,j); Vt(isq,j) = Vt(isq,r); Vt(isq,r) = t; for (i=1; i<=n; i++) { t = Mx(x,i,j); Mx(x,i,j) = Mx(x,i,r); Mx(x,i,r) = t; } } for (u=0.0,i=r; i<=n; i++) u = u + Mx(x,i,r)*Mx(x,i,r); u = sqrt(u); if (Mx(x,r,r)<0.0) u = -u; Mx(x, r, r) = Mx(x,r,r) + u; t = 1.0/(Mx(x,r,r)*u); for (j=1; j<=r-1; j++) Mx(x,r,j)=0.0; for (j=r+1; j<=m; j++) { for (s=0.0,i=r; i<=n; i++) s = s + Mx(x,i,r)*Mx(x,i,j); for (i=r; i<=n; i++) Mx(x,i,j) = Mx(x,i,j) - s*t*Mx(x,i,r); } Mx(x,r,r) = -u; } for (i=1; i<=m; i++) { for (j=1; j<=m; j++) Mx(a,i,j) = Mx(x,i,j); } free_matrix(&nsq); free_matrix(&isq); free_matrix(&x); return a; } /** matrix minimum2(matrix y, matrix x) 機能: 最小2乗法で方程式の近似解を解き,結果を返す。 ただし, x,yは2次元行列のみ。 引数: y -- 連立方程式の結果の行列 (例を見よ) x -- 連立方程式の変数の行列 (例を見よ) 戻り値: 連立方程式の係数の行列 (例を見よ) 例: Y = X・A y1 = x11*a1 + x12*a2 y2 = x21*a1 + x22*a2 y3 = x31*a1 + x32*a2 の場合 A = minimum2(Y, X) で解く(a1,a2を求める)。 */ matrix minimum2(matrix y, matrix x) { int i, n, m; imatrix cl; matrix rx, rt, rr, aa, bb, cc; cc.n = cc.r = 0; cc.sz = NULL; cc.mx = NULL; if (y.mx==NULL || x.mx==NULL) return cc; if (y.sz[0]!=x.sz[0]) return cc; n = x.sz[0]; m = x.sz[1]; /* n×m 行列 */ cl = make_imatrix(1, &m); if (cl.mx==NULL) return cc; cc = make_matrix (1, &m); if (cc.mx==NULL) {free_imatrix(&cl); return cc;} rx = decompQR(x, cl); rr = invrU_matrix(rx), rt = mlt_matrix(rr, trans_matrix(rr)); aa = mlt_matrix(trans_matrix(x), y), bb = mlt_matrix(rt, aa); if (bb.mx!=NULL) for (i=0; i