Templates -- Meow  204.13.18
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 
48  Self<Myself> const self;
49 public:
56  Matrix(): self() { }
57 
65  Matrix(Matrix const& m): self(m.self, Self<Myself>::COPY_FROM) {
66  }
67 
77  Matrix(size_t r, size_t c, Entry const& e): self(Myself(r, c, e)) {
78  }
79 
81  ~Matrix() { }
82 
91  Matrix& copyFrom(Matrix const& m) {
92  self().copyFrom(m.self);
93  return *this;
94  }
95 
105  self().referenceFrom(m.self);
106  return *this;
107  }
108 
110  void reset(size_t r, size_t c, Entry const& e) {
111  self()->rows_ = r;
112  self()->cols_ = c;
113  self()->entries_.clear();
114  self()->entries_.resize(r * c, e);
115  }
116 
118  bool valid() const {
119  return (rows() > 0 && cols() > 0);
120  }
121 
123  size_t rows() const {
124  return self->rows_;
125  }
126 
128  size_t cols() const {
129  return self->cols_;
130  }
131 
133  size_t size() const {
134  return rows() * cols();
135  }
136 
146  size_t rows(size_t r, Entry const& e) {
147  if (r != rows()) {
148  self()->entries_.resize(r * cols(), e);
149  self()->rows_ = r;
150  }
151  return rows();
152  }
153 
163  size_t cols(size_t c, Entry const& e) {
164  if (c != cols()) {
165  Self<Myself> const old(self, Self<Myself>::COPY_FROM);
166  self()->entries_.resize(rows() * c);
167  self()->cols_ = c;
168  for (size_t i = 0, I = rows(); i < I; i++) {
169  size_t j, J1 = std::min(old->cols_, cols()), J2 = cols();
170  for (j = 0; j < J1; j++)
171  self()->entries_[self->index(i, j)] = old->entries_[old->index(i, j)];
172  for (j = J1; j < J2; j++)
173  self()->entries_[self->index(i, j)] = e;
174  }
175  }
176  return cols();
177  }
178 
189  size_t size(size_t r, size_t c, Entry const& e) {
190  cols(c, e);
191  rows(r, e);
192  return rows() * cols();
193  }
194 
196  Entry entry(size_t r, size_t c) const {
197  return self->entries_[self->index(r, c)];
198  }
199 
201  Entry entry(size_t r, size_t c, Entry const& e) {
202  self()->entries_[self->index(r, c)] = e;
203  return entry(r, c);
204  }
205 
207  EntryRef entryGet(size_t r, size_t c) {
208  return self()->entries_[self->index(r, c)];
209  }
210 
221  void entries(ssize_t rFirst, ssize_t rLast,
222  ssize_t cFirst, ssize_t cLast,
223  Entry const& e) {
224  for (ssize_t r = rFirst; r <= rLast; r++) {
225  for (ssize_t c = cFirst; c <=cFirst; c++) {
226  entry(r, c, e);
227  }
228  }
229  }
230 
242  Matrix subMatrix(size_t rFirst, size_t rLast,
243  size_t cFirst, size_t cLast) const {
244  if (rFirst > rLast || cFirst > cLast) return Matrix();
245  if (rFirst == 0 && cFirst == 0) {
246  Matrix ret(*this);
247  ret.size(rLast + 1, cLast + 1, Entry(0));
248  return ret;
249  }
250  Matrix ret(rLast - rFirst + 1, cLast - cFirst + 1, entry(rFirst, cFirst));
251  for (size_t r = rFirst; r <= rLast; r++)
252  for (size_t c = cFirst; c <= cLast; c++)
253  ret.entry(r - rFirst, c - cFirst, entry(r, c));
254  return ret;
255  }
256 
258  Matrix row(size_t r) const {
259  return subMatrix(r, r, 0, cols() - 1);
260  }
261 
263  Matrix col(size_t c) const {
264  return subMatrix(0, rows() - 1, c, c);
265  }
266 
268  Matrix positive() const {
269  return *this;
270  }
271 
273  Matrix negative() const {
274  Matrix ret(*this);
275  for (size_t r = 0, R = rows(); r < R; r++)
276  for (size_t c = 0, C = cols(); c < C; c++)
277  ret.entry(r, c, -ret.entry(r, c));
278  return ret;
279  }
280 
285  Matrix add(Matrix const& m) const {
286  if (rows() != m.rows() || cols() != m.cols()) return Matrix();
287  Matrix ret(*this);
288  for (size_t r = 0, R = rows(); r < R; r++)
289  for (size_t c = 0, C = cols(); c < C; c++)
290  ret.entry(r, c, ret.entry(r, c) + m.entry(r, c));
291  return ret;
292  }
293 
298  Matrix sub(Matrix const& m) const {
299  if (rows() != m.rows() || cols() != m.cols()) return Matrix();
300  Matrix ret(*this);
301  for (size_t r = 0, R = rows(); r < R; r++)
302  for (size_t c = 0, C = cols(); c < C; c++)
303  ret.entry(r, c, ret.entry(r, c) - m.entry(r, c));
304  return ret;
305  }
306 
311  Matrix mul(Matrix const& m) const {
312  if (cols() != m.rows()) return Matrix();
313  Matrix ret(rows(), m.cols(), Entry(0));
314  for (size_t r = 0, R = rows(); r < R; r++)
315  for (size_t c = 0, C = m.cols(); c < C; c++)
316  for (size_t k = 0, K = cols(); k < K; k++)
317  ret.entry(r, c, ret.entry(r, c) + entry(r, k) * m.entry(k, c));
318  return ret;
319  }
320 
322  Matrix mul(Entry const& s) const {
323  Matrix ret(*this);
324  for (size_t r = 0, R = rows(); r < R; r++)
325  for (size_t c = 0, C = cols(); c < C; c++)
326  ret.entry(r, c, ret.entry(r, c) * s);
327  return ret;
328  }
329 
331  Matrix div(Entry const& s) const {
332  Matrix ret(*this);
333  for (size_t r = 0, R = rows(); r < R; r++)
334  for (size_t c = 0, C = cols(); c < C; c++)
335  ret.entry(r, c, ret.entry(r, c) / s);
336  return ret;
337  }
338 
340  Matrix identity() const {
341  Matrix ret(*this);
342  ret.identitied();
343  return ret;
344  }
345 
352  for (size_t r = 0, R = rows(); r < R; r++)
353  for (size_t c = 0, C = cols(); c < C; c++)
354  entry(r, c, (r == c ? Entry(1) : Entry(0)));
355  return *this;
356  }
357 
362  triangulared();
363  for (size_t i = 0, I = rows(); i < I; ++i) {
364  for (size_t j = i + 1, J = cols(); j < J; ++j) {
365  entry(i, j, Entry(0));
366  }
367  }
368  return *this;
369  }
370 
374  Matrix diagonal() const {
375  Matrix ret(*this);
376  ret.diagonaled();
377  return ret;
378  }
379 
385  Matrix inverse() const {
386  if (rows() != cols() || rows() == 0) return Matrix<Entry>();
387  Matrix tmp(rows(), cols() * 2, Entry(0));
388  for (size_t r = 0, R = rows(); r < R; r++) {
389  for (size_t c = 0, C = cols(); c < C; c++) {
390  tmp.entry(r, c, entry(r, c));
391  tmp.entry(r, c + cols(), (r == c ? Entry(1) : Entry(0)));
392  }
393  }
394  tmp.triangulared();
395  for (ssize_t r = rows() - 1; r >= 0; r--) {
396  if (tmp(r, r) == Entry(0)) return Matrix<Entry>();
397  for (ssize_t r2 = r - 1; r2 >= 0; r2--) {
398  Entry rat(-tmp.entry(r2, r) / tmp.entry(r, r));
399  for (size_t c = r, C = tmp.cols(); c < C; c++) {
400  tmp.entry(r2, c, tmp.entry(r2, c) + rat * tmp(r, c));
401  }
402  }
403  Entry rat(tmp.entry(r, r));
404  for (size_t c = cols(), C = tmp.cols(); c < C; c++) {
405  tmp.entry(r, c - cols(), tmp.entry(r, c) / rat);
406  }
407  }
408  tmp.size(cols(), rows(), Entry(0));
409  return tmp;
410  }
411 
414  copyFrom(inverse());
415  return *this;
416  }
417 
419  Matrix transpose() const {
420  Matrix ret(cols(), rows(), Entry(0));
421  for (size_t r = 0, R = cols(); r < R; r++)
422  for (size_t c = 0, C = rows(); c < C; c++)
423  ret.entry(r, c, entry(c, r));
424  return ret;
425  }
426 
429  copyFrom(transpose());
430  return *this;
431  }
432 
434  Matrix triangular() const {
435  Matrix<Entry> ret(*this);
436  ret.triangulared();
437  return ret;
438  }
439 
442  for (size_t r = 0, c = 0, R = rows(), C = cols(); r < R && c < C; r++) {
443  ssize_t maxR;
444  for ( ; c < C; c++) {
445  maxR = -1;
446  for (size_t r2 = r; r2 < R; r2++)
447  if (maxR == -1 || tAbs(entry(r2, c)) > tAbs(entry(maxR, c)))
448  maxR = r2;
449  if (entry(maxR, c) != Entry(0)) break;
450  }
451  if (c >= C) break;
452  if (maxR != (ssize_t)r) {
453  for (size_t c2 = c; c2 < C; c2++)
454  std::swap(self()->entries_[self->index( r, c2)],
455  self()->entries_[self->index(maxR, c2)]);
456  }
457  for (size_t r2 = r + 1; r2 < R; r2++) {
458  Entry rati = -entry(r2, c) / entry(r, c);
459  entry(r2, c, Entry(0));
460  for (size_t c2 = c + 1; c2 < C; c2++)
461  entry(r2, c2, entry(r2, c2) + entry(r, c2) * rati);
462  }
463  }
464  return *this;
465  }
466 
468  Matrix& operator=(Matrix const& m) {
469  return copyFrom(m);
470  }
471 
473  Entry operator()(size_t r, size_t c) const {
474  return entry(r, c);
475  }
476 
478  Entry operator()(size_t r, size_t c, Entry const& e) {
479  return entry(r, c, e);
480  }
481 
483  Matrix operator+() const {
484  return positive();
485  }
486 
488  Matrix operator-() const {
489  return negative();
490  }
491 
493  Matrix operator+(Matrix const& m) const {
494  return add(m);
495  }
496 
498  Matrix operator-(Matrix const& m) const {
499  return sub(m);
500  }
501 
503  Matrix operator*(Matrix const& m) const {
504  return mul(m);
505  }
506 
508  Matrix operator*(Entry const& s) const {
509  return mul(s);
510  }
511 
513  Matrix operator/(Entry const& s) const {
514  return div(s);
515  }
516 };
517 
518 } // meow
519 
520 #endif // math_Matrix_H__
Matrix col(size_t c) const
Return the c -th column.
Definition: Matrix.h:263
Matrix & triangulared()
triangluar itself
Definition: Matrix.h:441
std::vector< Entry >::const_reference EntryRefK
Definition: Matrix.h:21
Matrix & referenceFrom(Matrix const &m)
reference
Definition: Matrix.h:104
size_t rows() const
Return number of rows.
Definition: Matrix.h:123
Matrix operator*(Entry const &s) const
same as mul(m)
Definition: Matrix.h:508
Matrix div(Entry const &s) const
return (*this) / s. s is a scalar
Definition: Matrix.h:331
Matrix operator+() const
same as positive()
Definition: Matrix.h:483
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:146
Matrix & transposed()
Let itself become itself's transpose matrix.
Definition: Matrix.h:428
size_t cols() const
Return number of cols.
Definition: Matrix.h:128
Entry operator()(size_t r, size_t c, Entry const &e)
same as entry(r,c,e)
Definition: Matrix.h:478
Matrix inverse() const
Return a matrix which is an inverse matrix of (*this)
Definition: Matrix.h:385
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:242
bool valid() const
Return whether it is a valid matrix.
Definition: Matrix.h:118
Matrix operator*(Matrix const &m) const
same as mul(m)
Definition: Matrix.h:503
Matrix row(size_t r) const
Return the r -th row.
Definition: Matrix.h:258
Matrix & operator=(Matrix const &m)
same as copyFrom
Definition: Matrix.h:468
Matrix()
constructor
Definition: Matrix.h:56
Matrix diagonal() const
Return a matrix which is a diangonal form of me.
Definition: Matrix.h:374
Matrix(Matrix const &m)
constructor
Definition: Matrix.h:65
Matrix & copyFrom(Matrix const &m)
copy
Definition: Matrix.h:91
T tAbs(T const &t)
就只是個取絕對值
Definition: utility.h:141
Matrix(size_t r, size_t c, Entry const &e)
constructor
Definition: Matrix.h:77
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:221
size_t size() const
Return number of rows times number of cols.
Definition: Matrix.h:133
size_t size(size_t r, size_t c, Entry const &e)
resize
Definition: Matrix.h:189
Matrix identity() const
Return a identity matrix with size equal to itself.
Definition: Matrix.h:340
Matrix & diagonaled()
Let itself be an diagonal form of original itself.
Definition: Matrix.h:361
Matrix transpose() const
return itself's transpose matrix
Definition: Matrix.h:419
~Matrix()
destructor
Definition: Matrix.h:81
Matrix mul(Matrix const &m) const
return (*this) times m.
Definition: Matrix.h:311
Matrix mul(Entry const &s) const
return (*this) times s. s is a scalar
Definition: Matrix.h:322
EntryRef entryGet(size_t r, size_t c)
Get the entry at r x c.
Definition: Matrix.h:207
Matrix & inversed()
let itself become itself's inverse matrix
Definition: Matrix.h:413
Matrix sub(Matrix const &m) const
return (*this) - m.
Definition: Matrix.h:298
Matrix operator+(Matrix const &m) const
same as add(m)
Definition: Matrix.h:493
Entry operator()(size_t r, size_t c) const
same as entry(r,c)
Definition: Matrix.h:473
matrix
Definition: Matrix.h:18
Matrix operator-() const
same as negative()
Definition: Matrix.h:488
Entry entry(size_t r, size_t c, Entry const &e)
Change the entry at r x c.
Definition: Matrix.h:201
Matrix & identitied()
Let itself be an identity matrix.
Definition: Matrix.h:351
Entry entry(size_t r, size_t c) const
Access the entry at r x c.
Definition: Matrix.h:196
Matrix negative() const
return -(*this)
Definition: Matrix.h:273
size_t cols(size_t c, Entry const &e)
resize the matrix such that number of cols become c
Definition: Matrix.h:163
Matrix operator/(Entry const &s) const
same as div(s)
Definition: Matrix.h:513
Matrix positive() const
return +(*this)
Definition: Matrix.h:268
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:110
Matrix operator-(Matrix const &m) const
same as sub(m)
Definition: Matrix.h:498
Matrix triangular() const
return a matrix which is the triangular form of (*this)
Definition: Matrix.h:434
Matrix add(Matrix const &m) const
return (*this) + m.
Definition: Matrix.h:285