ALPSCore reference
count.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1998-2018 ALPS Collaboration. See COPYRIGHT.TXT
3  * All rights reserved. Use is subject to license terms. See LICENSE.TXT
4  * For use in publications, see ACKNOWLEDGE.TXT
5  */
6 
7 #pragma once
8 
9 #include <alps/config.hpp>
10 
12 
13 #include <alps/hdf5/archive.hpp>
15 
16 #include <boost/cstdint.hpp>
17 
18 #include <stdexcept>
19 #include <type_traits>
20 
21 namespace alps {
22  namespace accumulators {
23  // this should be called namespace tag { struct count; }
24  // but gcc <= 4.4 has lookup error, so name it different
25  struct count_tag;
26 
27  template<typename T> struct count_type {
28  typedef boost::uint64_t type;
29  };
30 
31  template<typename T> struct has_feature<T, count_tag> {
32  template<typename C> static char helper(typename count_type<T>::type (C::*)() const);
33  template<typename C> static char check(std::integral_constant<std::size_t, sizeof(helper(&C::count))>*);
34  template<typename C> static double check(...);
35  typedef std::integral_constant<bool, sizeof(char) == sizeof(check<T>(0))> type;
36  constexpr static bool value = type::value;
37  };
38 
39  template<typename T> typename count_type<T>::type count(T const & arg) {
40  return arg.count();
41  }
42 
43  namespace detail {
44 
45  template<typename A> typename std::enable_if<
47  >::type count_impl(A const & acc) {
48  return count(acc);
49  }
50 
51  template<typename A> typename std::enable_if<
52  !has_feature<A, count_tag>::value, typename count_type<A>::type
53  >::type count_impl(A const & acc) {
54  throw std::runtime_error(std::string(typeid(A).name()) + " has no count-method" + ALPS_STACKTRACE);
55  return typename count_type<A>::type();
56  }
57 
58  }
59 
60  namespace impl {
61 
62  template<typename T, typename B> class Result<T, count_tag, B> : public B {
63 
64  public:
65  typedef typename count_type<T>::type count_type;
66  typedef typename detail::make_scalar_result_type<impl::Result,T,count_tag,B>::type scalar_result_type;
67 
69  : m_count(count_type())
70  {}
71 
72  template<typename A> Result(A const & acc)
73  : m_count(detail::count_impl(acc))
74  {}
75 
76  count_type count() const {
77  return m_count;
78  }
79 
80  void operator()(T const &);
81 
82  template<typename W> void operator()(T const &, W) {
83  throw std::runtime_error("No values can be added to a result" + ALPS_STACKTRACE);
84  }
85 
86  template<typename S> void print(S & os, bool /*terse*/=false) const {
87  os << " #" << alps::short_print(count());
88  }
89 
90  void save(hdf5::archive & ar) const;
91  void load(hdf5::archive & ar);
92 
93  static std::size_t rank() { return 1; }
94  static bool can_load(hdf5::archive & ar);
95 
96  template<typename U> void operator+=(U const & arg) { augadd(arg); }
97  template<typename U> void operator-=(U const & arg) { augsub(arg); }
98  template<typename U> void operator*=(U const & arg) { augmul(arg); }
99  template<typename U> void operator/=(U const & arg) { augdiv(arg); }
100 
101  void reset();
102 
103  private:
104 
105  // TODO: make macro ...
106  template<typename U> void augadd(U const & arg, typename std::enable_if<std::is_scalar<U>::value, int>::type = 0) {
107  if (m_count == 0)
108  throw std::runtime_error("The results need measurements" + ALPS_STACKTRACE);
109  B::operator+=(arg);
110  }
111  template<typename U> void augadd(U const & arg, typename std::enable_if<!std::is_scalar<U>::value, int>::type = 0) {
112  if (m_count == 0 || arg.count() == 0)
113  throw std::runtime_error("Both results need measurements" + ALPS_STACKTRACE);
114  m_count = std::min(m_count, arg.count());
115  B::operator+=(arg);
116  }
117 
118  template<typename U> void augsub(U const & arg, typename std::enable_if<std::is_scalar<U>::value, int>::type = 0) {
119  if (m_count == 0)
120  throw std::runtime_error("The results need measurements" + ALPS_STACKTRACE);
121  B::operator-=(arg);
122  }
123  template<typename U> void augsub(U const & arg, typename std::enable_if<!std::is_scalar<U>::value, int>::type = 0) {
124  if (m_count == 0 || arg.count() == 0)
125  throw std::runtime_error("Both results need measurements" + ALPS_STACKTRACE);
126  m_count = std::min(m_count, arg.count());
127  B::operator-=(arg);
128  }
129 
130  template<typename U> void augmul(U const & arg, typename std::enable_if<std::is_scalar<U>::value, int>::type = 0) {
131  if (m_count == 0)
132  throw std::runtime_error("The results need measurements" + ALPS_STACKTRACE);
133  B::operator*=(arg);
134  }
135  template<typename U> void augmul(U const & arg, typename std::enable_if<!std::is_scalar<U>::value, int>::type = 0) {
136  if (m_count == 0 || arg.count() == 0)
137  throw std::runtime_error("Both results need measurements" + ALPS_STACKTRACE);
138  m_count = std::min(m_count, arg.count());
139  B::operator*=(arg);
140  }
141 
142  template<typename U> void augdiv(U const & arg, typename std::enable_if<std::is_scalar<U>::value, int>::type = 0) {
143  if (m_count == 0)
144  throw std::runtime_error("The results need measurements" + ALPS_STACKTRACE);
145  B::operator/=(arg);
146  }
147  template<typename U> void augdiv(U const & arg, typename std::enable_if<!std::is_scalar<U>::value, int>::type = 0) {
148  if (m_count == 0 || arg.count() == 0)
149  throw std::runtime_error("Both results need measurements" + ALPS_STACKTRACE);
150  m_count = std::min(m_count, arg.count());
151  B::operator/=(arg);
152  }
153 
154  count_type m_count;
155  };
156 
157  template<typename T, typename B> struct Accumulator<T, count_tag, B> : public B {
158 
159  public:
160  typedef typename count_type<T>::type count_type;
162 
163  Accumulator(): m_count(count_type()) {}
164 
165  Accumulator(Accumulator const & arg): m_count(arg.m_count) {}
166 
167  template<typename ArgumentPack> Accumulator(ArgumentPack const & /*args*/, typename std::enable_if<!is_accumulator<ArgumentPack>::value, int>::type = 0)
168  : m_count(count_type())
169  {}
170 
171  count_type count() const {
172  return m_count;
173  }
174 
175  void operator()(T const &) {
176  ++m_count;
177  }
178  template<typename W> void operator()(T const &, W) {
179  throw std::runtime_error("Observable has no binary call operator" + ALPS_STACKTRACE);
180  }
181 
182  template<typename S> void print(S & os, bool /*terse*/=false) const {
183  os << " #" << alps::short_print(count());
184  }
185 
186  void save(hdf5::archive & ar) const;
187  void load(hdf5::archive & ar);
188 
189  static std::size_t rank() { return 1; }
190  static bool can_load(const hdf5::archive & ar);
191 
192  inline void reset() {
193  m_count = 0;
194  }
195 
197  template <typename A>
198  void merge(const A& rhs)
199  {
200  m_count += rhs.m_count;
201  }
202 
203 #ifdef ALPS_HAVE_MPI
204  void collective_merge(
205  alps::mpi::communicator const & comm
206  , int root
207  );
208  void collective_merge(
209  alps::mpi::communicator const & comm
210  , int root
211  ) const;
212 #endif
213 
214  private:
215  count_type m_count;
216  };
217 
218  template<typename T, typename B> class BaseWrapper<T, count_tag, B> : public B {
219  public:
220  virtual bool has_count() const = 0;
221  virtual boost::uint64_t count() const = 0;
222  };
223 
224  template<typename T, typename B> class DerivedWrapper<T, count_tag, B> : public B {
225  public:
226  DerivedWrapper(): B() {}
227  DerivedWrapper(T const & arg): B(arg) {}
228 
230 
231  typename boost::uint64_t count() const { return detail::count_impl(this->m_data); }
232  };
233 
234  }
235  }
236 }
void load(archive &ar, std::string const &path, T &value, std::vector< std::size_t > chunk=std::vector< std::size_t >(), std::vector< std::size_t >=std::vector< std::size_t >())
Definition: archive.hpp:309
detail::make_scalar_result_type< impl::Result, T, count_tag, B >::type scalar_result_type
Definition: count.hpp:66
std::integral_constant< bool, sizeof(char)==sizeof(check< T >0))> type
Definition: count.hpp:35
detail::short_print_proxy< T const > short_print(T const &v, std::size_t p=6)
Definition: short_print.hpp:29
Encapsulation of an MPI communicator and some communicator-related operations.
Definition: mpi.hpp:111
boost::array< T, N > & operator+=(boost::array< T, N > &lhs, boost::array< T, N > const &rhs)
void reset(accumulator_wrapper &arg)
boost::array< T, N > & operator/=(boost::array< T, N > &lhs, boost::array< T, N > const &rhs)
boost::array< T, N > & operator*=(boost::array< T, N > &lhs, boost::array< T, N > const &rhs)
boost::uint64_t type
Definition: count.hpp:28
void merge(const A &rhs)
Merge the counter of the given accumulator of type A into this counter.
Definition: count.hpp:198
#define ALPS_STACKTRACE
Definition: stacktrace.hpp:37
Accumulator(ArgumentPack const &, typename std::enable_if<!is_accumulator< ArgumentPack >::value, int >::type=0)
Definition: count.hpp:167
void print(S &os, bool=false) const
Definition: count.hpp:86
Result< T, count_tag, typename B::result_type > result_type
Definition: count.hpp:161
count_type< T >::type count(T const &arg)
Definition: count.hpp:39
boost::array< T, N > & operator-=(boost::array< T, N > &lhs, boost::array< T, N > const &rhs)
void save(archive &ar, std::string const &path, T const &value, std::vector< std::size_t >=std::vector< std::size_t >(), std::vector< std::size_t > chunk=std::vector< std::size_t >(), std::vector< std::size_t >=std::vector< std::size_t >())
Definition: archive.hpp:292