3
0
mirror of https://github.com/triqs/dft_tools synced 2024-11-01 03:33:50 +01:00
dft_tools/triqs/arrays/cache.hpp
Olivier Parcollet f2c7d449cc First commit : triqs libs version 1.0 alpha1
for earlier commits, see TRIQS0.x repository.
2013-07-17 19:24:07 +02:00

119 lines
5.7 KiB
C++

/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2012 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 <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#ifndef TRIQS_ARRAYS_CACHE_H
#define TRIQS_ARRAYS_CACHE_H
#include "./array.hpp"
#include <triqs/utility/view_tools.hpp>
namespace triqs { namespace arrays {
template<typename DataType, typename CacheType> class const_cache;
template<typename DataType, typename CacheType> class cache;
template<typename D>
const_cache<D, array<typename D::value_type, D::domain_type::rank> >
make_const_cache( D const & x, memory_layout< D::domain_type::rank> ml = memory_layout< D::domain_type::rank>('C') ) {
return const_cache<D, array<typename D::value_type, D::domain_type::rank> > (x,ml);
}
template<typename D>
cache<D, array<typename D::value_type, D::domain_type::rank> >
make_cache( D const & x, memory_layout< D::domain_type::rank> ml = memory_layout< D::domain_type::rank>('C') ) {
return cache<D, array<typename D::value_type, D::domain_type::rank> > (x,ml);
}
// ----------------- implementation ----------------------------------
// The type of A1, and A2 can already imply a copy. Compile time decision.
template<typename A1, typename A2, typename Enable =void > struct need_copy_ct : mpl::true_{};
template<typename A1, typename A2> struct need_copy_ct<A1,A2, ENABLE_IF(is_amv_value_or_view_class<A1>)> :
mpl::not_<std::is_same< typename A1::value_type, typename A2::value_type> > {};
//mpl::not_<indexmaps::IndexOrder::same_order<typename A1::indexmap_type::index_order_type, typename A2::indexmap_type::index_order_type> >{};
template<typename DataType, typename CacheType> class const_cache {
protected:
typedef memory_layout< DataType::domain_type::rank> ml_t;
const ml_t ml;
typename view_type_if_exists_else_type<DataType>::type keeper;
static const bool CT_need_copy = need_copy_ct<DataType,CacheType>::value;
const bool need_copy;
typedef typename CacheType::view_type exposed_view_type;
struct internal_data {
CacheType copy;
exposed_view_type view;
internal_data(const_cache const & P,ml_t ml) : copy(CacheType(P.keeper,ml)), view(copy) {
#ifdef TRIQS_ARRAYS_CACHE_COPY_VERBOSE
std::cerr<< " Cache : copy made "<< std::endl<< " -- TRACE = --" << std::endl << triqs::utility::stack_trace() << std::endl;
#endif
}
};
friend struct internal_data;
mutable boost::shared_ptr<internal_data> _id;
internal_data & id() const { if (!_id) _id= boost::make_shared<internal_data>(*this,ml); return *_id;}
//exposed_view_type & view2 () { if (need_copy) return id().view; else return keeper;}
//exposed_view_type const & view2 () const { if (need_copy) return id().view; else return keeper;}
// avoid compiling the transformation keeper-> exposed_view_type when it does not make sense
exposed_view_type & view1 (mpl::false_) { if (need_copy) return id().view; else return keeper; }
exposed_view_type const & view1 (mpl::false_) const { if (need_copy) return id().view; else return keeper;}
exposed_view_type & view1 (mpl::true_) { return id().view; }
exposed_view_type const & view1 (mpl::true_) const { return id().view; }
exposed_view_type & view2 () { return view1(mpl::bool_<CT_need_copy>());}
exposed_view_type const & view2 () const { return view1(mpl::bool_<CT_need_copy>());}
template<typename D>
typename std::enable_if< ! is_amv_value_or_view_class<D>::value, bool>::type
need_copy_dynamic ( D const & x) const { return false;}
template<typename D>
typename std::enable_if<is_amv_value_or_view_class<D>::value, bool>::type
need_copy_dynamic ( D const & x) const { return (x.indexmap().memory_indices_layout() != ml );}
public :
const_cache (DataType const & x, ml_t ml_ = ml_t()):
ml(ml_),keeper (x),
need_copy ( CT_need_copy || need_copy_dynamic(x) || (!has_contiguous_data(x)) ) {}
void update() { if (need_copy && _id) id().view = keeper;}
exposed_view_type const & view () const { return view2();}
operator exposed_view_type const & () const { return view2();}
};
// Non const case : just add the back copy in the destructor
template<typename DataType, typename CacheType> class cache : const_cache<DataType,CacheType> {
static_assert( is_amv_value_or_view_class<DataType>::value, "non const cache only for regular classes and views, not expressions");
typedef const_cache<DataType,CacheType> B;
typedef typename B::ml_t ml_t;
public :
cache (DataType const & x, ml_t ml = ml_t() ): B(x,ml) {}
~cache() { back_update(); }
void back_update() { if (this->need_copy) this->keeper = this->id().view;}
typename B::exposed_view_type & view () {return B::view2();}
typename B::exposed_view_type const & view () const {return B::view2();}
operator typename B::exposed_view_type & () {return B::view2();}
operator typename B::exposed_view_type const & () const {return B::view2();}
};
}}//namespace triqs::arrays
#endif