/******************************************************************************* * * TRIQS: a Toolbox for Research in Interacting Quantum Systems * * Copyright (C) 2011 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_ASSIGN2_H_ #define TRIQS_ARRAYS_ASSIGN2_H_ #include "iterator_adapter.hpp" #include "../indexmaps/cuboid/foreach.hpp" #include "../storages/memcopy.hpp" namespace triqs { namespace arrays { namespace Tag {struct indexmap_storage_pair{}; }// defined here since needed below... namespace assignment { template struct impl; } // puts the contents of RHS into LHS. LHS must be an indexmap_storage_pair // it is specialized in various cases for optimisation. template void triqs_arrays_assign_delegation (LHS & lhs, const RHS & rhs ) { static_assert( !LHS::is_const, "Can not assign to a const view !"); assignment::impl(lhs, rhs).invoke(); } template void triqs_arrays_compound_assign_delegation (LHS & lhs, const RHS & rhs, mpl::char_ ) { static_assert( !LHS::is_const, "Can not apply a compound operator to a const view !"); assignment::impl(lhs, rhs).invoke(); } #define TRIQS_DEFINE_COMPOUND_OPERATORS(MYTYPE)\ template MYTYPE & operator +=(RHS const & rhs) { triqs_arrays_compound_assign_delegation (*this,rhs, mpl::char_<'A'>()); return *this;}\ template MYTYPE & operator -=(RHS const & rhs) { triqs_arrays_compound_assign_delegation (*this,rhs, mpl::char_<'S'>()); return *this;}\ template MYTYPE & operator *=(RHS const & rhs) { triqs_arrays_compound_assign_delegation (*this,rhs, mpl::char_<'M'>()); return *this;}\ template MYTYPE & operator /=(RHS const & rhs) { triqs_arrays_compound_assign_delegation (*this,rhs, mpl::char_<'D'>()); return *this;} #define TRIQS_DELETE_COMPOUND_OPERATORS(MYTYPE)\ template MYTYPE & operator +=(RHS const & rhs) = delete;\ template MYTYPE & operator -=(RHS const & rhs) = delete;\ template MYTYPE & operator *=(RHS const & rhs) = delete;\ template MYTYPE & operator /=(RHS const & rhs) = delete; // -------- IMPLEMENTATION ---------------------------- namespace assignment { template struct _ops_; template struct _ops_ { static void invoke (A & a, B const & b) { a =b;} }; template struct _ops_ { static void invoke (A & a, B const & b) { a+=b;} }; template struct _ops_ { static void invoke (A & a, B const & b) { a-=b;} }; template struct _ops_ { static void invoke (A & a, B const & b) { a*=b;} }; template struct _ops_ { static void invoke (A & a, B const & b) { a/=b;} }; // RHS is considered to be an indexmap_storage_pair if it is one, ... except if it is the scalar type of hte LHS // think about an Array< Array > e.g. template struct is_isp : std::integral_constant::value && (!is_scalar_for::value) > {}; #define TRIQS_REJECT_ASSIGN_TO_CONST \ static_assert( (!std::is_const::value ), "Assignment : The value type of the LHS is const and can not be assigned to !"); #define TRIQS_REJECT_MATRIX_COMPOUND_MUL_DIV_NON_SCALAR\ static_assert( (!((OP=='M' || OP=='D') && MutableMatrix::value && (!is_scalar_for::value))),\ "*= and /= operator for non scalar RHS are deleted for a type modeling MutableMatrix (e.g. matrix, matrix_view) matrix, because this is ambiguous"); // ----------------- standard assignment for indexmap_storage_pair -------------------------------------------------- template struct impl) > { TRIQS_REJECT_ASSIGN_TO_CONST; TRIQS_REJECT_MATRIX_COMPOUND_MUL_DIV_NON_SCALAR; typedef typename LHS::value_type value_type; typedef typename LHS::indexmap_type indexmap_type; LHS & lhs; const RHS & rhs; typedef typename std::remove_cv::type v_t; impl(LHS & lhs_, const RHS & rhs_): lhs(lhs_), rhs(rhs_) {} template void operator()(Args const & ... args) const { _ops_::type, typename RHS::value_type, OP>::invoke(lhs(args...), rhs(args...)) ;} void invoke () { #ifdef TRIQS_ARRAYS_DEBUG if (!indexmaps::compatible_for_assignment(lhs.indexmap(), rhs.indexmap())) TRIQS_RUNTIME_ERROR<< "Size mismatch in operation "<