ALPSCore reference
feature.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 #include <alps/numeric/inf.hpp>
14 
15 #include "alps/numeric/scalar.hpp"
17 
18 #include <boost/utility.hpp>
19 
20 #include <type_traits>
21 
22 #ifdef ALPS_HAVE_MPI
23  #include <alps/hdf5/archive.hpp>
24  #include <alps/accumulators/mpi.hpp>
25 #endif
26 
27 namespace alps {
28  namespace accumulators {
29 
30  template<typename T, typename F> struct has_feature
31  : std::false_type
32  {};
33 
34  template<typename T> struct has_result_type {
35  template<typename U> static char check(typename U::result_type *);
36  template<typename U> static double check(...);
37  typedef std::integral_constant<bool, sizeof(char) == sizeof(check<T>(0))> type;
38  constexpr static bool value = type::value;
39  };
40 
41  #define NUMERIC_FUNCTION_OPERATOR(OP_NAME, OP, OP_TOKEN) \
42  namespace detail { \
43  using ::alps::numeric:: OP_NAME ; \
44  template<typename T, typename U> struct has_operator_ ## OP_TOKEN ## _impl { \
45  template<typename R> static char helper(R); \
46  template<typename C, typename D> static char check(std::integral_constant<std::size_t, sizeof(helper(C() OP D()))>*); \
47  template<typename C, typename D> static double check(...); \
48  typedef std::integral_constant<bool, sizeof(char) == sizeof(check<T, U>(0))> type; \
49  }; \
50  } \
51  template<typename T, typename U> struct has_operator_ ## OP_TOKEN : public detail::has_operator_ ## OP_TOKEN ## _impl<T, U> {};
52 
53  NUMERIC_FUNCTION_OPERATOR(operator+, +, add)
54  NUMERIC_FUNCTION_OPERATOR(operator-, -, sub)
55  NUMERIC_FUNCTION_OPERATOR(operator*, *, mul)
56  NUMERIC_FUNCTION_OPERATOR(operator/, /, div)
57  #undef NUMERIC_FUNCTION_OPERATOR
58 
59  template<typename T> struct value_type {
60  typedef typename T::value_type type;
61  };
62 
63  namespace detail {
64 
66  template <template<typename,typename,typename> class R,
67  typename T, typename F, typename B>
68  class make_scalar_result_type {
69  typedef typename alps::numeric::scalar<T>::type scalar_type_;
70  typedef typename B::scalar_result_type parent_scalar_result_type_;
71  typedef R<scalar_type_, F, parent_scalar_result_type_> this_scalar_result_type_;
72  public:
73  typedef typename std::conditional<alps::is_scalar<T>::value,
74  void,
75  this_scalar_result_type_>::type type;
76  };
77  }
78 
79  namespace impl {
80 
81  template<typename T> struct ResultBase {
82  typedef T value_type;
83  typedef typename std::conditional<alps::is_scalar<T>::value,
84  void,
87 
89  template <typename A>
90  void merge(const A& /*rhs*/) {
91  throw std::runtime_error("A result cannot be merged " + ALPS_STACKTRACE);
92  }
93 
94 #ifdef ALPS_HAVE_MPI
95  inline void collective_merge(
96  alps::mpi::communicator const & /*comm*/
97  , int /*root*/
98  ) const {
99  throw std::logic_error("A result cannot be merged " + ALPS_STACKTRACE);
100  }
101 #endif
102 
103  template<typename U> void operator+=(U const &) {}
104  template<typename U> void operator-=(U const &) {}
105  template<typename U> void operator*=(U const &) {}
106  template<typename U> void operator/=(U const &) {}
107  void negate() {}
108  void inverse() {}
109 
110  void sin() {}
111  void cos() {}
112  void tan() {}
113  void sinh() {}
114  void cosh() {}
115  void tanh() {}
116  void asin() {}
117  void acos() {}
118  void atan() {}
119  void abs() {}
120  void sq() {}
121  void sqrt() {}
122  void cb() {}
123  void cbrt() {}
124  void exp() {}
125  void log() {}
126  };
127 
128  template<typename T> class AccumulatorBase {
129  public:
130  typedef T value_type;
132 
133  template<typename U> void operator+=(U) {
134  throw std::runtime_error("The Function operator += is not implemented for accumulators, only for results" + ALPS_STACKTRACE);
135  }
136  template<typename U> void operator-=(U) {
137  throw std::runtime_error("The Function operator -= is not implemented for accumulators, only for results" + ALPS_STACKTRACE);
138  }
139  template<typename U> void operator*=(U) {
140  throw std::runtime_error("The Function operator *= is not implemented for accumulators, only for results" + ALPS_STACKTRACE);
141  }
142  template<typename U> void operator/=(U) {
143  throw std::runtime_error("The Function operator /= is not implemented for accumulators, only for results" + ALPS_STACKTRACE);
144  }
145  void negate() {
146  throw std::runtime_error("The Function negate is not implemented for accumulators, only for results" + ALPS_STACKTRACE);
147  }
148  void inverse() {
149  throw std::runtime_error("The Function inverse is not implemented for accumulators, only for results" + ALPS_STACKTRACE);
150  }
151 
152  void sin() { throw std::runtime_error("The Function sin is not implemented for accumulators, only for results" + ALPS_STACKTRACE); }
153  void cos() { throw std::runtime_error("The Function cos is not implemented for accumulators, only for results" + ALPS_STACKTRACE); }
154  void tan() { throw std::runtime_error("The Function tan is not implemented for accumulators, only for results" + ALPS_STACKTRACE); }
155  void sinh() { throw std::runtime_error("The Function sinh is not implemented for accumulators, only for results" + ALPS_STACKTRACE); }
156  void cosh() { throw std::runtime_error("The Function cosh is not implemented for accumulators, only for results" + ALPS_STACKTRACE); }
157  void tanh() { throw std::runtime_error("The Function tanh is not implemented for accumulators, only for results" + ALPS_STACKTRACE); }
158  void asin() { throw std::runtime_error("The Function asin is not implemented for accumulators, only for results" + ALPS_STACKTRACE); }
159  void acos() { throw std::runtime_error("The Function acos is not implemented for accumulators, only for results" + ALPS_STACKTRACE); }
160  void atan() { throw std::runtime_error("The Function atan is not implemented for accumulators, only for results" + ALPS_STACKTRACE); }
161  void abs() { throw std::runtime_error("The Function ags is not implemented for accumulators, only for results" + ALPS_STACKTRACE); }
162  void sq() { throw std::runtime_error("The Function sq is not implemented for accumulators, only for results" + ALPS_STACKTRACE); }
163  void sqrt() { throw std::runtime_error("The Function sqrt is not implemented for accumulators, only for results" + ALPS_STACKTRACE); }
164  void cb() { throw std::runtime_error("The Function cb is not implemented for accumulators, only for results" + ALPS_STACKTRACE); }
165  void cbrt() { throw std::runtime_error("The Function cbrt is not implemented for accumulators, only for results" + ALPS_STACKTRACE); }
166  void exp() { throw std::runtime_error("The Function exp is not implemented for accumulators, only for results" + ALPS_STACKTRACE); }
167  void log() { throw std::runtime_error("The Function log is not implemented for accumulators, only for results" + ALPS_STACKTRACE); }
168 
169 #ifdef ALPS_HAVE_MPI
170  protected:
171  template <typename U, typename Op> void static reduce_if(
172  alps::mpi::communicator const & comm
173  , U const & arg
174  , U & res
175  , Op op
176  , typename std::enable_if<std::is_scalar<typename alps::hdf5::scalar_type<U>::type>::value, int>::type root
177  ) {
178  alps::alps_mpi::reduce(comm, arg, res, op, root);
179  }
180  template <typename U, typename Op> void static reduce_if(
182  , U const &
183  , U &
184  , Op
185  , typename std::enable_if<!std::is_scalar<typename alps::hdf5::scalar_type<U>::type>::value, int>::type
186  ) {
187  throw std::logic_error("No alps::mpi::reduce available for this type " + std::string(typeid(U).name()) + ALPS_STACKTRACE);
188  }
189 
190  template <typename U, typename Op> void static reduce_if(
191  alps::mpi::communicator const & comm
192  , U const & arg
193  , Op op
194  , typename std::enable_if<std::is_scalar<typename alps::hdf5::scalar_type<U>::type>::value, int>::type root
195  ) {
196  alps::alps_mpi::reduce(comm, arg, op, root);
197  }
198  template <typename U, typename Op> void static reduce_if(
200  , U const &
201  , Op
202  , typename std::enable_if<!std::is_scalar<typename alps::hdf5::scalar_type<U>::type>::value, int>::type
203  ) {
204  throw std::logic_error("No alps::mpi::reduce available for this type " + std::string(typeid(U).name()) + ALPS_STACKTRACE);
205  }
206 #endif
207  };
208 
209  template<typename T, typename F, typename B> class Accumulator {};
210 
211  template<typename T, typename F, typename B> class Result {};
212 
213  template<typename T, typename F, typename B> class BaseWrapper {};
214 
215  template<typename A, typename F, typename B> class DerivedWrapper {};
216 
217  template<typename T> struct is_accumulator : public std::false_type {};
218  template<typename T, typename tag, typename B> struct is_accumulator<Accumulator<T, tag, B> > : public std::true_type {};
219 
220  }
221  }
222 }
std::conditional< alps::is_scalar< T >::value, void, ResultBase< typename alps::numeric::scalar< T >::type > >::type scalar_result_type
Definition: feature.hpp:86
#define NUMERIC_FUNCTION_OPERATOR(OP_NAME, OP, OP_TOKEN)
Definition: feature.hpp:41
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
void merge(const A &)
Dummy function for merging results (always throws an exception)
Definition: feature.hpp:90
#define ALPS_STACKTRACE
Definition: stacktrace.hpp:37
std::integral_constant< bool, sizeof(char)==sizeof(check< T >0))> type
Definition: feature.hpp:37