32constexpr size_t MAX_SIZE = ~0ULL;
37 typename =
typename std::enable_if<
38 std::is_integral<T>::value || std::is_floating_point<T>::value,
41 std::vector<std::vector<T>> _mat;
50 template <
typename Integer,
51 typename =
typename std::enable_if<
52 std::is_integral<Integer>::value, Integer>::type>
54 for (
size_t i = 0; i <
size; ++i) {
55 _mat.emplace_back(std::vector<T>(
size, 0));
66 template <
typename Integer,
67 typename =
typename std::enable_if<
68 std::is_integral<Integer>::value, Integer>::type>
69 Matrix(
const Integer rows,
const Integer cols) {
70 for (
size_t i = 0; i < rows; ++i) {
71 _mat.emplace_back(std::vector<T>(cols, 0));
79 inline std::pair<size_t, size_t>
size()
const {
80 return {_mat.size(), _mat[0].size()};
90 template <
typename Integer,
91 typename =
typename std::enable_if<
92 std::is_integral<Integer>::value, Integer>::type>
106 Matrix slice(
const size_t row_start,
const size_t row_end = MAX_SIZE,
107 const size_t col_start = MAX_SIZE,
108 const size_t col_end = MAX_SIZE)
const {
109 const size_t h_size =
110 (row_end != MAX_SIZE ? row_end : _mat.size()) - row_start;
111 const size_t v_size = (col_end != MAX_SIZE ? col_end : _mat[0].size()) -
112 (col_start != MAX_SIZE ? col_start : 0);
115 const size_t v_start = (col_start != MAX_SIZE ? col_start : 0);
116 for (
size_t i = 0; i < h_size; ++i) {
117 for (
size_t j = 0; j < v_size; ++j) {
118 result._mat[i][j] = _mat[i + row_start][j + v_start];
130 template <
typename Number,
typename =
typename std::enable_if<
131 std::is_integral<Number>::value ||
132 std::is_floating_point<Number>::value,
135 assert(_mat.size() == other._mat.size());
136 for (
size_t i = 0; i < other._mat.size(); ++i) {
137 for (
size_t j = 0; j < other._mat[i].size(); ++j) {
138 _mat[i].push_back(other._mat[i][j]);
149 template <
typename Number,
typename =
typename std::enable_if<
150 std::is_integral<Number>::value ||
151 std::is_floating_point<Number>::value,
154 assert(_mat[0].
size() == other._mat[0].size());
155 for (
size_t i = 0; i < other._mat.size(); ++i) {
156 _mat.emplace_back(std::vector<T>(other._mat[i].size()));
157 for (
size_t j = 0; j < other._mat[i].size(); ++j) {
158 _mat.back()[j] = other._mat[i][j];
169 template <
typename Number,
typename =
typename std::enable_if<
170 std::is_integral<Number>::value ||
171 std::is_floating_point<Number>::value,
174 assert(this->
size() == other.
size());
176 for (
size_t i = 0; i < _mat.size(); ++i) {
177 for (
size_t j = 0; j < _mat[i].size(); ++j) {
178 C._mat[i][j] = _mat[i][j] + other._mat[i][j];
190 template <
typename Number,
typename =
typename std::enable_if<
191 std::is_integral<Number>::value ||
192 std::is_floating_point<Number>::value,
195 assert(this->
size() == other.
size());
196 for (
size_t i = 0; i < _mat.size(); ++i) {
197 for (
size_t j = 0; j < _mat[i].size(); ++j) {
198 _mat[i][j] += other._mat[i][j];
210 template <
typename Number,
typename =
typename std::enable_if<
211 std::is_integral<Number>::value ||
212 std::is_floating_point<Number>::value,
215 assert(this->
size() == other.
size());
217 for (
size_t i = 0; i < _mat.size(); ++i) {
218 for (
size_t j = 0; j < _mat[i].size(); ++j) {
219 C._mat[i][j] = _mat[i][j] - other._mat[i][j];
231 template <
typename Number,
typename =
typename std::enable_if<
232 std::is_integral<Number>::value ||
233 std::is_floating_point<Number>::value,
236 assert(this->
size() == other.
size());
237 for (
size_t i = 0; i < _mat.size(); ++i) {
238 for (
size_t j = 0; j < _mat[i].size(); ++j) {
239 _mat[i][j] -= other._mat[i][j];
251 template <
typename Number,
typename =
typename std::enable_if<
252 std::is_integral<Number>::value ||
253 std::is_floating_point<Number>::value,
256 assert(_mat[0].
size() == other._mat.size());
258 const size_t row =
size.first, col =
size.second;
262 return (row == col && (row & 1) == 0)
273 template <
typename Number,
typename =
typename std::enable_if<
274 std::is_integral<Number>::value ||
275 std::is_floating_point<Number>::value,
279 for (
size_t i = 0; i < _mat.size(); ++i) {
280 for (
size_t j = 0; j < _mat[i].size(); ++j) {
281 C._mat[i][j] = _mat[i][j] * other;
293 template <
typename Number,
typename =
typename std::enable_if<
294 std::is_integral<Number>::value ||
295 std::is_floating_point<Number>::value,
298 for (
size_t i = 0; i < _mat.size(); ++i) {
299 for (
size_t j = 0; j < _mat[i].size(); ++j) {
312 template <
typename Number,
typename =
typename std::enable_if<
313 std::is_integral<Number>::value ||
314 std::is_floating_point<Number>::value,
319 for (
size_t i = 0; i < _mat.size(); ++i) {
320 for (
size_t k = 0; k < _mat[0].size(); ++k) {
321 for (
size_t j = 0; j < other._mat[0].size(); ++j) {
322 C._mat[i][j] += _mat[i][k] * other._mat[k][j];
336 template <
typename Number,
typename =
typename std::enable_if<
337 std::is_integral<Number>::value ||
338 std::is_floating_point<Number>::value,
341 const size_t size = _mat.size();
346 if (
size <= 64ULL || (
size & 1ULL)) {
375 Matrix C11 = P5 + P4 - P2 + P6;
378 Matrix C22 = P1 + P5 - P3 - P7;
394 if (_mat.size() != other._mat.size() ||
395 _mat[0].size() != other._mat[0].size()) {
398 for (
size_t i = 0; i < _mat.size(); ++i) {
399 for (
size_t j = 0; j < _mat[i].size(); ++j) {
400 if (_mat[i][j] != other._mat[i][j]) {
408 friend std::ostream &operator<<(std::ostream &out,
const Matrix<T> &mat) {
409 for (
auto &row : mat._mat) {
410 for (
auto &elem : row) {
428 const size_t s = 512;
432 for (
size_t i = 0; i < s; ++i) {
433 for (
size_t j = 0; j < s; ++j) {
434 matrix_demo[i][j] = i + j;
440 for (
size_t i = 0; i < s; ++i) {
441 for (
size_t j = 0; j < s; ++j) {
442 matrix_demo2[i][j] = 2 + i + j;
446 auto start = std::chrono::system_clock::now();
447 auto Mat3 = matrix_demo2 * matrix_demo;
448 auto end = std::chrono::system_clock::now();
450 std::chrono::duration<double> time = (end - start);
451 std::cout <<
"Strassen time: " << time.count() <<
"s" << std::endl;
453 start = std::chrono::system_clock::now();
454 auto conf = matrix_demo2.naive_multiplication(matrix_demo);
455 end = std::chrono::system_clock::now();
458 std::cout <<
"Normal time: " << time.count() <<
"s" << std::endl;
461 assert(Mat3 == conf);
Matrix(const Integer size)
Constructor.
Matrix slice(const size_t row_start, const size_t row_end=MAX_SIZE, const size_t col_start=MAX_SIZE, const size_t col_end=MAX_SIZE) const
Creates a new matrix and returns a part of it.
Matrix & operator-=(const Matrix< Number > &other) const
Subtract another matrices to current matrix.
Matrix(const Integer rows, const Integer cols)
Constructor.
bool operator==(const Matrix< T > &other) const
Compares two matrices if each of them are equal or not.
Matrix naive_multiplication(const Matrix< Number > &other) const
Naive multiplication performed on this.
Matrix operator*(const Matrix< Number > &other) const
Multiply two matrices and returns a new matrix.
Matrix operator-(const Matrix< Number > &other) const
Subtract two matrices and returns a new matrix.
Matrix strassens_multiplication(const Matrix< Number > &other) const
Strassens method of multiplying two matrices References: https://en.wikipedia.org/wiki/Strassen_algor...
void h_stack(const Matrix< Number > &other)
Horizontally stack the matrix (one after the other)
std::vector< T > & operator[](const Integer index)
returns the address of the element at ith place (here ith row of the matrix)
Matrix operator+(const Matrix< Number > &other) const
Add two matrices and returns a new matrix.
Matrix & operator+=(const Matrix< Number > &other) const
Add another matrices to current matrix.
std::pair< size_t, size_t > size() const
Get the matrix shape.
Matrix operator*(const Number other) const
Multiply matrix with a number and returns a new matrix.
Matrix & operator*=(const Number other) const
Multiply a number to current matrix.
void v_stack(const Matrix< Number > &other)
Horizontally stack the matrix (current matrix above the other)
Namespace for performing strassen's multiplication.