openGPMP
Open Source Mathematics Package
mtx_tmpl.hpp
Go to the documentation of this file.
1 /*************************************************************************
2  *
3  * Project
4  * _____ _____ __ __ _____
5  * / ____| __ \| \/ | __ \
6  * ___ _ __ ___ _ __ | | __| |__) | \ / | |__) |
7  * / _ \| '_ \ / _ \ '_ \| | |_ | ___/| |\/| | ___/
8  *| (_) | |_) | __/ | | | |__| | | | | | | |
9  * \___/| .__/ \___|_| |_|\_____|_| |_| |_|_|
10  * | |
11  * |_|
12  *
13  * Copyright (C) Akiel Aries, <akiel@akiel.org>, et al.
14  *
15  * This software is licensed as described in the file LICENSE, which
16  * you should have received as part of this distribution. The terms
17  * among other details are referenced in the official documentation
18  * seen here : https://akielaries.github.io/openGPMP/ along with
19  * important files seen in this project.
20  *
21  * You may opt to use, copy, modify, merge, publish, distribute
22  * and/or sell copies of the Software, and permit persons to whom
23  * the Software is furnished to do so, under the terms of the
24  * LICENSE file. As this is an Open Source effort, all implementations
25  * must be of the same methodology.
26  *
27  *
28  *
29  * This software is distributed on an AS IS basis, WITHOUT
30  * WARRANTY OF ANY KIND, either express or implied.
31  *
32  ************************************************************************/
33 
41 #ifndef MATRIX_TMPL_HPP
42 #define MATRIX_TMPL_HPP
43 
44 #include <cassert>
45 #include <cmath>
46 #include <functional>
47 #include <iostream>
48 #include <random>
49 #include <stdio.h>
50 #include <tuple>
51 #include <vector>
52 
53 namespace gpmp {
54 
55 namespace linalg {
56 
61 template <typename Type> class Matrix {
62  public:
63  size_t cols;
64  size_t rows;
65 
66  std::vector<Type> data;
67  std::tuple<size_t, size_t> dim;
68 
69  int64_t num_elements = rows * cols;
70 
77  Matrix(size_t mtx_rows, size_t mtx_cols)
78  : cols(cols), rows(rows), data({}) {
79  // initialize an empty vector for storage
80  data.resize(cols * rows, Type());
81  dim = std::make_tuple(rows, cols);
82  }
83  Matrix() : cols(0), rows(0), data({}) {
84  dim = {rows, cols};
85  };
86 
93  Type &operator()(size_t row, size_t col) {
94  assert(0 <= row && row < rows);
95  assert(0 <= col && col < cols);
96 
97  return data[row * cols + col];
98  }
99 
107  Matrix mult(Matrix &target) {
108  assert(cols == target.rows);
109  Matrix res(rows, target.cols);
110 
111  for (size_t r = 0; res.rows; ++r) {
112  for (size_t c = 0; res.cols; ++c) {
113  for (size_t n = 0; n < target.rows; ++n) {
114  res(r, c) += (*this)(r, n) * target(n, c);
115  }
116  }
117  }
118  return res;
119  }
120 
121  /*
122  * Multiply scalars
123  */
124  Matrix scalar_mult(Type scalar) {
125  Matrix res((*this));
126 
127  for (size_t r = 0; r < res.rows; ++r) {
128  for (size_t c = 0; c < res.cols; ++c) {
129  res(r, c) = scalar * (*this)(r, c);
130  }
131  }
132  return res;
133  }
134 
135  /*
136  * square matrix whose entries are either +1 or −1 and whose rows are
137  * mutually orthogonal
138  */
139  Matrix hadamard(Matrix &target) {
140  assert(dim == target.dim);
141  Matrix res((*this));
142 
143  for (size_t r = 0; r < res.rows; ++r) {
144  for (size_t c = 0; c < res.cols; ++c) {
145  res(r, c) = target(r, c) * (*this)(r, c);
146  }
147  }
148  return res;
149  }
150 
151  /*
152  * Element based squaring of matrices. Method allows for finding
153  * the squared error
154  */
156  Matrix res((*this));
157 
158  res = hadamard(res);
159  return res;
160  }
161 
162  /*
163  * Matrix Addition
164  */
165  Matrix add(Matrix &target) {
166  assert(dim == target.dim);
167  Matrix res(rows, target.cols);
168 
169  for (size_t r = 0; r < res.rows; ++r) {
170  for (size_t c = 0; c < res.cols; ++c) {
171  res(r, c) = (*this)(r, c) + target(r, c);
172  }
173  }
174  return res;
175  }
177  return add(target);
178  }
179 
180  /*
181  * Addition of scalars
182  */
183  Matrix scalar_add(Type scalar) {
184  Matrix res((*this));
185 
186  for (size_t r = 0; r < rows; ++r) {
187  for (size_t c = 0; c < cols; ++c) {
188  res(r, c) = (*this)(r, c) + scalar;
189  }
190  }
191  return res;
192  }
193 
195  Matrix res(rows, cols);
196 
197  for (size_t r = 0; r < rows; ++r) {
198  for (size_t c = 0; c < cols; ++c) {
199  res(r, c) = -(*this)(r, c);
200  }
201  }
202  return res;
203  }
204 
205  /*
206  * Matrix subtraction
207  */
208  Matrix sub(Matrix &target) {
209  Matrix target_neg = -target;
210  return add(target_neg);
211  }
213  return sub(target);
214  }
215 
217  assert(dim == target.dim);
219 
220  for (int64_t r = 0; r < rows; ++r) {
221  for (int64_t c = 0; c < cols; ++c) {
222  if ((*this)(r, c) - target(r, c) == 0.)
223  res(r, c) = 1;
224  else
225  res(r, c) = 0;
226  }
227  }
228  return res;
229  }
230 
231  // Matrix<ushort> operator!=(Matrix &target) {
232  // return (!(*this)) == target;
233  //}
234 
235  bool all() {
236  int64_t counter{0};
237 
238  for (int64_t r = 0; r < rows; ++r) {
239  for (int64_t c = 0; c < cols; ++c) {
240  if ((*this)(r, c))
241  counter++;
242  }
243  }
244  return (counter == num_elements);
245  }
246 
247  /*
248  * Transpose the matrix
249  */
251  size_t new_rows{cols}, new_cols{rows};
252  Matrix transposed(new_rows, new_cols);
253 
254  for (size_t r = 0; r < new_rows; ++r) {
255  for (size_t c = 0; c < new_cols; ++c) {
256  transposed(r, c) = (*this)(c, r);
257  }
258  }
259  return transposed;
260  }
261 
262  Matrix T() {
263  return (*this).transpose();
264  }
265 
266  /*
267  * Compute sum of matrix by element
268  */
270  Matrix res{1, 1};
271 
272  for (size_t r = 0; r < rows; ++r) {
273  for (size_t c = 0; c < cols; ++c) {
274  res(0, 0) += (*this)(r, c);
275  }
276  }
277  return res;
278  }
279 
280  /*
281  * Compute sum of matrix by dimension
282  */
283  Matrix sum(size_t dimension) {
284  assert(0 <= dimension && dimension < 2);
285  auto res = (dimension = 0) ? Matrix{1, cols} : Matrix{rows, 1};
286 
287  if (dimension == 0) {
288  for (size_t c = 0; c < cols; ++c) {
289  for (size_t r = 0; r < rows; ++r) {
290  res(0, c) += (*this)(r, c);
291  }
292  }
293  } else {
294  for (size_t r = 0; r < rows; ++r) {
295  for (size_t c = 0; c < cols; ++c) {
296  res(r, 0) += (*this)(r, c);
297  }
298  }
299  }
300  return res;
301  }
302 
303  // Compute mean of matrix by elements
305  auto m = Type(num_elements);
306  return sum().scalar_mult(1 / m);
307  }
308 
309  /*
310  * Compute mean of matrix by dimension
311  */
312  Matrix mean(size_t dimension) {
313  auto m = (dimension == 0) ? Type(rows) : Type(cols);
314  return sum().scalar_mult(1 / m);
315  }
316 
317  /*
318  * Concatenate two given matrices
319  */
320  Matrix concatenate(Matrix target, size_t dimension) {
321  (dimension == 0) ? assert(rows == target.rows)
322  : assert(cols == target.cols);
323 
324  auto res = (dimension == 0) ? Matrix{rows + target.rows, cols}
325  : Matrix{rows, cols + target.cols};
326 
327  // copy self
328  for (size_t r = 0; r < rows; ++r) {
329  for (size_t c = 0; c < cols; ++c) {
330  res(r, c) = (*this)(r, c);
331  }
332  }
333 
334  // copy target
335  if (dimension == 0) {
336  for (size_t r = 0; r < target.rows; ++r) {
337  for (size_t c = 0; c < cols; ++c) {
338  res(r + rows, c) = target(r, c);
339  }
340  }
341  } else {
342  for (size_t r = 0; r < rows; ++r) {
343  for (size_t c = 0; c < target.cols; ++c) {
344  res(r, c + cols) = target(r, c);
345  }
346  }
347  }
348  return res;
349  }
350 
352  assert((rows == 1 || cols == 1) || (rows == cols));
353 
354  if (rows == 1 || cols == 1) {
355  Matrix res{std::max(rows, cols), std::max(rows, cols)};
356  for (size_t i = 0; i < rows; ++i)
357  res(i, i) = (*this)(i, 0);
358  return res;
359  } else {
360  assert(rows == cols);
361  Matrix res{rows, 1};
362  for (size_t i = 0; i < rows; ++i)
363  res(i, 0) = (*this)(i, i);
364  return res;
365  }
366  }
367 
368  Matrix apply_func(const std::function<Type(const Type &)> &function) {
369  Matrix res((*this));
370 
371  for (size_t r = 0; r < rows; ++r) {
372  for (size_t c = 0; c < cols; ++c) {
373  res(r, c) = function((*this)(r, c));
374  }
375  }
376  return res;
377  }
378 
379  void print_shape() {
380  std::cout << "Matrix Size([" << rows << ", " << cols << "])"
381  << std::endl;
382  }
383 
384  void print_mtx() {
385  for (size_t r = 0; r < rows; ++r) {
386  for (int64_t c = 0; c < cols; ++c) {
387  std::cout << (*this)(r, c) << " ";
388  }
389  std::cout << std::endl;
390  }
391  std::cout << std::endl;
392  }
393 
394  void fill_index(Type val) {
395  for (size_t r = 0; r < rows; ++r) {
396  for (int64_t c = 0; c < cols; ++c) {
397  (*this)(r, c) = val;
398  }
399  }
400  }
401 };
402 
403 template <typename T>
408 struct mtx {
412  static Matrix<T> zeros(size_t rows, size_t cols) {
413  Matrix<T> MTX{rows, cols};
414  // fill by index
415  MTX.fill_index(T(0));
416  return MTX;
417  }
418 
419  static Matrix<T> ones(size_t rows, size_t cols) {
420  Matrix<T> MTX{rows, cols};
421  MTX.fill_index(T(1));
422  return MTX;
423  }
424 
425  static Matrix<T> randn(size_t rows, size_t cols) {
426  Matrix<T> MTX{rows, cols};
427 
428  std::random_device rd{};
429  std::mt19937 gen{rd()};
430  T n(MTX.num_elements);
431  T stdev{1 / sqrt(n)};
432  std::normal_distribution<T> d{0, stdev};
433 
434  for (size_t r = 0; r < rows; ++r) {
435  for (uint64_t c = 0; c < cols; ++c) {
436  MTX(r, c) = d(gen);
437  }
438  }
439  return MTX;
440  }
441  static Matrix<T> rand(size_t rows, size_t cols) {
442  Matrix<T> MTX{rows, cols};
443 
444  std::random_device rd{};
445  std::mt19937 gen{rd()};
446  std::uniform_real_distribution<T> d{0, 1};
447 
448  for (size_t r = 0; r < rows; ++r) {
449  for (int64_t c = 0; c < cols; ++c) {
450  MTX(r, c) = d(gen);
451  }
452  }
453  return MTX;
454  }
455 };
456 
457 } // namespace linalg
458 
459 } // namespace gpmp
460 
461 #endif
Matrix and Scalar operations.
Definition: mtx_tmpl.hpp:61
Matrix(size_t mtx_rows, size_t mtx_cols)
Matrix Class constructor initializing empty vector.
Definition: mtx_tmpl.hpp:77
Matrix operator-(Matrix &target)
Definition: mtx_tmpl.hpp:212
Matrix< unsigned short > operator==(Matrix &target)
Definition: mtx_tmpl.hpp:216
Matrix mean(size_t dimension)
Definition: mtx_tmpl.hpp:312
std::vector< Type > data
Definition: mtx_tmpl.hpp:66
Matrix scalar_add(Type scalar)
Definition: mtx_tmpl.hpp:183
void fill_index(Type val)
Definition: mtx_tmpl.hpp:394
Matrix add(Matrix &target)
Definition: mtx_tmpl.hpp:165
Matrix hadamard(Matrix &target)
Definition: mtx_tmpl.hpp:139
Type & operator()(size_t row, size_t col)
Overload operator.
Definition: mtx_tmpl.hpp:93
Matrix sum(size_t dimension)
Definition: mtx_tmpl.hpp:283
Matrix operator+(Matrix &target)
Definition: mtx_tmpl.hpp:176
std::tuple< size_t, size_t > dim
Definition: mtx_tmpl.hpp:67
Matrix concatenate(Matrix target, size_t dimension)
Definition: mtx_tmpl.hpp:320
Matrix sub(Matrix &target)
Definition: mtx_tmpl.hpp:208
Matrix apply_func(const std::function< Type(const Type &)> &function)
Definition: mtx_tmpl.hpp:368
Matrix mult(Matrix &target)
Matrix Multiplication.
Definition: mtx_tmpl.hpp:107
Matrix scalar_mult(Type scalar)
Definition: mtx_tmpl.hpp:124
The source C++ openGPMP namespace.
Matrix struct.
Definition: mtx_tmpl.hpp:408
static Matrix< T > zeros(size_t rows, size_t cols)
Matrix zeros method.
Definition: mtx_tmpl.hpp:412
static Matrix< T > randn(size_t rows, size_t cols)
Definition: mtx_tmpl.hpp:425
static Matrix< T > ones(size_t rows, size_t cols)
Definition: mtx_tmpl.hpp:419
static Matrix< T > rand(size_t rows, size_t cols)
Definition: mtx_tmpl.hpp:441