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

Tools/Math/Matrix_nxn.h

Go to the documentation of this file.
00001 /**
00002 * @file Matrix_nxn.h
00003 * Contains class Matrix_nxn
00004 *
00005 * @author <a href="mailto:stefanuhrig@gmx.net">Stefan Uhrig</a>
00006 */
00007 //------------------------------------------------------------------------------
00008 #ifndef MATRIX_NXN_H_INCLUDED
00009 #define MATRIX_NXN_H_INCLUDED
00010 //------------------------------------------------------------------------------
00011 #define MATRIX_NXN_HEAP
00012 //------------------------------------------------------------------------------
00013 
00014 #ifdef _WIN32
00015 #pragma warning(disable:4786) 
00016 // The VC6 compiler produced the uncritical warning 4786 (too long debug identifier)
00017 #endif
00018 
00019 #include "MVTools.h"
00020 #include "Vector_n.h"
00021 //------------------------------------------------------------------------------
00022 // Ensure that memory version (use stack or heap) ist defined
00023 #if !defined(MATRIX_NXN_STACK) && !defined(MATRIX_NXN_HEAP)
00024 #error Define MATRIX_NXN_STACK if you'd like Matrix_nxn to use stack memory or \
00025 MATRIX_NXN_HEAP if you'd like Matrix_nxn to use heap memory!
00026 #endif
00027 //------------------------------------------------------------------------------
00028 // Forward-Deklarationen
00029 //------------------------------------------------------------------------------
00030 template <class T, size_t N>
00031 class Matrix_nxn;
00032 template<class T, size_t N>
00033 Matrix_nxn<T, N> operator*(const Matrix_nxn<T, N>& m1,
00034                            const Matrix_nxn<T, N>& m2);
00035 //------------------------------------------------------------------------------
00036 /**
00037 * @class Matrix_nxn
00038 * Represents a nxn matrix of type T
00039 *
00040 * Matrix_nxn represents a nxn matrix of type T. The class supplies
00041 * standard arithmetic operations.
00042 */
00043 template <class T, size_t N>
00044 class Matrix_nxn
00045 {
00046 public:
00047   //----------------------------------------------------------------------------
00048   /**
00049   * Standard constructor
00050   *
00051   * Initializes the matrix with values supplied by the standard constructor
00052   * of T.
00053   *
00054   * Complexity: n^2
00055   */
00056   Matrix_nxn()
00057   {
00058 #ifdef MATRIX_NXN_HEAP
00059     content = new Vector_n<T, N>[N];
00060 #endif
00061     
00062     Vector_n<T, N>* init = content;
00063     Vector_n<T, N> zero = Vector_n<T, N>();
00064     for (size_t i = 0; i < N; ++i, ++init)
00065       *init = zero;
00066   }
00067   //----------------------------------------------------------------------------
00068   /**
00069   * Constructor that initializes the matrix with the values in the passed array
00070   * @param v Array with initialization values
00071   *
00072   * Complexity: n^2
00073   */
00074   Matrix_nxn(const T* v)
00075   {
00076 #ifdef MATRIX_NXN_HEAP
00077     content = new Vector_n<T, N>[N];
00078 #endif
00079     
00080     Vector_n<T, N>* init = content;
00081     for (size_t i = 0; i < N; ++i, ++init, v+=N)
00082       *init = Vector_n<T, N>(v);
00083   }
00084   //----------------------------------------------------------------------------
00085   /** 
00086   * Copy constructor
00087   * @param m Matrix to copy
00088   *
00089   * Complexity: n^2
00090   */
00091   Matrix_nxn(const Matrix_nxn<T, N>& m)
00092   {
00093 #ifdef MATRIX_NXN_HEAP
00094     content = new Vector_n<T, N>[N];
00095 #endif
00096     
00097     *this = m;
00098   }
00099   //----------------------------------------------------------------------------
00100   /**
00101   * Destructor
00102   *
00103   * Complexity: n^2
00104   */
00105   ~Matrix_nxn()
00106   {
00107 #ifdef MATRIX_NXN_HEAP
00108     delete [] content;
00109 #endif
00110   }
00111   //----------------------------------------------------------------------------
00112   /**
00113   * Copy operator
00114   * @param m Matrix to copy
00115   *
00116   * Complexity: n^2
00117   */
00118   Matrix_nxn<T, N>& operator=(const Matrix_nxn<T, N>& m)
00119   {
00120     for (size_t i = 0; i < N; ++i)
00121       content[i] = m.content[i];
00122     return *this;
00123   }
00124   //----------------------------------------------------------------------------
00125   /**
00126   * Copy operator
00127   * @param m Array with values to assign to this matrix
00128   *
00129   * Complexity: n^2
00130   */
00131   Matrix_nxn<T, N>& operator=(const T* m)
00132   {
00133     for (size_t i = 0; i < N; ++i)
00134       for (size_t j = 0; j <N; ++j, ++m)
00135         content[i][j] = *m;
00136       return *this;
00137   }
00138   //----------------------------------------------------------------------------
00139   /**
00140   * Copies contents of matrix to passed array
00141   * @param m Array the values are stored to
00142   *
00143   * Complexity: n^2
00144   */
00145   void copyTo(T* m) const
00146   {
00147     const Vector_n<T, N>* con = content;
00148     for (size_t i = 0; i < N; ++i, m+=N, ++con)
00149       con->copyTo(m);
00150   }
00151   //----------------------------------------------------------------------------
00152   /**
00153   * Constant row vector access operator
00154   * @param i Index of row vector to access (first row vector has index 0)
00155   * @return Constant reference to row vector
00156   *
00157   * Complexity: 1
00158   */
00159   const Vector_n<T, N>& operator[](size_t i) const
00160   {
00161     return content[i];
00162   }
00163   //----------------------------------------------------------------------------
00164   /**
00165   * Row vector access operator
00166   * @param i Index of row vector to access (first row vector has index 0)
00167   * @return Reference to row vector
00168   *
00169   * Complexity: 1
00170   */
00171   Vector_n<T, N>& operator[](size_t i)
00172   {
00173     return content[i];
00174   }
00175   //----------------------------------------------------------------------------
00176   /**
00177   * Operator +=
00178   * @param m Matrix to add
00179   *
00180   * Complexity: n^2
00181   */
00182   Matrix_nxn<T, N>& operator+=(const Matrix_nxn<T, N>& m)
00183   {
00184     for (size_t i = 0; i < N; ++i)
00185       content[i] += m.content[i];
00186     return *this;
00187   }
00188   //----------------------------------------------------------------------------
00189   /**
00190   * Operator -=
00191   * @param m Matrix to subtract
00192   *
00193   * Complexity: n^2
00194   */
00195   Matrix_nxn<T, N>& operator-=(const Matrix_nxn<T, N>& m)
00196   {
00197     for (size_t i = 0; i < N; ++i)
00198       content[i] -= m.content[i];
00199     return *this;
00200   }
00201   //----------------------------------------------------------------------------
00202   /**
00203   * Operator *=
00204   * @param m Matrix this matrix is to multiplied with
00205   *
00206   * Complexity: n^3
00207   */
00208   Matrix_nxn<T, N>& operator*=(const Matrix_nxn<T, N>& m)
00209   {
00210     *this = *this * m;
00211     return *this;
00212   }
00213   //----------------------------------------------------------------------------
00214   /**
00215   * Operator /=
00216   * @param m Matrix this matrix is to divided by
00217   *
00218   * Complexity: n^3
00219   */
00220   Matrix_nxn<T, N>& operator/=(const Matrix_nxn<T, N>& m)
00221   {
00222     *this = *this / m;
00223     return *this;
00224   }
00225   //----------------------------------------------------------------------------
00226   /**
00227   * Transposes this matrix
00228   */
00229   Matrix_nxn<T, N> transpose()
00230   {
00231     //template<class T, size_t N>
00232     Matrix_nxn<T, N> res;
00233     for (size_t i = 0; i < N; ++i)
00234       for (size_t j = 0; j < N; ++j)
00235         res[i][j] = (*this)[j][i];
00236       return res;
00237   }
00238   //------------------------------------------------------------------------------
00239   /**
00240   * Inverts this matrix. Matrix must not be singular
00241   * @return Inverted matrix
00242   */
00243   Matrix_nxn<T, N> invert()
00244   {
00245     Matrix_nxn<T, N> left(*this);
00246     Matrix_nxn<T, N> right(Matrix_nxn::identity());
00247     Vector_n<int, N> ranking;
00248 
00249     int i;
00250     for (i = 0; i < (int)N; ++i) 
00251     {
00252        ranking[i] = i;
00253     }
00254     
00255     T zero = T();
00256     int r, r2, maxrow;
00257     for (r = 0; r < (int)(N-1); ++r)
00258     {
00259       // find highest value
00260       T maxval = left[ranking[r]][r];
00261       maxrow = r;
00262       if (maxval < zero)
00263         maxval = -maxval;
00264       for (r2 = r+1; r2 < (int)N; ++r2)
00265       {
00266         T val = left[ranking[r2]][r];
00267         if (val < zero)
00268           val = -val;
00269         if (val > maxval)
00270         {
00271           maxval = val;
00272           maxrow = r2;
00273         }
00274       }
00275       
00276       // swap rows
00277       int temp = ranking[r];
00278       ranking[r] = ranking[maxrow];
00279       ranking[maxrow] = temp;
00280       
00281       if (MVTools::isNearZero(left[ranking[r]][r]))
00282       {
00283         if (MVTools::isNearNegZero(left[ranking[r]][r]))
00284           throw MVException(MVException::DivByNegZero);
00285         else
00286           throw MVException(MVException::DivByPosZero);
00287       }
00288       
00289       for (r2 = r+1; r2 < (int)N; ++r2)
00290       {
00291         // calc factor for subtracting
00292         T factor = left[ranking[r2]][r] / left[ranking[r]][r];
00293         if (MVTools::isNearInf(factor))
00294         {
00295           if (MVTools::isNearPosInf(factor))
00296             throw MVException(MVException::PosInfValue);
00297           else
00298             throw MVException(MVException::NegInfValue);
00299         }
00300         
00301         // change left matrix
00302         left[ranking[r2]] -= factor*left[ranking[r]];
00303         
00304         // change right matrix
00305         right[ranking[r2]] -= factor*right[ranking[r]];
00306       }
00307     }
00308     
00309     // matrix has triangle form
00310     // bring to diagonal form
00311     for (r = (int)(N-1); r > 0; --r)
00312     {
00313       if (MVTools::isNearZero(left[ranking[r]][r]))
00314       {
00315         if (MVTools::isNearNegZero(left[ranking[r]][r]))
00316           throw MVException(MVException::DivByNegZero);
00317         else
00318           throw MVException(MVException::DivByPosZero);
00319       }
00320       for (r2 = r-1; r2 >= 0; --r2)
00321       {
00322         T factor = left[ranking[r2]][r] / left[ranking[r]][r];
00323         if (MVTools::isNearInf(factor))
00324         {
00325           if (MVTools::isNearPosInf(factor))
00326             throw MVException(MVException::PosInfValue);
00327           else
00328             throw MVException(MVException::NegInfValue);
00329         }
00330         
00331         // change left matrix
00332         left[ranking[r2]] -= factor*left[ranking[r]];
00333         
00334         // change right matrix
00335         right[ranking[r2]] -= factor*right[ranking[r]];
00336       }
00337     }
00338     
00339     // matrix has diagonal form
00340     // set entries of left matrix to 1 and apply multiplication to right
00341     Matrix_nxn<T, N> res;
00342     for (r = 0; r < (int)N; ++r)
00343     {
00344       res[r] = right[ranking[r]];
00345       
00346       if (MVTools::isNearZero(left[ranking[r]][r]))
00347       {
00348         if (MVTools::isNearNegZero(left[ranking[r]][r]))
00349           throw MVException(MVException::DivByNegZero);
00350         else
00351           throw MVException(MVException::DivByPosZero);
00352       }
00353       res[r] /= left[ranking[r]][r];
00354     }
00355     
00356     return res;
00357   }  
00358   //------------------------------------------------------------------------------
00359   /**
00360   * Inverts this matrix. Matrix must not be singular
00361   * @return Inverted matrix
00362   */
00363   Matrix_nxn<T, N> invert2()
00364   {
00365     Matrix_nxn<T, N> res;
00366     for (size_t i = 0; i < N; ++i)
00367     {
00368       Vector_n<T, N> e;
00369       e[i] = (T)1;
00370       res[i] = *this.solve(e);
00371     }
00372     return res.transpose();
00373   }
00374   //----------------------------------------------------------------------------
00375   /**
00376   * Solves the system A*x=b where A is the actual matrix
00377   * @param b Vector b
00378   * @return Solution x
00379   *
00380   * Complexity: n^3
00381   *
00382   */
00383   Vector_n<T, N> solve(Vector_n<T, N> b) const
00384   {
00385     // create copy of actual matrix
00386     Matrix_nxn<T, N> m(*this);
00387     
00388     // initialize ranking vector
00389     Vector_n<int, N> ranking;
00390     size_t i;
00391     for (i = 0; i < N; ++i)
00392       ranking[i] = i;
00393     
00394     T z = T();
00395     int c;
00396     int r;
00397     for (c = 0; c < (int)N-1; ++c)
00398     {
00399       // find row containing highest value
00400       int maxRow = c;
00401       T maxValue = m[ranking[maxRow]][c];
00402       if (maxValue < z)
00403         maxValue = -maxValue;
00404       for (r = c+1; r < (int)N; ++r)
00405       {
00406         T value = m[ranking[r]][c];
00407         if (value < z)
00408           value = -value;
00409         if (value > maxValue)
00410         {
00411           maxRow = r;
00412           maxValue = value;
00413         }
00414       }
00415       
00416       // if maximum value zero --> matrix is singular
00417       if (MVTools::isNearZero(maxValue))
00418       {
00419         if (MVTools::isNearNegZero(maxValue))
00420           throw MVException(MVException::DivByNegZero);
00421         else
00422           throw MVException(MVException::DivByPosZero);
00423       }
00424       /*
00425       if (maxValue == z)
00426       return Vector_n<T, N>();
00427       */
00428       
00429       // swap rows in ranking
00430       int temp = ranking[c];
00431       ranking[c] = ranking[maxRow];
00432       ranking[maxRow] = temp;
00433       
00434       // process all following rows
00435       for (r = c+1; r < (int)N; ++r)
00436       {
00437         // calc factor for subtracting
00438         T factor = m[ranking[r]][c] / m[ranking[c]][c];
00439         if (MVTools::isNearInf(factor))
00440         {
00441           if (MVTools::isNearPosInf(factor))
00442             throw MVException(MVException::PosInfValue);
00443           else
00444             throw MVException(MVException::NegInfValue);
00445         }
00446         
00447         T sub;
00448         sub = factor*b[ranking[c]];
00449         if (MVTools::isNearInf(sub))
00450         {
00451           if (MVTools::isNearPosInf(sub))
00452             throw MVException(MVException::PosInfValue);
00453           else
00454             throw MVException(MVException::NegInfValue);
00455         }
00456         
00457         // change vector b
00458         b[ranking[r]] -= sub;
00459         
00460         // change matrix
00461         m[ranking[r]][c] = T();
00462         for (int c2 = c+1; c2 < (int)N; ++c2)
00463         {
00464           sub = factor*m[ranking[c]][c2];
00465           if (MVTools::isNearInf(sub))
00466           {
00467             if (MVTools::isNearPosInf(sub))
00468               throw MVException(MVException::PosInfValue);
00469             else
00470               throw MVException(MVException::NegInfValue);
00471           }
00472           m[ranking[r]][c2] -= sub;
00473         }
00474       }
00475     }
00476     
00477     // if last entry of matrix zero --> matrix is singular
00478     if (MVTools::isNearZero(m[ranking[N-1]][N-1]))
00479     {
00480       if (MVTools::isNearNegZero(m[ranking[N-1]][N-1]))
00481         throw MVException(MVException::DivByNegZero);
00482       else
00483         throw MVException(MVException::DivByPosZero);
00484     }
00485     /*
00486     if (m[ranking[N-1]][N-1] == z)
00487     return Vector_n<T, N>();
00488     */
00489     
00490     // matrix has triangle form
00491     // calculate solutions
00492     b[ranking[N-1]] /= m[ranking[N-1]][N-1];
00493     for (r = N-2; r >= 0; --r)
00494     {
00495       T sum = T();
00496       for (c = r+1; c < (int)N; ++c)
00497         sum += m[ranking[r]][c] * b[ranking[c]];
00498       if (MVTools::isNearInf(sum))
00499       {
00500         if (MVTools::isNearPosInf(sum))
00501           throw MVException(MVException::PosInfValue);
00502         else
00503           throw MVException(MVException::NegInfValue);
00504       }
00505       
00506       if (MVTools::isNearZero(m[ranking[r]][r]))
00507       {
00508         if (MVTools::isNearNegZero(m[ranking[r]][r]))
00509           throw MVException(MVException::DivByNegZero);
00510         else
00511           throw MVException(MVException::DivByPosZero);
00512       }
00513       b[ranking[r]] = (b[ranking[r]] - sum) / m[ranking[r]][r];
00514       
00515       if (MVTools::isNearInf(b[ranking[r]]))
00516       {
00517         if (MVTools::isNearPosInf(b[ranking[r]]))
00518           throw MVException(MVException::PosInfValue);
00519         else
00520           throw MVException(MVException::NegInfValue);
00521       }
00522     }
00523     
00524     // create vector with correct order
00525     Vector_n<T, N> x;
00526     for (r = 0; r < (int)N; ++r)
00527       x[r] = b[ranking[r]];
00528     
00529     return x;
00530   }
00531   //----------------------------------------------------------------------------
00532   /**
00533   * Returns determinant of this matrix
00534   * @return determinant
00535   *
00536   * Complexity: n^3
00537   */
00538   T det() const
00539   {
00540     // create copy of actual matrix
00541     Matrix_nxn<T, N> m(*this);
00542     
00543     // initialize ranking vector
00544     Vector_n<int, N> ranking;
00545     size_t i;
00546     for (i = 0; i < N; ++i)
00547       ranking[i] = i;
00548     
00549     T z = T();
00550     bool bPositive = true;
00551     int c;
00552     int r;
00553     for (c = 0; c < (int)(N-1); ++c)
00554     {
00555       // find row containing highest value
00556       int maxRow = c;
00557       T maxValue = m[ranking[maxRow]][c];
00558       if (maxValue < z)
00559         maxValue = -maxValue;
00560       for (r = c+1; r < (int)N; ++r)
00561       {
00562         T value = m[ranking[r]][c];
00563         if (value < z)
00564           value = -value;
00565         if (value > maxValue)
00566         {
00567           maxRow = r;
00568           maxValue = value;
00569         }
00570       }
00571       
00572       // if maximum value zero --> determinant is zero
00573       if (MVTools::isNearZero(maxValue))
00574         return z;
00575         /*if (maxValue == z)
00576       return z;*/
00577       
00578       // swap rows in ranking
00579       if (c != maxRow)
00580       {
00581         int temp = ranking[c];
00582         ranking[c] = ranking[maxRow];
00583         ranking[maxRow] = temp;
00584         bPositive = !bPositive;
00585       }
00586       
00587       // process all following rows
00588       for (r = c+1; r < (int)N; ++r)
00589       {
00590         // calc factor for subtracting
00591         T factor = m[ranking[r]][c] / m[ranking[c]][c];
00592         if (MVTools::isNearInf(factor))
00593         {
00594           if (MVTools::isNearPosInf(factor))
00595             throw MVException(MVException::PosInfValue);
00596           else
00597             throw MVException(MVException::NegInfValue);
00598         }
00599         
00600         // change matrix
00601         m[ranking[r]][c] = T();
00602         for (int c2 = c+1; c2 < (int)N; ++c2)
00603         {
00604           m[ranking[r]][c2] -= factor*m[ranking[c]][c2];
00605           T sub;
00606           sub = factor*m[ranking[c]][c2];
00607           if (MVTools::isNearInf(sub))
00608           {
00609             if (MVTools::isNearPosInf(sub))
00610               throw MVException(MVException::PosInfValue);
00611             else
00612               throw MVException(MVException::NegInfValue);
00613           }
00614         }
00615       }
00616     }
00617     
00618     // if last entry of matrix zero --> determinant is zero
00619     if (MVTools::isNearZero(m[ranking[N-1]][N-1]))
00620       return z;
00621       /*if (m[ranking[N-1]][N-1] == z)
00622     return z;*/
00623     
00624     // matrix has triangle form
00625     // calculate determinant
00626     T res = m[ranking[0]][0];
00627     for (r = 1; r < (int)N; ++r)
00628     {
00629       res *= m[ranking[r]][r];
00630       if (MVTools::isNearInf(res))
00631       {
00632         if (MVTools::isNearPosInf(res))
00633           throw MVException(MVException::PosInfValue);
00634         else
00635           throw MVException(MVException::NegInfValue);
00636       }
00637     }    
00638     
00639     if (!bPositive)
00640       res = -res;
00641     return res;
00642   }
00643   //----------------------------------------------------------------------------
00644   /**
00645   * Returns the identity matrix with same dimensions like this matrix
00646   * @return nxn identity matrix
00647   */
00648   static Matrix_nxn<T, N> identity()
00649   {
00650     Matrix_nxn<T, N> res;
00651     for (size_t i = 0; i < N; ++i)
00652       res[i][i] = (T)1;
00653     return res;
00654   }
00655   //----------------------------------------------------------------------------
00656 private:
00657   /** The vectors holding the contents of the matrix */
00658 #if defined(MATRIX_NXN_HEAP)
00659   Vector_n<T, N>* content;
00660 #elif defined(MATRIX_NXN_STACK)
00661   Vector_n<T, N> content[N];
00662 #endif
00663 };
00664 //------------------------------------------------------------------------------
00665 /**
00666 * Operator + for matrix additions
00667 * @param m1 First matrix
00668 * @param m2 Second matrix
00669 * @return m1+m2
00670 *
00671 * Complexity: n^2
00672 */
00673 template<class T, size_t N>
00674 Matrix_nxn<T, N> operator+(const Matrix_nxn<T, N>& m1,
00675                            const Matrix_nxn<T, N>& m2)
00676 {
00677   Matrix_nxn<T, N> res(m1);
00678   res += m2;
00679   return res;
00680 }
00681 //------------------------------------------------------------------------------
00682 /**
00683 * Operator - for matrix subtractions
00684 * @param m1 First matrix
00685 * @param m2 Second matrix
00686 * @return m1-m2
00687 *
00688 * Complexity: n^2
00689 */
00690 template<class T, size_t N>
00691 Matrix_nxn<T, N> operator-(const Matrix_nxn<T, N>& m1,
00692                            const Matrix_nxn<T, N>& m2)
00693 {
00694   Matrix_nxn<T, N> res(m1);
00695   res -= m2;
00696   return res;
00697 }
00698 //------------------------------------------------------------------------------
00699 /**
00700 * Operator * for matrix-matrix multiplication
00701 * @param m1 First matrix
00702 * @param m2 Second matrix
00703 * @return m1*m2
00704 *
00705 * Complexity: n^3
00706 */
00707 template<class T, size_t N>
00708 Matrix_nxn<T, N> operator*(const Matrix_nxn<T, N>& m1,
00709                            const Matrix_nxn<T, N>& m2)
00710 {
00711   Matrix_nxn<T, N> res;
00712   size_t i, j, k;
00713   for (i = 0; i < N; ++i)
00714   {
00715     for (j = 0; j < N; ++j)
00716     {
00717       for (k = 0; k < N; ++k)
00718       {
00719         res[i][j] += m1[i][k] * m2[k][j];
00720       }
00721       if (MVTools::isNearInf(res[i][j]))
00722       {
00723         if (MVTools::isNearPosInf(res[i][j]))
00724           throw MVException(MVException::PosInfValue);
00725         else
00726           throw MVException(MVException::NegInfValue);
00727       }
00728     }
00729   }
00730   return res;
00731 }
00732 //------------------------------------------------------------------------------
00733 /**
00734 * Operator * for matrix-vector multiplication
00735 * @param m Matrix
00736 * @param v Vector
00737 * @return m*v
00738 *
00739 * Complexity: n^2
00740 */
00741 template<class T, size_t N>
00742 Vector_n<T, N> operator*(const Matrix_nxn<T, N>& m,
00743                          const Vector_n<T, N>& v)
00744 {
00745   Vector_n<T, N> res;
00746   for (size_t i = 0; i < N; ++i)
00747   {
00748     for (size_t j = 0; j < N; ++j)
00749     {
00750       res[i] += m[i][j]*v[j];
00751     }
00752     if (MVTools::isNearInf(res[i]))
00753     {
00754       if (MVTools::isNearPosInf(res[i]))
00755         throw MVException(MVException::PosInfValue);
00756       else
00757         throw MVException(MVException::NegInfValue);
00758     }
00759   }
00760   return res;
00761 }
00762 //------------------------------------------------------------------------------
00763 /**
00764 * Divides first matrix by second matrix (multiplicates with inverse of
00765 * second matrix).
00766 * @param m1 First matrix
00767 * @param m2 Second matrix
00768 * @return m1 & m2
00769 *
00770 * Complexity: n^3
00771 */
00772 template<class T, size_t N>
00773 Matrix_nxn<T, N> operator/(const Matrix_nxn<T, N>& m1,
00774                            const Matrix_nxn<T, N>& m2)
00775 {
00776   return m1*m2.invert();
00777 }
00778 //------------------------------------------------------------------------------
00779 #endif
00780 //------------------------------------------------------------------------------

Generated on Mon Mar 20 22:00:07 2006 for GT2005 by doxygen 1.3.6