/** * @file Matrix.hpp * * A simple matrix template library. * * @author James Goppert */ #pragma once #include #include #include #include #include #if defined(SUPPORT_STDIOSTREAM) #include #include #endif // defined(SUPPORT_STDIOSTREAM) #include "math.hpp" namespace matrix { template class Vector; template class Matrix { public: Type _data[M][N]; virtual ~Matrix() {}; Matrix() : _data() { } Matrix(const Type *data_) : _data() { memcpy(_data, data_, sizeof(_data)); } Matrix(const Matrix &other) : _data() { memcpy(_data, other._data, sizeof(_data)); } /** * Accessors/ Assignment etc. */ Type *data() { return _data[0]; } inline Type operator()(size_t i, size_t j) const { return _data[i][j]; } inline Type &operator()(size_t i, size_t j) { return _data[i][j]; } void operator=(const Matrix &other) { if (this != &other) { memcpy(_data, other._data, sizeof(_data)); } } /** * Matrix Operations */ // this might use a lot of programming memory // since it instantiates a class for every // required mult pair, but it provides // compile time size_t checking template Matrix operator*(const Matrix &other) const { const Matrix &self = *this; Matrix res; res.setZero(); for (size_t i = 0; i < M; i++) { for (size_t k = 0; k < P; k++) { for (size_t j = 0; j < N; j++) { res(i, k) += self(i, j) * other(j, k); } } } return res; } Matrix emult(const Matrix &other) const { Matrix res; const Matrix &self = *this; for (size_t i = 0; i < M; i++) { for (size_t j = 0; j < N; j++) { res(i , j) = self(i, j)*other(i, j); } } return res; } Matrix operator+(const Matrix &other) const { Matrix res; const Matrix &self = *this; for (size_t i = 0; i < M; i++) { for (size_t j = 0; j < N; j++) { res(i , j) = self(i, j) + other(i, j); } } return res; } bool operator==(const Matrix &other) const { const Matrix &self = *this; static const Type eps = Type(1e-4); for (size_t i = 0; i < M; i++) { for (size_t j = 0; j < N; j++) { if (fabs(self(i , j) - other(i, j)) > eps) { return false; } } } return true; } Matrix operator-(const Matrix &other) const { Matrix res; const Matrix &self = *this; for (size_t i = 0; i < M; i++) { for (size_t j = 0; j < N; j++) { res(i , j) = self(i, j) - other(i, j); } } return res; } // unary minus Matrix operator-() const { Matrix res; const Matrix &self = *this; for (size_t i = 0; i < M; i++) { for (size_t j = 0; j < N; j++) { res(i , j) = -self(i, j); } } return res; } void operator+=(const Matrix &other) { Matrix &self = *this; self = self + other; } void operator-=(const Matrix &other) { Matrix &self = *this; self = self - other; } template void operator*=(const Matrix &other) { Matrix &self = *this; self = self * other; } /** * Scalar Operations */ Matrix operator*(Type scalar) const { Matrix res; const Matrix &self = *this; for (size_t i = 0; i < M; i++) { for (size_t j = 0; j < N; j++) { res(i , j) = self(i, j) * scalar; } } return res; } inline Matrix operator/(Type scalar) const { return (*this)*(1/scalar); } Matrix operator+(Type scalar) const { Matrix res; const Matrix &self = *this; for (size_t i = 0; i < M; i++) { for (size_t j = 0; j < N; j++) { res(i , j) = self(i, j) + scalar; } } return res; } inline Matrix operator-(Type scalar) const { return (*this) + (-1*scalar); } void operator*=(Type scalar) { Matrix &self = *this; for (size_t i = 0; i < M; i++) { for (size_t j = 0; j < N; j++) { self(i, j) = self(i, j) * scalar; } } } void operator/=(Type scalar) { Matrix &self = *this; self = self * (1.0f / scalar); } inline void operator+=(Type scalar) { *this = (*this) + scalar; } inline void operator-=(Type scalar) { *this = (*this) - scalar; } /** * Misc. Functions */ void write_string(char * buf, size_t n) const { const Matrix &self = *this; char data_buf[500] = {0}; for (size_t i = 0; i < M; i++) { char data_line[100] = {0}; char data_line_formatted[100] = {0}; for (size_t j = 0; j < N; j++) { char val_buf[15]; if (j == N-1) { snprintf(val_buf, 15, "\t%10g", double(self(i, j))); } else { snprintf(val_buf, 15, "\t%10g,", double(self(i, j))); } strncat(data_line, val_buf, 300); } if (i == M-1) { snprintf(data_line_formatted, n, "[%s]", data_line); } else { snprintf(data_line_formatted, n, "[%s],\n", data_line); } strncat(data_buf, data_line_formatted, n); } snprintf(buf, n, "[%s]", data_buf); } void print() const { char buf[200]; write_string(buf, 200); printf("%s\n", buf); } Matrix transpose() const { Matrix res; const Matrix &self = *this; for (size_t i = 0; i < M; i++) { for (size_t j = 0; j < N; j++) { res(j, i) = self(i, j); } } return res; } // tranpose alias inline Matrix T() const { return transpose(); } template Matrix slice(size_t x0, size_t y0) const { Matrix res(&(_data[x0][y0])); return res; } template void set(const Matrix &m, size_t x0, size_t y0) { Matrix &self = *this; for (size_t i = 0; i < P; i++) { for (size_t j = 0; j < Q; j++) { self(i + x0, j + y0) = m(i, j); } } } void setZero() { memset(_data, 0, sizeof(_data)); } void setAll(Type val) { Matrix &self = *this; for (size_t i = 0; i < M; i++) { for (size_t j = 0; j < N; j++) { self(i, j) = val; } } } inline void setOne() { setAll(1); } void setIdentity() { setZero(); Matrix &self = *this; for (size_t i = 0; i < M and i < N; i++) { self(i, i) = 1; } } inline void swapRows(size_t a, size_t b) { if (a == b) { return; } Matrix &self = *this; for (size_t j = 0; j < N; j++) { Type tmp = self(a, j); self(a, j) = self(b, j); self(b, j) = tmp; } } inline void swapCols(size_t a, size_t b) { if (a == b) { return; } Matrix &self = *this; for (size_t i = 0; i < M; i++) { Type tmp = self(i, a); self(i, a) = self(i, b); self(i, b) = tmp; } } Matrix abs() { Matrix r; for (size_t i=0; i max_val) { max_val = val; } } } return max_val; } Type min() { Type min_val = (*this)(0,0); for (size_t i=0; i Matrix zeros() { Matrix m; m.setZero(); return m; } template Matrix ones() { Matrix m; m.setOne(); return m; } template Matrix operator*(Type scalar, const Matrix &other) { return other * scalar; } template bool isEqual(const Matrix &x, const Matrix & y) { if (!(x == y)) { char buf_x[100]; char buf_y[100]; x.write_string(buf_x, 100); y.write_string(buf_y, 100); printf("not equal\nx:\n%s\ny:\n%s\n", buf_x, buf_y); } return x == y; } #if defined(SUPPORT_STDIOSTREAM) template std::ostream& operator<<(std::ostream& os, const matrix::Matrix& matrix) { for (size_t i = 0; i < M; ++i) { os << "["; for (size_t j = 0; j < N; ++j) { os << std::setw(10) << static_cast(matrix(i, j)); os << "\t"; } os << "]" << std::endl; } return os; } #endif // defined(SUPPORT_STDIOSTREAM) typedef Matrix Matrix3f; } // namespace matrix /* vim: set et fenc=utf-8 ff=unix sts=0 sw=4 ts=4 : */