Tomographer  v5.2
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)
59  {
60  return ( (const typename std::tuple_element<I, std::tuple<ValueCalculators...> >::type *) valcalc)
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 void * _valcalc, PointType&& x)
74  {
75  if (IterI == _i) {
76  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<IterI>(_valcalc, x) ;
77  }
78  return getValue<PointType, IterI+1>(_i, _valcalc, 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 void * , 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 void * _valcalc, 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>(_valcalc, 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 void * _valcalc, PointType&& x)
109  {
110  tomographer_assert(_i >= 0 && _i < (int)sizeof...(ValueCalculators) && "i out of range");
111  switch (_i) {
112  case 0:
113  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<0>(_valcalc, x) ;
114  default:
115  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<1>(_valcalc, x) ;
116  }
117  }
118 };
119 //--
120 template<typename ValueType, typename... ValueCalculators>
121 struct MplxVC_getval_helper<3, ValueType, ValueCalculators...>
122 {
123  TOMO_STATIC_ASSERT_EXPR(sizeof...(ValueCalculators) == 3) ;
124  template<typename PointType>
125  static inline ValueType getValue(const int _i, const void * _valcalc, PointType&& x)
126  {
127  tomographer_assert(_i >= 0 && _i < (int)sizeof...(ValueCalculators) && "i out of range");
128  switch (_i) {
129  case 0:
130  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<0>(_valcalc, x) ;
131  case 1:
132  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<1>(_valcalc, x) ;
133  default:
134  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<2>(_valcalc, x) ;
135  }
136  }
137 };
138 //--
139 template<typename ValueType, typename... ValueCalculators>
140 struct MplxVC_getval_helper<4, ValueType, ValueCalculators...>
141 {
142  TOMO_STATIC_ASSERT_EXPR(sizeof...(ValueCalculators) == 4) ;
143  template<typename PointType>
144  static inline ValueType getValue(const int _i, const void * _valcalc, PointType&& x)
145  {
146  tomographer_assert(_i >= 0 && _i < (int)sizeof...(ValueCalculators) && "i out of range");
147  switch (_i) {
148  case 0:
149  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<0>(_valcalc, x) ;
150  case 1:
151  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<1>(_valcalc, x) ;
152  case 2:
153  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<2>(_valcalc, x) ;
154  default:
155  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<3>(_valcalc, x) ;
156  }
157  }
158 };
159 //--
160 template<typename ValueType, typename... ValueCalculators>
161 struct MplxVC_getval_helper<5, ValueType, ValueCalculators...>
162 {
163  TOMO_STATIC_ASSERT_EXPR(sizeof...(ValueCalculators) == 5) ;
164  template<typename PointType>
165  static inline ValueType getValue(const int _i, const void * _valcalc, PointType&& x)
166  {
167  tomographer_assert(_i >= 0 && _i < (int)sizeof...(ValueCalculators) && "i out of range");
168  switch (_i) {
169  case 0:
170  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<0>(_valcalc, x) ;
171  case 1:
172  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<1>(_valcalc, x) ;
173  case 2:
174  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<2>(_valcalc, x) ;
175  case 3:
176  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<3>(_valcalc, x) ;
177  default:
178  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<4>(_valcalc, x) ;
179  }
180  }
181 };
182 //--
183 template<typename ValueType, typename... ValueCalculators>
184 struct MplxVC_getval_helper<6, ValueType, ValueCalculators...>
185 {
186  TOMO_STATIC_ASSERT_EXPR(sizeof...(ValueCalculators) == 6) ;
187  template<typename PointType>
188  static inline ValueType getValue(const int _i, const void * _valcalc, PointType&& x)
189  {
190  tomographer_assert(_i >= 0 && _i < (int)sizeof...(ValueCalculators) && "i out of range");
191  switch (_i) {
192  case 0:
193  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<0>(_valcalc, x) ;
194  case 1:
195  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<1>(_valcalc, x) ;
196  case 2:
197  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<2>(_valcalc, x) ;
198  case 3:
199  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<3>(_valcalc, x) ;
200  case 4:
201  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<4>(_valcalc, x) ;
202  default:
203  return MplxVC_getval_helper_helper<ValueType,ValueCalculators...>::template callGetValue<5>(_valcalc, x) ;
204  }
205  }
206 };
207 
208 } // namespace tomo_internal
209 
210 
211 
212 
213 
221 template<typename ValueType_, typename... ValueCalculators>
222 class TOMOGRAPHER_EXPORT MultiplexorValueCalculator
223  : public virtual Tools::NeedOwnOperatorNew<ValueCalculators...>::ProviderType
224 {
225 public:
226  typedef ValueType_ ValueType;
227 
228  static constexpr int NumValueCalculators = sizeof...(ValueCalculators);
229  static constexpr int NumStaticallyOptimizedIfs = 6;
230 
231  // typedef std::tuple<ValueCalculators&...> ValueCalculatorsRefTupleType;
232  typedef std::tuple<ValueCalculators...> ValueCalculatorsTupleType;
233 
234 private:
235 
236  const void * _valcalc;
237  const int _i;
238 
239  template<typename TupleCreators>
240  static inline const void * _create_Ith_valcalc(int i, TupleCreators && creators)
241  {
242  tomographer_assert(0 <= i);
243  tomographer_assert(i < NumValueCalculators);
244  return _create_Ith_valcalc_a(i, std::forward<TupleCreators>(creators));
245  }
246 
247  template<int I = 0, typename TupleCreators = void,
249  static inline const void * _create_Ith_valcalc_a(int i, TupleCreators && creators)
250  {
251  if (i == I) {
252  return (const void *) std::get<I>(creators)();
253  }
254  return _create_Ith_valcalc_a<I+1>(i, std::forward<TupleCreators>(creators));
255  }
256  template<int I = 0, typename TupleCreators = void,
258  static inline const void * _create_Ith_valcalc_a(int , TupleCreators && ) { return NULL; }
259 
260 
261  template<int I = 0, typename std::enable_if<(I<NumValueCalculators),bool>::type = true>
262  inline void _delete_all()
263  {
264  if (_i == I && _valcalc != NULL) {
265  delete (const typename std::tuple_element<I, ValueCalculatorsTupleType>::type *) _valcalc;
266  }
267  _delete_all<I+1>();
268  }
269  template<int I = 0, typename std::enable_if<(I==NumValueCalculators),bool>::type = true>
270  inline void _delete_all() { }
271 
272 
273  static inline const void * _create_Ith_copy(int i, const void * src)
274  {
275  tomographer_assert(0 <= i);
276  tomographer_assert(i < NumValueCalculators);
277  tomographer_assert( src != NULL && "Copy constructor invoked with invalid other object." ) ;
278 
279  return _create_Ith_copy_a(i, src);
280  }
281 
282  template<int I = 0, typename std::enable_if<(I<NumValueCalculators),bool>::type = true>
283  inline static const void * _create_Ith_copy_a(int i, const void * src) {
284  if (I == i) {
285  typedef typename std::tuple_element<I, ValueCalculatorsTupleType>::type ValueCalculator;
286  return new ValueCalculator( *(const ValueCalculator*)src ) ; // copy constructor
287  }
288  return _create_Ith_copy_a<I+1>(i, src);
289  }
290  template<int I = 0, typename std::enable_if<(I==NumValueCalculators),bool>::type = true>
291  inline static const void * _create_Ith_copy_a(int , const void * ) { return NULL; }
292 
293 public:
294 
306  template<typename... CreatorFns>
307  inline MultiplexorValueCalculator(const int i, CreatorFns&&... creators)
308  : _valcalc(_create_Ith_valcalc(i, std::forward_as_tuple(creators...))), _i(i)
309  {
310  }
311 
315  {
316  _delete_all();
317  }
318 
319  // No move constructor, because we want the internal array to be absolutely constant (so
320  // that the compiler can optimize more aggressively).
321 
327  : _valcalc(_create_Ith_copy(other._i, other._valcalc)), _i(other._i)
328  {
329  }
330 
332  template<int I>
333  inline const typename std::tuple_element<I, ValueCalculatorsTupleType>::type * getValueCalculator() const
334  {
335  if (_i != I) {
336  return NULL;
337  }
338  return (const typename std::tuple_element<I, ValueCalculatorsTupleType>::type *) _valcalc;
339  }
340 
346  template<typename PointType>
347  inline ValueType getValue(PointType&& x) const
348  {
349  return tomo_internal::MplxVC_getval_helper<
350  NumValueCalculators,ValueType,ValueCalculators...
351  >::getValue(_i, _valcalc, std::forward<PointType>(x));
352  }
353 
354 };
355 
356 
357 
358 } // namespace Tomographer
359 
360 
361 
362 
363 #endif
A ValueCalculator-instance which the choice of which ValueCalculator to use at run-time.
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.
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.
#define tomographer_assert(...)
Assertion test macro.
Definition: cxxdefs.h:84