ALPSCore reference
result_wrapper.cpp
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 
8 #include <sstream>
9 
10 namespace alps {
11  namespace accumulators {
12 
13  //
14  // constructors
15  //
16 
18  : m_variant()
19  {}
20 
21  struct copy_visitor: public boost::static_visitor<> {
22  copy_visitor(detail::variant_type & s): self(s) {}
23  template<typename T> void operator()(T const & arg) const {
24  const_cast<detail::variant_type &>(self) = T(arg->clone());
25  }
26  detail::variant_type & self;
27  };
29  : m_variant()
30  {
31  copy_visitor visitor(m_variant);
32  boost::apply_visitor(visitor, rhs.m_variant);
33  }
35  ar[""] >> *this;
36  }
37 
38  //
39  // operator=
40  //
41 
42  struct result_wrapper::assign_visitor: public boost::static_visitor<> {
43  assign_visitor(result_wrapper * s): self(s) {}
44  template<typename T> void operator()(T & arg) const {
45  self->m_variant = arg;
46  }
47  mutable result_wrapper * self;
48  };
49  result_wrapper & result_wrapper::operator=(std::shared_ptr<result_wrapper> const & rhs) {
50  boost::apply_visitor(assign_visitor(this), rhs->m_variant);
51  return *this;
52  }
53 
54  //
55  // count
56  //
57 
58  struct count_visitor: public boost::static_visitor<boost::uint64_t> {
59  template<typename T> boost::uint64_t operator()(T const & arg) const {
60  return arg->count();
61  }
62  };
63  boost::uint64_t result_wrapper::count() const {
64  count_visitor visitor;
65  return boost::apply_visitor(visitor, m_variant);
66  }
67 
68  //
69  // save
70  //
71 
72  struct save_visitor: public boost::static_visitor<> {
73  save_visitor(hdf5::archive & a): ar(a) {}
74  template<typename T> void operator()(T & arg) const { ar[""] = *arg; }
75  hdf5::archive & ar;
76  };
78  boost::apply_visitor(save_visitor(ar), m_variant);
79  }
80 
81  //
82  // load
83  //
84 
85  struct load_visitor: public boost::static_visitor<> {
86  load_visitor(hdf5::archive & a): ar(a) {}
87  template<typename T> void operator()(T const & arg) const { ar[""] >> *arg; }
88  hdf5::archive & ar;
89  };
91  boost::apply_visitor(load_visitor(ar), m_variant);
92  }
93 
94  //
95  // print
96  //
97 
98  struct print_visitor: public boost::static_visitor<> {
99  print_visitor(std::ostream & o, bool t): os(o), terse(t) {}
100  template<typename T> void operator()(T const & arg) const { arg->print(os, terse); }
101  std::ostream & os;
102  bool terse;
103  };
104  void result_wrapper::print(std::ostream & os, bool terse) const {
105  boost::apply_visitor(print_visitor(os, terse), m_variant);
106  }
107 
108  //
109  // unary plus
110  //
111 
113  return result_wrapper(*this);
114  }
115 
116  //
117  // unary minus
118  //
119 
120  struct unary_add_visitor : public boost::static_visitor<> {
121  template<typename X> void operator()(X & arg) const {
122  arg->negate();
123  }
124  };
126  result_wrapper clone(*this);
127  unary_add_visitor visitor;
128  boost::apply_visitor(visitor, clone.m_variant);
129  return clone;
130  }
131 
132  //
133  // Arithmetical operations
134  //
135 
136  // Naming conventions:
137  // Operation is `lhs_var AUGOP rhs_var`, where AUGOP is `+=` , `-=` etc.
138  // lhsvar contains a variant over LHSPT types
139  // rhsvar contains a variant over RHSPT types
140  // LHSPT: lhs (pointer) type, which is shared_ptr<LHSWT>
141  // LHSWT: lhs (base_wrapper<...>) type
142  // RHSPT: rhs (pointer) type, which is shared_ptr<RHSWT>
143  // RHSWT: rhs (base_wrapper<...>) type
144  #define ALPS_ACCUMULATOR_OPERATOR_PROXY(OPNAME, AUGOPNAME, AUGOP, FUN) \
145  template<typename LHSWT> struct FUN ## _arg_visitor: public boost::static_visitor<> { \
146  FUN ## _arg_visitor(LHSWT & v): lhs_value(v) {} \
147  template<typename RHSWT> \
148  void apply(const RHSWT&, \
149  typename std::enable_if<!detail::is_compatible_op<LHSWT,RHSWT>::value >::type* =0) const { \
150  throw std::logic_error("only results with compatible value types are allowed in operators" \
151  + ALPS_STACKTRACE); \
152  } \
153  template<typename RHSWT> \
154  void apply(const RHSWT& rhs_value, \
155  typename std::enable_if<detail::is_compatible_op<LHSWT,RHSWT>::value >::type* =0) { \
156  lhs_value AUGOP rhs_value; \
157  } \
158  void apply(LHSWT const & rhs_value) { \
159  lhs_value AUGOP rhs_value; \
160  } \
161  template<typename RHSPT> void operator()(RHSPT const & rhs_ptr) { \
162  apply(*rhs_ptr); \
163  } \
164  LHSWT & lhs_value; \
165  }; \
166  struct result_wrapper:: FUN ## _self_visitor: public boost::static_visitor<> { \
167  FUN ## _self_visitor(result_wrapper const & v): rhs_value(v) {} \
168  template<typename LHSPT> void operator()(LHSPT & self) const { \
169  FUN ## _arg_visitor<typename LHSPT::element_type> visitor(*self); \
170  boost::apply_visitor(visitor, rhs_value.m_variant); \
171  } \
172  result_wrapper const & rhs_value; \
173  }; \
174  \
175  /* @note `long double` is chosen as the widest scalar numeric type */ \
176  /* @note No use of template: calls non-templatable virtual function. */ \
177  struct FUN ## _ldouble_visitor: public boost::static_visitor<> { \
178  FUN ## _ldouble_visitor(long double v): value(v) {} \
179  template<typename X> void operator()(X & arg) const { \
180  *arg AUGOP value; \
181  } \
182  long double value; \
183  }; \
184  \
185  result_wrapper & result_wrapper:: AUGOPNAME (result_wrapper const & rhs) { \
186  FUN ## _self_visitor visitor(rhs); \
187  boost::apply_visitor(visitor, m_variant); \
188  return *this; \
189  } \
190  \
191  result_wrapper & result_wrapper:: AUGOPNAME (long double arg) { \
192  FUN ## _ldouble_visitor visitor(arg); \
193  boost::apply_visitor(visitor, m_variant); \
194  return *this; \
195  } \
196  result_wrapper result_wrapper:: OPNAME (result_wrapper const & arg) const { \
197  result_wrapper clone(*this); \
198  clone AUGOP arg; \
199  return clone; \
200  } \
201  \
202  result_wrapper result_wrapper:: OPNAME (long double arg) const { \
203  result_wrapper clone(*this); \
204  clone AUGOP arg; \
205  return clone; \
206  }
207  ALPS_ACCUMULATOR_OPERATOR_PROXY(operator+, operator+=, +=, add)
208  ALPS_ACCUMULATOR_OPERATOR_PROXY(operator-, operator-=, -=, sub)
209  ALPS_ACCUMULATOR_OPERATOR_PROXY(operator*, operator*=, *=, mul)
210  ALPS_ACCUMULATOR_OPERATOR_PROXY(operator/, operator/=, /=, div)
211  #undef ALPS_ACCUMULATOR_OPERATOR_PROXY
212 
213  //
214  // inverse
215  //
216 
217  struct inverse_visitor: public boost::static_visitor<> {
218  template<typename T> void operator()(T & arg) const { arg->inverse(); }
219  };
221  result_wrapper clone(*this);
222  boost::apply_visitor(inverse_visitor(), clone.m_variant);
223  return clone;
224  }
225 
226  //
227  // Math functions
228  //
229 
230  #define ALPS_ACCUMULATOR_FUNCTION_PROXY(FUN) \
231  struct FUN ## _visitor: public boost::static_visitor<> { \
232  template<typename T> void operator()(T & arg) const { \
233  arg-> FUN (); \
234  } \
235  }; \
236  result_wrapper result_wrapper:: FUN () const { \
237  result_wrapper clone(*this); \
238  boost::apply_visitor( FUN ## _visitor(), clone.m_variant); \
239  return clone; \
240  }
256  #undef ALPS_ACCUMULATOR_FUNCTION_PROXY
257 
258  //
259  // Free functions
260  //
261 
262 #define EXTERNAL_FUNCTION(FUN) \
263  result_wrapper FUN (result_wrapper const & arg) { \
264  return arg. FUN (); \
265  }
281 
282 #undef EXTERNAL_FUNCTION
283 
284  detail::printable_type short_print(const result_wrapper& arg)
285  {
286  std::ostringstream ostr;
287  arg.print(ostr,true);
288  return ostr.str();
289  }
290 
291  detail::printable_type full_print(const result_wrapper& arg)
292  {
293  std::ostringstream ostr;
294  arg.print(ostr,false);
295  return ostr.str();
296  }
297 
298  std::ostream & operator<<(std::ostream & os, const result_wrapper & arg) {
299  arg.print(os, true); // terse printing by default
300  return os;
301  }
302 
303  }
304 }
#define ALPS_ACCUMULATOR_OPERATOR_PROXY(OPNAME, AUGOPNAME, AUGOP, FUN)
detail::printable_type short_print(const result_wrapper &arg)
Return an "ostream-able" object to print result in a terse format.
F::result_type apply_visitor(F &visitor, dictionary::const_iterator it)
Const-access visitor to a value by an iterator.
Definition: dictionary.hpp:110
#define ALPS_ACCUMULATOR_FUNCTION_PROXY(FUN)
std::ostream & operator<<(std::ostream &os, const result_wrapper &arg)
detail::printable_type full_print(const result_wrapper &arg)
Return an "ostream-able" object to print result in a verbose format.
void print(std::ostream &os, bool terse=false) const
#define EXTERNAL_FUNCTION(FUN)
boost::uint64_t count() const
void save(hdf5::archive &ar) const
result_wrapper & operator=(std::shared_ptr< result_wrapper > const &rhs)
result_wrapper operator-() const
result_wrapper operator+() const