TooN: gauss_jordan.h Source File

TooN 2.0.0-beta8

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List

gauss_jordan.h

    00001 // -*- c++ -*-
    00002
    00003 //    Copyright (C) 2009 Ed Rosten (er258@cam.ac.uk)
    00004 //
    00005 // This file is part of the TooN Library.  This library is free
    00006 // software; you can redistribute it and/or modify it under the
    00007 // terms of the GNU General Public License as published by the
    00008 // Free Software Foundation; either version 2, or (at your option)
    00009 // any later version.
    00010
    00011 // This library is distributed in the hope that it will be useful,
    00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00014 // GNU General Public License for more details.
    00015
    00016 // You should have received a copy of the GNU General Public License along
    00017 // with this library; see the file COPYING.  If not, write to the Free
    00018 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
    00019 // USA.
    00020
    00021 // As a special exception, you may use this file as part of a free software
    00022 // library without restriction.  Specifically, if other files instantiate
    00023 // templates or use macros or inline functions from this file, or you compile
    00024 // this file and link it with other files to produce an executable, this
    00025 // file does not by itself cause the resulting executable to be covered by
    00026 // the GNU General Public License.  This exception does not however
    00027 // invalidate any other reasons why the executable file might be covered by
    00028 // the GNU General Public License.
    00029
    00030
    00031 #ifndef TOON_INC_GAUSS_JORDAN_H
    00032 #define TOON_INC_GAUSS_JORDAN_H
    00033
    00034 #include <utility>
    00035 #include <cmath>
    00036 #include <TooN/TooN.h>
    00037
    00038 namespace TooN
    00039 {
    00040 /// Perform Gauss-Jordan reduction on m
    00041 ///
    00042 /// If m is of the form \f$[A | I ]\f$, then after reduction, m
    00043 /// will be \f$[ I | A^{-1}]\f$. There is no restriction on the input,
    00044 /// in that the matrix augmenting A does not need to be I, or square.
    00045 /// The reduction is performed using elementary row operations and
    00046 /// partial pivoting.
    00047 ///
    00048 /// @param m The matrix to be reduced.
    00049 /// @ingroup gDecomps
    00050 template<int R, int C, class Precision, class Base> void gauss_jordan(Matrix<R, C, Precision, Base>& m)
    00051 {
    00052     using std::swap;
    00053
    00054     //Loop over columns to reduce.
    00055     for(int col=0; col < m.num_rows(); col++)
    00056     {
    00057         //Reduce the current column to a single element
    00058
    00059
    00060         //Search down the current column in the lower triangle for the largest
    00061         //absolute element (pivot).  Then swap the pivot row, so that the pivot
    00062         //element is on the diagonal. The benchmarks show that it is actually
    00063         //faster to swap whole rows than it is to access the rows via indirection
    00064         //and swap the indirection element. This holds for both pointer indirection
    00065         //and using a permutation vector over rows.
    00066         {
    00067           using std::abs;
    00068             int pivotpos = col;
    00069             double pivotval = abs(m[pivotpos][col]);
    00070             for(int p=col+1; p <m.num_rows(); p++)
    00071               if(abs(m[p][col]) > pivotval)
    00072                 {
    00073                     pivotpos = p;
    00074                     pivotval = abs(m[pivotpos][col]);
    00075                 }
    00076
    00077             if(col != pivotpos)
    00078                 for(int c=0; c < m.num_cols(); c++)
    00079                     swap(m[col][c], m[pivotpos][c]);
    00080         }
    00081
    00082         //Reduce the current column in every row to zero, excluding elements on
    00083         //the leading diagonal.
    00084         for(int row = 0; row < m.num_rows(); row++)
    00085         {
    00086             if(row != col)
    00087             {
    00088                 double multiple = m[row][col] / m[col][col];
    00089
    00090                 //We could eliminate some of the computations in the augmented
    00091                 //matrix, if the augmented half is the identity. In general, it
    00092                 //is not.
    00093
    00094                 //Subtract the pivot row from all other rows, to make
    00095                 //column col zero.
    00096                 m[row][col] = 0;
    00097                 for(int c=col+1; c < m.num_cols(); c++)
    00098                     m[row][c] = m[row][c] - m[col][c] * multiple;
    00099             }
    00100         }
    00101     }
    00102
    00103     //Final pass to make diagonal elements one. Performing this in a final
    00104     //pass allows us to avoid any significant computations on the left-hand
    00105     //square matrix, since it is diagonal, and ends up as the identity.
    00106     for(int row=0;row < m.num_rows(); row++)
    00107     {
    00108         double mul = 1/m[row][row];
    00109
    00110         m[row][row] = 1;
    00111
    00112         for(int col=m.num_rows(); col < m.num_cols(); col++)
    00113             m[row][col] *= mul;
    00114     }
    00115 }
    00116
    00117 }
    00118 #endif