NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
matdatastructures.hpp
Go to the documentation of this file.
1/*****************************************************************************
2 NumeRe: Framework fuer Numerische Rechnungen
3 Copyright (C) 2021 Erik Haenel et al.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17******************************************************************************/
18
19#ifndef MATDATASTRUCTURES_HPP
20#define MATDATASTRUCTURES_HPP
21
22#include <vector>
23#include <string>
24#include <complex>
25#include <utility>
26
27#include "../ui/error.hpp"
28#include "../utils/stringtools.hpp"
29
37class Matrix
38{
39 private:
40 std::vector<mu::value_type> m_storage;
41 size_t m_rows;
42 size_t m_cols;
44
54 mu::value_type& get(size_t i, size_t j)
55 {
56 return m_transpose ? m_storage[i*m_cols + j] : m_storage[i + j*m_rows];
57 }
58
68 const mu::value_type& get(size_t i, size_t j) const
69 {
70 return m_transpose ? m_storage[i*m_cols + j] : m_storage[i + j*m_rows];
71 }
72
82 {
83 if (m_transpose)
84 {
85 std::vector<mu::value_type> buffer(m_cols*m_rows);
86
87 for (size_t i = 0; i < m_rows; i++)
88 {
89 for (size_t j = 0; j < m_cols; j++)
90 {
91 buffer[i + j*m_rows] = m_storage[i*m_cols + j];
92 }
93 }
94
95 std::swap(buffer, m_storage);
96 m_transpose = false;
97 }
98 }
99
100 public:
104 Matrix() : m_rows(0u), m_cols(0u), m_transpose(false) {}
105
114 Matrix(size_t r, size_t c = 1u, const mu::value_type& init = NAN) : m_rows(r), m_cols(c), m_transpose(false)
115 {
116 m_storage.resize(r*c, init);
117 }
118
125 Matrix(const Matrix& mat)
126 {
127 assign(mat);
128 }
129
130 // We do not declare the move constructor by ourselves
131 Matrix(Matrix&& mat) = default;
132
140 Matrix(const std::vector<std::vector<mu::value_type>>& vectMatrix) : Matrix()
141 {
142 m_rows = vectMatrix.size();
143 m_cols = vectMatrix[0].size();
144
145 for (size_t i = 1; i < m_rows; i++)
146 {
147 m_cols = std::max(m_cols, vectMatrix[i].size());
148 }
149
150 m_storage.resize(m_rows*m_cols, NAN);
151
152 for (size_t i = 0; i < m_rows; i++)
153 {
154 for (size_t j = 0; j < vectMatrix[i].size(); j++)
155 get(i, j) = vectMatrix[i][j];
156 }
157 }
158
168 Matrix(size_t r, size_t c, mu::value_type* vVals, int nVals)
169 {
170 assign(r, c, vVals, nVals);
171 }
172
181 {
182 assign(mat);
183 return *this;
184 }
185
193 void assign(const Matrix& mat)
194 {
195 m_rows = mat.m_rows;
196 m_cols = mat.m_cols;
197 m_storage = mat.m_storage;
199 }
200
211 void assign(size_t r, size_t c, mu::value_type* vVals, int nVals)
212 {
213 m_storage.assign(vVals, vVals+std::min(r*c, (size_t)nVals));
214 m_rows = r;
215 m_cols = c;
216 m_storage.resize(m_rows*m_cols);
217 m_transpose = false;
218 }
219
229 void assign(size_t r, size_t c, const std::vector<mu::value_type>& vVals)
230 {
231 m_storage.assign(vVals.begin(), vVals.begin()+std::min(r*c, vVals.size()));
232 m_rows = r;
233 m_cols = c;
234 m_storage.resize(m_rows*m_cols);
235 m_transpose = false;
236 }
237
245 std::vector<mu::value_type>& data()
246 {
247 return m_storage;
248 }
249
257 const std::vector<mu::value_type>& data() const
258 {
259 return m_storage;
260 }
261
269 {
270 std::swap(m_rows, m_cols);
272 }
273
280 size_t rows() const
281 {
282 return m_rows;
283 }
284
291 size_t cols() const
292 {
293 return m_cols;
294 }
295
302 std::pair<size_t,size_t> dims() const
303 {
304 return std::make_pair(m_rows, m_cols);
305 }
306
314 bool isScalar() const
315 {
316 return m_rows == 1 && m_cols == 1;
317 }
318
326 bool isSquare() const
327 {
328 return m_rows == m_cols;
329 }
330
338 bool isEmpty() const
339 {
340 return !m_rows || !m_cols;
341 }
342
351 {
352 for (auto& v : m_storage)
353 {
354 if (mu::isnan(v) || mu::isinf(v))
355 return true;
356 }
357
358 return false;
359 }
360
368 std::string printDims() const
369 {
370 return toString(m_rows) + "x" + toString(m_cols);
371 }
372
382 mu::value_type& operator()(size_t i, size_t j = 0u)
383 {
384 if (i >= m_rows || j >= m_cols)
385 throw SyntaxError(SyntaxError::INVALID_INDEX, "INTERNAL INDEXING ERROR",
387 "MAT(" + toString(i) + "," + toString(j) + ") vs. size = " + printDims());
388
389 return get(i, j);
390 }
391
401 const mu::value_type& operator()(size_t i, size_t j = 0u) const
402 {
403 if (i >= m_rows || j >= m_cols)
404 throw SyntaxError(SyntaxError::INVALID_INDEX, "INTERNAL INDEXING ERROR",
406 "MAT(" + toString(i) + "," + toString(j) + ") vs. size = " + printDims());
407
408 return get(i, j);
409 }
410
421 void resize(size_t r, size_t c)
422 {
423 if (r == m_rows && c == m_cols)
424 return;
425
426 // Use a buffer
427 std::vector<mu::value_type> buffer(r*c);
428
429 // Copy the remaining elements
430 #pragma omp parallel for
431 for (size_t i = 0; i < std::min(r, m_rows); i++)
432 {
433 for (size_t j = 0; j < std::min(c, m_cols); j++)
434 {
435 buffer[i + j*r] = m_storage[i + j*m_rows];
436 }
437 }
438
439 // Swap storage with the buffer
440 std::swap(m_storage, buffer);
441
442 // Update the sizes
443 m_rows = r;
444 m_cols = c;
445 }
446
458 void extend(size_t r, size_t c)
459 {
460 if (isScalar())
461 return;
462
463 // We need to bake the transposition
465
466 if (r != m_rows || c != m_cols)
467 {
468 // Keep the relevant scalar dimensions
469 bool rowScalar = m_rows == 1 && r > 1;
470 bool colScalar = m_cols == 1 && c > 1;
471
472 // Resize the matrix
473 resize(r, c);
474
475 if (rowScalar)
476 {
477 for (size_t i = 1; i < m_rows; i++)
478 {
479 for (size_t j = 0; j < m_cols; j++)
480 {
481 get(i, j) = get(0, j);
482 }
483 }
484 }
485 else if (colScalar)
486 {
487 for (size_t j = 1; j < m_cols; j++)
488 {
489 for (size_t i = 0; i < m_rows; i++)
490 {
491 get(i, j) = get(i, 0);
492 }
493 }
494 }
495 }
496 }
497
507 {
508 assign(operator*(mat));
509 return *this;
510 }
511
520 Matrix operator*(const Matrix& mat) const
521 {
522 if (mat.m_rows != m_cols)
523 throw SyntaxError(SyntaxError::WRONG_MATRIX_DIMENSIONS_FOR_MATOP, "INTERNAL INDEXING ERROR",
525 printDims() + " vs. " + mat.printDims());
526
527 Matrix ret(m_rows, mat.m_cols, 0.0);
528
529 #pragma omp parallel for
530 for (size_t i = 0; i < ret.m_rows; i++)
531 {
532 for (size_t j = 0; j < ret.m_cols; j++)
533 {
534 for (size_t k = 0; k < m_cols; k++)
535 {
536 // Using the private method avoids addressing
537 // issues occuring with transposed matrices
538 ret.get(i, j) += get(i, k) * mat.get(k, j);
539 }
540 }
541 }
542
543 return ret;
544 }
545
553 Matrix hcat(const Matrix& mat) const
554 {
555 size_t cols = m_cols + mat.m_cols;
556 size_t rows = std::max(m_rows, mat.m_rows);
557
558 Matrix mRet(rows, cols);
559
560 // Copy this matrix
561 for (size_t i = 0; i < m_rows; i++)
562 {
563 for (size_t j = 0; j < m_cols; j++)
564 {
565 mRet.get(i, j) = get(i, j);
566 }
567 }
568
569 // Copy other matrix
570 for (size_t i = 0; i < mat.m_rows; i++)
571 {
572 for (size_t j = 0; j < mat.m_cols; j++)
573 {
574 mRet.get(i, j+m_cols) = mat.get(i, j);
575 }
576 }
577
578 return mRet;
579 }
580
588 Matrix vcat(const Matrix& mat) const
589 {
590 size_t cols = std::max(m_cols, mat.m_cols);
591 size_t rows = m_rows + mat.m_rows;
592
593 Matrix mRet(rows, cols);
594
595 // Copy this matrix
596 for (size_t i = 0; i < m_rows; i++)
597 {
598 for (size_t j = 0; j < m_cols; j++)
599 {
600 mRet.get(i, j) = get(i, j);
601 }
602 }
603
604 // Copy other matrix
605 for (size_t i = 0; i < mat.m_rows; i++)
606 {
607 for (size_t j = 0; j < mat.m_cols; j++)
608 {
609 mRet.get(i+m_rows, j) = mat.get(i, j);
610 }
611 }
612
613 return mRet;
614 }
615};
616
617
618
619// Erster Index: No. of Line; zweiter Index: No. of Col (push_back verwendet dazu stets zeilen!)
623//typedef std::vector<std::vector<std::complex<double>> > Matrix;
624
625
631{
632 const Matrix& mat1;
633 const Matrix& mat2;
634 const Matrix& mat3;
636 int nVal;
637 int mVal;
638
639 MatFuncData() : mat1(Matrix()), mat2(Matrix()), mat3(Matrix()), fVal(NAN), nVal(0), mVal(0) {}
640 MatFuncData(const Matrix& _mat, int n = 0) : mat1(_mat), mat2(Matrix()), mat3(Matrix()), fVal(NAN), nVal(n), mVal(0) {}
641 MatFuncData(const Matrix& _mat1, const Matrix& _mat2, int n) : mat1(_mat1), mat2(_mat2), mat3(Matrix()), fVal(NAN), nVal(n), mVal(0) {}
642 MatFuncData(const Matrix& _mat1, const Matrix& _mat2) : mat1(_mat1), mat2(_mat2), mat3(Matrix()), fVal(NAN), nVal(0), mVal(0) {}
643 MatFuncData(const Matrix& _mat1, const Matrix& _mat2, const Matrix& _mat3) : mat1(_mat1), mat2(_mat2), mat3(_mat3), fVal(NAN), nVal(0), mVal(0) {}
644 MatFuncData(const Matrix& _mat, mu::value_type f) : mat1(_mat), mat2(Matrix()), mat3(Matrix()), fVal(f), nVal(0), mVal(0) {}
645 MatFuncData(const Matrix& _mat, mu::value_type f, int n) : mat1(_mat), mat2(Matrix()), mat3(Matrix()), fVal(f), nVal(n), mVal(0) {}
646 MatFuncData(const Matrix& _mat, int n, int m) : mat1(_mat), mat2(Matrix()), mat3(Matrix()), fVal(NAN), nVal(n), mVal(m) {}
647 MatFuncData(int n, int m = 0) : mat1(Matrix()), mat2(Matrix()), mat3(Matrix()), fVal(NAN), nVal(n), mVal(m) {}
648};
649
650
656{
657 const std::string& command;
658 const std::string& expression;
659 size_t position;
660
661 MatFuncErrorInfo(const std::string& _sCmd, const std::string& _sExpr, size_t pos) : command(_sCmd), expression(_sExpr), position(pos) {}
662};
663
664
668typedef Matrix (*MatFunc)(const MatFuncData&, const MatFuncErrorInfo&);
669
670
676{
688
689
697{
701
703 MatFuncDef(MatFuncSignature sig, MatFunc f, bool isMatFunc = true) : signature(sig), func(f), isPureMatFunc(isMatFunc) {}
704};
705
706#endif // MATDATASTRUCTURES_HPP
707
This class defines a dynamic size 2D matrix with a single 1D internal buffer. If the internal buffer ...
Matrix(size_t r, size_t c, mu::value_type *vVals, int nVals)
Assign constructor from large array.
Matrix operator*(const Matrix &mat) const
Multiply this matrix with a matrix from the right.
std::string printDims() const
Convert the dimensions to a printable string.
void extend(size_t r, size_t c)
Extend this matrix to be prepared for the acutal mathematical operation. Scalars are not touched and ...
void bakeTransposition()
Bakes the transposition by swapping the actual elements instead of changing the read order.
const std::vector< mu::value_type > & data() const
Get a const reference to the internal data structure.
const mu::value_type & get(size_t i, size_t j) const
Const declared overload to the indexed access.
Matrix vcat(const Matrix &mat) const
Vertically concatenate two matrices.
void assign(size_t r, size_t c, mu::value_type *vVals, int nVals)
Assign a large array.
size_t m_rows
Number of rows.
Matrix()
Empty matrix default constructor.
std::vector< mu::value_type > & data()
Get a reference to the internal data structure.
Matrix & operator=(const Matrix &mat)
Assignment operator overload.
void resize(size_t r, size_t c)
Resize the matrix to another dimension. New elements will be zero-initialized.
void assign(size_t r, size_t c, const std::vector< mu::value_type > &vVals)
Assign a vector.
mu::value_type & operator()(size_t i, size_t j=0u)
Get a reference to the indexed element.
Matrix & operator*=(const Matrix &mat)
Multiply a matrix from the right to this matrix.
bool isSquare() const
Simple function to identify square matrices.
bool isEmpty() const
Simple function to identify empty matrices.
const mu::value_type & operator()(size_t i, size_t j=0u) const
Get a const reference to the indexed element.
size_t cols() const
The cols of this matrix.
mu::value_type & get(size_t i, size_t j)
Unchecked method to access indexed elements.
void assign(const Matrix &mat)
Assign a matrix.
size_t m_cols
Number of columns.
Matrix(const Matrix &mat)
Matrix copy constructor.
size_t rows() const
The rows of this matrix.
void transpose()
Transpose this matrix.
bool isScalar() const
Check, whether this matrix is actually a scalar.
Matrix hcat(const Matrix &mat) const
Horizontally concatenate two matrices.
std::vector< mu::value_type > m_storage
The internal buffer.
std::pair< size_t, size_t > dims() const
Get both dimensions at once.
Matrix(const std::vector< std::vector< mu::value_type > > &vectMatrix)
Construct a matrix from a vector matrix.
bool m_transpose
Is this Matrix transposed.
Matrix(Matrix &&mat)=default
bool containsInvalidValues() const
Returns true, if this matrix contains invalid values.
Matrix(size_t r, size_t c=1u, const mu::value_type &init=NAN)
Fill constructor.
Common exception class for all exceptions thrown in NumeRe.
Definition: error.hpp:32
@ WRONG_MATRIX_DIMENSIONS_FOR_MATOP
Definition: error.hpp:227
@ INVALID_INDEX
Definition: error.hpp:129
static size_t invalid_position
Definition: error.hpp:235
MatFuncSignature
Defines the different matrix function signatures.
@ MATSIG_MAT_F
@ MATSIG_MAT
@ MATSIG_MAT_F_N
@ MATSIG_N_MOPT
@ MATSIG_MAT_MAT_MAT
@ MATSIG_MAT_MAT
@ MATSIG_MAT_MAT_N
@ MATSIG_MAT_N_MOPT
@ MATSIG_MAT_NOPT
@ MATSIG_INVALID
Matrix(* MatFunc)(const MatFuncData &, const MatFuncErrorInfo &)
Defines the MatFunc type.
MUP_BASETYPE value_type
The numeric datatype used by the parser.
Definition: muParserDef.h:251
bool isnan(const value_type &v)
Definition: muParserDef.h:379
bool isinf(const value_type &v)
Definition: muParserDef.h:374
#define min(a, b)
Definition: resampler.cpp:34
#define max(a, b)
Definition: resampler.cpp:30
Defines a Matrix.
mu::value_type fVal
const Matrix & mat3
MatFuncData(const Matrix &_mat, int n=0)
MatFuncData(const Matrix &_mat1, const Matrix &_mat2)
MatFuncData(int n, int m=0)
MatFuncData(const Matrix &_mat, mu::value_type f, int n)
MatFuncData(const Matrix &_mat1, const Matrix &_mat2, const Matrix &_mat3)
MatFuncData(const Matrix &_mat, int n, int m)
const Matrix & mat1
MatFuncData(const Matrix &_mat1, const Matrix &_mat2, int n)
MatFuncData(const Matrix &_mat, mu::value_type f)
const Matrix & mat2
Defines a matrix function itself by containing the signature, the pointer to the implementation and a...
MatFuncDef(MatFuncSignature sig, MatFunc f, bool isMatFunc=true)
MatFuncSignature signature
Defines the needed information for displaying a reasonable error information.
MatFuncErrorInfo(const std::string &_sCmd, const std::string &_sExpr, size_t pos)
const std::string & command
const std::string & expression
std::string toString(int)
Converts an integer to a string without the Settings bloat.