Blender V2.61 - r43446
|
00001 // Copyright (C) 2007 Ruben Smits <ruben dot smits at mech dot kuleuven dot be> 00002 00003 // Version: 1.0 00004 // Author: Ruben Smits <ruben dot smits at mech dot kuleuven dot be> 00005 // Maintainer: Ruben Smits <ruben dot smits at mech dot kuleuven dot be> 00006 // URL: http://www.orocos.org/kdl 00007 00008 // This library is free software; you can redistribute it and/or 00009 // modify it under the terms of the GNU Lesser General Public 00010 // License as published by the Free Software Foundation; either 00011 // version 2.1 of the License, or (at your option) any later version. 00012 00013 // This library is distributed in the hope that it will be useful, 00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 // Lesser General Public License for more details. 00017 00018 // You should have received a copy of the GNU Lesser General Public 00019 // License along with this library; if not, write to the Free Software 00020 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00021 00022 00023 //Based on the svd of the KDL-0.2 library by Erwin Aertbelien 00024 #ifndef SVD_EIGEN_HH_HPP 00025 #define SVD_EIGEN_HH_HPP 00026 00027 00028 #include <Eigen/Core> 00029 #include <algorithm> 00030 00031 namespace KDL 00032 { 00033 template<typename Scalar> inline Scalar PYTHAG(Scalar a,Scalar b) { 00034 double at,bt,ct; 00035 at = fabs(a); 00036 bt = fabs(b); 00037 if (at > bt ) { 00038 ct=bt/at; 00039 return Scalar(at*sqrt(1.0+ct*ct)); 00040 } else { 00041 if (bt==0) 00042 return Scalar(0.0); 00043 else { 00044 ct=at/bt; 00045 return Scalar(bt*sqrt(1.0+ct*ct)); 00046 } 00047 } 00048 } 00049 00050 00051 template<typename Scalar> inline Scalar SIGN(Scalar a,Scalar b) { 00052 return ((b) >= Scalar(0.0) ? fabs(a) : -fabs(a)); 00053 } 00054 00067 template<typename MatrixA, typename MatrixUV, typename VectorS> 00068 int svd_eigen_HH( 00069 const Eigen::MatrixBase<MatrixA>& A, 00070 Eigen::MatrixBase<MatrixUV>& U, 00071 Eigen::MatrixBase<VectorS>& S, 00072 Eigen::MatrixBase<MatrixUV>& V, 00073 Eigen::MatrixBase<VectorS>& tmp, 00074 int maxiter=150) 00075 { 00076 //get the rows/columns of the matrix 00077 const int rows = A.rows(); 00078 const int cols = A.cols(); 00079 00080 U = A; 00081 00082 int i(-1),its(-1),j(-1),jj(-1),k(-1),nm=0; 00083 int ppi(0); 00084 bool flag; 00085 e_scalar maxarg1,maxarg2,anorm(0),c(0),f(0),h(0),s(0),scale(0),x(0),y(0),z(0),g(0); 00086 00087 g=scale=anorm=e_scalar(0.0); 00088 00089 /* Householder reduction to bidiagonal form. */ 00090 for (i=0;i<cols;i++) { 00091 ppi=i+1; 00092 tmp(i)=scale*g; 00093 g=s=scale=e_scalar(0.0); 00094 if (i<rows) { 00095 // compute the sum of the i-th column, starting from the i-th row 00096 for (k=i;k<rows;k++) scale += fabs(U(k,i)); 00097 if (scale!=0) { 00098 // multiply the i-th column by 1.0/scale, start from the i-th element 00099 // sum of squares of column i, start from the i-th element 00100 for (k=i;k<rows;k++) { 00101 U(k,i) /= scale; 00102 s += U(k,i)*U(k,i); 00103 } 00104 f=U(i,i); // f is the diag elem 00105 g = -SIGN(e_scalar(sqrt(s)),f); 00106 h=f*g-s; 00107 U(i,i)=f-g; 00108 for (j=ppi;j<cols;j++) { 00109 // dot product of columns i and j, starting from the i-th row 00110 for (s=0.0,k=i;k<rows;k++) s += U(k,i)*U(k,j); 00111 f=s/h; 00112 // copy the scaled i-th column into the j-th column 00113 for (k=i;k<rows;k++) U(k,j) += f*U(k,i); 00114 } 00115 for (k=i;k<rows;k++) U(k,i) *= scale; 00116 } 00117 } 00118 // save singular value 00119 S(i)=scale*g; 00120 g=s=scale=e_scalar(0.0); 00121 if ((i <rows) && (i+1 != cols)) { 00122 // sum of row i, start from columns i+1 00123 for (k=ppi;k<cols;k++) scale += fabs(U(i,k)); 00124 if (scale!=0) { 00125 for (k=ppi;k<cols;k++) { 00126 U(i,k) /= scale; 00127 s += U(i,k)*U(i,k); 00128 } 00129 f=U(i,ppi); 00130 g = -SIGN(e_scalar(sqrt(s)),f); 00131 h=f*g-s; 00132 U(i,ppi)=f-g; 00133 for (k=ppi;k<cols;k++) tmp(k)=U(i,k)/h; 00134 for (j=ppi;j<rows;j++) { 00135 for (s=0.0,k=ppi;k<cols;k++) s += U(j,k)*U(i,k); 00136 for (k=ppi;k<cols;k++) U(j,k) += s*tmp(k); 00137 } 00138 for (k=ppi;k<cols;k++) U(i,k) *= scale; 00139 } 00140 } 00141 maxarg1=anorm; 00142 maxarg2=(fabs(S(i))+fabs(tmp(i))); 00143 anorm = maxarg1 > maxarg2 ? maxarg1 : maxarg2; 00144 } 00145 /* Accumulation of right-hand transformations. */ 00146 for (i=cols-1;i>=0;i--) { 00147 if (i<cols-1) { 00148 if (g) { 00149 for (j=ppi;j<cols;j++) V(j,i)=(U(i,j)/U(i,ppi))/g; 00150 for (j=ppi;j<cols;j++) { 00151 for (s=0.0,k=ppi;k<cols;k++) s += U(i,k)*V(k,j); 00152 for (k=ppi;k<cols;k++) V(k,j) += s*V(k,i); 00153 } 00154 } 00155 for (j=ppi;j<cols;j++) V(i,j)=V(j,i)=0.0; 00156 } 00157 V(i,i)=1.0; 00158 g=tmp(i); 00159 ppi=i; 00160 } 00161 /* Accumulation of left-hand transformations. */ 00162 for (i=cols-1<rows-1 ? cols-1:rows-1;i>=0;i--) { 00163 ppi=i+1; 00164 g=S(i); 00165 for (j=ppi;j<cols;j++) U(i,j)=0.0; 00166 if (g) { 00167 g=e_scalar(1.0)/g; 00168 for (j=ppi;j<cols;j++) { 00169 for (s=0.0,k=ppi;k<rows;k++) s += U(k,i)*U(k,j); 00170 f=(s/U(i,i))*g; 00171 for (k=i;k<rows;k++) U(k,j) += f*U(k,i); 00172 } 00173 for (j=i;j<rows;j++) U(j,i) *= g; 00174 } else { 00175 for (j=i;j<rows;j++) U(j,i)=0.0; 00176 } 00177 ++U(i,i); 00178 } 00179 00180 /* Diagonalization of the bidiagonal form. */ 00181 for (k=cols-1;k>=0;k--) { /* Loop over singular values. */ 00182 for (its=1;its<=maxiter;its++) { /* Loop over allowed iterations. */ 00183 flag=true; 00184 for (ppi=k;ppi>=0;ppi--) { /* Test for splitting. */ 00185 nm=ppi-1; /* Note that tmp(1) is always zero. */ 00186 if ((fabs(tmp(ppi))+anorm) == anorm) { 00187 flag=false; 00188 break; 00189 } 00190 if ((fabs(S(nm)+anorm) == anorm)) break; 00191 } 00192 if (flag) { 00193 c=e_scalar(0.0); /* Cancellation of tmp(l), if l>1: */ 00194 s=e_scalar(1.); 00195 for (i=ppi;i<=k;i++) { 00196 f=s*tmp(i); 00197 tmp(i)=c*tmp(i); 00198 if ((fabs(f)+anorm) == anorm) break; 00199 g=S(i); 00200 h=PYTHAG(f,g); 00201 S(i)=h; 00202 h=e_scalar(1.0)/h; 00203 c=g*h; 00204 s=(-f*h); 00205 for (j=0;j<rows;j++) { 00206 y=U(j,nm); 00207 z=U(j,i); 00208 U(j,nm)=y*c+z*s; 00209 U(j,i)=z*c-y*s; 00210 } 00211 } 00212 } 00213 z=S(k); 00214 00215 if (ppi == k) { /* Convergence. */ 00216 if (z < e_scalar(0.0)) { /* Singular value is made nonnegative. */ 00217 S(k) = -z; 00218 for (j=0;j<cols;j++) V(j,k)=-V(j,k); 00219 } 00220 break; 00221 } 00222 00223 x=S(ppi); /* Shift from bottom 2-by-2 minor: */ 00224 nm=k-1; 00225 y=S(nm); 00226 g=tmp(nm); 00227 h=tmp(k); 00228 f=((y-z)*(y+z)+(g-h)*(g+h))/(e_scalar(2.0)*h*y); 00229 00230 g=PYTHAG(f,e_scalar(1.0)); 00231 f=((x-z)*(x+z)+h*((y/(f+SIGN(g,f)))-h))/x; 00232 00233 /* Next QR transformation: */ 00234 c=s=1.0; 00235 for (j=ppi;j<=nm;j++) { 00236 i=j+1; 00237 g=tmp(i); 00238 y=S(i); 00239 h=s*g; 00240 g=c*g; 00241 z=PYTHAG(f,h); 00242 tmp(j)=z; 00243 c=f/z; 00244 s=h/z; 00245 f=x*c+g*s; 00246 g=g*c-x*s; 00247 h=y*s; 00248 y=y*c; 00249 for (jj=0;jj<cols;jj++) { 00250 x=V(jj,j); 00251 z=V(jj,i); 00252 V(jj,j)=x*c+z*s; 00253 V(jj,i)=z*c-x*s; 00254 } 00255 z=PYTHAG(f,h); 00256 S(j)=z; 00257 if (z) { 00258 z=e_scalar(1.0)/z; 00259 c=f*z; 00260 s=h*z; 00261 } 00262 f=(c*g)+(s*y); 00263 x=(c*y)-(s*g); 00264 for (jj=0;jj<rows;jj++) { 00265 y=U(jj,j); 00266 z=U(jj,i); 00267 U(jj,j)=y*c+z*s; 00268 U(jj,i)=z*c-y*s; 00269 } 00270 } 00271 tmp(ppi)=0.0; 00272 tmp(k)=f; 00273 S(k)=x; 00274 } 00275 } 00276 00277 //Sort eigen values: 00278 for (i=0; i<cols; i++){ 00279 00280 double S_max = S(i); 00281 int i_max = i; 00282 for (j=i+1; j<cols; j++){ 00283 double Sj = S(j); 00284 if (Sj > S_max){ 00285 S_max = Sj; 00286 i_max = j; 00287 } 00288 } 00289 if (i_max != i){ 00290 /* swap eigenvalues */ 00291 e_scalar tmp = S(i); 00292 S(i)=S(i_max); 00293 S(i_max)=tmp; 00294 00295 /* swap eigenvectors */ 00296 U.col(i).swap(U.col(i_max)); 00297 V.col(i).swap(V.col(i_max)); 00298 } 00299 } 00300 00301 00302 if (its == maxiter) 00303 return (-2); 00304 else 00305 return (0); 00306 } 00307 00308 } 00309 #endif