www.pudn.com > faces.rar > matrix.c


/*** 
 **     libface - Library of face recognition and supporting algorithms 
        Copyright (c) 2003 Stefan Farthofer 
 
	This file is part of libface, which is 
 
        free software; you can redistribute it and/or modify 
        it under the terms of the GNU General Public License as published by 
        the Free Software Foundation; either version 2 of the License, or 
        (at your option) any later version. 
 
        This program is distributed in the hope that it will be useful, 
        but WITHOUT ANY WARRANTY; without even the implied warranty of 
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
        GNU General Public License for more details. 
 
        You should have received a copy of the GNU General Public License 
        along with this program; if not, write to the Free Software 
        Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 
	For further information seek us at http://sourceforge.net/projects/openbio/ 
**	or write an email to dimitri.pissarenko@gmx.net or farthofer@chello.at. 
***/ 
 
/* we need error codes so include frbase.h */ 
#include  
#include  
#include  
#include "frbase.h" 
#include "matrix.h" 
 
void _matTransposeD(float* dst, float* src, unsigned int rowsSrc, unsigned int colsSrc) { 
	unsigned int i,j; 
 
	for (i=0; i < rowsSrc; i++) 
		for (j=0; j < colsSrc; j++) 
			dst[j*rowsSrc+i] = src[i*colsSrc+j]; 
} 
 
void _matTransposeQ(float* mat, unsigned int n) { 
	unsigned int i,j; 
	float tmp; 
 
	for(i=0; i < n; i++) {  
		for(j=i+1; j < n; j++) { 
			tmp = mat[i*n+j]; 
			mat[i*n+j] = mat[j*n+i]; 
			mat[j*n+i] = tmp; 
		} 
	} 
} 
 
/* computes m x n * n x p matrix multiply */ 
void _matMultiplyD(float* dst, float* a, float* b, unsigned int m, unsigned int n, unsigned int p) { 
	unsigned int i, j, k; 
 
	for (i=0; i < m; i++) { 
		for (j=0; j < p; j++) { 
			dst[i*p+j] = 0; 
			for (k=0; k < n; k++) dst[i*p+j] += a[i*n+k] * b[k*p+j]; 
		} 
	} 
} 
 
/* subtract same-sized matrizes */  
void _matSubtractD(float* dst, float* minuend, float* subtrahend, unsigned int m, unsigned int n) { 
	for(n *= m, m = 0; m < n; m++) 
		dst[m] = minuend[m] - subtrahend[m]; 
} 
 
/* add same-sized matrizes */  
void _matAdd(float* dst, float* b, unsigned int m, unsigned int n) { 
	for(n *= m, m = 0; m < n; m++) 
		dst[m] = dst[m] + b[m]; 
} 
 
 
/* computes eigenvalues and vectors of a symmetric matrix  
 * columns of matVectors contain the eigenvectors 
 * 
 * a - matrix 
 * n - dimension of matrix 
 * d - array for eigenvvalues 
 * v - array for eigenvectors (each vector occupies a column) 
 */ 
int _matEigenSD(float* a, int n, float* d, float* v) { 
  int j,iq,ip,ip_times_n,i ; 
  float tresh,theta,tau,t,sm,s,h,g,c,*b,*z; 
  int nrotint, *nrot = &nrotint; 
   
  b = (float *)malloc(n*sizeof(float)); 
  if (b == NULL) return FR_ERR_NOMEM; 
  z = (float *)malloc(n*sizeof(float)); 
  if (z == NULL) { free(b); return FR_ERR_NOMEM; } 
 
   
  for(ip_times_n=0, ip=0; ip 3 && g < EPS) 
		a[ip_times_n + iq] = 0.0 ; 
 
	      else if(fabs(a[ip_times_n+iq]) > tresh)  
		  { 
		  h=d[iq]-d[ip]; 
		  if(g < EPS) 
		    t = (fabs(a[ip_times_n+iq]) > EPS) ? (a[ip_times_n+iq])/h : 0.0f ;  
		  else 
		      {  
		      theta=(fabs(h) < EPS) ? 0.0f : 0.5f*h/(a[ip_times_n+iq]); 
		      t=1.0f/((float)fabs(theta)+(float)sqrt(1.0f+theta*theta)); 
		      if(theta < 0.0f) 
			t = -t ;  
		      }  
		  c=1.0f/(float)sqrt(1.0f+t*t); 
		  s=t*c; 
		  tau=s/(1.0f+c); 
		   
		  h=t*a[ip_times_n+iq]; 
		  z[ip] -= h; 
		  z[iq] += h; 
		  d[ip] -= h; 
		  d[iq] += h; 
		  a[ip_times_n+iq]=0.0; 
		   
		  for(j=0;j