Templates -- Meow  1.2.10
A C++ template contains kinds of interesting classes and functions
Matrix.h
Go to the documentation of this file.
1 #ifndef math_Matrix_H__
2 #define math_Matrix_H__
3 
4 #include "../Self.h"
5 #include "../math/utility.h"
6 
7 #include <vector>
8 #include <algorithm>
9 
10 #include <cstdlib>
11 
12 namespace meow {
18 template<class Entry>
19 class Matrix {
20 public:
21  typedef typename std::vector<Entry>::reference EntryRef ;
22  typedef typename std::vector<Entry>::const_reference EntryRefK;
23 private:
24  struct Myself {
25  size_t rows_;
26  size_t cols_;
27  std::vector<Entry> entries_;
28 
29  Myself():
30  rows_(0), cols_(0), entries_(0) {
31  }
32 
33  Myself(Myself const& b):
34  rows_(b.rows_), cols_(b.cols_), entries_(b.entries_) {
35  }
36 
37  Myself(size_t r, size_t c, Entry const& e):
38  rows_(r), cols_(c), entries_(r * c, e) {
39  }
40 
41  ~Myself() {
42  }
43 
44  size_t index(size_t r, size_t c) const {
45  return r * cols_ + c;
46  }
47 
48  void realSize() {
49  std::vector<Entry> tmp(entries_);
50  entries_.swap(tmp);
51  }
52  };
53 
54  Self<Myself> const self;
55 public:
62  Matrix(): self() { }
63 
71  Matrix(Matrix const& m): self(m.self, Self<Myself>::COPY_FROM) {
72  }
73 
83  Matrix(size_t r, size_t c, Entry const& e): self(Myself(r, c, e)) {
84  }
85 
87  ~Matrix() { }
88 
97  Matrix& copyFrom(Matrix const& m) {
98  self().copyFrom(m.self);
99  return *this;
100  }
101 
111  self().referenceFrom(m.self);
112  return *this;
113  }
114 
116  void reset(size_t r, size_t c, Entry const& e) {
117  self()->rows_ = r;
118  self()->cols_ = c;
119  self()->entries_.clear();
120  self()->entries_.resize(r * c, e);
121  }
122 
124  bool valid() const {
125  return (rows() > 0 && cols() > 0);
126  }
127 
129  size_t rows() const {
130  return self->rows_;
131  }
132 
134  size_t cols() const {
135  return self->cols_;
136  }
137 
139  size_t size() const {
140  return rows() * cols();
141  }
142 
152  size_t rows(size_t r, Entry const& e) {
153  if (r != rows()) {
154  self()->entries_.resize(r * cols(), e);
155  self()->rows_ = r;
156  }
157  return rows();
158  }
159 
169  size_t cols(size_t c, Entry const& e) {
170  if (c != cols()) {
171  Self<Myself> const old(self, Self<Myself>::COPY_FROM);
172  self()->entries_.resize(rows() * c);
173  self()->cols_ = c;
174  for (size_t i = 0, I = rows(); i < I; i++) {
175  size_t j, J1 = std::min(old->cols_, cols()), J2 = cols();
176  for (j = 0; j < J1; j++)
177  self()->entries_[self->index(i, j)] = old->entries_[old->index(i, j)];
178  for (j = J1; j < J2; j++)
179  self()->entries_[self->index(i, j)] = e;
180  }
181  }
182  return cols();
183  }
184 
195  size_t size(size_t r, size_t c, Entry const& e) {
196  cols(c, e);
197  rows(r, e);
198  return rows() * cols();
199  }
200 
204  void clear() {
205  self()->rows_ = 0;
206  self()->cols_ = 0;
207  self()->entries_.clear();
208  self()->realSize();
209  }
210 
212  Entry entry(size_t r, size_t c) const {
213  return self->entries_[self->index(r, c)];
214  }
215 
217  Entry entry(size_t r, size_t c, Entry const& e) {
218  self()->entries_[self->index(r, c)] = e;
219  return entry(r, c);
220  }
221 
223  EntryRef entryGet(size_t r, size_t c) {
224  return self()->entries_[self->index(r, c)];
225  }
226 
237  void entries(ssize_t rFirst, ssize_t rLast,
238  ssize_t cFirst, ssize_t cLast,
239  Entry const& e) {
240  for (ssize_t r = rFirst; r <= rLast; r++) {
241  for (ssize_t c = cFirst; c <=cFirst; c++) {
242  entry(r, c, e);
243  }
244  }
245  }
246 
258  Matrix subMatrix(size_t rFirst, size_t rLast,
259  size_t cFirst, size_t cLast) const {
260  if (rFirst > rLast || cFirst > cLast) return Matrix();
261  if (rFirst == 0 && cFirst == 0) {
262  Matrix ret(*this);
263  ret.size(rLast + 1, cLast + 1, Entry(0));
264  return ret;
265  }
266  Matrix ret(rLast - rFirst + 1, cLast - cFirst + 1, entry(rFirst, cFirst));
267  for (size_t r = rFirst; r <= rLast; r++)
268  for (size_t c = cFirst; c <= cLast; c++)
269  ret.entry(r - rFirst, c - cFirst, entry(r, c));
270  return ret;
271  }
272 
274  Matrix row(size_t r) const {
275  return subMatrix(r, r, 0, cols() - 1);
276  }
277 
279  Matrix col(size_t c) const {
280  return subMatrix(0, rows() - 1, c, c);
281  }
282 
284  Matrix positive() const {
285  return *this;
286  }
287 
289  Matrix negative() const {
290  Matrix ret(*this);
291  for (size_t r = 0, R = rows(); r < R; r++)
292  for (size_t c = 0, C = cols(); c < C; c++)
293  ret.entry(r, c, -ret.entry(r, c));
294  return ret;
295  }
296 
301  Matrix add(Matrix const& m) const {
302  if (rows() != m.rows() || cols() != m.cols()) return Matrix();
303  Matrix ret(*this);
304  for (size_t r = 0, R = rows(); r < R; r++)
305  for (size_t c = 0, C = cols(); c < C; c++)
306  ret.entry(r, c, ret.entry(r, c) + m.entry(r, c));
307  return ret;
308  }
309 
314  Matrix sub(Matrix const& m) const {
315  if (rows() != m.rows() || cols() != m.cols()) return Matrix();
316  Matrix ret(*this);
317  for (size_t r = 0, R = rows(); r < R; r++)
318  for (size_t c = 0, C = cols(); c < C; c++)
319  ret.entry(r, c, ret.entry(r, c) - m.entry(r, c));
320  return ret;
321  }
322 
327  Matrix mul(Matrix const& m) const {
328  if (cols() != m.rows()) return Matrix();
329  Matrix ret(rows(), m.cols(), Entry(0));
330  for (size_t r = 0, R = rows(); r < R; r++)
331  for (size_t c = 0, C = m.cols(); c < C; c++)
332  for (size_t k = 0, K = cols(); k < K; k++)
333  ret.entry(r, c, ret.entry(r, c) + entry(r, k) * m.entry(k, c));
334  return ret;
335  }
336 
338  Matrix mul(Entry const& s) const {
339  Matrix ret(*this);
340  for (size_t r = 0, R = rows(); r < R; r++)
341  for (size_t c = 0, C = cols(); c < C; c++)
342  ret.entry(r, c, ret.entry(r, c) * s);
343  return ret;
344  }
345 
347  Matrix div(Entry const& s) const {
348  Matrix ret(*this);
349  for (size_t r = 0, R = rows(); r < R; r++)
350  for (size_t c = 0, C = cols(); c < C; c++)
351  ret.entry(r, c, ret.entry(r, c) / s);
352  return ret;
353  }
354 
356  Matrix identity() const {
357  Matrix ret(*this);
358  ret.identitied();
359  return ret;
360  }
361 
368  for (size_t r = 0, R = rows(); r < R; r++)
369  for (size_t c = 0, C = cols(); c < C; c++)
370  entry(r, c, (r == c ? Entry(1) : Entry(0)));
371  return *this;
372  }
373 
378  triangulared();
379  for (size_t i = 0, I = rows(); i < I; ++i) {
380  for (size_t j = i + 1, J = cols(); j < J; ++j) {
381  entry(i, j, Entry(0));
382  }
383  }
384  return *this;
385  }
386 
390  Matrix diagonal() const {
391  Matrix ret(*this);
392  ret.diagonaled();
393  return ret;
394  }
395 
401  Matrix inverse() const {
402  if (rows() != cols() || rows() == 0) return Matrix<Entry>();
403  Matrix tmp(rows(), cols() * 2, Entry(0));
404  for (size_t r = 0, R = rows(); r < R; r++) {
405  for (size_t c = 0, C = cols(); c < C; c++) {
406  tmp.entry(r, c, entry(r, c));
407  tmp.entry(r, c + cols(), (r == c ? Entry(1) : Entry(0)));
408  }
409  }
410  tmp.triangulared();
411  for (ssize_t r = rows() - 1; r >= 0; r--) {
412  if (tmp(r, r) == Entry(0)) return Matrix<Entry>();
413  for (ssize_t r2 = r - 1; r2 >= 0; r2--) {
414  Entry rat(-tmp.entry(r2, r) / tmp.entry(r, r));
415  for (size_t c = r, C = tmp.cols(); c < C; c++) {
416  tmp.entry(r2, c, tmp.entry(r2, c) + rat * tmp(r, c));
417  }
418  }
419  Entry rat(tmp.entry(r, r));
420  for (size_t c = cols(), C = tmp.cols(); c < C; c++) {
421  tmp.entry(r, c - cols(), tmp.entry(r, c) / rat);
422  }
423  }
424  tmp.size(cols(), rows(), Entry(0));
425  return tmp;
426  }
427 
430  copyFrom(inverse());
431  return *this;
432  }
433 
435  Matrix transpose() const {
436  Matrix ret(cols(), rows(), Entry(0));
437  for (size_t r = 0, R = cols(); r < R; r++)
438  for (size_t c = 0, C = rows(); c < C; c++)
439  ret.entry(r, c, entry(c, r));
440  return ret;
441  }
442 
445  copyFrom(transpose());
446  return *this;
447  }
448 
450  Matrix triangular() const {
451  Matrix<Entry> ret(*this);
452  ret.triangulared();
453  return ret;
454  }
455 
458  for (size_t r = 0, c = 0, R = rows(), C = cols(); r < R && c < C; r++) {
459  ssize_t maxR;
460  for ( ; c < C; c++) {
461  maxR = -1;
462  for (size_t r2 = r; r2 < R; r2++)
463  if (maxR == -1 || tAbs(entry(r2, c)) > tAbs(entry(maxR, c)))
464  maxR = r2;
465  if (entry(maxR, c) != Entry(0)) break;
466  }
467  if (c >= C) break;
468  if (maxR != (ssize_t)r) {
469  for (size_t c2 = c; c2 < C; c2++)
470  std::swap(self()->entries_[self->index( r, c2)],
471  self()->entries_[self->index(maxR, c2)]);
472  }
473  for (size_t r2 = r + 1; r2 < R; r2++) {
474  Entry rati = -entry(r2, c) / entry(r, c);
475  entry(r2, c, Entry(0));
476  for (size_t c2 = c + 1; c2 < C; c2++)
477  entry(r2, c2, entry(r2, c2) + entry(r, c2) * rati);
478  }
479  }
480  return *this;
481  }
482 
484  Matrix& operator=(Matrix const& m) {
485  return copyFrom(m);
486  }
487 
489  Entry operator()(size_t r, size_t c) const {
490  return entry(r, c);
491  }
492 
494  Entry operator()(size_t r, size_t c, Entry const& e) {
495  return entry(r, c, e);
496  }
497 
499  Matrix operator+() const {
500  return positive();
501  }
502 
504  Matrix operator-() const {
505  return negative();
506  }
507 
509  Matrix operator+(Matrix const& m) const {
510  return add(m);
511  }
512 
514  Matrix operator-(Matrix const& m) const {
515  return sub(m);
516  }
517 
519  Matrix operator*(Matrix const& m) const {
520  return mul(m);
521  }
522 
524  Matrix operator*(Entry const& s) const {
525  return mul(s);
526  }
527 
529  Matrix operator/(Entry const& s) const {
530  return div(s);
531  }
532 };
533 
534 } // meow
535 
536 #endif // math_Matrix_H__
Matrix col(size_t c) const
Return the c -th column.
Definition: Matrix.h:279
Matrix & triangulared()
triangluar itself
Definition: Matrix.h:457
std::vector< Entry >::const_reference EntryRefK
Definition: Matrix.h:22
Matrix & referenceFrom(Matrix const &m)
reference
Definition: Matrix.h:110
size_t rows() const
Return number of rows.
Definition: Matrix.h:129
Matrix operator*(Entry const &s) const
same as mul(m)
Definition: Matrix.h:524
Matrix div(Entry const &s) const
return (*this) / s. s is a scalar
Definition: Matrix.h:347
Matrix operator+() const
same as positive()
Definition: Matrix.h:499
std::vector< Entry >::reference EntryRef
Definition: Matrix.h:21
size_t rows(size_t r, Entry const &e)
resize the matrix such that number of rows become r.
Definition: Matrix.h:152
Matrix & transposed()
Let itself become itself's transpose matrix.
Definition: Matrix.h:444
size_t cols() const
Return number of cols.
Definition: Matrix.h:134
Entry operator()(size_t r, size_t c, Entry const &e)
same as entry(r,c,e)
Definition: Matrix.h:494
Matrix inverse() const
Return a matrix which is an inverse matrix of (*this)
Definition: Matrix.h:401
Matrix subMatrix(size_t rFirst, size_t rLast, size_t cFirst, size_t cLast) const
Return a rLast-rFirst+1 x cLast-cFirst+1 matrix.
Definition: Matrix.h:258
bool valid() const
Return whether it is a valid matrix.
Definition: Matrix.h:124
Matrix operator*(Matrix const &m) const
same as mul(m)
Definition: Matrix.h:519
Matrix row(size_t r) const
Return the r -th row.
Definition: Matrix.h:274
Matrix & operator=(Matrix const &m)
same as copyFrom
Definition: Matrix.h:484
Matrix()
constructor
Definition: Matrix.h:62
Matrix diagonal() const
Return a matrix which is a diangonal form of me.
Definition: Matrix.h:390
Matrix(Matrix const &m)
constructor
Definition: Matrix.h:71
Matrix & copyFrom(Matrix const &m)
copy
Definition: Matrix.h:97
T tAbs(T const &t)
就只是個取絕對值
Definition: utility.h:151
Matrix(size_t r, size_t c, Entry const &e)
constructor
Definition: Matrix.h:83
void entries(ssize_t rFirst, ssize_t rLast, ssize_t cFirst, ssize_t cLast, Entry const &e)
Change the entries from rFirst x cFirst to rLast x cLast.
Definition: Matrix.h:237
size_t size() const
Return number of rows times number of cols.
Definition: Matrix.h:139
size_t size(size_t r, size_t c, Entry const &e)
resize
Definition: Matrix.h:195
void clear()
free the memory
Definition: Matrix.h:204
Matrix identity() const
Return a identity matrix with size equal to itself.
Definition: Matrix.h:356
Matrix & diagonaled()
Let itself be an diagonal form of original itself.
Definition: Matrix.h:377
Matrix transpose() const
return itself's transpose matrix
Definition: Matrix.h:435
~Matrix()
destructor
Definition: Matrix.h:87
Matrix mul(Matrix const &m) const
return (*this) times m.
Definition: Matrix.h:327
Matrix mul(Entry const &s) const
return (*this) times s. s is a scalar
Definition: Matrix.h:338
EntryRef entryGet(size_t r, size_t c)
Get the entry at r x c.
Definition: Matrix.h:223
Matrix & inversed()
let itself become itself's inverse matrix
Definition: Matrix.h:429
Matrix sub(Matrix const &m) const
return (*this) - m.
Definition: Matrix.h:314
Matrix operator+(Matrix const &m) const
same as add(m)
Definition: Matrix.h:509
Entry operator()(size_t r, size_t c) const
same as entry(r,c)
Definition: Matrix.h:489
matrix
Definition: Matrix.h:19
Matrix operator-() const
same as negative()
Definition: Matrix.h:504
Entry entry(size_t r, size_t c, Entry const &e)
Change the entry at r x c.
Definition: Matrix.h:217
Matrix & identitied()
Let itself be an identity matrix.
Definition: Matrix.h:367
Entry entry(size_t r, size_t c) const
Access the entry at r x c.
Definition: Matrix.h:212
Matrix negative() const
return -(*this)
Definition: Matrix.h:289
size_t cols(size_t c, Entry const &e)
resize the matrix such that number of cols become c
Definition: Matrix.h:169
Matrix operator/(Entry const &s) const
same as div(s)
Definition: Matrix.h:529
Matrix positive() const
return +(*this)
Definition: Matrix.h:284
void reset(size_t r, size_t c, Entry const &e)
reset the size of the matrix to r x c with entry all be e
Definition: Matrix.h:116
Matrix operator-(Matrix const &m) const
same as sub(m)
Definition: Matrix.h:514
Matrix triangular() const
return a matrix which is the triangular form of (*this)
Definition: Matrix.h:450
Matrix add(Matrix const &m) const
return (*this) + m.
Definition: Matrix.h:301