/*===========================================================================*\ * * * IsoEx * * Copyright (C) 2002 by Computer Graphics Group, RWTH Aachen * * www.rwth-graphics.de * * * *---------------------------------------------------------------------------* * * * License * * * * This library is free software; you can redistribute it and/or modify it * * under the terms of the GNU Library General Public License as published * * by the Free Software Foundation, version 2. * * * * This library 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 * * Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; if not, write to the Free Software * * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * \*===========================================================================*/ //============================================================================= // // SVD decomposition and back-substitution // //============================================================================= #define SVD_C //== INCLUDES ================================================================= #include "svd.hh" #include #include //== NAMESPACES =============================================================== namespace IsoEx { namespace Math { //============================================================================= inline double dsqr(double a) { double dsqrarg(a); return (dsqrarg == 0.0 ? 0.0 : dsqrarg*dsqrarg); } //----------------------------------------------------------------------------- inline double dmax(double a, double b) { double dmaxarg1(a), dmaxarg2(b); return (dmaxarg1 > dmaxarg2 ? dmaxarg1 : dmaxarg2); } //----------------------------------------------------------------------------- inline int imin(int a, int b) { int iminarg1(a), iminarg2(b); return (iminarg1 < iminarg2 ? iminarg1 : iminarg2); } //----------------------------------------------------------------------------- inline double sign(double a, double b) { return (b >= 0.0 ? fabs(a) : -fabs(a)); } //----------------------------------------------------------------------------- inline double dpythag(double a, double b) { double absa(fabs(a)), absb(fabs(b)); if (absa > absb) return absa*sqrt(1.0+dsqr(absb/absa)); else return (absb == 0.0 ? 0.0 : absb*sqrt(1.0+dsqr(absa/absb))); } //----------------------------------------------------------------------------- template bool svd_decomp( MAT_MxN& A, VEC_N& S, MAT_NxN& V ) { int m(A.rows()), n(A.cols()); int flag, i, its, j, jj, k, l(0), nm(0); double anorm(0.0), c, f, g(0.0), h, s, scale(0.0), x, y, z; VEC_N rv1(n); bool convergence(true); for (i=0;i= 0;i--) { if (i < (n-1)) { if (g) { for (j=l;j=0;i--) { l=i+1; g=S(i); for (j=l;j=0; k--) { for (its=1;its<=100;its++) { flag=1; for (l=k;l>=0;l--) { nm=l-1; if ((double)(fabs(rv1(l))+anorm) == anorm) { flag=0; break; } if ((double)(fabs(S(nm))+anorm) == anorm) break; } if (flag) { c=0.0; s=1.0; for (i=l;i<=k;i++) { f=s*rv1(i); rv1(i)=c*rv1(i); if ((double)(fabs(f)+anorm) == anorm) break; g=S(i); h=dpythag(f,g); S(i)=h; h=1.0/h; c=g*h; s = -f*h; for (j=0;j void svd_backsub( const MAT_MxN& A, const VEC_M& S, const MAT_NxN& V, const VEC_M& b, VEC_N& x ) { int m(A.rows()), n(V.cols()); int jj, j, i; double s; VEC_N tmp(n); // Calculate U^T * B for ( j=0; j