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