Sirikata
libcore/include/sirikata/core/util/Matrix3x3.hpp
Go to the documentation of this file.
00001 /*  Sirikata Utilities -- Math Library
00002  *  Matrix3x3.hpp
00003  *
00004  *  Copyright (c) 2009, Daniel Reiter Horn
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions are
00009  *  met:
00010  *  * Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer.
00012  *  * Redistributions in binary form must reproduce the above copyright
00013  *    notice, this list of conditions and the following disclaimer in
00014  *    the documentation and/or other materials provided with the
00015  *    distribution.
00016  *  * Neither the name of Sirikata nor the names of its contributors may
00017  *    be used to endorse or promote products derived from this software
00018  *    without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00021  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00022  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00023  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
00024  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00025  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00026  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00027  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00028  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00029  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00030  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031  */
00032 #ifndef _MATRIX3X3_HPP_
00033 #define _MATRIX3X3_HPP_
00034 namespace Sirikata {
00035 class COLUMNS{};
00036 class ROWS{};
00037 
00038 template <typename scalar> class Matrix3x3 {
00039 public:
00040     typedef Vector3<scalar> Vector3x;
00041 private:
00042     Vector3x mCol[3];
00043 public:
00044     typedef scalar real;
00045     Matrix3x3(){}
00046     static const Matrix3x3& zero() {
00047         static Matrix3x3 zero_(
00048             Vector3x::zero(),
00049             Vector3x::zero(),
00050             Vector3x::zero(),
00051             COLUMNS()
00052         );
00053         return zero_;
00054     }
00055     static const Matrix3x3& identity() {
00056         static Matrix3x3 identity (Vector3x::unitX(),
00057                                    Vector3x::unitY(),
00058                                    Vector3x::unitZ(),
00059                                    COLUMNS());
00060         return identity;
00061     }
00062     Matrix3x3(const Vector3x&col1, const Vector3x&col2, const Vector3x&col3, COLUMNS c){
00063         setCol(0,col1);
00064         setCol(1,col2);
00065         setCol(2,col3);
00066     }
00067     Matrix3x3(const Vector3x&row1, const Vector3x&row2, const Vector3x&row3, ROWS r){
00068         setRow(0,row1);
00069         setRow(1,row2);
00070         setRow(2,row3);
00071     }
00072     const Vector3x& getCol(unsigned int which) const {
00073         assert(which<3);
00074         return mCol[which];
00075     }
00076     void setCol(unsigned int which,const Vector3x &col) {
00077         assert(which<3);
00078         mCol[which]=col;
00079     }
00080     Vector3x getRow(unsigned int which) const {
00081         assert(which<3);
00082         return Vector3x(mCol[0][which],
00083             mCol[1][which],
00084             mCol[2][which]);
00085     }
00086     void setRow(unsigned int which, const Vector3x &row) {
00087         assert(which<3);
00088         mCol[0][which]=row[0];
00089         mCol[1][which]=row[1];
00090         mCol[2][which]=row[2];
00091     }
00092     scalar&operator() (unsigned int row, unsigned int column) {
00093         return mCol[column][row];
00094     }
00095     scalar operator() (unsigned int row, unsigned int column) const{
00096         return mCol[column][row];
00097     }
00098     template <typename T> Vector3<T> operator *(const Vector3<T>&other)const {
00099         return mCol[0]*other.x+mCol[1]*other.y+mCol[2]*other.z;
00100     }
00101     Matrix3x3 operator *(scalar other)const {
00102         return Matrix3x3(getCol(0)*other,getCol(1)*other,getCol(2)*other,COLUMNS());
00103     }
00104     Matrix3x3 operator /(scalar other)const {
00105         return Matrix3x3(getCol(0)/other,getCol(1)/other,getCol(2)/other,COLUMNS());
00106     }
00107     bool operator == (const Matrix3x3&other)const{
00108         return getCol(0)==other.getCol(0)&&getCol(1)==other.getCol(1)&&getCol(2)==other.getCol(2);
00109     }
00110     bool operator != (const Matrix3x3&other)const{
00111         return getCol(0)!=other.getCol(0) || getCol(1)!=other.getCol(1) || getCol(2)!=other.getCol(2);
00112     }
00113     Matrix3x3 operator+ (const Matrix3x3&other)const {
00114         return Matrix3x3(getCol(0)+other.getCol(0),
00115                        getCol(1)+other.getCol(1),
00116                        getCol(2)+other.getCol(2),
00117                        COLUMNS());
00118     }
00119     Matrix3x3 operator- (const Matrix3x3&other)const {
00120         return Matrix3x3(getCol(0)-other.getCol(0),
00121                        getCol(1)-other.getCol(1),
00122                        getCol(2)-other.getCol(2),
00123                        COLUMNS());
00124     }
00125     Matrix3x3 operator- ()const {
00126         return Matrix3x3(-getCol(0),
00127                        -getCol(1),
00128                        -getCol(2),
00129                        COLUMNS());
00130     }
00131     Matrix3x3& operator+= (const Matrix3x3&other) {
00132         mCol[0]+=other.getCol(0);
00133         mCol[1]+=other.getCol(1);
00134         mCol[2]+=other.getCol(2);
00135         return *this;
00136     }
00137     Matrix3x3& operator-= (const Matrix3x3&other) {
00138         mCol[0]-=other.getCol(0);
00139         mCol[1]-=other.getCol(1);
00140         mCol[2]-=other.getCol(2);
00141         return *this;
00142     }
00143     Matrix3x3 operator* (const Matrix3x3&other)const {
00144         Vector3<scalar> ocol0=other.getCol(0);
00145         Vector3<scalar> ocol1=other.getCol(1);
00146         Vector3<scalar> ocol2=other.getCol(2);
00147         return Matrix3x3(mCol[0]*ocol0.x+mCol[1]*ocol0.y+mCol[2]*ocol0.z,
00148                          mCol[0]*ocol1.x+mCol[1]*ocol1.y+mCol[2]*ocol1.z,
00149                          mCol[0]*ocol2.x+mCol[1]*ocol2.y+mCol[2]*ocol2.z,
00150                          COLUMNS());
00151     }
00152     Matrix3x3& operator*= (const Matrix3x3&other) {
00153         Vector3<scalar> ocol0=other.getCol(0);
00154         Vector3<scalar> ocol1=other.getCol(1);
00155         Vector3<scalar> ocol2=other.getCol(2);
00156         //cannot do this *= inplace
00157         ocol0=mCol[0]*ocol0.x+mCol[1]*ocol0.y+mCol[2]*ocol0.z;
00158         ocol1=mCol[0]*ocol1.x+mCol[1]*ocol1.y+mCol[2]*ocol1.z;
00159         ocol2=mCol[0]*ocol2.x+mCol[1]*ocol2.y+mCol[2]*ocol2.z;
00160         //have to copy back
00161         mCol[0]=ocol0;
00162         mCol[1]=ocol1;
00163         mCol[2]=ocol2;
00164         return *this;
00165     }
00166     Matrix3x3& operator*= (scalar other) {
00167         mCol[0]*=other;
00168         mCol[1]*=other;
00169         mCol[2]*=other;
00170         return *this;
00171     }
00172     Matrix3x3& operator/= (scalar other) {
00173         mCol[0]/=other;
00174         mCol[1]/=other;
00175         mCol[2]/=other;
00176         return *this;
00177     }
00178     Matrix3x3 transpose() const {
00179         return Matrix3x3(getCol(0),
00180                       getCol(1),
00181                       getCol(2),
00182                       ROWS());
00183     }
00184     Matrix3x3 inverse() const
00185     {
00186         Matrix3x3 inverted;
00187         inverted.setRow(0, Vector3x(
00188                 (*this)(1,1)*(*this)(2,2) - (*this)(1,2)*(*this)(2,1),
00189                 (*this)(0,2)*(*this)(2,1) - (*this)(0,1)*(*this)(2,2),
00190                 (*this)(0,1)*(*this)(1,2) - (*this)(0,2)*(*this)(1,1)));
00191         inverted.setRow(1, Vector3x(
00192                 (*this)(1,2)*(*this)(2,0) - (*this)(1,0)*(*this)(2,2),
00193                 (*this)(0,0)*(*this)(2,2) - (*this)(0,2)*(*this)(2,0),
00194                 (*this)(0,2)*(*this)(1,0) - (*this)(0,0)*(*this)(1,2)));
00195         inverted.setRow(2, Vector3x(
00196                 (*this)(1,0)*(*this)(2,1) - (*this)(1,1)*(*this)(2,0),
00197                 (*this)(0,1)*(*this)(2,0) - (*this)(0,0)*(*this)(2,1),
00198                 (*this)(0,0)*(*this)(1,1) - (*this)(0,1)*(*this)(1,0)));
00199 
00200         scalar fDet =
00201             (*this)(0,0)*inverted(0,0) +
00202             (*this)(0,1)*inverted(1,0)+
00203             (*this)(0,2)*inverted(2,0);
00204 
00205         scalar fInvDet = ((scalar)1.0)/fDet;
00206         for (size_t iRow = 0; iRow < 3; iRow++)
00207             for (size_t iCol = 0; iCol < 3; iCol++)
00208                 inverted(iRow,iCol) *= fInvDet;
00209 
00210         return inverted;
00211     }
00212     Matrix3x3 inverseTranspose() const {
00213         return inverse().transpose();
00214     }
00216     double determinant() const {
00217         return mCol[0].x*(double)mCol[1].y*mCol[2].z-
00218                mCol[0].x*(double)mCol[2].y*mCol[1].z +
00219                mCol[1].x*(double)mCol[2].y*mCol[0].z -
00220                mCol[1].x*(double)mCol[0].y*mCol[2].z +
00221                mCol[2].x*(double)mCol[0].y*mCol[1].z -
00222                mCol[2].x*(double)mCol[1].y*mCol[0].z;
00223     }
00224     std::string toString() const {
00225         std::ostringstream os;
00226         os<<"{ col1:"<<mCol[0]<<" col2:"<<mCol[1]<<" col3:"<<mCol[2]<<'}';
00227         return os.str();
00228     }
00229 };
00230 template<typename scalar> inline std::ostream& operator <<(std::ostream& os, const Matrix3x3<scalar> &rhs) {
00231     os<<"{ col1:"<<rhs.getCol(0)<<" col2:"<<rhs.getCol(1)<<" col3:"<<rhs.getCol(2)<<'}';
00232     return os;
00233 }
00234 
00235 template <typename T,typename S> Vector3<T> operator *(const Vector3<T>&vec, const Matrix3x3<S>&mat) {
00236     return Vector3<T>(mat.getCol(0).dot(vec),
00237                       mat.getCol(1).dot(vec),
00238                       mat.getCol(2).dot(vec));
00239 }
00240 template <typename T> Matrix3x3<T> operator *(T other, const Matrix3x3<T>&mat) {
00241     return Matrix3x3<T>(mat.getCol(0)*other,mat.getCol(1)*other,mat.getCol(2)*other,COLUMNS());
00242 }
00243 template <typename T> Matrix3x3<T> operator /(T other, const Matrix3x3<T>&mat) {
00244     return Matrix3x3<T>(other/mat.getCol(0),other/mat.getCol(1),other/mat.getCol(2),COLUMNS());
00245 }
00246 
00247 typedef Matrix3x3<float32> Matrix3x3f;
00248 typedef Matrix3x3<float64> Matrix3x3d;
00249 
00250 }
00251 #endif