Chi-Tech
dynamic_matrix.h
Go to the documentation of this file.
1#ifndef CHI_MATH_DYNAMIC_MATRIX_H
2#define CHI_MATH_DYNAMIC_MATRIX_H
3
4#include <vector>
5#include <stdexcept>
6#include <sstream>
7
8#include "chi_math.h"
9
10namespace chi_math
11{
12 template<class NumberFormat>
13 class DynamicMatrix;
14}
15
16#include "dynamic_vector.h"
17
18//###################################################################
19/**General dynamic matrix utility.*/
20template<class NumberFormat>
22{
23 typedef std::pair<size_t,size_t> MatDim;
24public:
25 std::vector<std::vector<NumberFormat>> elements_;
26
27 /**Default constructor. Does nothing.*/
29 {
30 static_assert(std::is_floating_point<NumberFormat>::value,
31 "Only floating point number formats are "
32 "supported for DynamicMatrix." );
33 }
34
35 /**Constructor with number of entries. Value defaults.*/
36 DynamicMatrix(size_t Nrows, size_t Ncols) :
37 elements_(Nrows, std::vector<NumberFormat>(Ncols))
38 {
39 static_assert(std::is_floating_point<NumberFormat>::value,
40 "Only floating point number formats are "
41 "supported for DynamicMatrix." );
42 }
43
44 /**Constructor with number of entries and default value.*/
45 DynamicMatrix(size_t Nrows, size_t Ncols, NumberFormat value) :
46 elements_(Nrows, std::vector<NumberFormat>(Ncols, value))
47 {
48 static_assert(std::is_floating_point<NumberFormat>::value,
49 "Only floating point number formats are "
50 "supported for DynamicMatrix." );
51 }
52
53 /**Copy constructor.*/
55
56 /**Assignment operator.*/
58 {
59 elements_ = other.elements_;
60 return *this;
61 }
62
63 /**Move constructor.*/
64 DynamicMatrix(DynamicMatrix&& other) noexcept
65 { elements_ = std::move(other.elements_);}
66
67 /**Move assignment operator.*/
69 {
70 elements_ = std::move(other.elements_);
71 return *this;
72 }
73
74 /**Constructor with vector.*/
75 explicit
76 DynamicMatrix(const std::vector<std::vector<double>>& in) { elements_ = in;}
77
78 /**Copy constructor with vector.*/
79 DynamicMatrix& operator=(const std::vector<std::vector<double>>& in)
80 {
81 elements_ = in;
82 return *this;
83 }
84
85 /**Constructor with vector.*/
86 DynamicMatrix(std::initializer_list<std::initializer_list<NumberFormat>> in)
87 {
88 elements_.clear();
89 for (auto& v : in)
90 elements_.push_back(v);
91 }
92
93 /**Copy constructor with vector.*/
94 DynamicMatrix& operator=(std::initializer_list<std::initializer_list<NumberFormat>> in)
95 {
96 elements_.clear();
97 for (auto& v : in)
98 elements_.push_back(v);
99 return *this;
100 }
101
102 //============================================= Element access
103 std::vector<NumberFormat>& operator[](size_t i) {return elements_[i];}
104
105 std::vector<NumberFormat>& at(size_t i) {return elements_.at(i);}
106
107 std::vector<NumberFormat>& back() {return elements_.back();}
108
109 std::vector<NumberFormat>& front() {return elements_.front();}
110
111 std::vector<NumberFormat>* data() {return elements_.data();}
112
113 void clear() {elements_.clear();}
114
115 void resize(size_t Nrows, size_t Ncols)
116 {
117 elements_.resize(Nrows);
118 for (auto& row : elements_)
119 row.resize(Ncols);
120 }
121
122 void resize(size_t Nrows, size_t Ncols, const NumberFormat& val)
123 {
124 elements_.resize(Nrows);
125 for (auto& row : elements_)
126 {
127 row.resize(Ncols,val);
128 for (auto& entry : row)
129 entry = val;
130 }
131 }
132
133 void reserve(size_t Nrows)
134 {
135 elements_.reserve(Nrows);
136 }
137
138 void push_back(const std::vector<NumberFormat>& val)
139 {elements_.push_back(val);}
140 void pop_back() {elements_.pop_back();}
141
142 bool empty() const noexcept {return elements_.empty();}
143
144 //============================================= Iterator access
145 typename std::vector<std::vector<NumberFormat>>::iterator
146 begin() {return elements_.begin();}
147
148 typename std::vector<std::vector<NumberFormat>>::iterator
149 end() {return elements_.end();}
150
151 size_t size() const {return elements_.size();}
152
154 {
155 if (elements_.empty())
156 return {0,0};
157 else
158 return {elements_.size(), elements_[0].size()};
159 }
160
161private:
162 static void bounds_check_rows_cols(const MatDim a, const MatDim b)
163 {
164 if ((a.first != b.first) or (a.second != b.second))
165 throw std::length_error("Mismatched square sizes of DynamicMatrix");
166 }
167
168 static void bounds_check_colsA_rowsB(const MatDim a, const MatDim b)
169 {
170 if (a.first != b.second)
171 throw std::length_error("Mismatched matrix A rows with matrix B cols"
172 " in DynamicMatrix");
173 }
174public:
175 //============================================= Addition
176 /**Component-wise addition of two matrices.
177 * \f$ \vec{w} = \vec{x} + \vec{y} \f$*/
179 {
180 auto dim = Dimensions();
182 DynamicMatrix<NumberFormat> newVector(dim.first, dim.second, 0.0);
183 for (int i=0; i<dim.first; ++i)
184 for (int j=0; j<dim.second;++j)
185 newVector.elements_[i][j] = elements_[i][j] + rhs.elements_[i][j];
186
187 return newVector;
188 }
189
190 /**In-place component-wise addition of two vectors.
191 * \f$ \vec{x} = \vec{x} + \vec{y} \f$*/
193 {
194 auto dim = Dimensions();
196 for (int i=0; i<dim.first; ++i)
197 for (int j=0; j<dim.second;++j)
198 elements_[i][j] = elements_[i][j] + rhs.elements_[i][j];
199
200 return *this;
201 }
202
203 //=========================================== Subtraction
204 /**Component-wise subtraction.
205 * \f$ \vec{w} = \vec{x} - \vec{y} \f$*/
207 {
208 auto dim = Dimensions();
210 DynamicMatrix<NumberFormat> newVector(dim.first, dim.second, 0.0);
211 for (int i=0; i<dim.first; ++i)
212 for (int j=0; j<dim.second;++j)
213 newVector.elements_[i][j] = elements_[i][j] - rhs.elements_[i][j];
214
215 return newVector;
216 }
217
218 /**In-place component-wise subtraction.
219 * \f$ \vec{x} = \vec{x} - \vec{y} \f$*/
221 {
222 auto dim = Dimensions();
224 for (int i=0; i<dim.first; ++i)
225 for (int j=0; j<dim.second;++j)
226 elements_[i][j] = elements_[i][j] - rhs.elements_[i][j];
227
228 return *this;
229 }
230
231 //=========================================== Multiplication
232 /**Vector component-wise multiplication by scalar.
233 * \f$ \vec{w} = \vec{x} \alpha \f$*/
234 DynamicMatrix operator*(const NumberFormat value) const
235 {
236 auto dim = Dimensions();
237 DynamicMatrix<NumberFormat> newVector(dim.first, dim.second);
238 for (int i=0; i<dim.first; ++i)
239 for (int j=0; j<dim.second;++j)
240 newVector.elements_[i][j] = elements_[i][j] * value;
241
242 return newVector;
243 }
244
245 /**Vector in-place component-wise multiplication by scalar.
246 * \f$ \vec{x} = \vec{x} \alpha \f$*/
247 DynamicMatrix& operator*=(const NumberFormat value)
248 {
249 auto dim = Dimensions();
250 for (int i=0; i<dim.first; ++i)
251 for (int j=0; j<dim.second;++j)
252 elements_[i][j] *= value;
253
254 return *this;
255 }
256
257 /** Matrix-Matrix multiplication */
259 {
260 auto dimA = Dimensions();
261 auto dimB = rhs.Dimensions();
262 bounds_check_colsA_rowsB(dimA,dimB);
263
264 DynamicMatrix<NumberFormat> newMatrix(dimA.first, dimB.second);
265 unsigned int istar=0;
266 unsigned int jstar=0;
267 for (unsigned int i=0; i<dimA.first; ++i)
268 {
269 for (unsigned int j=0; j<dimA.first; ++j)
270 {
271 NumberFormat value = 0.0;
272 for (unsigned int k=0; k<dimA.second; ++k)
273 value += elements_[i][k] * rhs.elements_[k][j];
274
275 newMatrix[istar][jstar] = value;
276 ++jstar;
277 }
278 ++istar;
279 jstar = 0;
280 }//for i
281
282 return newMatrix;
283 }
284
285 /** Matrix-Vector multiplication */
287 {
288 auto dimA = Dimensions();
289 auto dimV = V.size();
290
291 if (dimA.second != dimV)
292 throw std::length_error("Mismatched matrix vector sizes in"
293 " matrix-vector multiplication: DynamicMatrix");
294
295 DynamicVector<NumberFormat> newV(dimA.first);
296 unsigned int k=0;
297 for (unsigned int i=0; i<dimA.first; ++i)
298 {
299 NumberFormat value = 0.0;
300 for (unsigned int j=0; j<dimA.second; ++j)
301 value += elements_[i][j] * V[j];
302 newV[k] = value;
303 ++k;
304 }
305
306 return newV;
307 }
308
309 //=========================================== Division
310 /**Vector component-wise division by scalar.
311 * \f$ w_i = \frac{x_i}{\alpha} \f$*/
312 DynamicMatrix operator/(const NumberFormat value) const
313 {
314 auto dim = Dimensions();
315 DynamicMatrix<NumberFormat> newVector(dim.first, dim.second);
316 for (int i=0; i<dim.first; ++i)
317 for (int j=0; j<dim.second;++j)
318 newVector.elements_[i][j] = elements_[i][j] / value;
319
320 return newVector;
321 }
322
323 /**Vector in-place component-wise division by scalar.
324 * \f$ x_i = \frac{x_i}{\alpha} \f$*/
325 DynamicMatrix& operator/=(const NumberFormat value)
326 {
327 auto dim = Dimensions();
328 for (int i=0; i<dim.first; ++i)
329 for (int j=0; j<dim.second;++j)
330 elements_[i][j] /= value;
331
332 return *this;
333 }
334
335 //============================================= Operations
336 /**Obtains the inverse with Gauss-Elimination.*/
338 {
339 auto inv_elems = chi_math::InverseGEPivoting(elements_);
340
341 return DynamicMatrix<NumberFormat>(inv_elems);
342 }
343
344 /** Set the diagonal using a vector.*/
346 {
347 auto dimA = Dimensions();
348 auto dimV = V.size();
349
350 if ((dimA.first != dimV) or (dimA.second != dimV))
351 {
352 throw std::length_error("Mismatched matrix vector sizes in"
353 " matrix-vector diagonal assignment: DynamicMatrix");
354 }
355
356 for (int i=0; i<dimA.first; ++i)
357 elements_[i][i] = V[i];
358 }
359
360 /** Set the diagonal using value.*/
361 void SetDiagonal(NumberFormat val)
362 {
363 auto dimA = Dimensions();
364
365 for (int i=0; i<dimA.first; ++i)
366 elements_[i][i] = val;
367 }
368
369 /**Prints the matrix to a string and then returns the string.*/
370 std::string PrintStr() const
371 {
372 auto dim = Dimensions();
373 std::stringstream out;
374
375 for (int i = 0; i<dim.first ; ++i)
376 {
377 for (int j=0; j<(dim.second-1); ++j)
378 out << elements_[i][j] << " ";
379 out << elements_[i][dim.second - 1];
380
381 if (i<(dim.first -1)) out << "\n";
382 }
383
384 return out.str();
385 }
386};
387
388/**Multiplication by a scalar from the left.*/
389template<class NumberFormat>
392{
393 auto dim = that.Dimensions();
394 chi_math::DynamicMatrix<NumberFormat> newMatrix(dim.first, dim.second);
395 for (int i=0; i<dim.first; ++i)
396 for (int j=0; j<dim.second;++j)
397 newMatrix.elements_[i][j] = that.elements_[i][j] * value;
398
399 return newMatrix;
400}
401
402#endif //CHI_MATH_DYNAMIC_MATRIX_H
DynamicMatrix(DynamicMatrix &&other) noexcept
static void bounds_check_rows_cols(const MatDim a, const MatDim b)
DynamicMatrix operator-(const DynamicMatrix &rhs) const
DynamicMatrix & operator-=(const DynamicMatrix &rhs)
DynamicMatrix Inverse() const
DynamicMatrix & operator+=(const DynamicMatrix &rhs)
static void bounds_check_colsA_rowsB(const MatDim a, const MatDim b)
void SetDiagonal(DynamicVector< NumberFormat > &V)
DynamicMatrix & operator=(DynamicMatrix &&other) noexcept
std::vector< std::vector< NumberFormat > > elements_
DynamicMatrix operator*(const DynamicMatrix &rhs)
std::vector< NumberFormat > & at(size_t i)
bool empty() const noexcept
std::vector< std::vector< NumberFormat > >::iterator end()
DynamicMatrix & operator*=(const NumberFormat value)
std::vector< NumberFormat > * data()
DynamicMatrix operator*(const NumberFormat value) const
void resize(size_t Nrows, size_t Ncols)
DynamicMatrix & operator=(const DynamicMatrix &other)
std::vector< NumberFormat > & front()
DynamicMatrix operator/(const NumberFormat value) const
std::string PrintStr() const
DynamicMatrix operator+(const DynamicMatrix &rhs) const
MatDim Dimensions() const
void resize(size_t Nrows, size_t Ncols, const NumberFormat &val)
DynamicVector< NumberFormat > operator*(const DynamicVector< NumberFormat > &V)
DynamicMatrix(size_t Nrows, size_t Ncols)
DynamicMatrix(size_t Nrows, size_t Ncols, NumberFormat value)
void reserve(size_t Nrows)
std::vector< NumberFormat > & operator[](size_t i)
std::vector< std::vector< NumberFormat > >::iterator begin()
DynamicMatrix & operator=(std::initializer_list< std::initializer_list< NumberFormat > > in)
std::vector< NumberFormat > & back()
std::pair< size_t, size_t > MatDim
DynamicMatrix(std::initializer_list< std::initializer_list< NumberFormat > > in)
void push_back(const std::vector< NumberFormat > &val)
DynamicMatrix & operator/=(const NumberFormat value)
DynamicMatrix(const DynamicMatrix &other)
DynamicMatrix & operator=(const std::vector< std::vector< double > > &in)
void SetDiagonal(NumberFormat val)
DynamicMatrix(const std::vector< std::vector< double > > &in)
chi_math::DynamicMatrix< NumberFormat > operator*(const double value, chi_math::DynamicMatrix< NumberFormat > &that)
MatDbl InverseGEPivoting(const MatDbl &A)