/* * GXML/Graphite: Geometry and Graphics Programming Library + Utilities * Copyright (C) 2000 Bruno Levy * * This program 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., 675 Mass Ave, Cambridge, MA 02139, USA. * * If you modify this software, you should include a notice giving the * name of the person performing the modification, the date of modification, * and the reason for such modification. * * Contact: Bruno Levy * * levy@loria.fr * * ISA Project * LORIA, INRIA Lorraine, * Campus Scientifique, BP 239 * 54506 VANDOEUVRE LES NANCY CEDEX * FRANCE * * Note that the GNU General Public License does not permit incorporating * the Software into proprietary programs. */ #include "matrix_util.h" #include namespace OGF { namespace MatrixUtil { static const double EPS = 0.00001 ; static int MAX_ITER = 100 ; void semi_definite_symmetric_eigen( const double *mat, int n, double *eigen_vec, double *eigen_val ) { double *a,*v; double a_norm,a_normEPS,thr,thr_nn; int nb_iter = 0; int jj; int i,j,k,ij,ik,l,m,lm,mq,lq,ll,mm,imv,im,iq,ilv,il,nn; int *index; double a_ij,a_lm,a_ll,a_mm,a_im,a_il; double a_lm_2; double v_ilv,v_imv; double x; double sinx,sinx_2,cosx,cosx_2,sincos; double delta; // Number of entries in mat nn = (n*(n+1))/2; // Step 1: Copy mat to a a = new double[nn]; for( ij=0; ij a_normEPS && nb_iter < MAX_ITER ) { nb_iter++; thr_nn = thr / nn; for( l=1 ; l< n; l++ ) { for( m=l+1; m<=n; m++ ) { // compute sinx and cosx lq = (l*l-l)/2; mq = (m*m-m)/2; lm = l+mq; a_lm = a[lm]; a_lm_2 = a_lm*a_lm; if( a_lm_2 < thr_nn ) { continue ; } ll = l+lq; mm = m+mq; a_ll = a[ll]; a_mm = a[mm]; delta = a_ll - a_mm; if( delta == 0.0 ) { x = - M_PI/4 ; } else { x = - atan( (a_lm+a_lm) / delta ) / 2.0 ; } sinx = sin(x) ; cosx = cos(x) ; sinx_2 = sinx*sinx; cosx_2 = cosx*cosx; sincos = sinx*cosx; // rotate L and M columns ilv = n*(l-1); imv = n*(m-1); for( i=1; i<=n;i++ ) { if( (i!=l) && (i!=m) ) { iq = (i*i-i)/2; if( i