00001 #ifndef MATRIX_H
00002 #define MATRIX_H
00003
00004 #include <stdexcept>
00005 #include <string>
00006 #include <typeinfo>
00007 #include "utils.h"
00008
00009
00010
00013 template<typename T>
00014 class Matrix
00015 {
00016 public:
00018 class Row {
00019 public:
00024 Row(Matrix *parent, size_t i) : _par(parent), _i(i) {}
00029 T& operator[](int j) { return _par->at(_i, j); }
00030 private:
00031 Matrix<T>* _par;
00032 size_t _i;
00033 };
00034
00040 Matrix(size_t n, size_t m, T v = static_cast<T>(0));
00041
00046 Matrix(Matrix<T> const& other);
00047
00049 ~Matrix();
00050
00052 const size_t getN() const { return m_width; }
00053
00055 const size_t getM() const { return m_height; }
00056
00062 T& at(size_t i, size_t j);
00063
00069 T& operator()(size_t i, size_t j) { return at(i, j); }
00070
00076 T get(size_t i, size_t j) const;
00077
00083 void set(size_t i, size_t j, T v);
00084
00089 Matrix<T> &operator=(Matrix<T> const& other);
00090
00096 Row operator[](size_t i) { return Row(this, i); }
00097
00103 Matrix<T> transposed();
00108 Matrix<T> &transposeSelf();
00109
00115 Matrix<T> &operator+=(Matrix<T>& right);
00116
00122 Matrix<T> &operator-=(Matrix<T>& right);
00123
00129 Matrix<T> &operator*=(Matrix<T>& right);
00130
00136 Matrix<T> &operator*=(T scalar);
00137
00138 private:
00139 size_t m_width;
00140 size_t m_height;
00141 T *m_matrix;
00142 };
00143
00144 template<typename T>
00145 Matrix<T>::Matrix(size_t n, size_t m, T v) :
00146 m_width(n), m_height(m)
00147 {
00148 m_matrix = new T[n*m];
00149 for (size_t i = 0; i < n*m; ++i) {
00150 m_matrix[i] = v;
00151 }
00152 }
00153
00154 template<typename T>
00155 Matrix<T>::Matrix(Matrix const& other) :
00156 m_width(other.getN()), m_height(other.getM())
00157 {
00158 m_matrix = new T[getN()*getM()];
00159 for (size_t i = 0; i < other.getN(); ++i) {
00160 for (size_t j = 0; j < other.getM(); ++j) {
00161 m_matrix[i + j * getN()] = other.get(i, j);
00162 }
00163 }
00164 }
00165
00166 template<typename T>
00167 Matrix<T>::~Matrix()
00168 {
00169 delete[] m_matrix;
00170 m_matrix = NULL;
00171 }
00172
00173 template<typename T>
00174 T& Matrix<T>::at(size_t i, size_t j)
00175 {
00176 if (i < 0 || i >= getN() || j < 0 || j >= getM()) {
00177 std::string err = "Matrix<";
00178 err += typeid(T).name();
00179 err += ">::at(" + convertTo<size_t, std::string>(i) + ", " + convertTo<size_t, std::string>(j);
00180 err += "): index out of range. Dimensions are: ";
00181 err += convertTo<size_t, std::string>(getN()) + ", " + convertTo<size_t, std::string>(getM());
00182 throw std::out_of_range(err.c_str());
00183 }
00184
00185 return m_matrix[i + j * getN()];
00186 }
00187
00188 template<typename T>
00189 T Matrix<T>::get(size_t i, size_t j) const
00190 {
00191
00192 if (i < 0 || i >= getN() || j < 0 || j >= getM()) {
00193 std::string err = "Matrix<";
00194 err += typeid(T).name();
00195 err += ">::get(" + convertTo<size_t, std::string>(i) + ", " + convertTo<size_t, std::string>(j);
00196 err += "): index out of range. Dimensions";
00197 err += convertTo<size_t, std::string>(getN()) + ", " + convertTo<size_t, std::string>(getM());
00198 throw std::out_of_range(err.c_str());
00199 }
00200
00201 return m_matrix[i + j * getN()];
00202 }
00203
00204 template<typename T>
00205 void Matrix<T>::set(size_t i, size_t j, T v)
00206 {
00207 at(i, j) = v;
00208 }
00209
00210 template<typename T>
00211 Matrix<T>& Matrix<T>::operator=(Matrix<T> const &other)
00212 {
00213 if (&other == this)
00214 return *this;
00215
00216 if (other.getN() != getN() || other.getM() != getM()) {
00217 T *temp = m_matrix;
00218 m_width = other.getN();
00219 m_height = other.getM();
00220 m_matrix = new T[getN()*getM()];
00221 delete[] temp;
00222 }
00223
00224 for (size_t i = 0; i < other.getN(); ++i) {
00225 for (size_t j = 0; j < other.getM(); ++j) {
00226 m_matrix[i + j * getN()] = other.get(i, j);
00227 }
00228 }
00229 return *this;
00230 }
00231
00232 template<typename T>
00233 Matrix<T> &Matrix<T>::transposeSelf()
00234 {
00235 Matrix<T> temp(transposed());
00236 *this = temp;
00237 return *this;
00238 }
00239
00240 template<typename T>
00241 Matrix<T> Matrix<T>::transposed()
00242 {
00243 Matrix<T> temp(getM(), getN());
00244 for (size_t i = 0; i < getN(); ++i) {
00245 for (size_t j = 0; j < getM; ++j) {
00246 temp.at(j, i) = get(i, j);
00247 }
00248 }
00249 return temp;
00250 }
00251
00252 template<typename T>
00253 Matrix<T> &Matrix<T>::operator+=(Matrix<T>& right)
00254 {
00255 if (getN() != right.getN() || getM() != right.getM()) {
00256 std::string err = "Matrix<";
00257 err += typeid(T).name();
00258 err += ">::operator+=(Matrix<T>& right): Matrix sizes do not match: ";
00259 err += convertTo<size_t, std::string>(getN()) + ", " + convertTo<size_t, std::string>(getM());
00260 err += " vs " + convertTo<size_t, std::string>(right.getN()) + ", " + convertTo<size_t, std::string>(right.getM());
00261 throw std::out_of_range(err.c_str());
00262 }
00263
00264 Matrix temp(*this);
00265 for (size_t i = 0; i < getN(); ++i) {
00266 for (size_t j = 0; j < getM(); ++j) {
00267 temp.at(i, j) += right.at(i, j);
00268 }
00269 }
00270
00271 *this = temp;
00272 return *this;
00273 }
00274
00275 template<typename T>
00276 Matrix<T> &Matrix<T>::operator-=(Matrix<T>& right)
00277 {
00278 if (getN() != right.getN() || getM() != right.getM()) {
00279 std::string err = "Matrix<";
00280 err += typeid(T).name();
00281 err += ">::operator+=(Matrix<T>& right): Matrix sizes do not match: ";
00282 err += convertTo<size_t, std::string>(getN()) + ", " + convertTo<size_t, std::string>(getM());
00283 err += " vs " + convertTo<size_t, std::string>(right.getN()) + ", " + convertTo<size_t, std::string>(right.getM());
00284 throw std::out_of_range(err.c_str());
00285 }
00286
00287 Matrix temp(*this);
00288 for (size_t i = 0; i < getN(); ++i) {
00289 for (size_t j = 0; j < getM(); ++j) {
00290 temp.at(i, j) -= right.at(i, j);
00291 }
00292 }
00293
00294 *this = temp;
00295 return *this;
00296 }
00297
00298 template<typename T>
00299 Matrix<T> &Matrix<T>::operator*=(Matrix<T>& right)
00300 {
00301 if (getM() != right.getN()) {
00302 std::string err = "Matrix<";
00303 err += typeid(T).name();
00304 err += ">::operator+=(Matrix<T>& right): Matrix sizes do not match: ";
00305 err += convertTo<size_t, std::string>(getN()) + ", " + convertTo<size_t, std::string>(getM());
00306 err += " vs " + convertTo<size_t, std::string>(right.getN()) + ", " + convertTo<size_t, std::string>(right.getM());
00307 throw std::out_of_range(err.c_str());
00308 }
00309
00310 Matrix temp(getN(), right.getM());
00311 for (size_t i = 0; i < getN(); ++i) {
00312 for (size_t j = 0; j < right.getM(); ++j) {
00313 for (size_t k = 0; k < getM(); ++k) {
00314 temp.at(i, j) += get(i, k) + get(k, j);
00315 }
00316 }
00317 }
00318
00319 *this = temp;
00320 return *this;
00321 }
00322
00323 template<typename T>
00324 Matrix<T> &Matrix<T>::operator*=(T scalar)
00325 {
00326 for (size_t i = 0; i < getN() * getM(); ++i) {
00327 m_matrix[i] *= scalar;
00328 }
00329 }
00330
00331 #endif