/******************************************************************************* * * TRIQS: a Toolbox for Research in Interacting Quantum Systems * * Copyright (C) 2011-2014 by O. Parcollet * * TRIQS is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * TRIQS. If not, see . * ******************************************************************************/ #pragma once #include "indexmaps/cuboid/map.hpp" #include "indexmaps/cuboid/slice.hpp" #include "impl/indexmap_storage_pair.hpp" #include "impl/assignment.hpp" #include "vector.hpp" namespace triqs { namespace arrays { template class matrix_view; template class matrix; // ---------------------- matrix -------------------------------- // #define _IMPL_MATRIX_COMMON \ bool is_square() const { return this->shape()[0] == this->shape()[1]; } \ \ view_type transpose() const { \ typename indexmap_type::lengths_type l; \ l[0] = this->indexmap().lengths()[1]; \ l[1] = this->indexmap().lengths()[0]; \ typename indexmap_type::strides_type s; \ s[0] = this->indexmap().strides()[1]; \ s[1] = this->indexmap().strides()[0]; \ return view_type(indexmap_type(l, s, this->indexmap().start_shift()), this->storage()); \ } \ bool memory_layout_is_c() const { return this->indexmap().strides()[0] >= this->indexmap().strides()[1]; } \ bool memory_layout_is_fortran() const { return this->indexmap().strides()[0] < this->indexmap().strides()[1]; } #define IMPL_TYPE \ indexmap_storage_pair, storages::shared_block, TraversalOrder, IsConst, true, \ Tag::matrix_view> template class matrix_view : Tag::matrix_view, TRIQS_CONCEPT_TAG_NAME(MutableMatrix), public IMPL_TYPE { public: using regular_type = matrix; using view_type = matrix_view; using const_view_type = matrix_view; using weak_view_type = matrix_view; using indexmap_type = typename IMPL_TYPE::indexmap_type; using storage_type = typename IMPL_TYPE::storage_type; /// Build from an IndexMap and a storage template matrix_view(typename IMPL_TYPE::indexmap_type const& Ind, S const& Mem) : IMPL_TYPE(Ind, Mem) {} /// Build from anything that has an indexmap and a storage compatible with this class template matrix_view(const ISP& X) : IMPL_TYPE(X.indexmap(), X.storage()) {} #ifdef TRIQS_WITH_PYTHON_SUPPORT /// Build from a numpy.array : throws if X is not a numpy.array explicit matrix_view(PyObject* X) : IMPL_TYPE(X, false, "matrix_view ") {} #endif /// Copy construction matrix_view(matrix_view const& X) : IMPL_TYPE(X.indexmap(), X.storage()) {} matrix_view() = delete; // Move matrix_view(matrix_view&& X) { this->swap_me(X); } /// Swap friend void swap(matrix_view& A, matrix_view& B) { A.swap_me(B); } /// Rebind the view void rebind(matrix_view const& X) { this->indexmap_ = X.indexmap_; this->storage_ = X.storage_; } // rebind the other view, iif this is const, and the other is not. template ENABLE_IFC(C) rebind(matrix_view const& X) { this->indexmap_ = X.indexmap_; this->storage_ = X.storage_; } /** Assignement. The size of the array MUST match exactly. */ template matrix_view& operator=(const RHS& X) { triqs_arrays_assign_delegation(*this, X); return *this; } matrix_view& operator=(matrix_view const& X) { triqs_arrays_assign_delegation(*this, X); return *this; } // cf array_view class comment // Move assignment not defined : will use the copy = since view must copy data TRIQS_DEFINE_COMPOUND_OPERATORS(matrix_view); _IMPL_MATRIX_COMMON; }; //--------------------------------------------------------------------- // this traits is used by indexmap_storage_pair, when slicing to find the correct view type. template struct ISPViewType : std::conditional, matrix_view> {}; #undef IMPL_TYPE template using matrix_const_view = matrix_view; // ---------------------- matrix -------------------------------- #define IMPL_TYPE \ indexmap_storage_pair, storages::shared_block, TraversalOrder, false, \ false, Tag::matrix_view> template class matrix : Tag::matrix, TRIQS_CONCEPT_TAG_NAME(MutableMatrix), public IMPL_TYPE { public: using value_type = typename IMPL_TYPE::value_type; using storage_type = typename IMPL_TYPE::storage_type; using indexmap_type = typename IMPL_TYPE::indexmap_type; using regular_type = matrix; using view_type = matrix_view; using const_view_type = matrix_view; using weak_view_type = matrix_view; /// Empty matrix. matrix(memory_layout<2> ml = memory_layout<2>{}) : IMPL_TYPE(indexmap_type(ml)) {} /// Move explicit matrix(matrix&& X) { this->swap_me(X); } /// matrix(size_t dim1, size_t dim2, memory_layout<2> ml = memory_layout<2>{}) : IMPL_TYPE(indexmap_type(mini_vector(dim1, dim2), ml)) {} /// matrix(mini_vector const& sha, memory_layout<2> ml = memory_layout<2>{}) : IMPL_TYPE(indexmap_type(sha, ml)) {} /** Makes a true (deep) copy of the data. */ matrix(const matrix& X) : IMPL_TYPE(X.indexmap(), X.storage().clone()) {} /// Build a new matrix from X.domain() and fill it with by evaluating X. X can be : template matrix(const T& X, TYPE_ENABLE_IF(memory_layout<2>, ImmutableCuboidArray) ml = memory_layout<2>{}) : IMPL_TYPE(indexmap_type(X.domain(), ml)) { triqs_arrays_assign_delegation(*this, X); } #ifdef TRIQS_WITH_PYTHON_SUPPORT /// Build from a numpy.array X (or any object from which numpy can make a numpy.array). Makes a copy. explicit matrix(PyObject* X) : IMPL_TYPE(X, true, "matrix ") {} #endif // build from a init_list template matrix(std::initializer_list> const& l) : IMPL_TYPE(memory_layout<2>()) { size_t i = 0, j = 0; int s = -1; for (auto const& l1 : l) { if (s == -1) s = l1.size(); else if (s != l1.size()) TRIQS_RUNTIME_ERROR << "initializer list not rectangular !"; } IMPL_TYPE::resize(typename IMPL_TYPE::domain_type(mini_vector(l.size(), s))); for (auto const& l1 : l) { for (auto const& x : l1) { (*this)(i, j++) = x; } j = 0; ++i; } } /** * Resizes the matrix. NB : all references to the storage is invalidated. * Does not initialize the matrix by default */ matrix& resize(size_t n1, size_t n2) { IMPL_TYPE::resize(typename IMPL_TYPE::domain_type(mini_vector(n1, n2))); return *this; } /** * Resizes the matrix. NB : all references to the storage is invalidated. * Does not initialize the matrix by default */ matrix& resize(const indexmaps::cuboid::domain_t& l) { IMPL_TYPE::resize(l); return *this; } /// Assignement resizes the matrix. All references to the storage are therefore invalidated. matrix& operator=(const matrix& X) { IMPL_TYPE::resize_and_clone_data(X); return *this; } /// Move assignment matrix& operator=(matrix&& X) { this->swap_me(X); return *this; } /// Swap friend void swap(matrix& A, matrix& B) { A.swap_me(B); } /** * Assignement resizes the matrix. All references to the storage are therefore invalidated. * NB : to avoid that, do make_view(A) = X instead of A = X */ template matrix& operator=(const RHS& X) { static_assert(ImmutableCuboidArray::value, "Assignment : RHS not supported"); IMPL_TYPE::resize(X.domain()); triqs_arrays_assign_delegation(*this, X); return *this; } TRIQS_DEFINE_COMPOUND_OPERATORS(matrix); _IMPL_MATRIX_COMMON; }; // matrix class #undef _IMPL_MATRIX_COMMON #undef IMPL_TYPE template matrix make_unit_matrix(int dim) { matrix r(dim, dim); r() = 1; return r; } template matrix_view make_matrix_view(ArrayType const& a) { static_assert(ArrayType::rank == 2, "make_matrix_view only works for array of rank 2"); return a; } template matrix make_matrix(ArrayType const& a) { static_assert(ArrayType::domain_type::rank == 2, "make_matrix only works for array of rank 2"); return a; } template TYPE_ENABLE_IF(typename M::value_type, ImmutableMatrix) trace(M const& m) { auto r = typename M::value_type{}; if (first_dim(m) != second_dim(m)) TRIQS_RUNTIME_ERROR << " Trace of a non square matrix"; auto d = first_dim(m); for (int i = 0; i < d; ++i) r += m(i, i); return r; } } } // namespace triqs::arrays // The std::swap is WRONG for a view because of the copy/move semantics of view. // Use swap instead (the correct one, found by ADL). namespace std { template void swap(triqs::arrays::matrix_view& a, triqs::arrays::matrix_view& b) = delete; } #include "./expression_template/matrix_algebra.hpp"