/******************************************************************************* * * TRIQS: a Toolbox for Research in Interacting Quantum Systems * * Copyright (C) 2011-2013 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 . * ******************************************************************************/ #ifndef TRIQS_ARRAYS_ARRAY_H #define TRIQS_ARRAYS_ARRAY_H #include #include "indexmaps/cuboid/map.hpp" #include "indexmaps/cuboid/slice.hpp" #include "impl/indexmap_storage_pair.hpp" #include "impl/assignment.hpp" #include "impl/flags.hpp" #include "algorithms.hpp" #include "functional/fold.hpp" #include "functional/map.hpp" namespace triqs { namespace arrays { template class array_view; template class array; // ---------------------- array_view -------------------------------- #define IMPL_TYPE indexmap_storage_pair< indexmaps::cuboid::map, \ storages::shared_block, Opt, TraversalOrder, IsConst, true, Tag::array_view > template class array_view: Tag::array_view, TRIQS_CONCEPT_TAG_NAME(MutableArray), public IMPL_TYPE { static_assert( Rank>0, " Rank must be >0"); public: typedef typename IMPL_TYPE::indexmap_type indexmap_type; typedef typename IMPL_TYPE::storage_type storage_type; typedef array regular_type; typedef array_view view_type; typedef array_view const_view_type; typedef array_view weak_view_type; /// Build from an IndexMap and a storage template array_view(indexmap_type const& Ind, S const& Mem) : IMPL_TYPE(Ind, Mem) {} /// Copy constructor array_view(array_view const & X): IMPL_TYPE(X.indexmap(),X.storage()) {} /// Build from anything that has an indexmap and a storage compatible with this class template array_view(const ISP & X): IMPL_TYPE(X.indexmap(),X.storage()) { // to be activated static_assert(IsConst || (!ISP::is_const), "Cannot construct a non const view from a const one !"); } #ifdef TRIQS_WITH_PYTHON_SUPPORT /// Build from a numpy.array (X is a borrowed reference) : throws if X is not a numpy.array explicit array_view (PyObject * X): IMPL_TYPE(X, false, "array_view "){} #endif array_view () = delete; // Move array_view(array_view && X) { this->swap_me(X); } /// Swap friend void swap( array_view & A, array_view & B) { A.swap_me(B);} /// Rebind the view void rebind(array_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(array_view const& X) { this->indexmap_ = X.indexmap_; this->storage_ = X.storage_; } /// Assignment. The size of the array MUST match exactly, except in the empty case template array_view & operator=(RHS const & X) { triqs_arrays_assign_delegation(*this,X); return *this; } /// array_view & operator=(array_view const & X) { triqs_arrays_assign_delegation(*this,X); return *this; } //without this, the standard = is synthetized... // Move assignment not defined : will use the copy = since view must copy data TRIQS_DEFINE_COMPOUND_OPERATORS(array_view); // to forbid serialization of views... //template void serialize(Archive & ar, const unsigned int version) = delete; template friend array_view transposed_view(array_view const& a, INT... is) { return array_view{transpose(a.indexmap_, is...), a.storage_}; } }; #undef IMPL_TYPE template using array_const_view = array_view; //------------------------------- array --------------------------------------------------- #define IMPL_TYPE indexmap_storage_pair< indexmaps::cuboid::map, \ storages::shared_block, Opt, TraversalOrder, false, false, Tag::array_view > template class array: Tag::array, TRIQS_CONCEPT_TAG_NAME(MutableArray), public IMPL_TYPE { public: typedef typename IMPL_TYPE::value_type value_type; typedef typename IMPL_TYPE::storage_type storage_type; typedef typename IMPL_TYPE::indexmap_type indexmap_type; typedef array regular_type; typedef array_view view_type; typedef array_view const_view_type; typedef array_view weak_view_type; /// Empty array. explicit array(memory_layout ml = memory_layout(IMPL_TYPE::indexmap_type::traversal_order)) :IMPL_TYPE(ml){} /// From a domain explicit array( typename indexmap_type::domain_type const & dom, memory_layout ml = memory_layout(IMPL_TYPE::indexmap_type::traversal_order)): IMPL_TYPE(indexmap_type(dom,ml)){} #ifdef TRIQS_DOXYGEN /// Construction from the dimensions. NB : the number of parameters must be exactly rank (checked at compile time). array (size_t I_1, .... , size_t I_rank); #else #define IMPL(z, NN, unused) \ explicit array (BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(NN), size_t I_),memory_layout ml = memory_layout(IMPL_TYPE::indexmap_type::traversal_order)): \ IMPL_TYPE(indexmap_type(mini_vector(BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(NN), I_)),ml)) {\ static_assert(IMPL_TYPE::rank-1==NN,"array : incorrect number of variables in constructor");} BOOST_PP_REPEAT(ARRAY_NRANK_MAX , IMPL, nil) #undef IMPL #endif // Makes a true (deep) copy of the data. array(const array & X): IMPL_TYPE(X.indexmap(),X.storage().clone()) {} // Move explicit array(array && X) { this->swap_me(X); } // from a temporary storage and an indexmap. Used for reshaping a temporary array explicit array(typename indexmap_type::domain_type const & dom, storage_type && sto, memory_layout ml = memory_layout(IMPL_TYPE::indexmap_type::traversal_order)): IMPL_TYPE(indexmap_type(dom,ml), std::move(sto)){} /** * Build a new array from X.domain() and fill it with by evaluating X. X can be : * - another type of array, array_view, matrix,.... (any pair) * - a expression : e.g. array A = B+ 2*C; */ template array(const T & X, TYPE_ENABLE_IF(memory_layout, ImmutableCuboidArray) ml = memory_layout(IMPL_TYPE::indexmap_type::traversal_order)): 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 array (PyObject * X): IMPL_TYPE(X, true, "array "){} #endif // build from a init_list template array(std::initializer_list const & l, typename std::enable_if::type * dummy =0): IMPL_TYPE(indexmap_type(mini_vector(l.size()),memory_layout(IMPL_TYPE::indexmap_type::traversal_order))) { size_t i=0; for (auto const & x : l) (*this)(i++) = x; } template array (std::initializer_list> const & l, typename std::enable_if::type * dummy =0): IMPL_TYPE(memory_layout(IMPL_TYPE::indexmap_type::traversal_order)) { 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 array. NB : all references to the storage is invalidated. * Does not initialize the array by default: to resize and init, do resize(IND).init() */ array & resize (const indexmaps::cuboid::domain_t & l) { IMPL_TYPE::resize(l); return *this; } /// Assignement resizes the array. All references to the storage are therefore invalidated. array & operator=(const array & X) { IMPL_TYPE::resize_and_clone_data(X); return *this; } /// Move assignment array & operator=(array && X) { this->swap_me(X); return *this;} /// Swap friend void swap( array & A, array & B) { A.swap_me(B);} /** * Assignement resizes the array (if necessary). * All references to the storage are therefore invalidated. * NB : to avoid that, do make_view(A) = X instead of A = X */ template array & 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(array); template friend const_view_type transposed_view(array const& a, INT... is) { return view_type{transpose(a.indexmap_, is...), a.storage_}; }; template friend view_type transposed_view(array& a, INT... is) { return view_type{transpose(a.indexmap_, is...), a.storage_}; }; };//array class #undef IMPL_TYPE //---------------------------------------------------------------------------------- // how to build the view type .... template < class V, int R, ull_t Opt, ull_t TraversalOrder, bool Borrowed, bool IsConst > struct ISPViewType< V, R, Opt, TraversalOrder,Tag::array_view, Borrowed,IsConst> { typedef array_view type; }; }}//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::array_view & a , triqs::arrays::array_view & b)= delete; } #include "./expression_template/array_algebra.hpp" #endif