📄 hmath.c
字号:
}/* EXPORT->CovInvert: puts inverse of c in invc, returns log(Det(c)) *//* Note that c must be positive definite */LogFloat CovInvert(TriMat c, Matrix invc){ DMatrix l; /* Lower Tri Choleski Matrix */ DVector x,y; /* for f/b substitution */ LogFloat ldet = 0.0; int i,j,n; Boolean isTri; n = TriMatSize(c); isTri = IsTriMat(invc); l = CreateDMatrix(&gstack,n,n); x = CreateDVector(&gstack,n); y = CreateDVector(&gstack,n); if (Choleski(c,l)){ for (j=1; j<=n; j++){ MSolve(l,j,x,y); for (i=isTri?j:1; i<=n; i++) invc[i][j] = x[i]; ldet += log(l[j][j]); } } else HError(5220,"CovInvert: [%f ...] not invertible",c[1][1]); FreeDMatrix(&gstack,l); /* cut back stack to entry state */ return 2.0*ldet;}/* EXPORT->CovDet: Returns log(Det(c)), c must be positive definite */LogFloat CovDet(TriMat c){ DMatrix l; /* Lower Tri Choleski Matrix */ LogFloat ldet = 0.0; int j,n; n = TriMatSize(c); l = CreateDMatrix(&gstack,n,n); if (Choleski(c,l)){ for (j=1; j<=n; j++) ldet += log(l[j][j]); } else HError(5220,"CovDet: [%f ...] not invertible",c[1][1]); FreeDMatrix(&gstack,l); return 2.0*ldet;}/* Quadratic prod of a full square matrix C and an arbitry full matrix transform A */void LinTranQuaProd(Matrix Prod, Matrix A, Matrix C){ int i,j,k; float tempElem; Matrix tempMatrix_A_mult_C; if (NumRows(C) != NumCols(C)){ HError(999,"HMath: LinTranQuaProd: Matrix C is not square!\n"); } else { tempMatrix_A_mult_C = CreateMatrix(&gstack,NumRows(A),NumCols(C)); ZeroMatrix(tempMatrix_A_mult_C); for (i=1;i<=NumRows(tempMatrix_A_mult_C);i++){ for (j=1;j<=NumCols(tempMatrix_A_mult_C);j++){ tempElem = 0.0; for (k=1;k<=NumCols(A);k++){ tempElem += A[i][k]*C[j][k]; } tempMatrix_A_mult_C[i][j] = tempElem; } } for (i=1;i<=NumRows(Prod);i++){ for (j=1;j<=i;j++){ tempElem = 0.0; for (k=1;k<=NumCols(tempMatrix_A_mult_C);k++){ tempElem += tempMatrix_A_mult_C[i][k]*A[j][k]; } Prod[i][j] = tempElem; } } for (i=1;i<=NumRows(Prod);i++){ for (j=1;j>i;j++){ Prod[i][j] = Prod[j][i]; } } FreeMatrix(&gstack,tempMatrix_A_mult_C); }}/* ------------- Singular Value Decomposition --------------- *//************************************************************************** ** ** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved. ** ** Meschach Library ** ** This Meschach Library is provided "as is" without any express ** or implied warranty of any kind with respect to this software. ** In particular the authors shall not be liable for any direct, ** indirect, special, incidental or consequential damages arising ** in any way from use of the software.** ** Everyone is granted permission to copy, modify and redistribute this** Meschach Library, provided:** 1. All copies contain this copyright notice.** 2. All modified copies shall carry a notice stating who** made the last modification and the date of such modification.** 3. No charge is made for this software or works derived from it. ** This clause shall not be construed as constraining other software** distributed on the same medium as this software, nor is a** distribution fee considered a charge.**** Modifications made to conform with HTK formats by ** Daniel Kershaw, Entropic Ltd, Cambridge, England.*****************************************************************************/#define MACHEPS 2.22045e-16#define FZERO 1.0e-6#define sgn(x) ((x) >= 0 ? 1 : -1)#define minab(a,b) ((a) > (b) ? (b) : (a))#define MAX_STACK 100/* Givens -- returns c,s parameters for Givens rotation to eliminate y in the vector [ x y ]' */static void Givens(double x, double y, double *c, double *s){ double norm; norm = sqrt(x*x+y*y); if ( norm == 0.0 ) { *c = 1.0; *s = 0.0; } /* identity */ else { *c = x/norm; *s = y/norm; }}/* RotRows -- premultiply mat by givens rotation described by c,s */static void RotRows(DMatrix M, int i, int k, double c, double s){ int j, n; double temp; n = NumDRows(M); if (i > n || k > n) HError(1, "RotRows: Index tooo big i=%d k=%d\n", i, k); for ( j=1; j<=n; j++ ) { temp = c*M[i][j] + s*M[k][j]; M[k][j] = -s*M[i][j] + c*M[k][j]; M[i][j] = temp; } }/* FixSVD -- fix minor details about SVD make singular values non-negative -- sort singular values in decreasing order */static void FixSVD(DVector d, DMatrix U, DMatrix V){ int i, j, n; n = DVectorSize(d); /* make singular values non-negative */ for (i = 1; i <= n; i++) { if ( d[i] < 0.0 ) { d[i] = - d[i]; for ( j = 1; j <= NumDRows(U); j++ ) U[i][j] = - U[i][j]; } } return;#if 0 /* #### ge: what is this code after return supposed to do here? */ { int k, l, r, stack[MAX_STACK], sp; double tmp, v; /* sort singular values */ sp = -1; l = 1; r = n; for ( ; ; ) { while ( r >= l ) { /* i = partition(d->ve,l,r) */ v = d[r]; i = l-1; j = r; for ( ; ; ) { /* inequalities are "backwards" for **decreasing** order */ while ( d[++i] > v ); while ( d[--j] < v ); if ( i >= j ) break; /* swap entries in d->ve */ tmp = d[i]; d[i] = d[j]; d[j] = tmp; /* swap rows of U & V as well */ for ( k = 1; k <= DVectorSize(U[1]); k++ ) { tmp = U[i][k]; U[i][k] = U[j][k]; U[j][k] = tmp; } for ( k = 1; k <= DVectorSize(V[1]); k++ ) { tmp = V[i][k]; V[i][k] = V[j][k]; V[j][k] = tmp; } } tmp = d[i]; d[i] = d[r]; d[r] = tmp; for ( k = 1; k <= DVectorSize(U[1]); k++ ) { tmp = U[i][k]; U[i][k] = U[r][k]; U[r][k] = tmp; } for ( k = 1; k <= DVectorSize(V[1]); k++ ) { tmp = V[i][k]; V[i][k] = V[r][k]; V[r][k] = tmp; } /* end i = partition(...) */ if ( i - l > r - i ) { stack[++sp] = l; stack[++sp] = i-1; l = i+1; } else { stack[++sp] = i+1; stack[++sp] = r; r = i-1; } } if ( sp < 0 ) break; r = stack[sp--]; l = stack[sp--]; } }#endif}/* BiSvd -- svd of a bidiagonal m x n matrix represented by d (diagonal) and f (super-diagonals) */static void BiSVD(DVector d, DVector f, DMatrix U, DMatrix V){ int i, j, n; int i_min, i_max, split; double c, s, shift, size, z; double d_tmp, diff, t11, t12, t22; if ( ! d || ! f ) HError(1,"BiSVD: Vectors are null!"); if ( DVectorSize(d) != DVectorSize(f) + 1 ) HError(1, "BiSVD: Error with the vector sizes!"); n = DVectorSize(d); if ( ( U && DVectorSize(U[1]) < n ) || ( V && NumDRows(V) < n ) ) HError(1, "BiSVD: Error Matrix sizes!"); if ( ( U && NumDRows(U) != DVectorSize(U[1])) || ( V && NumDRows(V) != DVectorSize(V[1])) ) HError(1, "BiSVD: One of the matrices must be square"); if ( n == 1 ) return; s = 0.0; for ( i = 1; i <= n; i++) s += d[i]*d[i]; size = sqrt(s); s = 0.0; for ( i = 1; i < n; i++) s += f[i]*f[i]; size += sqrt(s); s = 0.0; i_min = 1; while ( i_min <= n ) { /* outer while loop */ /* find i_max to suit; submatrix i_min..i_max should be irreducible */ i_max = n; for ( i = i_min; i < n; i++ ) if ( d[i] == 0.0 || f[i] == 0.0 ) { i_max = i; if ( f[i] != 0.0 ) { /* have to ``chase'' f[i] element out of matrix */ z = f[i]; f[i] = 0.0; for ( j = i; j < n && z != 0.0; j++ ) { Givens(d[j+1],z, &c, &s); s = -s; d[j+1] = c*d[j+1] - s*z; if ( j+1 < n ) { z = s*f[j+1]; f[j+1] = c*f[j+1]; } RotRows(U,i,j+1,c,s); } } break; } if ( i_max <= i_min ) { i_min = i_max + 1; continue; } split = FALSE; while ( ! split ) { /* compute shift */ t11 = d[i_max-1]*d[i_max-1] + (i_max > i_min+1 ? f[i_max-2]*f[i_max-2] : 0.0); t12 = d[i_max-1]*f[i_max-1]; t22 = d[i_max]*d[i_max] + f[i_max-1]*f[i_max-1]; /* use e-val of [[t11,t12],[t12,t22]] matrix closest to t22 */ diff = (t11-t22)/2; shift = t22 - t12*t12/(diff + sgn(diff)*sqrt(diff*diff+t12*t12)); /* initial Givens' rotation */ Givens(d[i_min]*d[i_min]-shift, d[i_min]*f[i_min], &c, &s); /* do initial Givens' rotations */ d_tmp = c*d[i_min] + s*f[i_min]; f[i_min] = c*f[i_min] - s*d[i_min]; d[i_min] = d_tmp; z = s*d[i_min+1]; d[i_min+1] = c*d[i_min+1]; RotRows(V,i_min,i_min+1,c,s); /* 2nd Givens' rotation */ Givens(d[i_min],z, &c, &s); d[i_min] = c*d[i_min] + s*z; d_tmp = c*d[i_min+1] - s*f[i_min]; f[i_min] = s*d[i_min+1] + c*f[i_min]; d[i_min+1] = d_tmp; if ( i_min+1 < i_max ) { z = s*f[i_min+1]; f[i_min+1] = c*f[i_min+1]; } RotRows(U,i_min,i_min+1,c,s); for ( i = i_min+1; i < i_max; i++ ) { /* get Givens' rotation for zeroing z */ Givens(f[i-1],z, &c, &s); f[i-1] = c*f[i-1] + s*z; d_tmp = c*d[i] + s*f[i]; f[i] = c*f[i] - s*d[i]; d[i] = d_tmp; z = s*d[i+1]; d[i+1] = c*d[i+1]; RotRows(V,i,i+1,c,s); /* get 2nd Givens' rotation */ Givens(d[i],z, &c, &s); d[i] = c*d[i] + s*z; d_tmp = c*d[i+1] - s*f[i]; f[i] = c*f[i] + s*d[i+1]; d[i+1] = d_tmp; if ( i+1 < i_max ) { z = s*f[i+1]; f[i+1] = c*f[i+1]; } RotRows(U,i,i+1,c,s); } /* should matrix be split? */ for ( i = i_min; i < i_max; i++ ) if ( fabs(f[i]) < MACHEPS*(fabs(d[i])+fabs(d[i+1])) ) { split = TRUE; f[i] = 0.0; } else if ( fabs(d[i]) < MACHEPS*size ) { split = TRUE; d[i] = 0.0; } } }}/* HholdVec -- calulates Householder vector to eliminate all entries after the i0 entry of the vector vec. It is returned as out. May be in-situ */static void HholdVec(DVector tmp, int i0, int size, double *beta, double *newval){ int i; double norm = 0.0; for (i = i0; i <= size; i++) { norm += tmp[i]*tmp[i]; } norm = sqrt(norm); if ( norm <= 0.0 ) { *beta = 0.0; } else { *beta = 1.0/(norm * (norm+fabs(tmp[i0]))); if ( tmp[i0] > 0.0 ) *newval = -norm; else *newval = norm; tmp[i0] -= *newval; }}/* HholdTrRows -- transform a matrix by a Householder vector by rows starting at row i0 from column j0 -- in-situ */static void HholdTrRows(DMatrix M, int i0, int j0, DVector hh, double beta){ double ip, scale; int i, j; int m,n; m = NumDRows(M); n = DVectorSize(M[1]); if ( M==NULL || hh==NULL ) HError(1,"HholdTrRows: matrix or vector is NULL!"); if ( DVectorSize(hh) != n ) HError(1,"HholdTrRows: hh vector size must = number of M columns"); if ( i0 > m+1 || j0 > n+1 ) HError(1,"HholdTrRows: Bounds matrix/vec size error i=%d j=%d m=%d n=%d", i0, j0, m, n); if ( beta != 0.0 ) { /* for each row ... */ for ( i = i0; i <= m; i++ ) { /* compute inner product */ /* ip = __ip__(&(M->me[i][j0]),&(hh->ve[j0]),(int)(M->n-j0));*/ ip = 0.0; for ( j = j0; j <= n; j++ ) ip += M[i][j]*hh[j]; scale = beta*ip; if ( scale == 0.0 ) continue; /* __mltadd__(&(M->me[i][j0]),&(hh->ve[j0]),-scale, (int)(M->n-j0)); */ for ( j = j0; j <= n; j++ ) M[i][j] -= scale*hh[j]; } }}/* HholdTrCols -- transform a matrix by a Householder vector by columns starting at row i0 from column j0 -- in-situ */static void HholdTrCols(DMatrix M, int i0, int j0, DVector hh, double beta, DVector w){ int i, j; int n; n = NumDRows(M); if ( M==NULL || hh==NULL ) HError(1,"HholdTrCols: matrix or vector is NULL!"); if ( DVectorSize(hh) != n ) HError(1,"HholdTrCols: hh vector size must = number of M columns"); if ( i0 > n+1 || j0 > n+1 ) HError(1,"HholdTrCols: Bounds matrix/vec size error i=%d j=%d n=%d", i0, j0, n); ZeroDVector(w); if ( beta != 0.0 ) { for ( i = i0; i <= n; i++ ) if ( hh[i] != 0.0 ) for ( j = j0; j <= n; j++ ) w[j] += M[i][j]*hh[i]; for ( i = i0; i <= n; i++ ) if ( hh[i] != 0.0 ) for ( j = j0; j <= n; j++ ) M[i][j] -= w[j]*beta*hh[i]; }}/* copy a row from a matrix into a vector */static void CopyDRow(DMatrix M, int k, DVector v) { int i, size; DVector w; if (v == NULL) HError(1, "CopyDRow: Vector is NULL"); size = DVectorSize(v); w = M[k]; for (i = 1; i <= size; i++) v[i] = w[i];}/* copy a column from a matrix into a vector */static void CopyDColumn(DMatrix M, int k, DVector v) { int i, size; if (v == NULL) HError(1, "CopyDColumn: Vector is NULL"); size = DVectorSize(v); for (i = 1; i <= size; i++) v[i] = M[i][k];}/* BiFactor -- perform preliminary factorisation for bisvd -- updates U and/or V, which ever is not NULL */static void BiFactor(DMatrix A, DMatrix U, DMatrix V){ int n, k; DVector tmp1, tmp2, tmp3; double beta; n = NumDRows(A); tmp1 = CreateDVector(&gstack, n); tmp2 = CreateDVector(&gstack, n); tmp3 = CreateDVector(&gstack, n); for ( k = 1; k <= n; k++ ) { CopyDColumn(A,k,tmp1); HholdVec(tmp1,k,n,&beta,&(A[k][k])); HholdTrCols(A,k,k+1,tmp1,beta,tmp3); if ( U ) HholdTrCols(U,k,1,tmp1,beta,tmp3); if ( k+1 > n ) continue; CopyDRow(A,k,tmp2); HholdVec(tmp2,k+1,n,&beta,&(A[k][k+1])); HholdTrRows(A,k+1,k+1,tmp2,beta); if ( V ) HholdTrCols(V,k+1,1,tmp2,beta,tmp3); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -