pelib  2.0.0
include/pelib/Matrix.hpp
Go to the documentation of this file.
00001 /*
00002  Copyright 2015 Nicolas Melot
00003 
00004  This file is part of Pelib.
00005 
00006  Pelib is free software: you can redistribute it and/or modify
00007  it under the terms of the GNU General Public License as published by
00008  the Free Software Foundation, either version 3 of the License, or
00009  (at your option) any later version.
00010 
00011  Pelib 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
00017  along with Pelib. If not, see <http://www.gnu.org/licenses/>.
00018 */
00019 
00020 
00021 #include <iostream>
00022 #include <cstdlib>
00023 #include <fstream>
00024 #include <sstream>
00025 #include <string>
00026 #include <boost/regex.hpp>
00027 #include <iomanip>
00028 
00029 #include <pelib/AlgebraData.hpp>
00030 #include <pelib/PelibException.hpp>
00031 
00032 #ifndef PELIB_MATRIX
00033 #define PELIB_MATRIX
00034 
00035 namespace pelib
00036 {
00038         template <class Col, class Row, class Value>
00039         class Matrix: public AlgebraData
00040         {
00042                 typedef std::map<Col, Value> RowType;
00044                 typedef std::map<Row, RowType> MatrixType;
00045                 
00046                 public:
00048                         Matrix(const std::string name, const MatrixType values) : AlgebraData(name)
00049                         {
00050                                 this->values = values;
00051                         }
00052 
00054                         Matrix(const Matrix<Col, Row, Value>* matrix): AlgebraData(matrix->getName()), values(matrix->getValues())
00055                         {
00056                                 // Do nothing
00057                         }
00058 
00060                         virtual
00061                         Matrix*
00062                         clone() const
00063                         {
00064                                 return new Matrix<Col, Row, Value>(name, values);
00065                         }
00066 
00068                         virtual
00069                         const MatrixType&
00070                         getValues() const
00071                         {
00072                                 return values;
00073                         }
00074 
00076                         virtual
00077                         const Value&
00078                         find(Col col, Row row) const
00079                         {
00080                                 return values.find(row)->second.find(col)->second;
00081                         }
00082 
00084                         virtual
00085                         size_t
00086                         getColSize() const // /!\ This is the size of a column, i.e. the number of rows
00087                         {
00088                                 return values.size();
00089                         }
00090 
00092                         virtual
00093                         size_t
00094                         getRowSize() const // /!\ This is the size of a row, i.e. the number of columns
00095                         {
00096                                 return values.begin()->second.size();
00097                         }
00098 
00100                         virtual
00101                         Matrix<Row, Col, Value>
00102                         transpose() const
00103                         {
00104                                 std::map<Col, std::map<Row, Value> > new_values;
00105                                 for(typename MatrixType::const_iterator i = values.begin(); i != values.end(); i++)
00106                                 {
00107                                         for(typename RowType::const_iterator j = i->second.begin(); j != i->second.end(); j++)
00108                                         {
00109                                                 Value val = j->second;
00110                                                 new_values[j->first][i->first] = val;
00111                                         }
00112                                 }
00113 
00114                                 return Matrix<Row, Col, Value>(this->getName(), new_values);
00115                         }
00116                         
00117                         void
00118                         merge(const AlgebraData* ptr)
00119                         {
00120                                 // Only allow merging if both this and ptr are of same name, type and row size
00121                                 if(ptr->getName().compare(this->getName()) == 0 &&
00122                                         std::string(typeid(*ptr).name()).compare(typeid(Matrix<Col, Row, Value>).name()) == 0)
00123                                 {
00124                                         Matrix<Col, Row, Value> *matrix = (Matrix<Col, Row, Value>*)ptr;
00125                                         // Do some complex merge work if the matrix to merge actually has data to merge
00126                                         if(matrix->getValues().size() > 0 && matrix->getValues().begin()->second.size() > 0)
00127                                         {
00128                                                 // Only allow merge if this matrix is empty, or if not, 
00129                                                 // if both matrices are of same row size (same number of columns)
00130                                                 if (this->getValues().begin() == this->getValues().end() ||
00131                                                         this->getValues().begin()->second.size() == matrix->getValues().begin()->second.size())
00132                                                 {
00133                                                         // Take all rows of the new matrix and merge it with the rows of this matrix
00134                                                         for(typename MatrixType::iterator i = matrix->values.begin(); i != matrix->values.end(); i++)
00135                                                         {
00136                                                                 // If this row's key already exists in this matrix, then delete the existing row
00137                                                                 if(this->getValues().find(i->first) != this->getValues().end())
00138                                                                 {
00139                                                                         this->values.erase(this->values.find(i->first));
00140                                                                 }
00141 
00142                                                                 // Add the new row in this matrix
00143                                                                 this->values.insert(std::pair<Row, std::map<Col, Value> >(i->first, i->second));
00144                                                         }
00145                                                 }
00146                                                 else
00147                                                 {
00148                                                         throw PelibException(std::string("Matrices \"") + ptr->getName() + "\" and " + this->getName() + "\" are of incompatible size to merge.");
00149                                                 }
00150                                         }
00151                                         else
00152                                         {
00153                                                 // Nothing to merge, do nothing and return quietly
00154                                         }
00155                                 }
00156                                 else
00157                                 {
00158                                         throw PelibException(std::string("Cannot merge data \"") + ptr->getName() + "\" with " + typeid(Value).name() + " matrix of name \"" + this->getName() + "\".");
00159                                 }
00160                         }
00161                 protected:
00163                         MatrixType values;
00164                 private:        
00165         };
00166 }
00167 
00168 #endif