Tomographer  v5.4
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 void * valcalc, PointType && x) // const version
59  {
60  return ( (const typename std::tuple_element<I, std::tuple<ValueCalculators...> >::type *) valcalc)
61  -> getValue(std::forward<PointType>(x));
62  }
63  template<int I, typename PointType>
64  static inline ValueType callGetValue(void * valcalc, PointType && x) // non-const version
65  {
66  return ( (typename std::tuple_element<I, std::tuple<ValueCalculators...> >::type *) valcalc)
67  -> getValue(std::forward<PointType>(x));
68  }
69 };
70 
71 //
72 // helper for getValue()
73 //
74 template<int NumValueCalculators, typename ValueType, typename... ValueCalculators>
75 struct MplxVC_getval_helper
76 {
77  template<typename PointType, typename VoidPtr, // VoidPtr is `void*' or `const void*'
78  int IterI = 0, TOMOGRAPHER_ENABLED_IF_TMPL(IterI < NumValueCalculators)>
79  static inline ValueType getValue(const int _i, VoidPtr _valcalc, PointType&& x)
80  {
81  if (IterI == _i) {
82  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<IterI>(_valcalc, x) ;
83  }
84  return getValue<PointType, VoidPtr, IterI+1>(_i, _valcalc, std::forward<PointType>(x));
85  }
86  //
87  template<typename PointType, typename VoidPtr, // VoidPtr is `void*' or `const void*'
88  int IterI = 0, TOMOGRAPHER_ENABLED_IF_TMPL(IterI == NumValueCalculators)>
89  static inline ValueType getValue(const int, VoidPtr, PointType&& )
90  {
91  tomographer_assert(false && "Invalid i: i>=NumValueCalculators or i<0");
92  return ValueType();// silence ICC "missing return statement" warning
93  }
94 };
95 
96 // a few specializations, for optimizing a chain of if's to a faster switch statement (?)
97 template<typename ValueType, typename... ValueCalculators>
98 struct MplxVC_getval_helper<1, ValueType, ValueCalculators...>
99 {
100  TOMO_STATIC_ASSERT_EXPR(sizeof...(ValueCalculators) == 1) ;
101  template<typename PointType, typename VoidPtr>
102  static inline ValueType getValue(const int _i, VoidPtr _valcalc, PointType&& x)
103  {
104  tomographer_assert(_i == 0 && "i != 0 but NumValueCalculators == 1");(void)_i;
105  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<0>(_valcalc, x) ;
106  }
107 };
108 //--
109 template<typename ValueType, typename... ValueCalculators>
110 struct MplxVC_getval_helper<2, ValueType, ValueCalculators...>
111 {
112  TOMO_STATIC_ASSERT_EXPR(sizeof...(ValueCalculators) == 2) ;
113  template<typename PointType, typename VoidPtr>
114  static inline ValueType getValue(const int _i, VoidPtr _valcalc, PointType&& x)
115  {
116  tomographer_assert(_i >= 0 && _i < (int)sizeof...(ValueCalculators) && "i out of range");
117  switch (_i) {
118  case 0:
119  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<0>(_valcalc, x) ;
120  default:
121  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<1>(_valcalc, x) ;
122  }
123  }
124 };
125 //--
126 template<typename ValueType, typename... ValueCalculators>
127 struct MplxVC_getval_helper<3, ValueType, ValueCalculators...>
128 {
129  TOMO_STATIC_ASSERT_EXPR(sizeof...(ValueCalculators) == 3) ;
130  template<typename PointType, typename VoidPtr>
131  static inline ValueType getValue(const int _i, VoidPtr _valcalc, PointType&& x)
132  {
133  tomographer_assert(_i >= 0 && _i < (int)sizeof...(ValueCalculators) && "i out of range");
134  switch (_i) {
135  case 0:
136  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<0>(_valcalc, x) ;
137  case 1:
138  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<1>(_valcalc, x) ;
139  default:
140  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<2>(_valcalc, x) ;
141  }
142  }
143 };
144 //--
145 template<typename ValueType, typename... ValueCalculators>
146 struct MplxVC_getval_helper<4, ValueType, ValueCalculators...>
147 {
148  TOMO_STATIC_ASSERT_EXPR(sizeof...(ValueCalculators) == 4) ;
149  template<typename PointType, typename VoidPtr>
150  static inline ValueType getValue(const int _i, VoidPtr _valcalc, PointType&& x)
151  {
152  tomographer_assert(_i >= 0 && _i < (int)sizeof...(ValueCalculators) && "i out of range");
153  switch (_i) {
154  case 0:
155  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<0>(_valcalc, x) ;
156  case 1:
157  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<1>(_valcalc, x) ;
158  case 2:
159  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<2>(_valcalc, x) ;
160  default:
161  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<3>(_valcalc, x) ;
162  }
163  }
164 };
165 //--
166 template<typename ValueType, typename... ValueCalculators>
167 struct MplxVC_getval_helper<5, ValueType, ValueCalculators...>
168 {
169  TOMO_STATIC_ASSERT_EXPR(sizeof...(ValueCalculators) == 5) ;
170  template<typename PointType, typename VoidPtr>
171  static inline ValueType getValue(const int _i, VoidPtr _valcalc, PointType&& x)
172  {
173  tomographer_assert(_i >= 0 && _i < (int)sizeof...(ValueCalculators) && "i out of range");
174  switch (_i) {
175  case 0:
176  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<0>(_valcalc, x) ;
177  case 1:
178  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<1>(_valcalc, x) ;
179  case 2:
180  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<2>(_valcalc, x) ;
181  case 3:
182  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<3>(_valcalc, x) ;
183  default:
184  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<4>(_valcalc, x) ;
185  }
186  }
187 };
188 //--
189 template<typename ValueType, typename... ValueCalculators>
190 struct MplxVC_getval_helper<6, ValueType, ValueCalculators...>
191 {
192  TOMO_STATIC_ASSERT_EXPR(sizeof...(ValueCalculators) == 6) ;
193  template<typename PointType, typename VoidPtr>
194  static inline ValueType getValue(const int _i, VoidPtr * _valcalc, PointType&& x)
195  {
196  tomographer_assert(_i >= 0 && _i < (int)sizeof...(ValueCalculators) && "i out of range");
197  switch (_i) {
198  case 0:
199  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<0>(_valcalc, x) ;
200  case 1:
201  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<1>(_valcalc, x) ;
202  case 2:
203  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<2>(_valcalc, x) ;
204  case 3:
205  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<3>(_valcalc, x) ;
206  case 4:
207  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<4>(_valcalc, x) ;
208  default:
209  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<5>(_valcalc, x) ;
210  }
211  }
212 };
213 
214 } // namespace tomo_internal
215 
216 
217 
218 
219 
275 template<typename ValueType_, typename... ValueCalculators>
276 class TOMOGRAPHER_EXPORT MultiplexorValueCalculator
277  : public virtual Tools::NeedOwnOperatorNew<ValueCalculators...>::ProviderType
278 {
279 public:
281  typedef ValueType_ ValueType;
282 
284  static constexpr int NumValueCalculators = sizeof...(ValueCalculators);
285 
293  static constexpr int NumStaticallyOptimizedIfs = 6;
294 
295  // typedef std::tuple<ValueCalculators&...> ValueCalculatorsRefTupleType;
296  typedef std::tuple<ValueCalculators...> ValueCalculatorsTupleType;
297 
298 private:
299 
300  // pointer to the actual ValueCalculator instance in use, or NULL
301  void * const _valcalc;
302 
303  // the index of the actual ValueCalculator in use in the list of possible ones
304  const int _i;
305 
306  // helper functions
307 
308  template<typename TupleCreators>
309  static inline void * _create_Ith_valcalc(int i, TupleCreators && creators)
310  {
311  tomographer_assert(0 <= i);
312  tomographer_assert(i < NumValueCalculators);
313  return _create_Ith_valcalc_a(i, std::forward<TupleCreators>(creators));
314  }
315 
316  template<int I = 0, typename TupleCreators = void,
318  static inline void * _create_Ith_valcalc_a(int i, TupleCreators && creators)
319  {
320  if (i == I) {
321  typename std::tuple_element<I, ValueCalculatorsTupleType>::type * valcalc =
322  std::get<I>(creators)();
323  return (void *) valcalc;
324  }
325  return _create_Ith_valcalc_a<I+1>(i, std::forward<TupleCreators>(creators));
326  }
327  template<int I = 0, typename TupleCreators = void,
329  static inline void * _create_Ith_valcalc_a(int , TupleCreators && ) { return NULL; }
330 
331 
332  template<int I = 0, typename std::enable_if<(I<NumValueCalculators),bool>::type = true>
333  inline void _delete_all()
334  {
335  if (_i == I && _valcalc != NULL) {
336  delete (typename std::tuple_element<I, ValueCalculatorsTupleType>::type *) _valcalc;
337  }
338  _delete_all<I+1>();
339  }
340  template<int I = 0, typename std::enable_if<(I==NumValueCalculators),bool>::type = true>
341  inline void _delete_all() { }
342 
343 
344  static inline void * _create_Ith_copy(int i, void * src)
345  {
346  tomographer_assert(0 <= i);
347  tomographer_assert(i < NumValueCalculators);
348  tomographer_assert( src != NULL && "Copy constructor invoked with invalid other object." ) ;
349 
350  return _create_Ith_copy_a<0>(i, src);
351  }
352 
353  template<int I = 0, TOMOGRAPHER_ENABLED_IF_TMPL(I<NumValueCalculators)>
354  inline static void * _create_Ith_copy_a(int i, void * src) {
355  if (I == i) {
356  typedef typename std::tuple_element<I, ValueCalculatorsTupleType>::type ValueCalculator;
357  return new ValueCalculator( *(const ValueCalculator*)src ) ; // copy constructor
358  }
359  return _create_Ith_copy_a<I+1>(i, src);
360  }
361  template<int I = 0, TOMOGRAPHER_ENABLED_IF_TMPL(I==NumValueCalculators)>
362  inline static void * _create_Ith_copy_a(int , void * ) { return NULL; }
363 
364 public:
365 
378  template<typename... CreatorFns>
379  inline MultiplexorValueCalculator(const int i, CreatorFns&&... creators)
380  : _valcalc(_create_Ith_valcalc(i, std::forward_as_tuple(creators...))), _i(i)
381  {
382  }
383 
387  {
388  _delete_all();
389  }
390 
391  // No move constructor because our members are const, and we would have to
392  // make sure we don't double-free the value calculator.
393 
399  : _valcalc(_create_Ith_copy(other._i, other._valcalc)), _i(other._i)
400  {
401  }
402 
408  template<int I>
409  inline const typename std::tuple_element<I, ValueCalculatorsTupleType>::type * getValueCalculator() const
410  {
411  if (_i != I) {
412  return NULL;
413  }
414  return (const typename std::tuple_element<I, ValueCalculatorsTupleType>::type *) _valcalc;
415  }
416 
422  template<int I>
423  inline typename std::tuple_element<I, ValueCalculatorsTupleType>::type * getValueCalculator()
424  {
425  if (_i != I) {
426  return NULL;
427  }
428  return (typename std::tuple_element<I, ValueCalculatorsTupleType>::type *) _valcalc;
429  }
430 
437  template<typename PointType>
438  inline ValueType getValue(PointType&& x) const
439  {
440  return tomo_internal::MplxVC_getval_helper<
441  NumValueCalculators,ValueType,ValueCalculators...
442  >::getValue(_i, (const void*)_valcalc, std::forward<PointType>(x));
443  }
444 
451  template<typename PointType>
452  inline ValueType getValue(PointType&& x)
453  {
454  return tomo_internal::MplxVC_getval_helper<
455  NumValueCalculators,ValueType,ValueCalculators...
456  >::getValue(_i, _valcalc, std::forward<PointType>(x));
457  }
458 
459 };
460 
461 
462 
463 } // namespace Tomographer
464 
465 
466 
467 
468 #endif
A ValueCalculator implementation which the choice of which ValueCalculator to use at run-time...
ValueType_ ValueType
Value type returned by getValue() (see ValueCalculator Interface)
MultiplexorValueCalculator(const int i, CreatorFns &&... creators)
Constructor.
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...
STL namespace.
std::tuple_element< I, ValueCalculatorsTupleType >::type * getValueCalculator()
Get a particular value calculator [static index] (non-const)
ValueType getValue(PointType &&x)
The main method which computes the value according to the pre-chosen ValueCalculator (non-const versi...
ValueType getValue(PointType &&x) const
The main method which computes the value according to the pre-chosen ValueCalculator (const version) ...
#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] (const)
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.
#define tomographer_assert(...)
Assertion test macro.
Definition: cxxdefs.h:84