Tomographer  v5.0
Tomographer C++ Framework Documentation
valuecalculator.h
Go to the documentation of this file.
1 /* This file is part of the Tomographer project, which is distributed under the
2  * terms of the MIT license.
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2016 ETH Zurich, Institute for Theoretical Physics, Philippe Faist
7  * Copyright (c) 2017 Caltech, Institute for Quantum Information and Matter, Philippe Faist
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a copy
10  * of this software and associated documentation files (the "Software"), to deal
11  * in the Software without restriction, including without limitation the rights
12  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13  * copies of the Software, and to permit persons to whom the Software is
14  * furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included in
17  * all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25  * SOFTWARE.
26  */
27 
28 #ifndef TOMOGRAPHER_VALUECALCULATOR_H
29 #define TOMOGRAPHER_VALUECALCULATOR_H
30 
31 #include <tuple>
32 
35 
36 
45 namespace Tomographer {
46 
47 
48 
49 namespace tomo_internal {
50 
51 //
52 // helper for the helper for getValue()
53 //
54 template<typename ValueType, typename... ValueCalculators>
55 struct MplxVC_getval_helper_helper
56 {
57  template<int I, typename PointType>
58  static inline ValueType callGetValue(const std::array<void*,sizeof...(ValueCalculators)> & _valcalcs, PointType && x)
59  {
60  return ( (typename std::tuple_element<I, std::tuple<ValueCalculators...> >::type *) _valcalcs[I])
61  -> getValue(std::forward<PointType>(x));
62  }
63 };
64 
65 //
66 // helper for getValue()
67 //
68 template<int NumValueCalculators, typename ValueType, typename... ValueCalculators>
69 struct MplxVC_getval_helper
70 {
71  template<typename PointType, int IterI = 0,
72  TOMOGRAPHER_ENABLED_IF_TMPL(IterI < NumValueCalculators)>
73  static inline ValueType getValue(const int _i, const std::array<void*, sizeof...(ValueCalculators)> & _valcalcs, PointType&& x)
74  {
75  if (IterI == _i) {
76  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<IterI>(_valcalcs, x) ;
77  }
78  return getValue<PointType, IterI+1>(_i, _valcalcs, std::forward<PointType>(x));
79  }
80  //
81  template<typename PointType, int IterI = 0,
82  TOMOGRAPHER_ENABLED_IF_TMPL(IterI == NumValueCalculators)>
83  static inline ValueType getValue(const int, const std::array<void*, sizeof...(ValueCalculators)> & , PointType&& )
84  {
85  tomographer_assert(false && "Invalid i: i>=NumValueCalculators or i<0");
86  return ValueType();// silence ICC "missing return statement" warning
87  }
88 };
89 
90 // a few specializations, for optimizing a chain of if's to a faster switch statement (?)
91 template<typename ValueType, typename... ValueCalculators>
92 struct MplxVC_getval_helper<1, ValueType, ValueCalculators...>
93 {
94  TOMO_STATIC_ASSERT_EXPR(sizeof...(ValueCalculators) == 1) ;
95  template<typename PointType>
96  static inline ValueType getValue(const int _i, const std::array<void*, sizeof...(ValueCalculators)> & _valcalcs, PointType&& x)
97  {
98  tomographer_assert(_i == 0 && "i != 0 but NumValueCalculators == 1");(void)_i;
99  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<0>(_valcalcs, x) ;
100  }
101 };
102 //--
103 template<typename ValueType, typename... ValueCalculators>
104 struct MplxVC_getval_helper<2, ValueType, ValueCalculators...>
105 {
106  TOMO_STATIC_ASSERT_EXPR(sizeof...(ValueCalculators) == 2) ;
107  template<typename PointType>
108  static inline ValueType getValue(const int _i, const std::array<void*, sizeof...(ValueCalculators)> & _valcalcs, PointType&& x)
109  {
110  tomographer_assert(_i >= 0 && _i < (int)sizeof...(ValueCalculators) && "i out of range");
111  switch (_i) {
112  case 0: return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<0>(_valcalcs, x) ;
113  default: return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<1>(_valcalcs, x) ;
114  }
115  }
116 };
117 //--
118 template<typename ValueType, typename... ValueCalculators>
119 struct MplxVC_getval_helper<3, ValueType, ValueCalculators...>
120 {
121  TOMO_STATIC_ASSERT_EXPR(sizeof...(ValueCalculators) == 3) ;
122  template<typename PointType>
123  static inline ValueType getValue(const int _i, const std::array<void*, sizeof...(ValueCalculators)> & _valcalcs, PointType&& x)
124  {
125  tomographer_assert(_i >= 0 && _i < (int)sizeof...(ValueCalculators) && "i out of range");
126  switch (_i) {
127  case 0: return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<0>(_valcalcs, x) ;
128  case 1: return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<1>(_valcalcs, x) ;
129  default: return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<2>(_valcalcs, x) ;
130  }
131  }
132 };
133 //--
134 template<typename ValueType, typename... ValueCalculators>
135 struct MplxVC_getval_helper<4, ValueType, ValueCalculators...>
136 {
137  TOMO_STATIC_ASSERT_EXPR(sizeof...(ValueCalculators) == 4) ;
138  template<typename PointType>
139  static inline ValueType getValue(const int _i, const std::array<void*, sizeof...(ValueCalculators)> & _valcalcs, PointType&& x)
140  {
141  tomographer_assert(_i >= 0 && _i < (int)sizeof...(ValueCalculators) && "i out of range");
142  switch (_i) {
143  case 0: return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<0>(_valcalcs, x) ;
144  case 1: return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<1>(_valcalcs, x) ;
145  case 2: return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<2>(_valcalcs, x) ;
146  default: return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<3>(_valcalcs, x) ;
147  }
148  }
149 };
150 //--
151 template<typename ValueType, typename... ValueCalculators>
152 struct MplxVC_getval_helper<5, ValueType, ValueCalculators...>
153 {
154  TOMO_STATIC_ASSERT_EXPR(sizeof...(ValueCalculators) == 5) ;
155  template<typename PointType>
156  static inline ValueType getValue(const int _i, const std::array<void*, sizeof...(ValueCalculators)> & _valcalcs, PointType&& x)
157  {
158  tomographer_assert(_i >= 0 && _i < (int)sizeof...(ValueCalculators) && "i out of range");
159  switch (_i) {
160  case 0: return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<0>(_valcalcs, x) ;
161  case 1: return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<1>(_valcalcs, x) ;
162  case 2: return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<2>(_valcalcs, x) ;
163  case 3: return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<3>(_valcalcs, x) ;
164  default: return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<4>(_valcalcs, x) ;
165  }
166  }
167 };
168 //--
169 template<typename ValueType, typename... ValueCalculators>
170 struct MplxVC_getval_helper<6, ValueType, ValueCalculators...>
171 {
172  TOMO_STATIC_ASSERT_EXPR(sizeof...(ValueCalculators) == 6) ;
173  template<typename PointType>
174  static inline ValueType getValue(const int _i, const std::array<void*, sizeof...(ValueCalculators)> & _valcalcs, PointType&& x)
175  {
176  tomographer_assert(_i >= 0 && _i < (int)sizeof...(ValueCalculators) && "i out of range");
177  switch (_i) {
178  case 0: return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<0>(_valcalcs, x) ;
179  case 1: return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<1>(_valcalcs, x) ;
180  case 2: return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<2>(_valcalcs, x) ;
181  case 3: return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<3>(_valcalcs, x) ;
182  case 4: return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<4>(_valcalcs, x) ;
183  default: return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<5>(_valcalcs, x) ;
184  }
185  }
186 };
187 
188 } // namespace tomo_internal
189 
190 
191 
192 
193 
201 template<typename ValueType_, typename... ValueCalculators>
202 class TOMOGRAPHER_EXPORT MultiplexorValueCalculator
203  : public virtual Tools::NeedOwnOperatorNew<ValueCalculators...>::ProviderType
204 {
205 public:
206  typedef ValueType_ ValueType;
207 
208  static constexpr int NumValueCalculators = sizeof...(ValueCalculators);
209  static constexpr int NumStaticallyOptimizedIfs = 6;
210 
211  // typedef std::tuple<ValueCalculators&...> ValueCalculatorsRefTupleType;
212  typedef std::tuple<ValueCalculators...> ValueCalculatorsTupleType;
213 
214 private:
216 
217  const int _i;
218 
219 
220  template<int I = 0, typename TupleCreators = void,
222  inline void _create_Ith_valcalc(int i, TupleCreators && creators) {
223  if (i == I) {
224  _valcalcs[(std::size_t)i] = (void*)std::get<I>(creators)();
225  }
226  _create_Ith_valcalc<I+1>(i, std::forward<TupleCreators>(creators));
227  }
228  template<int I = 0, typename TupleCreators = void,
230  inline void _create_Ith_valcalc(int , TupleCreators && ) { }
231 
232  template<int I = 0, typename std::enable_if<(I<NumValueCalculators),bool>::type = true>
233  inline void _delete_all() {
234  if (_valcalcs[I] != NULL) {
235  delete (typename std::tuple_element<I, ValueCalculatorsTupleType>::type *) _valcalcs[I];
236  }
237  _delete_all<I+1>();
238  }
239  template<int I = 0, typename std::enable_if<(I==NumValueCalculators),bool>::type = true>
240  inline void _delete_all() { }
241 
242  template<int I = 0, typename std::enable_if<(I<NumValueCalculators),bool>::type = true>
243  inline void _create_Ith_copy(int i, const void * src) {
244  tomographer_assert( src != NULL && "Copy constructor invoked with invalid other object.") ;
245  if (I == i) {
246  typedef typename std::tuple_element<I, ValueCalculatorsTupleType>::type ValueCalculator;
247  _valcalcs[(std::size_t)i] = new ValueCalculator( *(const ValueCalculator*)src ) ; // copy constructor
248  }
249  _create_Ith_copy<I+1>(i, src);
250  }
251  template<int I = 0, typename std::enable_if<(I==NumValueCalculators),bool>::type = true>
252  inline void _create_Ith_copy(int , const void * ) { }
253 
254 public:
255 
267  template<typename... CreatorFns>
268  inline MultiplexorValueCalculator(const int i, CreatorFns&&... creators)
269  : _valcalcs(), _i(i)
270  {
271  _valcalcs.fill(NULL);
272  tomographer_assert(0 <= i);
273  tomographer_assert(i < NumValueCalculators);
274  _create_Ith_valcalc(i, std::forward_as_tuple(creators...));
275  }
276 
280  {
281  _delete_all();
282  }
283 
289  : _valcalcs(x._valcalcs), _i(x._i)
290  {
291  x._valcalcs.fill(NULL) ;
292  }
293 
299  : _valcalcs(), _i(other._i)
300  {
301  _valcalcs.fill(NULL) ;
302  _create_Ith_copy(_i, other._valcalcs[(std::size_t)_i]);
303  }
304 
306  template<int I>
307  inline const typename std::tuple_element<I, ValueCalculatorsTupleType>::type * getValueCalculator() const
308  {
309  return (typename std::tuple_element<I, ValueCalculatorsTupleType>::type *) _valcalcs[I];
310  }
311 
317  template<typename PointType>
318  inline ValueType getValue(PointType&& x) const
319  {
320  return tomo_internal::MplxVC_getval_helper<
321  NumValueCalculators,ValueType,ValueCalculators...
322  >::getValue(_i, _valcalcs, std::forward<PointType>(x));
323  }
324 
325 };
326 
327 
328 
329 } // namespace Tomographer
330 
331 
332 
333 
334 #endif
A ValueCalculator-instance which the choice of which ValueCalculator to use at run-time.
MultiplexorValueCalculator(const int i, CreatorFns &&... creators)
Constructor.
T forward_as_tuple(T... args)
Base namespace for the Tomographer project.
Definition: densellh.h:45
Provide appropriate operator new() definitions for a structure which has a member of the given stored...
ValueType getValue(PointType &&x) const
The main method which computes the value according to the pre-chosen ValueCalculator.
#define TOMO_STATIC_ASSERT_EXPR(...)
Tool for static assertions without message.
Definition: cxxdefs.h:77
MultiplexorValueCalculator(const MultiplexorValueCalculator &other)
Copy constructor.
const std::tuple_element< I, ValueCalculatorsTupleType >::type * getValueCalculator() const
Get a particular value calculator [static index].
Some C++ utilities, with a tad of C++11 tricks.
Managing the need for specific overrides to operator new() for some types (especially Eigen types) ...
~MultiplexorValueCalculator()
Destructor. Frees resources.
STL class.
T fill(T... args)
#define tomographer_assert(...)
Assertion test macro.
Definition: cxxdefs.h:84
MultiplexorValueCalculator(MultiplexorValueCalculator &&x)
Move constructor.