ALPSCore reference
error.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 
15 
16 #include <alps/hdf5/archive.hpp>
17 #include <alps/numeric/inf.hpp>
21 
24 
25 #include <boost/utility.hpp>
26 
27 #include <stdexcept>
28 #include <type_traits>
29 
30 namespace alps {
31  namespace accumulators {
32  // this should be called namespace tag { struct error; }
33  // but gcc <= 4.4 has lookup error, so name it different
34  struct error_tag;
35 
36  template<typename T> struct error_type : public mean_type<T> {};
37 
38  template<typename T> struct has_feature<T, error_tag> {
39  template<typename R, typename C> static char helper(R(C::*)() const);
40  template<typename R, typename C> static char helper(R(C::*)(std::size_t) const);
41  template<typename C> static char check(std::integral_constant<std::size_t, sizeof(helper(&C::error))>*);
42  template<typename C> static double check(...);
43  typedef std::integral_constant<bool, sizeof(char) == sizeof(check<T>(0))> type;
44  constexpr static bool value = type::value;
45  };
46 
47  template<typename T> typename error_type<T>::type error(T const & arg) {
48  return arg.error();
49  }
50 
51  namespace detail {
52 
53  template<typename A> typename std::enable_if<
55  , typename error_type<A>::type
56  >::type error_impl(A const & acc) {
57  return error(acc);
58  }
59 
60  template<typename A> typename std::enable_if<
61  !has_feature<A, error_tag>::value
62  , typename error_type<A>::type
63  >::type error_impl(A const & /*acc*/) {
64  throw std::runtime_error(std::string(typeid(A).name()) + " has no error-method" + ALPS_STACKTRACE);
65  return typename error_type<A>::type();
66  }
67  }
68 
69  namespace impl {
70 
71  template<typename T, typename B> struct Accumulator<T, error_tag, B> : public B {
72 
73  public:
77 
78  Accumulator(): B(), m_sum2(T()) {}
79 
80  Accumulator(Accumulator const & arg): B(arg), m_sum2(arg.m_sum2) {}
81 
82  template<typename ArgumentPack> Accumulator(ArgumentPack const & args, typename std::enable_if<!is_accumulator<ArgumentPack>::value, int>::type = 0)
83  : B(args), m_sum2(T())
84  {}
85 
86  error_type const error() const;
87 
88  using B::operator();
89  void operator()(T const & val);
90 
91  template<typename S> void print(S & os, bool terse=false) const {
92  B::print(os, terse);
93  os << " +/-" << alps::short_print(error());
94  }
95 
96  void save(hdf5::archive & ar) const;
97  void load(hdf5::archive & ar);
98 
99  static std::size_t rank() { return B::rank() + 1; }
100  static bool can_load(hdf5::archive & ar);
101 
102  void reset() {
103  B::reset();
104  m_sum2 = T();
105  }
106 
108  template <typename A>
109  void merge(const A& rhs)
110  {
111  using alps::numeric::operator+=;
113  B::merge(rhs);
114  check_size(m_sum2, rhs.m_sum2);
115  m_sum2 += rhs.m_sum2;
116  }
117 
118 #ifdef ALPS_HAVE_MPI
119  void collective_merge(
120  alps::mpi::communicator const & comm
121  , int root
122  );
123  void collective_merge(
124  alps::mpi::communicator const & comm
125  , int root
126  ) const;
127 #endif
128 
129  private:
130  T m_sum2;
131  };
132 
133  template<typename T, typename B> class Result<T, error_tag, B> : public B {
134 
135  public:
137  typedef typename alps::numeric::scalar<error_type>::type error_scalar_type; // FIXME: should be numeric::scalar<>
138  typedef typename detail::make_scalar_result_type<impl::Result,T,error_tag,B>::type scalar_result_type;
139 
141  : B()
142  , m_error(error_type())
143  {}
144 
145  template<typename A> Result(A const & acc)
146  : B(acc)
147  , m_error(detail::error_impl(acc))
148  {}
149 
150  error_type const error() const {
151  return m_error;
152  }
153 
154  template<typename S> void print(S & os, bool terse=false) const {
155  B::print(os, terse);
156  os << " +/-" << alps::short_print(error());
157  }
158 
159  void save(hdf5::archive & ar) const;
160  void load(hdf5::archive & ar);
161 
162  static std::size_t rank() { return B::rank() + 1; }
163  static bool can_load(hdf5::archive & ar);
164 
165  template<typename U> void operator+=(U const & arg) { augaddsub(arg); B::operator+=(arg); }
166  template<typename U> void operator-=(U const & arg) { augaddsub(arg); B::operator-=(arg); }
167  template<typename U> void operator*=(U const & arg) { augmul(arg); }
168  template<typename U> void operator/=(U const & arg) { augdiv(arg); }
169  void negate();
170  void inverse();
171 
172  void sin();
173  void cos();
174  void tan();
175  void sinh();
176  void cosh();
177  void tanh();
178  void asin();
179  void acos();
180  void atan();
181  void sq();
182  void sqrt();
183  void cb();
184  void cbrt();
185  void exp();
186  void log();
187 
188  private:
189 
190  error_type m_error;
191 
192  template<typename U> void augaddsub (U const & arg, typename std::enable_if<!std::is_scalar<U>::value, int>::type = 0) {
193  using alps::numeric::operator+;
194  m_error = m_error + arg.error();
195  }
196  template<typename U> void augaddsub (U const & /*arg*/, typename std::enable_if<std::is_scalar<U>::value, int>::type = 0) {}
197 
198  template<typename U> void augmul (U const & arg, typename std::enable_if<!std::is_scalar<U>::value, int>::type = 0) {
199  using alps::numeric::operator*;
200  using alps::numeric::operator+;
201  // FIXME? Originally: m_error = arg.mean() * m_error + this->mean() * arg.error();
202  // FIXME? Changed to:
203  m_error = m_error * arg.mean() + this->mean() * arg.error();
204  B::operator*=(arg);
205  }
206  template<typename U> void augmul (U const & arg, typename std::enable_if<std::is_scalar<U>::value, int>::type = 0) {
207  using alps::numeric::operator*;
208  m_error = m_error * static_cast<error_scalar_type>(arg);
209  B::operator*=(arg);
210  }
211 
212  template<typename U> void augdiv (U const & arg, typename std::enable_if<!std::is_scalar<U>::value, int>::type = 0) {
213  using alps::numeric::operator*;
214  using alps::numeric::operator/;
215  using alps::numeric::operator+;
216  m_error = m_error / arg.mean() + this->mean() * arg.error() / (arg.mean() * arg.mean());
217  B::operator/=(arg);
218  }
219  template<typename U> void augdiv (U const & arg, typename std::enable_if<std::is_scalar<U>::value, int>::type = 0) {
220  using alps::numeric::operator/;
221  m_error = m_error / static_cast<error_scalar_type>(arg);
222  B::operator/=(arg);
223  }
224  };
225 
226  template<typename T, typename B> class BaseWrapper<T, error_tag, B> : public B {
227  public:
228  virtual bool has_error() const = 0;
229  virtual typename error_type<B>::type error() const = 0;
230  };
231 
232  template<typename T, typename B> class DerivedWrapper<T, error_tag, B> : public B {
233  public:
234  DerivedWrapper(): B() {}
235  DerivedWrapper(T const & arg): B(arg) {}
236 
238 
239  typename error_type<B>::type error() const { return detail::error_impl(this->m_data); }
240  };
241 
242  }
243  }
244 }
void merge(const A &rhs)
Merge the mean & error of given accumulator of type A into this accumulator.
Definition: error.hpp:109
void print(S &os, bool terse=false) const
Definition: error.hpp:154
result_wrapper cbrt(result_wrapper const &arg)
void check_size(T &, U const &)
Definition: check_size.hpp:40
alps::numeric::scalar< error_type >::type error_scalar_type
Definition: error.hpp:75
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)
result_wrapper sq(result_wrapper const &arg)
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
Metafunction returning "mathematical scalar" type for type T.
Definition: scalar.hpp:28
boost::array< T, N > & operator+=(boost::array< T, N > &lhs, boost::array< T, N > const &rhs)
detail::make_scalar_result_type< impl::Result, T, error_tag, B >::type scalar_result_type
Definition: error.hpp:138
mean_type< T >::type mean(T const &arg)
Definition: mean.hpp:47
Accumulator(ArgumentPack const &args, typename std::enable_if<!is_accumulator< ArgumentPack >::value, int >::type=0)
Definition: error.hpp:82
result_wrapper log(result_wrapper const &arg)
void print(S &os, bool terse=false) const
Definition: error.hpp:91
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 > exp(boost::array< T, N > arg)
alps::numeric::scalar< error_type >::type error_scalar_type
Definition: error.hpp:137
result_wrapper tanh(result_wrapper const &arg)
error_type< T >::type error(T const &arg)
Definition: error.hpp:47
boost::array< T, N > & operator*=(boost::array< T, N > &lhs, boost::array< T, N > const &rhs)
alps::accumulators::error_type< B >::type error_type
Definition: error.hpp:136
result_wrapper acos(result_wrapper const &arg)
std::ostream & print(std::ostream &s, const dict_value &dv, bool terse)
Definition: dict_value.cpp:186
std::integral_constant< bool, sizeof(char)==sizeof(check< T >0))> type
Definition: error.hpp:43
#define ALPS_STACKTRACE
Definition: stacktrace.hpp:37
result_wrapper sin(result_wrapper const &arg)
result_wrapper asin(result_wrapper const &arg)
result_wrapper tan(result_wrapper const &arg)
alps::accumulators::error_type< B >::type error_type
Definition: error.hpp:74
result_wrapper sinh(result_wrapper const &arg)
std::vector< T > & merge(std::vector< T > &left, const std::vector< T > &right)
Vector merge.
Result< T, error_tag, typename B::result_type > result_type
Definition: error.hpp:76
result_wrapper cosh(result_wrapper const &arg)
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