Clipper
clipper_types.h
00001 
00004 //C Copyright (C) 2000-2006 Kevin Cowtan and University of York
00005 //L
00006 //L  This library is free software and is distributed under the terms
00007 //L  and conditions of version 2.1 of the GNU Lesser General Public
00008 //L  Licence (LGPL) with the following additional clause:
00009 //L
00010 //L     `You may also combine or link a "work that uses the Library" to
00011 //L     produce a work containing portions of the Library, and distribute
00012 //L     that work under terms of your choice, provided that you give
00013 //L     prominent notice with each copy of the work that the specified
00014 //L     version of the Library is used in it, and that you include or
00015 //L     provide public access to the complete corresponding
00016 //L     machine-readable source code for the Library including whatever
00017 //L     changes were used in the work. (i.e. If you make changes to the
00018 //L     Library you must distribute those, but you do not need to
00019 //L     distribute source or object code to those portions of the work
00020 //L     not covered by this licence.)'
00021 //L
00022 //L  Note that this clause grants an additional right and does not impose
00023 //L  any additional restriction, and so does not affect compatibility
00024 //L  with the GNU General Public Licence (GPL). If you wish to negotiate
00025 //L  other terms, please contact the maintainer.
00026 //L
00027 //L  You can redistribute it and/or modify the library under the terms of
00028 //L  the GNU Lesser General Public License as published by the Free Software
00029 //L  Foundation; either version 2.1 of the License, or (at your option) any
00030 //L  later version.
00031 //L
00032 //L  This library is distributed in the hope that it will be useful, but
00033 //L  WITHOUT ANY WARRANTY; without even the implied warranty of
00034 //L  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00035 //L  Lesser General Public License for more details.
00036 //L
00037 //L  You should have received a copy of the CCP4 licence and/or GNU
00038 //L  Lesser General Public License along with this library; if not, write
00039 //L  to the CCP4 Secretary, Daresbury Laboratory, Warrington WA4 4AD, UK.
00040 //L  The GNU Lesser General Public can also be obtained by writing to the
00041 //L  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00042 //L  MA 02111-1307 USA
00043 
00044 
00045 #ifndef CLIPPER_TYPES
00046 #define CLIPPER_TYPES
00047 
00048 
00049 #include "clipper_util.h"
00050 #include "clipper_memory.h"
00051 
00052 
00053 namespace clipper
00054 {
00055   // forward definitions
00056   template<class T> class Mat33sym;
00057 
00058 
00060 
00064   class String : public std::string
00065   {
00066   public:
00067     inline String() : std::string() {}  
00068     inline String( const std::string str ) : std::string( str ) {} 
00069     inline String( const char* str ) : std::string( str ) {} 
00070     String( const char* str, const int l );     
00071     String( const int i, const int w = 4 );     
00072     String( const long i, const int w = 4 );    
00073 
00074     String( const float f, const int w = 6, const int p = 6 );
00076     String( const double f, const int w = 6, const int p = 6 );
00077 
00079     std::vector<String> split(const String sep) const;
00081     String trim() const;
00082 
00084     String tail() const;
00086     String head() const;
00088     String nohead() const;
00090     String notail() const;
00091 
00093     static String rational( const double f, const int b, const bool sign=false );
00094 
00095     int i() const;     
00096     long l() const;    
00097     ftype32 f32() const;  
00098     ftype64 f64() const;  
00099     ftype f() const;      
00100     ftype rational() const;  
00101   };
00102 
00103 
00105   template<class T = ftype> class Vec3
00106   {
00107   public:
00109     inline Vec3() {}
00111     inline Vec3( const T& v0, const T& v1, const T& v2 )
00112       { vec[0] = v0; vec[1] = v1; vec[2] = v2; }
00114     template<class TT> explicit Vec3( const Vec3<TT>& v )
00115       { vec[0] = TT(v[0]); vec[1] = TT(v[1]); vec[2] = TT(v[2]); }
00117     bool equals( const Vec3<T>& v, const T& tol ) const;
00119     inline const T& operator []( const int& i ) const { return vec[i]; }
00121     inline T& operator []( const int& i ) { return vec[i]; }
00123     inline Vec3<T> unit() const
00124       { return (*this)*T(1.0/sqrt(ftype(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]))); }
00126     inline static Vec3<T> zero() { return Vec3<T>( 0, 0, 0 ); }
00128     inline static Vec3<T> null() { return Vec3<T>( T(Util::nan()), 0, 0 ); }
00130     inline bool is_null() const { return Util::is_nan( vec[0] ); }
00132     inline static T dot( const Vec3<T>& v1, const Vec3<T>& v2 )
00133       { return (v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]); }
00135     inline static Vec3<T> cross( const Vec3<T>& v1, const Vec3<T>& v2 )
00136       { return Vec3<T>(v1[1]*v2[2]-v2[1]*v1[2],
00137                        v1[2]*v2[0]-v2[2]*v1[0],
00138                        v1[0]*v2[1]-v2[0]*v1[1]); }
00140     String format() const
00141       { return "("+String(vec[0],10,4)+","+String(vec[1],10,4)+","+String(vec[2],10,4)+")"; }
00143     inline const Vec3<T>& operator += ( const Vec3<T>& v )
00144       { vec[0] += v[0]; vec[1] += v[1]; vec[2] += v[2]; return (*this); }
00146     inline const Vec3<T>& operator -= ( const Vec3<T>& v )
00147       { vec[0] -= v[0]; vec[1] -= v[1]; vec[2] -= v[2]; return (*this); }
00149     //-- friend int operator == ( const Vec3<T>& v1, const Vec3<T>& v2 );
00151     //-- friend int operator != ( const Vec3<T>& v1, const Vec3<T>& v2 );
00153     //-- friend Vec3<T> operator -( const Vec3<T>& v );
00155     //-- friend Vec3<T> operator +( const Vec3<T>& v1, const Vec3<T> &v2 );
00157     //-- friend Vec3<T> operator -( const Vec3<T>& v1, const Vec3<T>& v2 );
00159     //-- friend Vec3<T> operator *( const T& s, const Vec3<T>& v1 );
00161     //-- friend Vec3<T> operator *( const Vec3<T>& v1, const T& s );
00163     //-- friend T operator *( const Vec3<T>& v1, const Vec3<T>& v2 );
00164   private:
00165     T vec[3];
00166   };
00167   template<class T> inline int operator == ( const Vec3<T>& v1, const Vec3<T>& v2 ) { return (v1[0]==v2[0] && v1[1]==v2[1] && v1[2]==v2[2]); }
00168   template<class T> inline int operator != ( const Vec3<T>& v1, const Vec3<T>& v2 ) { return (v1[0]!=v2[0] || v1[1]!=v2[1] || v1[2]!=v2[2]); }
00169   template<class T> inline Vec3<T> operator -( const Vec3<T>& v )
00170     { return Vec3<T>( -v[0], -v[1], -v[2] ); }
00171   template<class T> inline Vec3<T> operator +( const Vec3<T>& v1, const Vec3<T> &v2 ) { return Vec3<T>( v1[0]+v2[0], v1[1]+v2[1], v1[2]+v2[2]); }
00172   template<class T> inline Vec3<T> operator -( const Vec3<T>& v1, const Vec3<T>& v2 ) { return Vec3<T>( v1[0]-v2[0], v1[1]-v2[1], v1[2]-v2[2]); }
00173   template<class T> inline Vec3<T> operator *( const T& s, const Vec3<T>& v1 )
00174     { return Vec3<T>( s*v1[0], s*v1[1], s*v1[2]); }
00175   template<class T> inline Vec3<T> operator *( const Vec3<T>& v1, const T& s )
00176     { return Vec3<T>( s*v1[0], s*v1[1], s*v1[2]); }
00177   template<class T> inline T operator *( const Vec3<T>& v1, const Vec3<T>& v2 )
00178     { return Vec3<T>::dot(v1,v2); }
00179 
00180 
00182   template<class T = ftype> class Mat33
00183   {
00184   public:
00186     inline Mat33() {}
00188     inline Mat33( const T& m00, const T& m01, const T& m02, const T& m10, const T& m11, const T& m12, const T& m20, const T& m21, const T& m22 )
00189       { mat[0][0] = m00; mat[0][1] = m01; mat[0][2] = m02; mat[1][0] = m10; mat[1][1] = m11; mat[1][2] = m12; mat[2][0] = m20; mat[2][1] = m21; mat[2][2] = m22; }
00191     template<class TT> explicit Mat33( const Mat33<TT>& m );
00193     template<class TT> explicit Mat33( const Mat33sym<TT>& m );
00194     T det() const;               
00195     Mat33<T> inverse() const;    
00196     Mat33<T> transpose() const;  
00197     bool equals( const Mat33<T>& m, const T& tol ) const;  
00198     inline const T& operator ()( const int& i, const int& j ) const
00199       { return mat[i][j]; }      
00200     inline T& operator ()( const int& i, const int& j )
00201       { return mat[i][j]; }      
00202 
00203     String format() const
00204       { return "|"+String(mat[0][0],10,4)+","+String(mat[0][1],10,4)+","+String(mat[0][2],10,4)+"|\n|"+String(mat[1][0],10,4)+","+String(mat[1][1],10,4)+","+String(mat[1][2],10,4)+"|\n|"+String(mat[2][0],10,4)+","+String(mat[2][1],10,4)+","+String(mat[2][2],10,4)+"|"; }
00206     inline static Mat33<T> identity() { Mat33<T> m; m.mat[0][0] = m.mat[1][1] = m.mat[2][2] = 1; m.mat[0][1] = m.mat[0][2] = m.mat[1][0] = m.mat[1][2] = m.mat[2][0] = m.mat[2][1] = 0; return m; }
00208     inline static Mat33<T> null() { Mat33<T> m; m.mat[0][0] = Util::nan(); return m; }
00210     bool inline is_null() const { return Util::is_nan( mat[0][0] ); }
00212 
00213     //-- friend Vec3<T> operator *( const Mat33<T>& m, const Vec3<T>& v );
00215 
00217     //-- friend Vec3<T> operator *( const Vec3<T>& v, const Mat33<T>& m );
00219     //-- friend Mat33<T> operator *(const Mat33<T>& m1, const Mat33<T>& m2);
00221     //-- friend Mat33<T> operator +(const Mat33<T>& m1, const Mat33<T>& m2);
00223     //-- friend Mat33<T> operator -(const Mat33<T>& m);
00224   private:
00225     T mat[3][3];
00226   };
00227   template<class T> inline Vec3<T> operator *( const Mat33<T>& m, const Vec3<T>& v )
00228     { return Vec3<T>( m(0,0)*v[0]+m(0,1)*v[1]+m(0,2)*v[2],
00229                       m(1,0)*v[0]+m(1,1)*v[1]+m(1,2)*v[2],
00230                       m(2,0)*v[0]+m(2,1)*v[1]+m(2,2)*v[2] ); }
00231   template<class T> inline Vec3<T> operator *( const Vec3<T>& v, const Mat33<T>& m )
00232     { return Vec3<T>( v[0]*m(0,0)+v[1]*m(1,0)+v[2]*m(2,0),
00233                       v[0]*m(0,1)+v[1]*m(1,1)+v[2]*m(2,1),
00234                       v[0]*m(0,2)+v[1]*m(1,2)+v[2]*m(2,2) ); }
00235   template<class T> inline Mat33<T> operator *( const Mat33<T>& m1, const Mat33<T>& m2 )
00236     {
00237       return Mat33<T> ( m1(0,0)*m2(0,0) + m1(0,1)*m2(1,0) + m1(0,2)*m2(2,0),
00238                         m1(0,0)*m2(0,1) + m1(0,1)*m2(1,1) + m1(0,2)*m2(2,1),
00239                         m1(0,0)*m2(0,2) + m1(0,1)*m2(1,2) + m1(0,2)*m2(2,2),
00240                         m1(1,0)*m2(0,0) + m1(1,1)*m2(1,0) + m1(1,2)*m2(2,0),
00241                         m1(1,0)*m2(0,1) + m1(1,1)*m2(1,1) + m1(1,2)*m2(2,1),
00242                         m1(1,0)*m2(0,2) + m1(1,1)*m2(1,2) + m1(1,2)*m2(2,2),
00243                         m1(2,0)*m2(0,0) + m1(2,1)*m2(1,0) + m1(2,2)*m2(2,0),
00244                         m1(2,0)*m2(0,1) + m1(2,1)*m2(1,1) + m1(2,2)*m2(2,1),
00245                         m1(2,0)*m2(0,2) + m1(2,1)*m2(1,2) + m1(2,2)*m2(2,2) );
00246     }
00247   template<class T> inline Mat33<T> operator +( const Mat33<T>& m1, const Mat33<T>& m2 )
00248     { return Mat33<T>( m1(0,0)+m2(0,0), m1(0,1)+m2(0,1), m1(0,2)+m2(0,2),
00249                        m1(1,0)+m2(1,0), m1(1,1)+m2(1,1), m1(1,2)+m2(1,2),
00250                        m1(2,0)+m2(2,0), m1(2,1)+m2(2,1), m1(2,2)+m2(2,2) ); }
00251   template<class T> inline Mat33<T> operator -( const Mat33<T>& m )
00252     { return Mat33<T>( -m(0,0), -m(0,1), -m(0,2),
00253                        -m(1,0), -m(1,1), -m(1,2),
00254                        -m(2,0), -m(2,1), -m(2,2) ); }
00255 
00256 
00258   template<class T = ftype> class Mat33sym
00259   {
00260   public:
00262     inline Mat33sym() {}
00264     template<class TT> explicit Mat33sym( const Mat33<TT>& m ) :
00265       m00(m(0,0)), m11(m(1,1)), m22(m(2,2)),
00266       m01(m(0,1)), m02(m(0,2)), m12(m(1,2)) {}
00268     template<class TT> explicit Mat33sym( const Mat33sym<TT>& m ) :
00269       m00(m.mat00()), m11(m.mat11()), m22(m.mat22()),
00270       m01(m.mat01()), m02(m.mat02()), m12(m.mat12()) {}
00272     inline Mat33sym( const T& c00, const T& c11, const T& c22,
00273                      const T& c01, const T& c02, const T& c12 ) :
00274       m00(c00), m11(c11), m22(c22), m01(c01), m02(c02), m12(c12) {}
00276     String format() const
00277       { return "|"+String(m00,10,4)+","+String(m01,10,4)+","+String(m02,10,4)+"|\n|"+String(m01,10,4)+","+String(m11,10,4)+","+String(m12,10,4)+"|\n|"+String(m02,10,4)+","+String(m12,10,4)+","+String(m22,10,4)+"|"; }
00279     inline static Mat33sym<T> identity()
00280       { return Mat33sym<T>( 1, 1, 1, 0, 0, 0 ); }
00282     inline static Mat33sym<T> null()
00283       { return Mat33sym<T>(Util::nan(),0,0,0,0,0); }
00285     inline bool is_null() const { return Util::is_nan( m00 ); }
00287     T quad_form( const Vec3<T>& v ) const;
00288     T det() const;               
00289     Mat33<T> sqrt() const;       
00290     Mat33sym<T> inverse() const; 
00291     inline const T& mat00() const { return m00; }  
00292     inline const T& mat11() const { return m11; }  
00293     inline const T& mat22() const { return m22; }  
00294     inline const T& mat01() const { return m01; }  
00295     inline const T& mat02() const { return m02; }  
00296     inline const T& mat12() const { return m12; }  
00297 
00298     const T& operator ()( const int& i, const int& j ) const;
00300     //-- friend Vec3<T> operator *( const Mat33sym<T>& m, const Vec3<T>& v );
00302     //-- friend Mat33sym<T> operator +( const Mat33sym<T>& m1, const Mat33sym<T>& m2 );
00304     //-- friend Mat33sym<T> operator -( const Mat33sym<T>& m );
00305    private:
00306     T m00, m11, m22, m01, m02, m12;
00307   };
00308   template<class T> inline Vec3<T> operator *( const Mat33sym<T>& m, const Vec3<T>& v )
00309     { return Vec3<T>( m.mat00()*v[0]+m.mat01()*v[1]+m.mat02()*v[2],
00310                       m.mat01()*v[0]+m.mat11()*v[1]+m.mat12()*v[2],
00311                       m.mat02()*v[0]+m.mat12()*v[1]+m.mat22()*v[2] ); }
00312   template<class T> inline Mat33sym<T> operator +( const Mat33sym<T>& m1, const Mat33sym<T>& m2 )
00313     { return Mat33sym<T>( m1.mat00()+m2.mat00(), m1.mat11()+m2.mat11(),
00314                           m1.mat22()+m2.mat22(), m1.mat01()+m2.mat01(),
00315                           m1.mat02()+m2.mat02(), m1.mat12()+m2.mat12() ); }
00316   template<class T> inline Mat33sym<T> operator -( const Mat33sym<T>& m )
00317     { return Mat33sym<T>( -m.mat00(), -m.mat11(), -m.mat22(),
00318                           -m.mat01(), -m.mat02(), -m.mat12() ); }
00319 
00320 
00322   template<class T = ftype> class RTop
00323   {
00324   public:
00326     inline RTop() {}
00328     inline explicit RTop( const Mat33<T>& r ) : rot_( r ), trn_( Vec3<T>::zero() ) {}
00330     inline RTop( const Mat33<T>& r, const Vec3<T>& t ) : rot_( r ), trn_( t ) {}
00332     RTop<T> inverse() const
00333       { Mat33<T> minv = rot().inverse(); return RTop<T>(minv, -(minv*trn())); }
00335     inline bool equals( const RTop<T>& m, const T& tol ) const
00336       { return ( rot().equals(m.rot(),tol) && trn().equals(m.trn(),tol) ); }
00337     inline const Mat33<T>& rot() const { return rot_; }  
00338     inline const Vec3<T>&  trn() const { return trn_; }  
00339     inline Mat33<T>& rot() { return rot_; } 
00340     inline Vec3<T>&  trn() { return trn_; } 
00341 
00342     inline static RTop<T> identity()
00343       { return RTop<T>( Mat33<T>::identity(), Vec3<T>::zero() ); }
00345     inline static RTop<T> null()
00346       { return RTop<T>( Mat33<T>::null(), Vec3<T>::null() ); }
00348     inline bool is_null() const { return rot_.is_null() || trn_.is_null(); }
00350     String format() const { return rot_.format() + "\n" + trn_.format(); }
00352     //-- friend Vec3<T> operator *( const RTop<T>& r, const Vec3<T>& v );
00354     //-- friend RTop<T> operator *( const RTop<T>& r1, const RTop<T>& r2 );
00355   private:
00356     Mat33<T> rot_; Vec3<T> trn_;
00357   };
00358   template<class T> inline Vec3<T> operator *( const RTop<T>& r, const Vec3<T>& v ) { return r.rot()*v + r.trn(); }
00359   template<class T> inline RTop<T> operator *( const RTop<T>& r1, const RTop<T>& r2 ) { return RTop<T>( r1.rot()*r2.rot(), r1.rot()*r2.trn()+r1.trn() ); }
00360 
00361 
00362 
00364   template<class T = ftype> class Array2d
00365   {
00366   public:
00368     inline Array2d() { d1_ = d2_ = 0; }
00370     inline Array2d( const int& d1, const int& d2 ) { resize( d1, d2 ); }
00372     inline Array2d( const int& d1, const int& d2, T val )
00373       { resize( d1, d2, val ); }
00375     void inline resize( const int& d1, const int& d2 )
00376       { d1_ = d1; d2_ = d2; data.resize( size() ); }
00378     void inline resize( const int& d1, const int& d2, const T& val )
00379       { d1_ = d1; d2_ = d2; data.resize( size(), val ); }
00380     inline int size() const { return d1_ * d2_; }    
00381     inline const int& rows() const { return d1_; }  
00382     inline const int& cols() const { return d2_; }  
00383 
00384     inline const T& operator () ( const int& i1, const int& i2 ) const
00385       { return data[ i1*d2_ + i2 ]; }
00387     inline T& operator () ( const int& i1, const int& i2 )
00388       { return data[ i1*d2_ + i2 ]; }
00389   protected:
00390     std::vector<T> data;
00391     int d1_, d2_;
00392   };
00393 
00394 
00396   template<class T = ftype> class Matrix : public Array2d<T>
00397   {
00398   public:
00400     inline Matrix() {}
00402     inline Matrix( const int& d1, const int& d2 )
00403       { Array2d<T>::resize( d1, d2 ); }
00405     inline Matrix( const int& d1, const int& d2, T val )
00406       { Array2d<T>::resize( d1, d2, val ); }
00408     std::vector<T> solve( const std::vector<T>& b ) const;
00410     std::vector<T> eigen( const bool sort = true );
00412 
00413     //-- friend std::vector<T> operator *( const Matrix<T>& m, const std::vector<T>& v );
00414   };
00415   template<class T> std::vector<T> operator *( const Matrix<T>& m, const std::vector<T>& v )
00416     {
00417       if ( m.cols() != v.size() )
00418         Message::message( Message_fatal( "Matrix*vector dimension mismatch" ) );
00419       std::vector<T> r( m.rows() );
00420       int i, j; T s;
00421       for ( i = 0; i < m.rows(); i++ ) {
00422         s = T(0);
00423         for ( j = 0; j < m.cols(); j++ ) s += m(i,j) * v[j];
00424         r[i] = s;
00425       }
00426       return r;
00427     }
00428 
00429 
00430 
00431   // template implementations
00432 
00433   template<class T> bool Vec3<T>::equals( const Vec3<T>& v, const T& tol ) const
00434   {
00435     return ( pow(vec[0]-v[0],T(2)) + pow(vec[1]-v[1],T(2)) + 
00436              pow(vec[2]-v[2],T(2)) <= pow(tol,T(2)) );
00437   }
00438 
00439   template<class T> template<class TT> Mat33<T>::Mat33( const Mat33<TT>& m )
00440   {
00441     mat[0][0]=T(m(0,0)); mat[0][1]=T(m(0,1)); mat[0][2]=T(m(0,2));
00442     mat[1][0]=T(m(1,0)); mat[1][1]=T(m(1,1)); mat[1][2]=T(m(1,2));
00443     mat[2][0]=T(m(2,0)); mat[2][1]=T(m(2,1)); mat[2][2]=T(m(2,2));
00444   }
00445 
00446   template<class T> template<class TT> Mat33<T>::Mat33( const Mat33sym<TT>& m )
00447   {
00448     mat[0][0]=T(m.mat00());
00449     mat[1][1]=T(m.mat11());
00450     mat[2][2]=T(m.mat22());
00451     mat[0][1]=mat[1][0]=T(m.mat01());
00452     mat[0][2]=mat[2][0]=T(m.mat02());
00453     mat[1][2]=mat[2][1]=T(m.mat12());
00454   }
00455 
00456   template<class T> bool Mat33<T>::equals( const Mat33<T>& m, const T& tol ) const
00457   {
00458     return ( pow(mat[0][0]-m(0,0),T(2)) + pow(mat[0][1]-m(0,1),T(2)) +
00459              pow(mat[0][2]-m(0,2),T(2)) + pow(mat[1][0]-m(1,0),T(2)) +
00460              pow(mat[1][1]-m(1,1),T(2)) + pow(mat[1][2]-m(1,2),T(2)) +
00461              pow(mat[2][0]-m(2,0),T(2)) + pow(mat[2][1]-m(2,1),T(2)) +
00462              pow(mat[2][2]-m(2,2),T(2)) <= pow(tol,T(2)) );
00463   }
00464 
00465   template<class T> T Mat33<T>::det() const
00466   {
00467     return ( mat[0][0]*(mat[1][1]*mat[2][2] - mat[1][2]*mat[2][1]) + 
00468              mat[0][1]*(mat[1][2]*mat[2][0] - mat[1][0]*mat[2][2]) +
00469              mat[0][2]*(mat[1][0]*mat[2][1] - mat[1][1]*mat[2][0]) );
00470   }
00471 
00472   template<class T> Mat33<T> Mat33<T>::inverse() const
00473   {
00474     T d = det();
00475     Mat33<T> inv;
00476     inv(0,0) = ( mat[1][1]*mat[2][2] - mat[1][2]*mat[2][1] ) / d;
00477     inv(1,0) = ( mat[1][2]*mat[2][0] - mat[1][0]*mat[2][2] ) / d;
00478     inv(2,0) = ( mat[1][0]*mat[2][1] - mat[1][1]*mat[2][0] ) / d;
00479     inv(0,1) = ( mat[2][1]*mat[0][2] - mat[2][2]*mat[0][1] ) / d;
00480     inv(1,1) = ( mat[2][2]*mat[0][0] - mat[2][0]*mat[0][2] ) / d;
00481     inv(2,1) = ( mat[2][0]*mat[0][1] - mat[2][1]*mat[0][0] ) / d;
00482     inv(0,2) = ( mat[0][1]*mat[1][2] - mat[0][2]*mat[1][1] ) / d;
00483     inv(1,2) = ( mat[0][2]*mat[1][0] - mat[0][0]*mat[1][2] ) / d;
00484     inv(2,2) = ( mat[0][0]*mat[1][1] - mat[0][1]*mat[1][0] ) / d;
00485     return inv;
00486   }
00487 
00488   template<class T> Mat33<T> Mat33<T>::transpose() const
00489   {
00490     Mat33<T> t;
00491     t(0,0) = mat[0][0]; t(0,1) = mat[1][0]; t(0,2) = mat[2][0];
00492     t(1,0) = mat[0][1]; t(1,1) = mat[1][1]; t(1,2) = mat[2][1];
00493     t(2,0) = mat[0][2]; t(2,1) = mat[1][2]; t(2,2) = mat[2][2];
00494     return t;
00495   }
00496 
00497   template<class T> T Mat33sym<T>::det() const
00498   {
00499     return ( m00*(m11*m22 - m12*m12) + m01*(m12*m02 - m01*m22) +
00500              m02*(m01*m12 - m11*m02) );
00501   }
00502 
00503   template<class T> Mat33<T> Mat33sym<T>::sqrt() const
00504   {
00505     Mat33<T> half( Mat33sym<T>( 0.5, 0.5, 0.5, 0.0, 0.0, 0.0 ) );
00506     Mat33<T> target( *this );
00507     Mat33<T> result( target );
00508     result(1,0) = result(2,0) = result(2,1) = 0.0;
00509     for ( int i = 0; i < 10; i++ )
00510       result = half * ( result.inverse() * target + result );
00511     return result;
00512   }
00513 
00514   template<class T> Mat33sym<T> Mat33sym<T>::inverse() const
00515   {
00516     T d = det();
00517     return Mat33sym<T> ( ( m11*m22 - m12*m12 ) / d,
00518                          ( m22*m00 - m02*m02 ) / d,
00519                          ( m00*m11 - m01*m01 ) / d,
00520                          ( m12*m02 - m22*m01 ) / d,
00521                          ( m01*m12 - m02*m11 ) / d,
00522                          ( m02*m01 - m00*m12 ) / d );
00523   }
00524 
00525   template<class T> T Mat33sym<T>::quad_form( const Vec3<T>& v ) const
00526   {
00527     return ( v[0]*( v[0]*m00 + 2*(v[1]*m01+v[2]*m02) ) +
00528              v[1]*( v[1]*m11 + 2*(v[2]*m12) ) + v[2]*v[2]*m22 );
00529   }
00530 
00531   template<class T> const T& Mat33sym<T>::operator ()( const int& i, const int& j ) const
00532   {
00533     switch (i) {
00534     case 0:
00535       switch (j) {
00536       case 0: return m00;
00537       case 1: return m01;
00538       default: return m02;
00539       }
00540     case 1:
00541       switch (j) {
00542       case 0: return m01;
00543       case 1: return m11;
00544       default: return m12;
00545       }
00546     default:
00547       switch (j) {
00548       case 0: return m02;
00549       case 1: return m12;
00550       default: return m22;
00551       }
00552     }
00553   }
00554 
00555 
00556 // complex matrix methods
00557 
00558 
00561 template<class T> std::vector<T> Matrix<T>::solve( const std::vector<T>& b ) const
00562 {
00563   if ( Array2d<T>::rows() != Array2d<T>::cols() )
00564     Message::message( Message_fatal("Matrix.solve() matrix not square") );
00565   if ( Array2d<T>::rows() != b.size() )
00566     Message::message( Message_fatal("Matrix.solve() matrix/vector mismatch") );
00567   const int n = Array2d<T>::rows();
00568 
00569   // solve for X by Gaussian elimination
00570   T s, pivot;
00571   int i, j, k;
00572 
00573   Matrix<T> a = *this;
00574   std::vector<T> x = b;
00575   for ( i = 0; i < n; i++ ) {
00576     // pick largest pivot
00577     j = i;
00578     for ( k = i+1; k < n; k++ )
00579       if ( fabs(a(k,i)) > fabs(a(j,i)) ) j = k;
00580     // swap rows
00581     for ( k = 0; k < n; k++ )
00582       Util::swap( a(i,k), a(j,k) );
00583     Util::swap( x[i], x[j] );
00584     // perform elimination
00585     pivot = a(i,i);
00586     for ( j = 0; j < n; j++ ) {
00587       if ( j != i ) {
00588         s = a(j,i) / pivot;
00589         for ( k = i+1; k < n; k++ ) a(j,k) = a(j,k) - s*a(i,k);
00590         x[j] = x[j] - s*x[i];
00591       }
00592     }
00593   }
00594   for ( i = 0; i < n; i++ ) x[i] /= a(i,i);
00595   return x;
00596 }
00597 
00598 
00604 template<class T> std::vector<T> Matrix<T>::eigen( const bool sort )
00605 {
00606   if ( Array2d<T>::rows() != Array2d<T>::cols() )
00607     Message::message( Message_fatal( "Matrix.eigen() matrix not square" ) );
00608   const int n = Array2d<T>::rows();
00609 
00610   int cyc, j, q, p;
00611   T spp, spq, t, s, c, theta, tau, h, ap, aq, a_pq;
00612 
00613   Matrix<T>& mat = *this;
00614   Matrix evec( n, n, 0.0 );
00615   std::vector<T> eval( n );
00616   std::vector<T> b( n );
00617   std::vector<T> z( n );
00618 
00619   // Set evec to identity, eval & b to diagonal, z to 0.
00620   for( p = 0; p < n; p++ ) {
00621     evec(p,p) = 1.0;
00622     eval[p] = b[p] = mat(p,p);
00623   }
00624 
00625   for ( cyc = 1; cyc <= 50; cyc++ ) {
00626 
00627     // calc sum of diagonal, off-diagonal
00628     spp = spq = 0.0;
00629     for ( p=0; p<n-1; p++ ) {
00630       for ( q=p+1; q<n; q++ )
00631         spq += fabs( mat(p,q) );
00632       spp += fabs( mat(p,p) );
00633     }
00634     if ( spq <= 1.0e-12 * spp ) break;
00635 
00636     // zero z
00637     for ( p = 0; p < n; p++ ) z[p] = 0.0;
00638 
00639     // now try and reduce each off-diagonal element in turn
00640     for( p=0; p<n-1; p++ ) {
00641       for( q=p+1; q<n; q++ ) {
00642         a_pq = mat( p, q );
00643         h = eval[q] - eval[p];
00644         if ( fabs(a_pq) > 1.0e-12*fabs(h) ) {
00645           theta = 0.5*h/a_pq;
00646           t = 1.0/(fabs(theta) + sqrt(1.0 + theta*theta));
00647           if ( theta < 0.0 ) t = -t;
00648         } else {
00649           t = a_pq/h;
00650         }
00651 
00652         // calc trig properties
00653         c   = 1.0/sqrt(1.0+t*t);
00654         s   = t*c;
00655         tau = s/(1.0+c);
00656         h   = t * a_pq;
00657 
00658         // update eigenvalues
00659         z[p] -= h;
00660         z[q] += h;
00661         eval[p] -= h;
00662         eval[q] += h;
00663 
00664         // rotate the upper diagonal of the matrix
00665         mat( p, q ) = 0.0;
00666         for ( j = 0; j < p; j++ ) {
00667           ap = mat( j, p );
00668           aq = mat( j, q );
00669           mat( j, p ) = ap - s * ( aq + ap * tau );
00670           mat( j, q ) = aq + s * ( ap - aq * tau );
00671         }
00672         for ( j = p+1; j < q; j++ ) {
00673           ap = mat( p, j );
00674           aq = mat( j, q );
00675           mat( p, j ) = ap - s * ( aq + ap * tau );
00676           mat( j, q ) = aq + s * ( ap - aq * tau );
00677         }
00678         for ( j = q+1; j < n; j++ ) {
00679           ap = mat( p, j );
00680           aq = mat( q, j );
00681           mat( p, j ) = ap - s * ( aq + ap * tau );
00682           mat( q, j ) = aq + s * ( ap - aq * tau );
00683         }
00684         // apply corresponding rotation to result
00685         for ( j = 0; j < n; j++ ) {
00686           ap = evec( j, p );
00687           aq = evec( j, q );
00688           evec( j, p ) = ap - s * ( aq + ap * tau );
00689           evec( j, q ) = aq + s * ( ap - aq * tau );
00690         }
00691       }
00692     }
00693 
00694     for ( p = 0; p < n; p++ ) {
00695       b[p] += z[p];
00696       eval[p] = b[p];
00697     }
00698   }
00699 
00700   // sort the eigenvalues
00701   if ( sort ) {
00702     for ( p = 0; p < n; p++ ) {
00703       j = p;        // set j to index of largest remaining eval
00704       for ( q = p+1; q < n; q++ )
00705         if ( eval[q] < eval[j] ) j = q;
00706       Util::swap( eval[p], eval[j] );  // now swap evals, evecs
00707       for ( q = 0; q < n; q++ )
00708         Util::swap( evec( q, p ), evec( q, j ) );
00709     }
00710   }
00711 
00712   // return eigenvalues
00713   mat = evec;
00714   return eval;
00715 }
00716 
00717 } // namespace clipper
00718 
00719 #endif