13 View(T *data, std::size_t start, std::size_t size, std::size_t stride)
14 : m_size(size), m_stride(stride), m_data(data +
long(start)) {}
16 std::size_t size()
const {
return m_size; }
19 T &
operator[](std::size_t i) {
return m_data[i * m_stride]; }
21 T
operator[](std::size_t i)
const {
return m_data[i * m_stride]; }
24 T &
at(std::size_t i) {
26 return m_data[i * m_stride];
29 T
at(std::size_t i)
const {
31 return m_data[i * m_stride];
38 T *data() {
return m_data; }
50 static_assert(std::is_same_v<T, double> ||
51 std::is_same_v<T, std::complex<double>>,
52 "Determinant only works for double");
54 assert(rows() == cols() &&
"Determinant only defined for square matrix");
58 auto gsl_view = LU.as_gsl_view();
59 gsl_permutation *permutn = gsl_permutation_alloc(rows());
60 if constexpr (std::is_same_v<T, double>) {
61 gsl_linalg_LU_decomp(&gsl_view.matrix, permutn, &sLU);
62 gsl_permutation_free(permutn);
63 return gsl_linalg_LU_det(&gsl_view.matrix, sLU);
64 }
else if constexpr (std::is_same_v<T, std::complex<double>>) {
65 gsl_linalg_complex_LU_decomp(&gsl_view.matrix, permutn, &sLU);
66 gsl_permutation_free(permutn);
67 const auto gsl_cmplx = gsl_linalg_complex_LU_det(&gsl_view.matrix, sLU);
69 return {GSL_REAL(gsl_cmplx), GSL_IMAG(gsl_cmplx)};
79 std::is_same_v<T, double> || std::is_same_v<T, std::complex<double>>,
80 "invert only works for Matrix<double> or Matrix<complex<double>>");
82 assert(rows() == cols() &&
"Inverse only defined for square matrix");
89 auto LU_gsl = LU.as_gsl_view();
90 auto iverse_gsl = this->as_gsl_view();
91 gsl_permutation *permutn = gsl_permutation_alloc(m_rows);
92 if constexpr (std::is_same_v<T, double>) {
93 gsl_linalg_LU_decomp(&LU_gsl.matrix, permutn, &sLU);
94 gsl_linalg_LU_invert(&LU_gsl.matrix, permutn, &iverse_gsl.matrix);
95 }
else if constexpr (std::is_same_v<T, std::complex<double>>) {
96 gsl_linalg_complex_LU_decomp(&LU_gsl.matrix, permutn, &sLU);
97 gsl_linalg_complex_LU_invert(&LU_gsl.matrix, permutn, &iverse_gsl.matrix);
99 gsl_permutation_free(permutn);
105 auto inverse = *
this;
113 if constexpr (std::is_same_v<T, double>) {
115 const auto this_gsl = as_gsl_view();
116 gsl_matrix_transpose_memcpy(&Tr_gsl.matrix, &this_gsl.matrix);
117 }
else if constexpr (std::is_same_v<T, float>) {
119 const auto this_gsl = as_gsl_view();
120 gsl_matrix_float_transpose_memcpy(&Tr_gsl.matrix, &this_gsl.matrix);
121 }
else if constexpr (std::is_same_v<T, std::complex<double>>) {
123 const auto this_gsl = as_gsl_view();
124 gsl_matrix_complex_transpose_memcpy(&Tr_gsl.matrix, &this_gsl.matrix);
125 }
else if constexpr (std::is_same_v<T, std::complex<float>>) {
127 const auto this_gsl = as_gsl_view();
128 gsl_matrix_complex_float_transpose_memcpy(&Tr_gsl.matrix, &this_gsl.matrix);
131 for (
auto i = 0ul; i < Tr.
rows(); ++i) {
132 for (
auto j = 0ul; j < Tr.
cols(); ++j) {
133 Tr[i][j] = (*this)[j][i];
144 assert(m_rows == m_cols &&
"Can only call make_identity() for square matrix");
145 for (
auto i = 0ul; i < m_rows; ++i) {
146 for (
auto j = 0ul; j < m_cols; ++j) {
147 at(i, j) = i == j ? T(1) : T(0);
155 for (std::size_t i = 0; i < size(); ++i) {
164 static_assert(is_complex_v<T>,
"conj() only available for complex Matrix");
165 std::vector<T> conj_data;
166 conj_data.reserve(m_data.size());
167 for (std::size_t i = 0; i < m_data.size(); ++i) {
168 conj_data.push_back(std::conj(m_data[i]));
170 return Matrix<T>{m_rows, m_cols, std::move(conj_data)};
175 static_assert(is_complex_v<T>,
"conj() only available for complex Matrix");
176 for (std::size_t i = 0; i < m_data.size(); ++i) {
177 m_data[i] = std::conj(m_data[i]);
184 static_assert(is_complex_v<T>,
"real() only available for complex Matrix");
185 std::vector<typename T::value_type> real_data;
186 real_data.reserve(m_data.size());
187 for (std::size_t i = 0; i < m_data.size(); ++i) {
188 real_data.push_back(std::real(m_data[i]));
195 static_assert(is_complex_v<T>,
"imag() only available for complex Matrix");
196 std::vector<typename T::value_type> imag_data;
197 imag_data.reserve(m_data.size());
198 for (std::size_t i = 0; i < m_data.size(); ++i) {
199 imag_data.push_back(std::imag(m_data[i]));
206 static_assert(!is_complex_v<T>,
"complex() only available for real Matrix");
208 std::vector<std::complex<T>> new_data;
209 new_data.reserve(m_data.size());
210 for (std::size_t i = 0; i < m_data.size(); ++i) {
211 new_data.push_back(m_data[i]);
219 assert(rows() == rhs.
rows() && cols() == rhs.
cols() &&
220 "Matrices must have same dimensions for addition");
222 this->m_data += rhs.m_data;
227 assert(rows() == rhs.
rows() && cols() == rhs.
cols() &&
228 "Matrices must have same dimensions for subtraction");
230 this->m_data -= rhs.m_data;
234Matrix<T> &Matrix<T>::operator*=(
const T x) {
240Matrix<T> &Matrix<T>::operator/=(
const T x) {
251 assert(m_rows == m_cols &&
"Can only call M+a for square matrix");
252 for (
auto i = 0ul; i < m_rows; ++i) {
261 assert(m_rows == m_cols &&
"Can only call M-a for square matrix");
262 for (
auto i = 0ul; i < m_rows; ++i) {
271 assert(rows() == a.
rows() && cols() == a.
cols() &&
272 "Matrices must have same dimensions for mult_elements_by");
273 for (
auto i = 0ul; i < m_data.size(); ++i) {
274 m_data[i] *= a.m_data[i];
284 "Matrices a and b must have correct dimension for multiplication");
288 auto product_gsl = product.as_gsl_view();
289 if constexpr (std::is_same_v<T, double>) {
290 gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, &a_gsl.matrix,
291 &b_gsl.matrix, 0.0, &product_gsl.matrix);
292 }
else if constexpr (std::is_same_v<T, float>) {
293 gsl_blas_sgemm(CblasNoTrans, CblasNoTrans, 1.0f, &a_gsl.matrix,
294 &b_gsl.matrix, 0.0f, &product_gsl.matrix);
295 }
else if constexpr (std::is_same_v<T, std::complex<double>>) {
296 gsl_blas_zgemm(CblasNoTrans, CblasNoTrans, GSL_COMPLEX_ONE, &a_gsl.matrix,
297 &b_gsl.matrix, GSL_COMPLEX_ZERO, &product_gsl.matrix);
298 }
else if constexpr (std::is_same_v<T, std::complex<float>>) {
299 const gsl_complex_float one{1.0f, 0.0f};
300 const gsl_complex_float zero{0.0f, 0.0f};
301 gsl_blas_cgemm(CblasNoTrans, CblasNoTrans, one, &a_gsl.matrix,
302 &b_gsl.matrix, zero, &product_gsl.matrix);
311 if constexpr (std::is_same_v<T, double>) {
312 return gsl_matrix_view_array(m_data.data(), m_rows, m_cols);
313 }
else if constexpr (std::is_same_v<T, float>) {
314 return gsl_matrix_float_view_array(m_data.data(), m_rows, m_cols);
315 }
else if constexpr (std::is_same_v<T, std::complex<double>>) {
317 return gsl_matrix_complex_view_array(
318 reinterpret_cast<double *
>(m_data.data()), m_rows, m_cols);
319 }
else if constexpr (std::is_same_v<T, std::complex<float>>) {
320 return gsl_matrix_complex_float_view_array(
321 reinterpret_cast<float *
>(m_data.data()), m_rows, m_cols);
323 assert(
false &&
"as_gsl_view() only available for double/float (or complex "
330 if constexpr (std::is_same_v<T, double>) {
331 return gsl_matrix_const_view_array(m_data.data(), m_rows, m_cols);
332 }
else if constexpr (std::is_same_v<T, float>) {
333 return gsl_matrix_float_const_view_array(m_data.data(), m_rows, m_cols);
334 }
else if constexpr (std::is_same_v<T, std::complex<double>>) {
335 return gsl_matrix_complex_const_view_array(
336 reinterpret_cast<const double *
>(m_data.data()), m_rows, m_cols);
337 }
else if constexpr (std::is_same_v<T, std::complex<float>>) {
338 return gsl_matrix_complex_float_const_view_array(
339 reinterpret_cast<const float *
>(m_data.data()), m_rows, m_cols);
341 assert(
false &&
"as_gsl_view() only for available double/float (or complex "
348std::ostream &operator<<(std::ostream &os,
const Matrix<T> &a) {
349 for (
auto i = 0ul; i < a.
rows(); ++i) {
350 for (
auto j = 0ul; j < a.
cols(); ++j) {
351 os << a(i, j) <<
" ";
366constexpr auto myEps() {
367 if constexpr (std::is_same_v<T, float> ||
368 std::is_same_v<T, std::complex<float>>) {
370 }
else if constexpr (std::is_same_v<T, double> ||
371 std::is_same_v<T, std::complex<double>>) {
386 for (
auto i = 0ul; i < lhs.
rows(); ++i) {
387 for (
auto j = 0ul; j < lhs.
cols(); ++j) {
389 if (std::abs(lhs(i, j) - rhs(i, j)) >
390 std::abs(eps * (lhs(i, j) + rhs(i, j))))
Matrix class; row-major.
Definition Matrix.hpp:35
Matrix< T > & make_identity()
Constructs a diagonal unit matrix (identity), in place; only for square.
Definition Matrix.ipp:143
Matrix< T > & invert_in_place()
Inverts the matrix, in place. Uses GSL; via LU decomposition. Only works for double/complex<double>.
Definition Matrix.ipp:77
std::size_t rows() const
Return rows [major index size].
Definition Matrix.hpp:89
Matrix< T > conj() const
Returns conjugate of matrix.
Definition Matrix.ipp:163
Matrix< T > & operator+=(const Matrix< T > &rhs)
Overload standard operators: do what expected.
Definition Matrix.ipp:218
auto complex() const
Converts a real to complex matrix (changes type; returns a complex matrix)
Definition Matrix.ipp:205
auto imag() const
Returns imag part of complex matrix (changes type; returns a real matrix)
Definition Matrix.ipp:194
auto as_gsl_view()
Returns gsl_matrix_view (or _float_view, _complex_view, _complex_float_view). Call ....
Definition Matrix.ipp:310
Matrix< T > & conj_in_place()
Conjugates matrix, in place.
Definition Matrix.ipp:174
Matrix< T > transpose() const
Returns transpose of matrix.
Definition Matrix.ipp:111
Matrix< T > & zero()
Sets all elements to zero, in place.
Definition Matrix.ipp:154
Matrix< T > inverse() const
Returns inverse of the matrix. Leaves original matrix intact. Uses GSL; via LU decomposition....
Definition Matrix.ipp:104
std::size_t cols() const
Return columns [minor index size].
Definition Matrix.hpp:91
T determinant() const
Returns the determinant. Uses GSL; via LU decomposition. Only works for double/complex<double>
Definition Matrix.ipp:49
Matrix< T > & mult_elements_by(const Matrix< T > &a)
Muplitplies all the elements by those of matrix a, in place: M_ij *= a_ij.
Definition Matrix.ipp:270
auto real() const
Returns real part of complex matrix (changes type; returns a real matrix)
Definition Matrix.ipp:183
Proved a "view" onto an array.
Definition Matrix.ipp:7
T operator[](std::size_t i) const
As above, but const.
Definition Matrix.ipp:21
T operator()(std::size_t i) const
As above, but const.
Definition Matrix.ipp:36
T & operator[](std::size_t i)
[] index access (with no range checking). [i][j] returns ith row, jth col
Definition Matrix.ipp:19
T at(std::size_t i) const
As above, but const.
Definition Matrix.ipp:29
T & at(std::size_t i)
() index access (with range checking). (i,j) returns ith row, jth col
Definition Matrix.ipp:24
T & operator()(std::size_t i)
() index access (with range checking). (i,j) returns ith row, jth col
Definition Matrix.ipp:34
Defines Matrix, Vector classes, and linear some algebra functions.
Definition Matrix.hpp:26
bool equal(const Matrix< T > &lhs, const Matrix< T > &rhs, T eps=myEps< T >())
Compares two matrices; returns true iff all elements compare relatively to better than eps.
Definition Matrix.ipp:381
namespace qip::overloads provides operator overloads for std::vector
Definition Vector.hpp:450
T product(T first, Args... rest)
Variadic product - helper function.
Definition Array.hpp:224