Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

matrix.cpp

Go to the documentation of this file.
00001 /*
00002     Sheep - A Rigid Body Dynamics Engine
00003     Copyright (C) 2001-2004 Francois Beaune
00004     Contact: http://toxicengine.sourceforge.net/
00005 
00006     This file is part of Sheep.
00007 
00008     Sheep is free software; you can redistribute it and/or modify
00009     it under the terms of the GNU General Public License as published by
00010     the Free Software Foundation; either version 2 of the License, or
00011     (at your option) any later version.
00012 
00013     Sheep 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
00016     GNU General Public License for more details.
00017 
00018     You should have received a copy of the GNU General Public License
00019     along with Sheep; if not, write to the Free Software
00020     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021 */
00022 
00023 #include "matrix.h" // include first
00024 
00025 #include <iostream>
00026 
00027 using namespace sheep;
00028 
00029 using std::endl;
00030 
00031 Matrix Matrix::operator*(const Matrix &m) const {
00032     assert(m_c == m.m_r);
00033 
00034     //!\todo Optimize.
00035 
00036     Matrix res(m_r, m.m_c);
00037 
00038     Real *v = res.m_v;
00039 
00040     for(int i = 0; i < m_r; i++)
00041         for(int j = 0; j < m.m_c; j++) {
00042             Real sum = 0;
00043 
00044             for(int k = 0; k < m_c; k++)
00045                 sum += operator()(i, k) * m(k, j);
00046 
00047             *(v++) = sum;
00048         }
00049 
00050     return res;
00051 }
00052 
00053 Vector Matrix::operator*(const Vector &v) const {
00054     assert(m_c == v.GetDimension());
00055 
00056     Vector res(m_r);
00057 
00058     for(int i = 0; i < m_r; i++) {
00059         Real sum = 0;
00060 
00061         for(int j = 0; j < m_c; j++)
00062             sum += operator()(i, j) * v[j];
00063 
00064         res[i] = sum;
00065     }
00066 
00067     return res;
00068 }
00069 
00070 Matrix Matrix::Transpose() const {
00071     Matrix res(m_c, m_r);
00072 
00073     Real *u = m_v;
00074 
00075     for(int i = 0; i < m_r; i++) {
00076         Real *v = res.m_v + i;
00077 
00078         for(int j = 0; j < m_c; j++, v += m_r)
00079             *v = *(u++);
00080     }
00081 
00082     return res;
00083 }
00084 
00085 Matrix Matrix::Inverse() const {
00086     assert(m_r == m_c);
00087 
00088     Matrix res = *this;
00089 
00090     int i,j,k;
00091                     /* Locations of pivot elements */
00092     int *pvt_i, *pvt_j;
00093     double pvt_val;                     /* Value of current pivot element */
00094     double hold;                        /* Temporary storage */
00095 
00096     pvt_i = new int[m_r];
00097     pvt_j = new int[m_r];
00098 
00099     for (k = 0; k < m_r; k++)
00100     {
00101         /* Locate k'th pivot element */
00102         pvt_val = res(k,k);            /* Initialize for search */
00103         pvt_i[k] = k;
00104         pvt_j[k] = k;
00105         for(i = k; i < m_r; i++)
00106             for(j = k; j < m_r; j++)
00107                 if(fabs(res(i,j)) > fabs(pvt_val)) {
00108                     pvt_i[k] = i;
00109                     pvt_j[k] = j;
00110                     pvt_val = res(i,j);
00111                 }
00112 
00113         if(pvt_val==0) {
00114             /* Matrix is singular (zero determinant). */
00115             delete [] pvt_i;
00116             delete [] pvt_j;
00117             assert(!"Matrix is singular.");
00118         }
00119 
00120         /* "Interchange" rows (with sign change stuff) */
00121         i = pvt_i[k];
00122         if (i != k)                     /* If rows are different */
00123             for (j = 0; j < m_r; j++)
00124             {
00125                 hold = -res(k,j);
00126                 res(k,j) = res(i,j);
00127                 res(i,j) = hold;
00128             }
00129 
00130         /* "Interchange" columns */
00131         j = pvt_j[k];
00132         if (j != k)                     /* If columns are different */
00133             for (i = 0; i < m_r; i++)
00134             {
00135                 hold = -res(i,k);
00136                 res(i,k) = res(i,j);
00137                 res(i,j) = hold;
00138             }
00139 
00140         /* Divide column by minus pivot value */
00141         for (i = 0; i < m_r; i++)
00142             if (i != k)                   /* Don't touch the pivot entry */
00143                 res(i,k) /= ( -pvt_val) ;  /* (Tricky C syntax for division) */
00144 
00145         /* Reduce the matrix */
00146         for (i = 0; i < m_r; i++)
00147         {
00148             hold = res(i,k);
00149             for (j = 0; j < m_r; j++)
00150                 if ( i != k && j != k )   /* Don't touch pivot. */
00151                     res(i,j) += hold * res(k,j);
00152         }
00153 
00154         /* Divide row by pivot */
00155         for (j = 0; j < m_r; j++)
00156             if (j != k)                   /* Don't touch the pivot! */
00157                 res(k,j) /= pvt_val;
00158 
00159         /* Replace pivot by reciprocal (at last we can touch it). */
00160         res(k,k) = 1.0/pvt_val;
00161     }
00162 
00163     /* That was most of the work, one final pass of row/column interchange */
00164     /* to finish */
00165     for (k = m_r-2; k >= 0; k--)  /* Don't need to work with 1 by 1 corner */
00166     {
00167         i = pvt_j[k];        /* Rows to swap correspond to pivot COLUMN */
00168         if (i != k)                     /* If rows are different */
00169             for(j = 0; j < m_r; j++)
00170             {
00171                 hold = res(k,j);
00172                 res(k,j) = -res(i,j);
00173                 res(i,j) = hold;
00174             }
00175 
00176         j = pvt_i[k];           /* Columns to swap correspond to pivot ROW */
00177         if (j != k)                     /* If columns are different */
00178             for (i = 0; i < m_r; i++)
00179             {
00180                 hold = res(i,k);
00181                 res(i,k) = -res(i,j);
00182                 res(i,j) = hold;
00183             }
00184     }
00185 
00186     delete [] pvt_i;
00187     delete [] pvt_j;
00188 
00189     return res;
00190 }
00191 
00192 Real Matrix::Determinant() const {
00193     assert(m_r == m_c);
00194 
00195     //!\todo Implement.
00196 
00197     return 0;
00198 }
00199 
00200 htmlstream &operator<<(htmlstream &s, const Matrix &m) {
00201     s << "<table border=\"1\">" << endl;
00202 
00203     for(int i = 0; i < m.GetRows(); ++i) {
00204         s << "<tr>" << endl;
00205 
00206         for(int j = 0; j < m.GetColumns(); ++j) {
00207             s << "<td>" << m(i, j) << "</td>" << endl;
00208         }
00209 
00210         s << "</tr>" << endl;
00211     }
00212 
00213     s << "</table>" << endl;
00214 
00215     return s;
00216 }

Generated on Tue May 11 01:31:50 2004 for toxic by doxygen 1.3.6