Mat.h

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                              SOFA :: Framework                              *
00020 *                                                                             *
00021 * Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
00022 * H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
00023 * M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
00024 *                                                                             *
00025 * Contact information: contact@sofa-framework.org                             *
00026 ******************************************************************************/
00027 #ifndef SOFA_DEFAULTTYPE_MAT_H
00028 #define SOFA_DEFAULTTYPE_MAT_H
00029 
00030 #include <sofa/defaulttype/Vec.h>
00031 #include <assert.h>
00032 #include <sofa/helper/static_assert.h>
00033 
00034 namespace sofa
00035 {
00036 
00037 namespace defaulttype
00038 {
00039 
00040 template <int L, int C, class real=float>
00041 class Mat : public helper::fixed_array<VecNoInit<C,real>,L>
00042         //class Mat : public Vec<L,Vec<C,real> >
00043 {
00044  public:
00045 
00046   enum { N = L*C };
00047 
00048   typedef real Real;
00049   typedef Vec<C,real> Line;
00050   typedef Vec<L,real> Col;
00051 
00052     Mat()
00053     {
00054     clear();
00055     }
00056 
00057     explicit Mat(NoInit)
00058     {
00059     }
00060 
00061 /*
00063   explicit Mat(Line r1)
00064   {
00065     BOOST_STATIC_ASSERT(L == 1);
00066     this->elems[0]=r1;
00067   }
00068 */
00069 
00071   Mat(Line r1, Line r2)
00072   {
00073     BOOST_STATIC_ASSERT(L == 2);
00074     this->elems[0]=r1;
00075     this->elems[1]=r2;
00076   }
00077 
00079   Mat(Line r1, Line r2, Line r3)
00080   {
00081     BOOST_STATIC_ASSERT(L == 3);
00082     this->elems[0]=r1;
00083     this->elems[1]=r2;
00084     this->elems[2]=r3;
00085   }
00086 
00088   Mat(Line r1, Line r2, Line r3, Line r4)
00089   {
00090     BOOST_STATIC_ASSERT(L == 4);
00091     this->elems[0]=r1;
00092     this->elems[1]=r2;
00093     this->elems[2]=r3;
00094     this->elems[3]=r4;
00095   }
00096   
00098   explicit Mat(const real& v)
00099   {
00100       for( int i=0; i<L; i++ )
00101           for( int j=0; j<C; j++ )
00102               this->elems[i][j] = v; 
00103   }
00104 
00106   template<typename real2>
00107   Mat(const Mat<L,C,real2>& m)
00108   {
00109     std::copy(m.begin(), m.begin()+L, this->begin());
00110   }
00111   
00113   template<typename real2>
00114   explicit Mat(const real2* p)
00115   {
00116     std::copy(p, p+N, this->begin()->begin());
00117   }
00118   
00120   real getNbLines() const
00121   {
00122       return L;
00123   }
00124   
00126   real getNbCols() const
00127   {
00128       return C;
00129   }
00130   
00131 
00133   void operator=(const real* p)
00134   {
00135     std::copy(p, p+N, this->begin()->begin());
00136   }
00137   
00139   template<typename real2> void operator=(const Mat<L,C,real2>& m)
00140   {
00141     std::copy(m.begin(), m.begin()+L, this->begin());
00142   }
00143 
00145   template<int L2, int C2> void operator=(const Mat<L2,C2,real>& m)
00146   {
00147     std::copy(m.begin(), m.begin()+(L>L2?L2:L), this->begin());
00148   }
00149 
00150   template<int L2, int C2> void getsub(int L0, int C0, Mat<L2,C2,real>& m) const
00151   {
00152     for (int i=0;i<L2;i++)
00153       for (int j=0;j<C2;j++)
00154         m[i][j] = this->elems[i+L0][j+C0];
00155   }
00156 
00157   template<int L2, int C2> void setsub(int L0, int C0, const Mat<L2,C2,real>& m)
00158   {
00159     for (int i=0;i<L2;i++)
00160       for (int j=0;j<C2;j++)
00161         this->elems[i+L0][j+C0] = m[i][j];
00162   }
00163 
00165   void clear()
00166   {
00167     for (int i=0;i<L;i++)
00168       this->elems[i].clear();
00169   }
00170 
00172   void fill(real r)
00173   {
00174     for (int i=0;i<L;i++)
00175       this->elems[i].fill(r);
00176   }
00177 
00179   const Line& line(int i) const
00180   {
00181     return this->elems[i];
00182   }
00183 
00185   Col col(int j) const
00186   {
00187     Col c;
00188     for (int i=0;i<L;i++)
00189       c[i]=this->elems[i][j];
00190     return c;
00191   }
00192 
00194   Line& operator[](int i)
00195   {
00196     return this->elems[i];
00197   }
00198 
00200   const Line& operator[](int i) const
00201   {
00202     return this->elems[i];
00203   }
00204 
00206   Line& operator()(int i)
00207   {
00208     return this->elems[i];
00209   }
00210 
00212   const Line& operator()(int i) const
00213   {
00214     return this->elems[i];
00215   }
00216 
00218   real& operator()(int i, int j)
00219   {
00220     return this->elems[i][j];
00221   }
00222 
00224   const real& operator()(int i, int j) const
00225   {
00226     return this->elems[i][j];
00227   }
00228 
00230   const Line* lptr() const
00231   {
00232     return this->elems;
00233   }
00234 
00236   Line* lptr()
00237   {
00238     return this->elems;
00239   }
00240 
00242   const real* ptr() const
00243   {
00244       return this->elems[0].ptr();;
00245   }
00246 
00248   real* ptr()
00249   {
00250       return this->elems[0].ptr();
00251   }
00252 
00254   Line& x() { BOOST_STATIC_ASSERT(L >= 1); return this->elems[0]; }
00256   Line& y() { BOOST_STATIC_ASSERT(L >= 2); return this->elems[1]; }
00258   Line& z() { BOOST_STATIC_ASSERT(L >= 3); return this->elems[2]; }
00260   Line& w() { BOOST_STATIC_ASSERT(L >= 4); return this->elems[3]; }
00261 
00263   const Line& x() const { BOOST_STATIC_ASSERT(L >= 1); return this->elems[0]; }
00265   const Line& y() const { BOOST_STATIC_ASSERT(L >= 2); return this->elems[1]; }
00267   const Line& z() const { BOOST_STATIC_ASSERT(L >= 3); return this->elems[2]; }
00269   const Line& w() const { BOOST_STATIC_ASSERT(L >= 4); return this->elems[3]; }
00270 
00272   void identity()
00273   {
00274     BOOST_STATIC_ASSERT(L == C);
00275     clear();
00276     for (int i=0;i<L;i++)
00277       this->elems[i][i]=1;
00278   }
00279 
00281   void transpose(const Mat<C,L,real> &m)
00282   {
00283     for (int i=0;i<L;i++)
00284       for (int j=0;j<C;j++)
00285         this->elems[i][j]=m[j][i];
00286   }
00287 
00289   Mat<C,L,real> transposed() const
00290   {
00291     Mat<C,L,real> m(NOINIT);
00292     for (int i=0;i<L;i++)
00293       for (int j=0;j<C;j++)
00294         m[j][i]=this->elems[i][j];
00295     return m;
00296   }
00297 
00299   void transpose()
00300   { BOOST_STATIC_ASSERT(L == C);
00301     for (int i=0;i<L;i++)
00302       for (int j=i+1;j<C;j++)
00303       {
00304     real t = this->elems[i][j];
00305     this->elems[i][j] = this->elems[j][i];
00306     this->elems[j][i] = t;
00307       }
00308   }
00309 
00312 
00313     bool operator==(const Mat<L,C,real>& b) const
00314     {
00315         for (int i=0;i<L;i++)
00316             if (!(this->elems[i]==b[i])) return false;
00317         return true;
00318     }
00319 
00320     bool operator!=(const Mat<L,C,real>& b) const
00321     {
00322         for (int i=0;i<L;i++)
00323             if (this->elems[i]!=b[i]) return true;
00324         return false;
00325     }
00326     
00327     
00328     bool isSymetric() const
00329     {
00330         for (int i=0;i<L;i++)
00331             for (int j=i+1;j<C;j++)
00332                 if( fabs( this->elems[i][j] - this->elems[j][i] ) > EQUALITY_THRESHOLD ) return false;
00333        return true;
00334     }
00335 
00336 
00338 
00339   // LINEAR ALGEBRA
00340 
00342   template <int P>
00343   Mat<L,P,real> operator*(const Mat<C,P,real>& m) const
00344   {
00345     Mat<L,P,real> r(NOINIT);
00346     for(int i=0;i<L;i++)
00347       for(int j=0;j<P;j++)
00348       {
00349     r[i][j]=(*this)[i][0] * m[0][j];
00350     for(int k=1;k<C;k++)
00351       r[i][j] += (*this)[i][k] * m[k][j];
00352       }
00353     return r;
00354   }
00355 
00357   Mat<L,C,real> operator+(const Mat<L,C,real>& m) const
00358   {
00359     Mat<L,C,real> r(NOINIT);
00360     for(int i = 0; i < L; i++)
00361       r[i] = (*this)[i] + m[i];
00362     return r;
00363   }
00364 
00366   Mat<L,C,real> operator-(const Mat<L,C,real>& m) const
00367   {
00368     Mat<L,C,real> r(NOINIT);
00369     for(int i = 0; i < L; i++)
00370       r[i] = (*this)[i] - m[i];
00371     return r;
00372   }
00373 
00375   Col operator*(const Line& v) const
00376   {
00377     Col r(NOINIT);
00378     for(int i=0;i<L;i++)
00379     {
00380       r[i]=(*this)[i][0] * v[0];
00381       for(int j=1;j<C;j++)
00382     r[i] += (*this)[i][j] * v[j];
00383     }
00384     return r;
00385   }
00386   
00388   Line multTranspose(const Col& v) const
00389   {
00390       Line r(NOINIT);
00391       for(int i=0;i<C;i++)
00392       {
00393           r[i]=(*this)[0][i] * v[0];
00394           for(int j=1;j<L;j++)
00395               r[i] += (*this)[j][i] * v[j];
00396       }
00397       return r;
00398   }
00399   
00400 
00402   template <int P>
00403   Mat<C,P,real> multTranspose(const Mat<L,P,real>& m) const
00404   {
00405     Mat<C,P,real> r(NOINIT);
00406     for(int i=0;i<C;i++)
00407       for(int j=0;j<P;j++)
00408       {
00409     r[i][j]=(*this)[0][i] * m[0][j];
00410     for(int k=1;k<L;k++)
00411       r[i][j] += (*this)[k][i] * m[k][j];
00412       }
00413     return r;
00414   }
00415   
00416 
00418   Mat<L,C,real> operator*(real f) const
00419   {
00420     Mat<L,C,real> r(NOINIT);
00421     for(int i=0;i<L;i++)
00422       for(int j=0;j<C;j++)
00423     r[i][j] = (*this)[i][j] * f;
00424     return r;
00425   }
00426   
00428   Mat<L,C,real> operator/(real f) const
00429   {
00430     Mat<L,C,real> r(NOINIT);
00431       for(int i=0;i<L;i++)
00432           for(int j=0;j<C;j++)
00433               r[i][j] = (*this)[i][j] / f;
00434       return r;
00435   }
00436 
00438   void operator *=(real r)
00439   {
00440     for(int i=0;i<L;i++)
00441       this->elems[i]*=r;
00442   }
00443 
00445   void operator /=(real r)
00446   {
00447     for(int i=0;i<L;i++)
00448       this->elems[i]/=r;
00449   }
00450 
00452   void operator +=(const Mat<L,C,real>& m)
00453   {
00454     for(int i=0;i<L;i++)
00455       this->elems[i]+=m[i];
00456   }
00457 
00459   void addTransposed(const Mat<L,C,real>& m)
00460   {
00461       BOOST_STATIC_ASSERT(L==C);
00462       for(int i=0;i<L;i++)
00463           for(int j=0;j<L;j++)
00464               (*this)[i][j] += m[j][i];
00465   }
00466 
00468   void subTransposed(const Mat<L,C,real>& m)
00469   {
00470       BOOST_STATIC_ASSERT(L==C);
00471       for(int i=0;i<L;i++)
00472           for(int j=0;j<L;j++)
00473               (*this)[i][j] += m[j][i];
00474   }
00475 
00477   void operator -=(const Mat<L,C,real>& m)
00478   {
00479     for(int i=0;i<L;i++)
00480       this->elems[i]-=m[i];
00481   }
00482 
00484   bool invert(const Mat<L,C,real>& m)
00485   {
00486     return invertMatrix(*this, m);
00487   }
00488 
00489 };
00490 
00492 template <int L, int C, typename real=float>
00493 class MatNoInit : public Mat<L,C,real>
00494 {
00495 public:
00496     MatNoInit()
00497     : Mat<L,C,real>(NOINIT)
00498     {
00499     }
00500 
00502     void operator=(const real* p)
00503     {
00504     this->Mat<L,C,real>::operator=(p);
00505     }
00506 
00508     template<int L2, int C2, typename real2> void operator=(const Mat<L2,C2,real2>& m)
00509     {
00510     this->Mat<L,C,real>::operator=(m);
00511     }
00512 };
00513 
00515 template<class real>
00516 inline real determinant(const Mat<3,3,real>& m)
00517 {
00518     return m(0,0)*m(1,1)*m(2,2)
00519          + m(1,0)*m(2,1)*m(0,2)
00520          + m(2,0)*m(0,1)*m(1,2)
00521          - m(0,0)*m(2,1)*m(1,2)
00522          - m(1,0)*m(0,1)*m(2,2)
00523          - m(2,0)*m(1,1)*m(0,2);
00524 }
00525 
00527 template<class real>
00528 inline real determinant(const Mat<2,2,real>& m)
00529 {
00530     return m(0,0)*m(1,1)
00531          - m(1,0)*m(0,1);
00532 }
00533 
00535 template<int S, class real>
00536 bool invertMatrix(Mat<S,S,real>& dest, const Mat<S,S,real>& from)
00537 {
00538   int i, j, k;
00539   Vec<S,int> r, c, row, col;
00540 
00541   Mat<S,S,real> m1 = from;
00542   Mat<S,S,real> m2;
00543   m2.identity();
00544 
00545   for ( k = 0; k < S; k++ )
00546   {
00547     // Choosing the pivot
00548     real pivot = 0;
00549     for (i = 0; i < S; i++)
00550     {
00551       if (row[i])
00552     continue;
00553       for (j = 0; j < S; j++)
00554       {
00555     if (col[j])
00556       continue;
00557     real t = m1[i][j]; if (t<0) t=-t;
00558     if ( t > pivot)
00559     {
00560       pivot = t;
00561       r[k] = i;
00562       c[k] = j;
00563     }
00564       }
00565     }
00566 
00567     if (pivot <= 1e-10)
00568     {
00569       return false;
00570     }
00571 
00572     row[r[k]] = col[c[k]] = 1;
00573     pivot = m1[r[k]][c[k]];
00574 
00575     // Normalization
00576     m1[r[k]] /= pivot; m1[r[k]][c[k]] = 1;
00577     m2[r[k]] /= pivot;
00578 
00579     // Reduction
00580     for (i = 0; i < S; i++)
00581     {
00582       if (i != r[k])
00583       {
00584     real f = m1[i][c[k]];
00585     m1[i] -= m1[r[k]]*f; m1[i][c[k]] = 0;
00586     m2[i] -= m2[r[k]]*f;
00587       }
00588     }
00589   }
00590 
00591   for (i = 0; i < S; i++)
00592     for (j = 0; j < S; j++)
00593       if (c[j] == i)
00594     row[i] = r[j];
00595 
00596   for ( i = 0; i < S; i++ )
00597     dest[i] = m2[row[i]];
00598 
00599   return true;
00600 }
00601 
00603 template<class real>
00604 bool invertMatrix(Mat<3,3,real>& dest, const Mat<3,3,real>& from)
00605 {
00606   real det=determinant(from);
00607 
00608   if ( -1e-10<=det && det<=1e-10)
00609     return false;
00610 
00611   dest(0,0)= (from(1,1)*from(2,2) - from(2,1)*from(1,2))/det;
00612   dest(1,0)= (from(1,2)*from(2,0) - from(2,2)*from(1,0))/det;
00613   dest(2,0)= (from(1,0)*from(2,1) - from(2,0)*from(1,1))/det;
00614   dest(0,1)= (from(2,1)*from(0,2) - from(0,1)*from(2,2))/det;
00615   dest(1,1)= (from(2,2)*from(0,0) - from(0,2)*from(2,0))/det;
00616   dest(2,1)= (from(2,0)*from(0,1) - from(0,0)*from(2,1))/det;
00617   dest(0,2)= (from(0,1)*from(1,2) - from(1,1)*from(0,2))/det;
00618   dest(1,2)= (from(0,2)*from(1,0) - from(1,2)*from(0,0))/det;
00619   dest(2,2)= (from(0,0)*from(1,1) - from(1,0)*from(0,1))/det;
00620   
00621   return true;
00622 }
00623 
00625 template<class real>
00626 bool invertMatrix(Mat<2,2,real>& dest, const Mat<2,2,real>& from)
00627 {
00628   real det=determinant(from);
00629 
00630   if ( -1e-10<=det && det<=1e-10)
00631     return false;
00632 
00633   dest(0,0)=  from(1,1)/det;
00634   dest(0,1)= -from(0,1)/det;
00635   dest(1,0)= -from(1,0)/det;
00636   dest(1,1)=  from(0,0)/det;
00637   
00638   return true;
00639 }
00640 
00641 typedef Mat<2,2,float> Mat2x2f;
00642 typedef Mat<2,2,double> Mat2x2d;
00643 
00644 typedef Mat<3,3,float> Mat3x3f;
00645 typedef Mat<3,3,double> Mat3x3d;
00646 
00647 typedef Mat<3,4,float> Mat3x4f;
00648 typedef Mat<3,4,double> Mat3x4d;
00649 
00650 typedef Mat<4,4,float> Mat4x4f;
00651 typedef Mat<4,4,double> Mat4x4d;
00652 
00653 #ifdef SOFA_FLOAT
00654 typedef Mat2x2f Matrix2;
00655 typedef Mat3x3f Matrix3;
00656 typedef Mat4x4f Matrix4;
00657 #else
00658 typedef Mat2x2d Matrix2;
00659 typedef Mat3x3d Matrix3;
00660 typedef Mat4x4d Matrix4;
00661 #endif
00662 
00663 
00664 template <int L, int C, typename real>
00665 std::ostream& operator<<(std::ostream& o, const Mat<L,C,real>& m)
00666 {
00667   o << '[' << m[0];
00668   for (int i=1; i<L; i++)
00669     o << ',' << m[i];
00670   o << ']';
00671   return o;
00672 }
00673 
00674 template <int L, int C, typename real>
00675     std::istream& operator>>(std::istream& in, sofa::defaulttype::Mat<L,C,real>& m)
00676 {
00677   int c;
00678   c = in.peek();
00679   while (c==' ' || c=='\n' || c=='[')
00680   {
00681     in.get();
00682     c = in.peek();
00683   }
00684   in >> m[0];
00685   for (int i=1; i<L; i++)
00686   {
00687     c = in.peek();
00688     while (c==' ' || c==',')
00689     {
00690       in.get();
00691       c = in.peek();
00692     }
00693     in >> m[i];
00694   }
00695   c = in.peek();
00696   while (c==' ' || c=='\n' || c==']')
00697   {
00698     in.get();
00699     c = in.peek();
00700   }
00701   return in;
00702 }
00703 
00704 
00706 template<class T1,class T2>
00707 inline const T1 S_MAX(const T1 &a, const T2 &b)
00708 {
00709     return b > a ? (b) : (a);
00710 }
00711 
00713 template<class T1,class T2>
00714 inline const T1 S_MIN(const T1 &a, const T2 &b)
00715 {
00716     return b < a ? (b) : (a);
00717 }
00718 
00719 template<class T1,class T2>
00720 inline const T1 S_SIGN(const T1 &a, const T2 &b)
00721 {
00722     return b >= 0 ? (a >= 0 ? a : -a) : (a >= 0 ? -a : a);
00723 }
00724 
00725 template<class T>
00726 inline const T S_SQR(const T a) 
00727 {
00728     return a*a;
00729 }
00730 
00732 template <class T1, class T2>
00733 T1 pythag(const T1 a, const T2 b)
00734 {
00735     T1 absa,absb;
00736     absa=fabs(a);
00737     absb=fabs(b);
00738     if (absa > absb) return absa*sqrt(1.0+SQR(absb/absa));
00739     else return (absb == 0.0 ? 0.0 : absb*sqrt(1.0+SQR(absa/absb)));
00740 }
00742 
00747 template< int m, int n, typename Real>
00748 void svddcmp(Mat<m,n,Real> &a, Vec<n,Real> &w, Mat<n,m,Real> &v)
00749 {
00750     bool flag;
00751     int i,its,j,jj,k,l,nm;
00752     Real anorm,c,f,g,h,s,scale,x,y,z;
00753 
00754     Vec<n,Real> rv1;
00755     g=scale=anorm=0.0;
00756     for (i=0;i<n;i++) {
00757         l=i+2;
00758         rv1[i]=scale*g;
00759         g=s=scale=0.0;
00760         if (i < m) {
00761             for (k=i;k<m;k++) scale += fabs(a[k][i]);
00762             if (scale != 0.0) {
00763                 for (k=i;k<m;k++) {
00764                     a[k][i] /= scale;
00765                     s += a[k][i]*a[k][i];
00766                 }
00767                 f=a[i][i];
00768                 g = -S_SIGN(sqrt(s),f);
00769                 h=f*g-s;
00770                 a[i][i]=f-g;
00771                 for (j=l-1;j<n;j++) {
00772                     for (s=0.0,k=i;k<m;k++) s += a[k][i]*a[k][j];
00773                     f=s/h;
00774                     for (k=i;k<m;k++) a[k][j] += f*a[k][i];
00775                 }
00776                 for (k=i;k<m;k++) a[k][i] *= scale;
00777             }
00778         }
00779         w[i]=scale *g;
00780         g=s=scale=0.0;
00781         if (i+1 <= m && i != n) {
00782             for (k=l-1;k<n;k++) scale += fabs(a[i][k]);
00783             if (scale != 0.0) {
00784                 for (k=l-1;k<n;k++) {
00785                     a[i][k] /= scale;
00786                     s += a[i][k]*a[i][k];
00787                 }
00788                 f=a[i][l-1];
00789                 g = -S_SIGN(sqrt(s),f);
00790                 h=f*g-s;
00791                 a[i][l-1]=f-g;
00792                 for (k=l-1;k<n;k++) rv1[k]=a[i][k]/h;
00793                 for (j=l-1;j<m;j++) {
00794                     for (s=0.0,k=l-1;k<n;k++) s += a[j][k]*a[i][k];
00795                     for (k=l-1;k<n;k++) a[j][k] += s*rv1[k];
00796                 }
00797                 for (k=l-1;k<n;k++) a[i][k] *= scale;
00798             }
00799         }
00800         anorm=S_MAX(anorm,(fabs(w[i])+fabs(rv1[i])));
00801     }
00802     for (i=n-1;i>=0;i--) {
00803         if (i < n-1) {
00804             if (g != 0.0) {
00805                 for (j=l;j<n;j++)
00806                     v[j][i]=(a[i][j]/a[i][l])/g;
00807                 for (j=l;j<n;j++) {
00808                     for (s=0.0,k=l;k<n;k++) s += a[i][k]*v[k][j];
00809                     for (k=l;k<n;k++) v[k][j] += s*v[k][i];
00810                 }
00811             }
00812             for (j=l;j<n;j++) v[i][j]=v[j][i]=0.0;
00813         }
00814         v[i][i]=1.0;
00815         g=rv1[i];
00816         l=i;
00817     }
00818     for (i=S_MIN(m,n)-1;i>=0;i--) {
00819         l=i+1;
00820         g=w[i];
00821         for (j=l;j<n;j++) a[i][j]=0.0;
00822         if (g != 0.0) {
00823             g=1.0/g;
00824             for (j=l;j<n;j++) {
00825                 for (s=0.0,k=l;k<m;k++) s += a[k][i]*a[k][j];
00826                 f=(s/a[i][i])*g;
00827                 for (k=i;k<m;k++) a[k][j] += f*a[k][i];
00828             }
00829             for (j=i;j<m;j++) a[j][i] *= g;
00830         } else for (j=i;j<m;j++) a[j][i]=0.0;
00831         ++a[i][i];
00832     }
00833     for (k=n-1;k>=0;k--) {
00834         for (its=0;its<30;its++) {
00835             flag=true;
00836             for (l=k;l>=0;l--) {
00837                 nm=l-1;
00838                 if (fabs(rv1[l])+anorm == anorm) {
00839                     flag=false;
00840                     break;
00841                 }
00842                 if (fabs(w[nm])+anorm == anorm) break;
00843             }
00844             if (flag) {
00845                 c=0.0;
00846                 s=1.0;
00847                 for (i=l-1;i<k+1;i++) {
00848                     f=s*rv1[i];
00849                     rv1[i]=c*rv1[i];
00850                     if (fabs(f)+anorm == anorm) break;
00851                     g=w[i];
00852                     h=pythag(f,g);
00853                     w[i]=h;
00854                     h=1.0/h;
00855                     c=g*h;
00856                     s = -f*h;
00857                     for (j=0;j<m;j++) {
00858                         y=a[j][nm];
00859                         z=a[j][i];
00860                         a[j][nm]=y*c+z*s;
00861                         a[j][i]=z*c-y*s;
00862                     }
00863                 }
00864             }
00865             z=w[k];
00866             if (l == k) {
00867                 if (z < 0.0) {
00868                     w[k] = -z;
00869                     for (j=0;j<n;j++) v[j][k] = -v[j][k];
00870                 }
00871                 break;
00872             }
00873             if (its == 29)
00874             {
00875 //              std::cerr<<"Warning: Mat.h :: svddcmp: no convergence in 30 svdcmp iterations"<<std::endl;
00876                 return;
00877             }
00878             x=w[l];
00879             nm=k-1;
00880             y=w[nm];
00881             g=rv1[nm];
00882             h=rv1[k];
00883             f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y);
00884             g=pythag(f,1.0);
00885             f=((x-z)*(x+z)+h*((y/(f+S_SIGN(g,f)))-h))/x;
00886             c=s=1.0;
00887             for (j=l;j<=nm;j++) {
00888                 i=j+1;
00889                 g=rv1[i];
00890                 y=w[i];
00891                 h=s*g;
00892                 g=c*g;
00893                 z=pythag(f,h);
00894                 rv1[j]=z;
00895                 c=f/z;
00896                 s=h/z;
00897                 f=x*c+g*s;
00898                 g=g*c-x*s;
00899                 h=y*s;
00900                 y *= c;
00901                 for (jj=0;jj<n;jj++) {
00902                     x=v[jj][j];
00903                     z=v[jj][i];
00904                     v[jj][j]=x*c+z*s;
00905                     v[jj][i]=z*c-x*s;
00906                 }
00907                 z=pythag(f,h);
00908                 w[j]=z;
00909                 if (z) {
00910                     z=1.0/z;
00911                     c=f*z;
00912                     s=h*z;
00913                 }
00914                 f=c*g+s*y;
00915                 x=c*y-s*g;
00916                 for (jj=0;jj<m;jj++) {
00917                     y=a[jj][j];
00918                     z=a[jj][i];
00919                     a[jj][j]=y*c+z*s;
00920                     a[jj][i]=z*c-y*s;
00921                 }
00922             }
00923             rv1[l]=0.0;
00924             rv1[k]=f;
00925             w[k]=x;
00926         }
00927     }
00928 }
00929 
00930 
00931 
00933 template< int m, int n, typename Real>
00934 Real cond(Mat<m,n,Real> &a)
00935 {
00936     Vec<n,Real>w;
00937     Mat<n,m,Real> *v = new Mat<n,m,Real>();
00938     
00939     svddcmp( a, w, *v );
00940     
00941     delete v;
00942     
00943     return fabs(w[0]/w[n-1]);
00944 }
00945 
00946 
00948 template< int n, typename Real>
00949         void ludcmp(Mat<n,n,Real> &a, Vec<n,int> &indx)
00950 {
00951     const Real TINY=(Real)1.0e-20;
00952     int i,imax=0,j,k; 
00953     Real big,dum,sum,temp;
00954 
00955     Vec<n,Real> vv;
00956     for (i=0;i<n;i++) {
00957         big=0.0;
00958         for (j=0;j<n;j++)
00959             if ((temp=fabs(a[i][j])) > big) big=temp;
00960         assert (big != 0.0);
00961         vv[i]=(Real)1.0/big;
00962     }
00963     for (j=0;j<n;j++) {
00964         for (i=0;i<j;i++) {
00965             sum=a[i][j];
00966             for (k=0;k<i;k++) sum -= a[i][k]*a[k][j];
00967             a[i][j]=sum;
00968         }
00969         big=0.0;
00970         for (i=j;i<n;i++) {
00971             sum=a[i][j];
00972             for (k=0;k<j;k++) sum -= a[i][k]*a[k][j];
00973             a[i][j]=sum;
00974             if ((dum=vv[i]*fabs(sum)) >= big) {
00975                 big=dum;
00976                 imax=i;
00977             }
00978         }
00979         if (j != imax) {
00980             for (k=0;k<n;k++) {
00981                 dum=a[imax][k];
00982                 a[imax][k]=a[j][k];
00983                 a[j][k]=dum;
00984             }
00985             vv[imax]=vv[j];
00986         }
00987         indx[j]=imax;
00988         if (a[j][j] == 0.0) a[j][j]=TINY;
00989         if (j != n-1) {
00990             dum=(Real)1.0/(a[j][j]);
00991             for (i=j+1;i<n;i++) a[i][j] *= dum;
00992         }
00993     }
00994 }
00995 
00997 template< int n, typename Real>
00998         void lubksb(const Mat<n,n,Real> &a, const Vec<n,int> &indx, Vec<n,Real> &b)
00999 {
01000     int i,ii=0,ip,j;
01001     Real sum;
01002 
01003     for (i=0;i<n;i++) {
01004         ip=indx[i];
01005         sum=b[ip];
01006         b[ip]=b[i];
01007         if (ii != 0)
01008             for (j=ii-1;j<i;j++) sum -= a[i][j]*b[j];
01009         else if (sum != 0.0)
01010             ii=i+1;
01011         b[i]=sum;
01012     }
01013     for (i=n-1;i>=0;i--) {
01014         sum=b[i];
01015         for (j=i+1;j<n;j++) sum -= a[i][j]*b[j];
01016         b[i]=sum/a[i][i];
01017     }
01018 }
01019 
01023 template< int n, typename Real>
01024         void luinv( Mat<n,n,Real> &inv, Mat<n,n,Real> &m )
01025 {
01026     Vec<n,int> idx;
01027     Vec<n,Real> col;
01028     
01029     ludcmp(m,idx);
01030     
01031     for( int i=0; i<n; i++ ){ 
01032         for( int j=0; j<n; j++ )
01033             col[j] = 0;
01034         col[i] = 1;
01035         lubksb(m,idx,col);
01036         for( int j=0; j<n; j++ )
01037             inv[j][i] = col[j];
01038     }
01039 }
01040 
01042 template <int L, int C, typename T>
01043 inline Mat<L,C,T> dyad( const Vec<L,T>& u, const Vec<C,T>& v )
01044 {
01045     Mat<L,C,T> res(NOINIT);
01046     for( int i=0; i<L; i++ )
01047         for( int j=0; j<C; j++ )
01048             res[i][j] = u[i]*v[j];
01049     return res;
01050 }
01051 
01052 } // namespace defaulttype
01053 
01054 } // namespace sofa
01055 
01056 // iostream
01057 
01058 
01059 
01061 template <int L, int C, typename real>
01062 sofa::defaulttype::Mat<L,C,real> operator*(real r, const sofa::defaulttype::Mat<L,C,real>& m)
01063 {
01064   return m*r;
01065 }
01066 
01067 #endif

Generated on Sun Nov 23 02:29:28 2008 for Sofa by  doxygen 1.5.7.1