3
0
mirror of https://github.com/triqs/dft_tools synced 2024-11-01 03:33:50 +01:00
dft_tools/triqs/arrays/storages/shared_block.hpp

150 lines
6.3 KiB
C++
Raw Normal View History

/*******************************************************************************
*
* 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 <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#ifndef TRIQS_STORAGE_SHARED_POINTER_H
#define TRIQS_STORAGE_SHARED_POINTER_H
#include <string.h>
#include <limits>
#include <boost/shared_ptr.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include "../impl/make_const.hpp"
#ifdef TRIQS_WITH_PYTHON_SUPPORT
#include "./mem_block.hpp"
#else
#include <vector>
//#include "basic_block.hpp"
#endif
namespace triqs { namespace arrays {
namespace Tag {struct storage{}; struct shared_block:storage{}; }
namespace storages {
template <class V, class Opt> struct __init_value;
template <class V> struct __init_value<V, Tag::no_init> { static void invoke (V * data, size_t s) {}};
template <class V> struct __init_value< V, Tag::default_init> {
static void invoke (V * restrict data, size_t s) { if (data!=NULL) for (size_t u=0; u<s; ++u) data[u] = V(); }
};
template <class V> struct __init_value< V, Tag::nan_inf_init> {
static void invoke (V * restrict data, size_t s) {
static_assert ( ( std::numeric_limits<V>::has_quiet_NaN || std::numeric_limits<V>::is_integer), "type has no Nan and is not integer. This init is impossible");
if (data==NULL) return;
if (std::numeric_limits<V>::has_quiet_NaN) for (size_t u=0; u<s; ++u) data[u] = std::numeric_limits<V>::quiet_NaN();
if (std::numeric_limits<V>::is_integer) for (size_t u=0; u<s; ++u) data[u] = std::numeric_limits<V>::max();
}
};
template <class V> struct __init_value< std::complex<V>, Tag::nan_inf_init> {
static void invoke (std::complex<V> * restrict data, size_t s) {
static_assert ( ( std::numeric_limits<V>::has_quiet_NaN || std::numeric_limits<V>::is_integer), "type has no Nan and is not integer. This init is impossible");
if (data==NULL) return;
if (std::numeric_limits<V>::has_quiet_NaN) for (size_t u=0; u<s; ++u) data[u] = std::complex<V>(std::numeric_limits<V>::quiet_NaN(),std::numeric_limits<V>::quiet_NaN()) ;
if (std::numeric_limits<V>::is_integer) for (size_t u=0; u<s; ++u) data[u] = std::complex<V>(std::numeric_limits<V>::max(),std::numeric_limits<V>::max());
}
};
/* Storage as a shared_ptr to a basic_block
* The shared pointer guarantees that the data will not be destroyed during the life of the array.
* Impl: we are not using shared_array directly because of serialization support for shared_ptr */
template<typename ValueType >
class shared_block : Tag::shared_block {
typedef typename boost::add_const<ValueType>::type const_value_type;
typedef typename boost::remove_const<ValueType>::type non_const_value_type;
#ifdef TRIQS_WITH_PYTHON_SUPPORT
typedef details::mem_block<non_const_value_type> block_type;
#else
// typedef details::basic_block<non_const_value_type> block_type;
typedef std::vector<non_const_value_type> block_type;
#endif
public:
typedef triqs::arrays::Tag::shared_block tag;
typedef ValueType value_type;
typedef shared_block<value_type> clone_type;
typedef shared_block<const_value_type> const_clone_type;
/// Construct a new block of memory of given size
template<typename InitOpt>
explicit shared_block(size_t size, InitOpt opt ): sptr(size ? new block_type(size) : NULL) {
init_data();
__init_value<value_type,InitOpt>::invoke (this-> data_, this->size());
}
explicit shared_block(): sptr() { init_data(); }
#ifdef TRIQS_WITH_PYTHON_SUPPORT
/// Construct from a numpy object
explicit shared_block(PyObject * arr, bool borrowed): sptr(new block_type(arr,borrowed)) { init_data();}
#endif
/// Shallow copy
shared_block(const shared_block<const_value_type> & X): sptr(X.sptr) { init_data(); }
/// Shallow copy
shared_block(const shared_block<non_const_value_type> & X): sptr(X.sptr) { init_data(); }
void operator=(const shared_block & X) { sptr=X.sptr; init_data(); }
/// True copy of the data
clone_type clone() const {
if (empty()) return clone_type ();
#ifdef TRIQS_WITH_PYTHON_SUPPORT
clone_type res; res.sptr = boost::make_shared<block_type > (*sptr); res.init_data();
#else
clone_type res(this->size(), Tag::no_init() ); (*res.sptr) = (*sptr);
#endif
return res;
}
// Make a clone forced to have const value_type
const_clone_type const_clone() const {return clone();}
value_type & operator[](size_t i) const { return data_[i];}
bool empty() const {return (sptr.get()==NULL);}
size_t size() const {return (empty () ? 0 : sptr.get()->size());}
#ifdef TRIQS_WITH_PYTHON_SUPPORT
PyObject * new_ref_to_guard() const {return sptr->new_ref_to_guard();}
#endif
private:
boost::shared_ptr<block_type > sptr;
value_type * restrict data_; // for optimization on some compilers.
void init_data(){ data_ = (sptr ? &((*sptr)[0]) : NULL); }
friend class shared_block <non_const_value_type>; friend class shared_block <const_value_type>;
friend class boost::serialization::access;
template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & boost::serialization::make_nvp("ptr",sptr); init_data(); }
};
}
namespace details {
template<bool Const, typename T> struct make_const_type<Const,storages::shared_block<T> > {
typedef storages::shared_block<typename make_const_type<Const,T>::type> type;
};
}
}}//namespace triqs::arrays
#endif