Templates -- Meow  1.1.2
不能,也不應該先編譯成obj-file的templates
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 std::vector<Entry>::reference EntryRef ;
21  typedef 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  Myself(Myself const& b):
32  rows_(b.rows_), cols_(b.cols_), entries_(b.entries_) {
33  }
34  Myself(size_t r, size_t c, Entry const& e):
35  rows_(r), cols_(c), entries(r * c, e) {
36  }
37  ~Myself() {
38  }
39 
40  size_t index(size_t r, size_t c) const {
41  return r * cols_ + c;
42  }
43  };
44 
45  Self<Myself> const self;
46 public:
53  Matrix(): self() { }
54 
62  Matrix(Matrix const& m): self(m.self, COPY_FROM) {
63  }
64 
74  Matrix(size_t r, size_t c, Entry const& e): self(Myself(r, c, e)) {
75  }
76 
78  ~Matrix() { }
79 
88  Matrix& copyFrom(Matrix const& m) {
89  self().copyFrom(m.self);
90  return *this;
91  }
92 
102  self().referenceFrom(m.self);
103  return *this;
104  }
105 
107  void reset(size_t r, size_t c, Entry const& e) {
108  self()->rows_ = r;
109  self()->cols_ = c;
110  self()->entries_.clear();
111  self()->entries_.resize(r * c, e);
112  }
113 
115  bool valid() const {
116  return (rows() > 0 && cols() > 0);
117  }
118 
120  size_t rows() const {
121  return self->rows_;
122  }
123 
125  size_t cols() const {
126  return self->cols_;
127  }
128 
130  size_t size() const {
131  return rows() * cols();
132  }
133 
143  size_t rows(size_t r, Entry const& e) {
144  if (r != rows()) {
145  self()->entries_.resize(r * cols(), e);
146  self()->rows_ = r;
147  }
148  return rows();
149  }
150 
160  size_t cols(size_t c, Entry const& e) {
161  if (c != cols()) {
162  Self<Myself> const old(false);
163  old().copyFrom(self);
164  self()->entries_.resize(rows() * c);
165  self()->cols_ = c;
166  for (size_t i = 0, I = rows(); i < I; i++) {
167  size_t j, J1 = std::min(old->cols_, cols()), J2 = cols();
168  for (j = 0; j < J1; j++)
169  self()->entries_[self->index(i, j)] = old->entries_[old->index(i, j)];
170  for (j = J1; j < J2; j++)
171  self()->entries_[self->index(i, j)] = e;
172  }
173  }
174  return cols();
175  }
176 
187  size_t size(size_t r, size_t c, Entry const& e) {
188  cols(c, e);
189  rows(r, e);
190  return rows() * cols();
191  }
192 
194  EntryRefK entry(size_t r, size_t c) const {
195  return self->entries_[self->index(r, c)];
196  }
197 
199  EntryRefK entry(size_t r, size_t c, Entry const& e) {
200  self()->entries_[self->index(r, c)] = e;
201  return entry(r, c);
202  }
203 
205  EntryRef entryGet(size_t r, size_t c) {
206  return self()->entries_[self->index(r, c)];
207  }
208 
219  void entries(ssize_t rFirst, ssize_t rLast,
220  ssize_t cFirst, ssize_t cLast,
221  Entry const& e) {
222  for (ssize_t r = rFirst; r <= rLast; r++) {
223  for (ssize_t c = cFirst; c <=cFirst; c++) {
224  entry(r, c, e);
225  }
226  }
227  }
228 
240  Matrix subMatrix(size_t rFirst, size_t rLast,
241  size_t cFirst, size_t cLast) const {
242  if (rFirst > rLast || cFirst > cLast) return Matrix();
243  if (rFirst == 0 || cFirst == 0) {
244  Matrix ret(*this);
245  ret.size(rLast + 1, cLast + 1, Entry(0));
246  return ret;
247  }
248  Matrix ret(rLast - rFirst + 1, cLast - cFirst + 1, entry(rFirst, cFirst));
249  for (size_t r = rFirst; r <= rLast; r++)
250  for (size_t c = cFirst; c <= cLast; c++)
251  ret.entry(r - rFirst, c - cFirst, entry(r, c));
252  return ret;
253  }
254 
256  Matrix row(size_t r) const {
257  return subMatrix(r, r, 0, cols() - 1);
258  }
259 
261  Matrix col(size_t c) const {
262  return subMatrix(0, rows() - 1, c, c);
263  }
264 
266  Matrix positive() const {
267  return *this;
268  }
269 
271  Matrix negative() const {
272  Matrix ret(*this);
273  for (size_t r = 0, R = rows(); r < R; r++)
274  for (size_t c = 0, C = cols(); c < C; c++)
275  ret.entry(r, c, -ret.entry(r, c));
276  return ret;
277  }
278 
283  Matrix add(Matrix const& m) const {
284  if (rows() != m.rows() || cols() != m.cols()) return Matrix();
285  Matrix ret(*this);
286  for (size_t r = 0, R = rows(); r < R; r++)
287  for (size_t c = 0, C = cols(); c < C; c++)
288  ret.entry(r, c, ret.entry(r, c) + m.entry(r, c));
289  return ret;
290  }
291 
296  Matrix sub(Matrix const& m) const {
297  if (rows() != m.rows() || cols() != m.cols()) return Matrix();
298  Matrix ret(*this);
299  for (size_t r = 0, R = rows(); r < R; r++)
300  for (size_t c = 0, C = cols(); c < C; c++)
301  ret.entry(r, c, ret.entry(r, c) - m.entry(r, c));
302  return ret;
303  }
304 
309  Matrix mul(Matrix const& m) const {
310  if (cols() != m.rows()) return Matrix();
311  Matrix ret(rows(), m.cols(), Entry(0));
312  for (size_t r = 0, R = rows(); r < R; r++)
313  for (size_t c = 0, C = m.cols(); c < C; c++)
314  for (size_t k = 0, K = cols(); k < K; k++)
315  ret.entry(r, c, ret.entry(r, c) + entry(r, k) * m.entry(k, c));
316  return ret;
317  }
318 
320  Matrix mul(Entry const& s) const {
321  Matrix ret(*this);
322  for (size_t r = 0, R = rows(); r < R; r++)
323  for (size_t c = 0, C = cols(); c < C; c++)
324  ret.entry(r, c, ret.entry(r, c) * s);
325  return ret;
326  }
327 
329  Matrix div(Entry const& s) const {
330  Matrix ret(*this);
331  for (size_t r = 0, R = rows(); r < R; r++)
332  for (size_t c = 0, C = cols(); c < C; c++)
333  ret.entry(r, c, ret.entry(r, c) / s);
334  return ret;
335  }
336 
338  Matrix identity() const {
339  Matrix ret(*this);
340  ret.identitied();
341  return ret;
342  }
343 
350  for (size_t r = 0, R = rows(); r < R; r++)
351  for (size_t c = 0, C = cols(); c < C; c++)
352  entry(r, c, (r == c ? Entry(1) : Entry(0)));
353  return *this;
354  }
355 
361  Matrix inverse() const {
362  if (rows() != cols() || rows() == 0) return Matrix<Entry>();
363  Matrix tmp(rows(), cols() * 2, Entry(0));
364  for (size_t r = 0, R = rows(); r < R; r++) {
365  for (size_t c = 0, C = cols(); c < C; c++) {
366  tmp.entry(r, c, entry(r, c));
367  tmp.entry(r, c + cols(), (r == c ? Entry(1) : Entry(0)));
368  }
369  }
370  tmp.triangulared();
371  for (ssize_t r = rows() - 1; r >= 0; r--) {
372  if (tmp(r, r) == Entry(0)) return Matrix<Entry>();
373  for (ssize_t r2 = r - 1; r2 >= 0; r2--) {
374  Entry rat(-tmp.entry(r2, r) / tmp.entry(r, r));
375  for (size_t c = r, C = tmp.cols(); c < C; c++) {
376  tmp.entry(r2, c, tmp.entry(r2, c) + rat * tmp(r, c));
377  }
378  }
379  Entry rat(tmp.entry(r, r));
380  for (size_t c = cols(), C = tmp.cols(); c < C; c++) {
381  tmp.entry(r, c - cols(), tmp.entry(r, c) / rat);
382  }
383  }
384  tmp.size(cols(), rows(), Entry(0));
385  return tmp;
386  }
387 
390  copyFrom(inverse());
391  return *this;
392  }
393 
395  Matrix transpose() const {
396  Matrix ret(cols(), rows(), Entry(0));
397  for (size_t r = 0, R = cols(); r < R; r++)
398  for (size_t c = 0, C = rows(); c < C; c++)
399  ret.entry(r, c, entry(c, r));
400  return ret;
401  }
402 
405  copyFrom(transpose());
406  return *this;
407  }
408 
410  Matrix triangular() const {
411  Matrix<Entry> ret(*this);
412  ret.triangulared();
413  return ret;
414  }
415 
418  for (size_t r = 0, c = 0, R = rows(), C = cols(); r < R && c < C; r++) {
419  ssize_t maxR;
420  for ( ; c < C; c++) {
421  maxR = -1;
422  for (size_t r2 = r; r2 < R; r2++)
423  if (maxR == -1 || tAbs(entry(r2, c)) > tAbs(entry(maxR, c)))
424  maxR = r2;
425  if (entry(maxR, c) != Entry(0)) break;
426  }
427  if (c >= C) break;
428  if (maxR != (ssize_t)r) {
429  for (size_t c2 = c; c2 < C; c2++)
430  std::swap(self()->entries_[self->index( r, c2)],
431  self()->entries_[self->index(maxR, c2)]);
432  }
433  for (size_t r2 = r + 1; r2 < R; r2++) {
434  Entry rati = -entry(r2, c) / entry(r, c);
435  entry(r2, c, Entry(0));
436  for (size_t c2 = c + 1; c2 < C; c2++)
437  entry(r2, c2, entry(r2, c2) + entry(r, c2) * rati);
438  }
439  }
440  return *this;
441  }
442 
444  Matrix& operator=(Matrix const& m) {
445  return copyFrom(m);
446  }
447 
449  EntryRefK operator()(size_t r, size_t c) const {
450  return entry(r, c);
451  }
452 
454  EntryRefK operator()(size_t r, size_t c, Entry const& e) {
455  return entry(r, c, e);
456  }
457 
459  Matrix operator+() const {
460  return positive();
461  }
462 
464  Matrix operator-() const {
465  return negative();
466  }
467 
469  Matrix operator+(Matrix const& m) const {
470  return add(m);
471  }
472 
474  Matrix operator-(Matrix const& m) const {
475  return sub(m);
476  }
477 
479  Matrix operator*(Matrix const& m) const {
480  return mul(m);
481  }
482 
484  Matrix operator*(Entry const& s) const {
485  return mul(s);
486  }
487 
489  Matrix operator/(Entry const& s) const {
490  return div(s);
491  }
492 };
493 
494 } // meow
495 
496 #endif // math_Matrix_H__