pelib
2.0.0
|
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