ALPSCore reference
wrappers.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 
16 
17 #include <alps/hdf5/archive.hpp>
18 
19 #include <boost/variant/variant.hpp>
20 #include <boost/variant/apply_visitor.hpp>
21 
22 #include <typeinfo>
23 #include <type_traits>
24 #include <stdexcept>
25 
26 namespace alps {
27  namespace accumulators {
28 
29  template<typename A> class derived_wrapper;
30 
31  namespace detail {
32  template<typename T> struct value_wrapper {
33  typedef T value_type;
34  };
35  }
36 
37  template<typename T> class base_wrapper : public
38  // impl::BaseWrapper<T, weight_tag,
39  impl::BaseWrapper<T, max_num_binning_tag,
40  impl::BaseWrapper<T, binning_analysis_tag,
41  impl::BaseWrapper<T, error_tag,
42  impl::BaseWrapper<T, mean_tag,
43  impl::BaseWrapper<T, count_tag,
44  detail::value_wrapper<T>
45  // >
46  > > > > > {
47 
48  public:
49  typedef typename detail::value_wrapper<T>::value_type value_type;
50 
51  virtual ~base_wrapper() {}
52 
53  virtual void operator()(value_type const & value) = 0;
54  // virtual void operator()(value_type const & value, detail::weight_variant_type const & weight) = 0;
55 
56  virtual void save(hdf5::archive & ar) const = 0;
57  virtual void load(hdf5::archive & ar) = 0;
58 
59  virtual void print(std::ostream & os, bool terse) const = 0;
60  virtual void reset() = 0;
61 
63  virtual void merge(const base_wrapper<T>&) = 0;
64 #ifdef ALPS_HAVE_MPI
65  virtual void collective_merge(alps::mpi::communicator const & comm, int root) = 0;
66 #endif
67 
68  virtual base_wrapper * clone() const = 0;
69  virtual base_wrapper * result() const = 0;
70 
71  template<typename A> A & extract() {
72  return dynamic_cast<derived_wrapper<A> &>(*this).extract();
73  }
74  template<typename A> A const & extract() const {
75  return dynamic_cast<derived_wrapper<A> const &>(*this).extract();
76  }
77 
78  private:
79  /* This machinery is to have `wrapped_value_type=base_wrapper< scalar_of_T > const &`
80  if T is a non-scalar type, and `wrapped_value_type=void*` if T is a scalar type.
81  */
82  template <typename X> struct wrap_value_type:
83  public std::conditional<
84  alps::is_scalar<X>::value,
85  void*,
86  base_wrapper<typename alps::numeric::scalar<X>::type> const & > {};
87 
88  protected:
90  typedef typename wrap_value_type<T>::type wrapped_scalar_value_type;
91 
92  public:
93 
94  virtual void operator+=(base_wrapper const &) = 0;
95  virtual void operator-=(base_wrapper const &) = 0;
96  virtual void operator*=(base_wrapper const &) = 0;
97  virtual void operator/=(base_wrapper const &) = 0;
98 
99  virtual void operator+=(wrapped_scalar_value_type) = 0;
100  virtual void operator-=(wrapped_scalar_value_type) = 0;
101  virtual void operator*=(wrapped_scalar_value_type) = 0;
102  virtual void operator/=(wrapped_scalar_value_type) = 0;
103 
104 
105  // These virtual functions accept `long double`: it's the "widest" RHS scalar type.
106  virtual void operator+=(long double) = 0;
107  virtual void operator-=(long double) = 0;
108  virtual void operator*=(long double) = 0;
109  virtual void operator/=(long double) = 0;
110 
111  virtual void negate() = 0;
112  virtual void inverse() = 0;
113 
114  virtual void sin() = 0;
115  virtual void cos() = 0;
116  virtual void tan() = 0;
117  virtual void sinh() = 0;
118  virtual void cosh() = 0;
119  virtual void tanh() = 0;
120  virtual void asin() = 0;
121  virtual void acos() = 0;
122  virtual void atan() = 0;
123  virtual void abs() = 0;
124  virtual void sqrt() = 0;
125  virtual void log() = 0;
126  virtual void sq() = 0;
127  virtual void cb() = 0;
128  virtual void cbrt() = 0;
129  };
130 
131  namespace detail {
132  template<typename A> class foundation_wrapper : public base_wrapper<typename value_type<A>::type> {
133  public:
134  foundation_wrapper(A const & arg): m_data(arg) {}
135 
136  protected:
137  A m_data;
138  };
139  }
140 
141  template<typename A> class derived_wrapper : public
142  // impl::DerivedWrapper<A, weight_tag,
143  impl::DerivedWrapper<A, max_num_binning_tag,
144  impl::DerivedWrapper<A, binning_analysis_tag,
145  impl::DerivedWrapper<A, error_tag,
146  impl::DerivedWrapper<A, mean_tag,
147  impl::DerivedWrapper<A, count_tag,
148  detail::foundation_wrapper<A>
149  // >
150  > > > > > {
151 
152  typedef typename detail::value_wrapper<typename value_type<A>::type>::value_type value_type;
153 
154  public:
156  :
157  // impl::DerivedWrapper<A, weight_tag,
158  impl::DerivedWrapper<A, max_num_binning_tag,
159  impl::DerivedWrapper<A, binning_analysis_tag,
160  impl::DerivedWrapper<A, error_tag,
161  impl::DerivedWrapper<A, mean_tag,
162  impl::DerivedWrapper<A, count_tag,
163  detail::foundation_wrapper<A>
164  // >
165  > > > > >()
166  {}
167 
168  derived_wrapper(A const & arg)
169  :
170  // impl::DerivedWrapper<A, weight_tag,
171  impl::DerivedWrapper<A, max_num_binning_tag,
172  impl::DerivedWrapper<A, binning_analysis_tag,
173  impl::DerivedWrapper<A, error_tag,
174  impl::DerivedWrapper<A, mean_tag,
175  impl::DerivedWrapper<A, count_tag,
176  detail::foundation_wrapper<A>
177  // >
178  > > > > >(arg)
179  {}
180 
181  A & extract() {
182  return this->m_data;
183  }
184  A const & extract() const {
185  return this->m_data;
186  }
187 
188  void operator()(value_type const & value) {
189  this->m_data(value);
190  }
191 
192  public:
193  void save(hdf5::archive & ar) const {
194  ar[""] = this->m_data;
195  }
196  void load(hdf5::archive & ar) {
197  ar[""] >> this->m_data;
198  }
199 
200  void print(std::ostream & os, bool terse) const {
201  this->m_data.print(os, terse);
202  }
203 
204  void reset() {
205  this->m_data.reset();
206  }
207 
210  {
211  this->m_data.merge(dynamic_cast<const derived_wrapper<A>&>(rhs).m_data);
212  }
213 
214 #ifdef ALPS_HAVE_MPI
215  void collective_merge(
216  alps::mpi::communicator const & comm
217  , int root = 0
218  ) {
219  this->m_data.collective_merge(comm, root);
220  }
221 
222  void collective_merge(
223  alps::mpi::communicator const & comm
224  , int root = 0
225  ) const {
226  this->m_data.collective_merge(comm, root);
227  }
228 #endif
229  };
230 
231  template<typename A> class derived_result_wrapper : public derived_wrapper<A> {
232  private:
233  typedef typename base_wrapper<typename value_type<A>::type>::wrapped_scalar_value_type wrapped_scalar_value_type;
234  public:
236 
237  derived_result_wrapper(A const & arg): derived_wrapper<A>(arg) {}
238 
240  return new derived_result_wrapper<A>(this->m_data);
241  }
243  throw std::runtime_error(std::string("A result(") + typeid(A).name() + ") cannot be converted to a result" + ALPS_STACKTRACE);
244  return NULL;
245  }
246 
247  #define OPERATOR_PROXY(AUGOPNAME, AUGOP, AUGOPFN) \
248  void AUGOPNAME(base_wrapper<typename value_type<A>::type> const & arg) { \
249  this->m_data AUGOP arg.template extract<A>(); \
250  } \
251  \
252  void do_##AUGOPFN(void*) { \
253  throw std::logic_error("This virtual method plug should never be called"); \
254  } \
255  template <typename W> \
256  void do_##AUGOPFN(W& arg) { \
257  this->m_data AUGOP arg.template extract<typename A::scalar_result_type>(); \
258  } \
259  void AUGOPNAME(wrapped_scalar_value_type arg) { \
260  do_##AUGOPFN(arg); \
261  } \
262  /* takes `long double`: it's the widest scalar numeric type */ \
263  void AUGOPNAME(long double arg) { \
264  this->m_data AUGOP arg; \
265  }
266  OPERATOR_PROXY(operator+=, +=, add)
267  OPERATOR_PROXY(operator-=, -=, sub)
268  OPERATOR_PROXY(operator*=, *=, mul)
269  OPERATOR_PROXY(operator/=, /=, div)
270  #undef OPERATOR_PROXY
271 
272  void negate() {
273  this->m_data.negate();
274  }
275  void inverse() {
276  this->m_data.inverse();
277  }
278 
279  #define FUNCTION_PROXY(FUN) \
280  void FUN () { \
281  this->m_data. FUN (); \
282  }
283 
299 
300  #undef FUNCTION_PROXY
301  };
302 
303  template<typename T, typename A> derived_result_wrapper<A> operator/(T arg, derived_result_wrapper<A> res) {
304  return arg * res.inverse();
305  }
306 
307  template<typename A> class derived_accumulator_wrapper : public derived_wrapper<A> {
308  private:
309  typedef typename base_wrapper<typename value_type<A>::type>::wrapped_scalar_value_type wrapped_scalar_value_type;
310  public:
312 
313  derived_accumulator_wrapper(A const & arg): derived_wrapper<A>(arg) {}
314 
316  return new derived_accumulator_wrapper<A>(this->m_data);
317  }
319  return result_impl<A>();
320  }
321 
322  void operator+=(base_wrapper<typename value_type<A>::type> const &) {
323  throw std::runtime_error("The Operator += is not implemented for accumulators, only for results" + ALPS_STACKTRACE);
324  }
325  void operator-=(base_wrapper<typename value_type<A>::type> const &) {
326  throw std::runtime_error("The Operator -= is not implemented for accumulators, only for results" + ALPS_STACKTRACE);
327  }
328  void operator*=(base_wrapper<typename value_type<A>::type> const &) {
329  throw std::runtime_error("The Operator *= is not implemented for accumulators, only for results" + ALPS_STACKTRACE);
330  }
331  void operator/=(base_wrapper<typename value_type<A>::type> const &) {
332  throw std::runtime_error("The Operator /= is not implemented for accumulators, only for results" + ALPS_STACKTRACE);
333  }
334 
335  void operator+=(long double) {
336  throw std::runtime_error("The operator += is not implemented for accumulators, only for results" + ALPS_STACKTRACE);
337  }
338  void operator-=(long double) {
339  throw std::runtime_error("The operator -= is not implemented for accumulators, only for results" + ALPS_STACKTRACE);
340  }
341  void operator*=(long double) {
342  throw std::runtime_error("The operator *= is not implemented for accumulators, only for results" + ALPS_STACKTRACE);
343  }
344  void operator/=(long double) {
345  throw std::runtime_error("The operator /= is not implemented for accumulators, only for results" + ALPS_STACKTRACE);
346  }
347 
348  void operator+=(wrapped_scalar_value_type /*arg*/) {
349  throw std::runtime_error("The Operator += is not implemented for accumulators, only for results" + ALPS_STACKTRACE);
350  }
351  void operator-=(wrapped_scalar_value_type /*arg*/) {
352  throw std::runtime_error("The Operator -= is not implemented for accumulators, only for results" + ALPS_STACKTRACE);
353  }
354  void operator*=(wrapped_scalar_value_type /*arg*/) {
355  throw std::runtime_error("The Operator *= is not implemented for accumulators, only for results" + ALPS_STACKTRACE);
356  }
357  void operator/=(wrapped_scalar_value_type /*arg*/) {
358  throw std::runtime_error("The Operator /= is not implemented for accumulators, only for results" + ALPS_STACKTRACE);
359  }
360 
361  void negate() {
362  throw std::runtime_error("The function negate is not implemented for accumulators, only for results" + ALPS_STACKTRACE);
363  }
364  void inverse() {
365  throw std::runtime_error("The function inverse is not implemented for accumulators, only for results" + ALPS_STACKTRACE);
366  }
367 
368  #define FUNCTION_PROXY(FUN) \
369  void FUN () { \
370  throw std::runtime_error("The Function " #FUN " is not implemented for accumulators, only for results" + ALPS_STACKTRACE); \
371  }
372 
388 
389  #undef FUNCTION_PROXY
390 
391  private:
392 
393  template<typename T> typename std::enable_if<has_result_type<T>::value, base_wrapper<typename value_type<A>::type> *>::type result_impl() const {
394  return new derived_result_wrapper<typename A::result_type>(this->m_data);
395  }
396  template<typename T> typename std::enable_if<!has_result_type<T>::value, base_wrapper<typename value_type<A>::type> *>::type result_impl() const {
397  throw std::runtime_error(std::string("The type ") + typeid(A).name() + " has no result_type" + ALPS_STACKTRACE);
398  return NULL;
399  }
400 
401  };
402  }
403 }
void operator-=(wrapped_scalar_value_type)
Definition: wrappers.hpp:351
result_wrapper cbrt(result_wrapper const &arg)
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
result_wrapper cos(result_wrapper const &arg)
result_wrapper sqrt(result_wrapper const &arg)
result_wrapper cb(result_wrapper const &arg)
void merge(const base_wrapper< value_type > &rhs)
Merge the given accumulator into this accumulator.
Definition: wrappers.hpp:209
result_wrapper sq(result_wrapper const &arg)
void print(std::ostream &os, bool terse) const
Definition: wrappers.hpp:200
Encapsulation of an MPI communicator and some communicator-related operations.
Definition: mpi.hpp:111
void operator*=(base_wrapper< typename value_type< A >::type > const &)
Definition: wrappers.hpp:328
void operator+=(base_wrapper< typename value_type< A >::type > const &)
Definition: wrappers.hpp:322
boost::array< T, N > & operator+=(boost::array< T, N > &lhs, boost::array< T, N > const &rhs)
wrap_value_type< T >::type wrapped_scalar_value_type
Either wrapped scalar<T>::type or unwrapped void*, depending on T.
Definition: wrappers.hpp:90
#define OPERATOR_PROXY(AUGOPNAME, AUGOP, AUGOPFN)
Definition: wrappers.hpp:247
result_wrapper log(result_wrapper const &arg)
base_wrapper< typename value_type< A >::type > * result() const
Definition: wrappers.hpp:318
void operator-=(base_wrapper< typename value_type< A >::type > const &)
Definition: wrappers.hpp:325
result_wrapper operator/(long double arg1, result_wrapper const &arg2)
void reset(accumulator_wrapper &arg)
boost::array< T, N > & operator/=(boost::array< T, N > &lhs, boost::array< T, N > const &rhs)
result_wrapper tanh(result_wrapper const &arg)
void operator+=(wrapped_scalar_value_type)
Definition: wrappers.hpp:348
boost::array< T, N > & operator*=(boost::array< T, N > &lhs, boost::array< T, N > const &rhs)
result_wrapper acos(result_wrapper const &arg)
void load(hdf5::archive &ar)
Definition: wrappers.hpp:196
std::ostream & print(std::ostream &s, const dict_value &dv, bool terse)
Definition: dict_value.cpp:186
void operator*=(wrapped_scalar_value_type)
Definition: wrappers.hpp:354
#define FUNCTION_PROXY(FUN)
Definition: wrappers.hpp:368
detail::value_wrapper< T >::value_type value_type
Definition: wrappers.hpp:49
void operator/=(wrapped_scalar_value_type)
Definition: wrappers.hpp:357
#define ALPS_STACKTRACE
Definition: stacktrace.hpp:37
base_wrapper< typename value_type< A >::type > * clone() const
Definition: wrappers.hpp:239
result_wrapper sin(result_wrapper const &arg)
result_wrapper asin(result_wrapper const &arg)
traits< Acc >::result_type result(const Acc &acc)
Definition: util.hpp:53
result_wrapper tan(result_wrapper const &arg)
result_wrapper abs(result_wrapper const &arg)
base_wrapper< typename value_type< A >::type > * clone() const
Definition: wrappers.hpp:315
void operator()(value_type const &value)
Definition: wrappers.hpp:188
void operator/=(base_wrapper< typename value_type< A >::type > const &)
Definition: wrappers.hpp:331
result_wrapper sinh(result_wrapper const &arg)
A const & extract() const
Definition: wrappers.hpp:74
std::vector< T > & merge(std::vector< T > &left, const std::vector< T > &right)
Vector merge.
result_wrapper cosh(result_wrapper const &arg)
void save(hdf5::archive &ar) const
Definition: wrappers.hpp:193
base_wrapper< typename value_type< A >::type > * result() const
Definition: wrappers.hpp:242
boost::array< T, N > & operator-=(boost::array< T, N > &lhs, boost::array< T, N > const &rhs)
result_wrapper atan(result_wrapper const &arg)
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