00001 // Yo Emacs, this -*- C++ -*- 00002 #ifndef MAT_H 00003 #define MAT_H 00004 00005 #include "vec.hpp" 00006 //#include "misc.h" 00007 00008 #include <cstring> 00009 #include <iostream> 00010 #include <cassert> 00011 00012 #define SWAP(a1, a2, tmp) { (tmp) = (a1); (a1) = (a2); (a2) = (tmp); } 00013 00014 using std::istream; 00015 using std::ostream; 00016 using std::endl; 00017 00018 /** 00019 * Matrix of primitive numeric values. 00020 * 00021 * This implementation is built for speed. 00022 * It does not work with non-primitive types! 00023 */ 00024 template <class T> 00025 class Mat 00026 { 00027 public: 00028 Mat(); 00029 explicit Mat(int xs,int ys); 00030 Mat(const Mat &); 00031 ~Mat(); 00032 00033 void setSize(int xs,int ys); 00034 inline int xs() const; 00035 inline int ys() const; 00036 inline T &operator ()(int x,int y); 00037 inline const T &operator ()(int x,int y) const; 00038 00039 Mat<T> operator ~() const; 00040 00041 inline void swapRows(int r0, int r1); 00042 inline const T *data() const; 00043 inline T *data(); 00044 00045 Mat<T> &operator =(const Mat<T> &); 00046 Mat<T> operator +(const Mat<T> &) const; 00047 Mat<T> &operator +=(const Mat<T> &); 00048 Mat<T> operator -(const Mat<T> &) const; 00049 Mat<T> &operator -=(const Mat<T> &); 00050 Mat<T> operator *(const Mat<T> &) const; 00051 Mat<T> &operator *=(const Mat<T> &); 00052 Mat<T> operator -() const; 00053 00054 Mat<T> &operator =(const T &); 00055 Mat<T> operator *(const T &) const; 00056 Mat<T> &operator *=(const T &); 00057 00058 Vec<T> operator *(const Vec<T> &v) const; 00059 00060 bool operator ==(const Mat<T> &) const; 00061 bool operator !=(const Mat<T> &) const; 00062 bool operator <(const Mat<T> &) const; 00063 bool operator <=(const Mat<T> &) const; 00064 bool operator >(const Mat<T> &) const; 00065 bool operator >=(const Mat<T> &) const; 00066 00067 bool operator ==(const T &t) const; 00068 bool operator !=(const T &t) const; 00069 bool operator <(const T &t) const; 00070 bool operator <=(const T &t) const; 00071 bool operator >(const T &t) const; 00072 bool operator >=(const T &t) const; 00073 private: 00074 int _xs,_ys; 00075 int _size; 00076 T *_v; 00077 }; 00078 00079 template<class T> 00080 ostream &operator <<(ostream &os, const Mat<T> &m); 00081 00082 // 00083 // IMPLEMENTATION 00084 // 00085 00086 template <class T> 00087 Mat<T>::Mat() : _xs(0), _ys(0), _size(0), _v(0) 00088 { 00089 } 00090 00091 template <class T> 00092 Mat<T>::Mat(int xs,int ys) : _xs(xs), _ys(ys), _size(_xs * _ys), _v(0) 00093 { 00094 if(_size > 0) 00095 _v = new T[_size]; 00096 } 00097 00098 template <class T> 00099 Mat<T>::Mat(const Mat &m) : _xs(m._xs), _ys(m._ys), _size(_xs * _ys),_v(0) 00100 { 00101 if(_size > 0) 00102 _v = new T[_size]; 00103 00104 // this shortcut may not work with non-primitive types 00105 memcpy(_v, m._v, _size * sizeof(T)); 00106 //for(int i = 0; i < _size; i++) 00107 // _v[i] = m._v[i]; 00108 } 00109 00110 template <class T> 00111 Mat<T>::~Mat() 00112 { 00113 if(_v) 00114 delete [] _v; 00115 } 00116 00117 template <class T> 00118 inline void Mat<T>::setSize(int xs,int ys) 00119 { 00120 if(_size != xs * ys) { 00121 if(_v) 00122 delete [] _v; 00123 _xs = xs; 00124 _ys = ys; 00125 _size = _xs * _ys; 00126 if(_size > 0) 00127 _v = new T[_size]; 00128 } 00129 } 00130 00131 template <class T> 00132 inline int Mat<T>::xs() const 00133 { 00134 return _xs; 00135 } 00136 00137 template <class T> 00138 inline int Mat<T>::ys() const 00139 { 00140 return _ys; 00141 } 00142 00143 template <class T> 00144 inline T &Mat<T>::operator ()(int x,int y) 00145 { 00146 assert(x >= 0 && x < _xs && y >= 0 && y < _ys); 00147 return _v[y * _xs + x]; 00148 } 00149 00150 template <class T> 00151 inline const T &Mat<T>::operator ()(int x,int y) const 00152 { 00153 assert(x >= 0 && x < _xs && y >= 0 && y < _ys); 00154 return _v[y * _xs + x]; 00155 } 00156 00157 template <class T> 00158 Mat<T> Mat<T>::operator ~() const 00159 { 00160 Mat<T> r(_ys, _xs); 00161 for(int x = 0; x < _xs; x++) { 00162 for(int y = 0; y < _ys; y++) 00163 r(y, x) = (*this)(x, y); 00164 } 00165 return r; 00166 } 00167 00168 template <class T> 00169 void Mat<T>::swapRows(int r0, int r1) 00170 { 00171 assert(0 <= r0 && r0 < _ys); 00172 assert(0 <= r1 && r1 < _ys); 00173 if(r0 != r1) { 00174 T tmp; 00175 T *v0 = _v + r0 * _xs; 00176 T *v1 = _v + r1 * _xs; 00177 for(int i = 0; i < _xs; i++) 00178 SWAP(v0[i], v1[i], tmp); 00179 } 00180 } 00181 00182 template <class T> 00183 const T *Mat<T>::data() const 00184 { 00185 return _v; 00186 } 00187 00188 template <class T> 00189 T *Mat<T>::data() 00190 { 00191 return _v; 00192 } 00193 00194 template <class T> 00195 Mat<T> &Mat<T>::operator =(const Mat<T> &m) 00196 { 00197 if(_size != m._size) { 00198 if(_v) 00199 delete [] _v; 00200 _xs = m._xs; 00201 _ys = m._ys; 00202 _size = _xs * _ys; 00203 if(_size) 00204 _v = new T[_size]; 00205 } 00206 // this shortcut may not work with non-primitive types 00207 memcpy(_v, m._v, _size * sizeof(T)); 00208 //for(int i = 0; i < _size; i++) 00209 // _v[i] = m._v[i]; 00210 return *this; 00211 } 00212 00213 template <class T> 00214 Mat<T> Mat<T>::operator +(const Mat<T> &m) const 00215 { 00216 assert(m._xs == _xs && m._ys == _ys); 00217 Mat<T> r(_xs,_ys); 00218 int x, y; 00219 for(x = 0; x < _xs; x++) 00220 for(y = 0; y < _ys; y++) 00221 r(x, y) -= (*this)(x, y) + m(x, y); 00222 return r; 00223 } 00224 00225 template <class T> 00226 Mat<T> &Mat<T>::operator +=(const Mat<T> &m) 00227 { 00228 assert(m._xs == _xs && m._ys == _ys); 00229 int x, y; 00230 for(x = 0; x < _xs; x++) 00231 for(y = 0; y < _ys; y++) 00232 (*this)(x, y) += m(x, y); 00233 return *this; 00234 } 00235 00236 template <class T> 00237 Mat<T> Mat<T>::operator -(const Mat<T> &m) const 00238 { 00239 assert(m._xs == _xs && m._ys == _ys); 00240 Mat<T> r(_xs,_ys); 00241 int x, y; 00242 for(x = 0; x < _xs; x++) 00243 for(y = 0; y < _ys; y++) 00244 r(x, y) -= (*this)(x, y) - m(x, y); 00245 return r; 00246 } 00247 00248 template <class T> 00249 Mat<T> &Mat<T>::operator -=(const Mat<T> &m) 00250 { 00251 assert(m._xs == _xs && m._ys == _ys); 00252 int x, y; 00253 for(x = 0; x < _xs; x++) 00254 for(y = 0; y < _ys; y++) 00255 (*this)(x, y) -= m(x, y); 00256 return *this; 00257 } 00258 00259 template <class T> 00260 Mat<T> Mat<T>::operator *(const Mat<T> &m) const 00261 { 00262 assert(_xs == m._ys); 00263 Mat<T> r(m._xs, _ys); 00264 int x, y,i; 00265 for(x = 0; x < r._xs; x++) { 00266 for(y = 0; y < r._ys; y++) { 00267 r(x, y) = 0; 00268 for(i = 0; i < _xs; i++) 00269 r(x, y) += (*this)(i, y) * m(x, i); 00270 } 00271 } 00272 return r; 00273 } 00274 00275 template <class T> 00276 Mat<T> &Mat<T>::operator *=(const Mat<T> &m) 00277 { 00278 (*this) = (*this) * m; 00279 return *this; 00280 } 00281 00282 template <class T> 00283 Mat<T> Mat<T>::operator -() const 00284 { 00285 Mat<T> r(_xs,_ys); 00286 for(int i = 0; i < _size; i++) 00287 r._v[i] = -_v[i]; 00288 return r; 00289 } 00290 00291 template <class T> 00292 Mat<T> &Mat<T>::operator =(const T &t) 00293 { 00294 for(int i = 0; i < _size; i++) 00295 _v[i] = t; 00296 return *this; 00297 } 00298 00299 template <class T> 00300 Mat<T> Mat<T>::operator *(const T &t) const 00301 { 00302 Mat<T> r(_xs,_ys); 00303 int x, y; 00304 for(x = 0; x < _xs; x++) 00305 for(y = 0; y < _ys; y++) 00306 r(x, y) = (*this)(x, y) * t; 00307 return r; 00308 } 00309 00310 template <class T> 00311 Mat<T> &Mat<T>::operator *=(const T &t) 00312 { 00313 int x, y; 00314 for(x = 0; x < _xs; x++) 00315 for(y = 0; y < _ys; y++) 00316 (*this)(x, y) *= t; 00317 return *this; 00318 } 00319 00320 template <class T> 00321 Vec<T> Mat<T>::operator *(const Vec<T> &v) const 00322 { 00323 assert(_xs == v.size()); 00324 Vec<T> r(_ys); 00325 for(int y = 0; y < _ys; y++) { 00326 r(y) = T(0); 00327 for(int x = 0; x < _xs; x++) 00328 r(y) += (*this)(x, y) * v(x); 00329 } 00330 return r; 00331 } 00332 00333 template <class T> 00334 bool Mat<T>::operator ==(const Mat<T> &m) const 00335 { 00336 for(int i = 0; i < _size; i++) { 00337 if(!(_v[i] == m._v[i])) 00338 return false; 00339 } 00340 return true; 00341 } 00342 00343 template <class T> 00344 bool Mat<T>::operator !=(const Mat<T> &m) const 00345 { 00346 for(int i = 0; i < _size; i++) { 00347 if(!(_v[i] != m._v[i])) 00348 return false; 00349 } 00350 return true; 00351 } 00352 00353 template <class T> 00354 bool Mat<T>::operator <(const Mat<T> &m) const 00355 { 00356 assert(_xs == m._xs && _ys == m._ys); 00357 for(int i = 0; i < _size; i++) { 00358 if(!(_v[i] < m._v[i])) 00359 return false; 00360 } 00361 return true; 00362 } 00363 00364 template <class T> 00365 bool Mat<T>::operator <=(const Mat<T> &m) const 00366 { 00367 assert(_xs == m._xs && _ys == m._ys); 00368 for(int i = 0; i < _size; i++) { 00369 if(!(_v[i] <= m._v[i])) 00370 return false; 00371 } 00372 return true; 00373 } 00374 00375 template <class T> 00376 bool Mat<T>::operator >(const Mat<T> &m) const 00377 { 00378 assert(_xs == m._xs && _ys == m._ys); 00379 for(int i = 0; i < _size; i++) { 00380 if(!(_v[i] > m._v[i])) 00381 return false; 00382 } 00383 return true; 00384 } 00385 00386 template <class T> 00387 bool Mat<T>::operator >=(const Mat<T> &m) const 00388 { 00389 assert(_xs == m._xs && _ys == m._ys); 00390 for(int i = 0; i < _size; i++) { 00391 if(!(_v[i] >= m._v[i])) 00392 return false; 00393 } 00394 return true; 00395 } 00396 00397 template <class T> 00398 bool Mat<T>::operator ==(const T &t) const 00399 { 00400 for(int i = 0; i < _size; i++) { 00401 if(!(_v[i] == t)) 00402 return false; 00403 } 00404 return true; 00405 } 00406 00407 template <class T> 00408 bool Mat<T>::operator !=(const T &t) const 00409 { 00410 for(int i = 0; i < _size; i++) { 00411 if(!(_v[i] != t)) 00412 return false; 00413 } 00414 return true; 00415 } 00416 00417 template <class T> 00418 bool Mat<T>::operator <(const T &t) const 00419 { 00420 for(int i = 0; i < _size; i++) { 00421 if(!(_v[i] < t)) 00422 return false; 00423 } 00424 return true; 00425 } 00426 00427 template <class T> 00428 bool Mat<T>::operator <=(const T &t) const 00429 { 00430 for(int i = 0; i < _size; i++) { 00431 if(!(_v[i] <= t)) 00432 return false; 00433 } 00434 return true; 00435 } 00436 00437 template <class T> 00438 bool Mat<T>::operator >(const T &t) const 00439 { 00440 for(int i = 0; i< _size; i++) { 00441 if(!(_v[i] > t)) 00442 return false; 00443 } 00444 return true; 00445 } 00446 00447 template <class T> 00448 bool Mat<T>::operator >=(const T &t) const 00449 { 00450 for(int i = 0; i < _size; i++) { 00451 if(!(_v[i] >= t)) 00452 return false; 00453 } 00454 return true; 00455 } 00456 00457 // 00458 // 00459 // 00460 00461 template <class T> 00462 ostream &operator <<(ostream &os, const Mat<T> &m) 00463 { 00464 os << "[" << endl; 00465 for(int y = 0; y < m.ys(); y++) { 00466 os << "["; 00467 for(int x = 0; x < m.xs(); x++) { 00468 if(x) os << ", "; 00469 os << m(x, y); 00470 } 00471 os << "]" << endl; 00472 } 00473 os << "]"; 00474 return os; 00475 } 00476 00477 #endif