/** @brief マトリックス&ベクトルライブラリ @file matrix.c @author Fumi.Iseki (C) */ #include "matrix.h" /** vector unit_vector(vector a) ベクトル aの単位ベクトルを返す. @param a 対象ベクトル. @return 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) 整数マトリックスのバッファ部を開放する. @param 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からではない). @code 参考: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) ................... @endcode */ double* get_matrix(matrix mtx, ...) { int m, d; int* args; va_list argsptr; if (mtx.n<1) return NULL; 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からではない). @code 参考: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) ................... @endcode */ int* get_imatrix(imatrix mtx, ...) { int m, d; int* args; va_list argsptr; if (mtx.n<1) return NULL; 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へコピーする.@n マトリックス全体のサイズが合わない場合は何もしない.@n 全体のサイズが合っていればコピーする. @param src コピー元マトリックス. @param 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; ixx = Q・R - xxのQR分解を行った後,係数のマトリックス(上三角行列 R)を返す. - ピボット操作(列の入れ換え)をした場合は整数ベクトル colに Qの 基底ベクトルが入る. - colは予め make_imatrix()等によって確保されていなければならない. @param xx QR分解を行う2次元行列. @param col メモリを確保し,初期化しておく.Qの基底ベクトルが入る. @return 上三角行列 R */ matrix decompQR(matrix xx, imatrix col) { int i, j, r, n, m, sz[2]; double s, t, u; matrix nsq, isq, x, a; a.n = a.r = 0; a.sz = NULL; a.mx = NULL; if (xx.mx==NULL || col.mx==NULL) return a; if (xx.n!=2 || (xx.sz[1]!=col.sz[0])) return a; nsq.mx = isq.mx = x.mx = NULL; n = xx.sz[0]; m = xx.sz[1]; sz[0] = sz[1] = m; nsq = make_matrix(1, &m); isq = make_matrix(1, &m); x = make_matrix(xx.n, xx.sz); a = make_matrix(xx.n, sz); if (nsq.mx==NULL || isq.mx==NULL || x.mx==NULL || a.mx==NULL) { free_matrix(&nsq); free_matrix(&isq); free_matrix(&x); return a; } 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次元行列のみ. @param y 連立方程式の結果の行列 (例を見よ) @param x 連立方程式の変数の行列 (例を見よ) @return 連立方程式の係数の行列 (例を見よ) @par 例 以下の場合 A = minimum2(Y, X) で解く(a1,a2を求める). @code Y = X・A y1 = x11*a1 + x12*a2 y2 = x21*a1 + x22*a2 y3 = x31*a1 + x32*a2 @endcode */ matrix minimum2(matrix y, matrix x) { int i, 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 行列 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