Tomographer  v5.4
Tomographer C++ Framework Documentation
cxxutil.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_TOOLS_UTILS_H
29 #define TOMOGRAPHER_TOOLS_UTILS_H
30 
37 #include <cassert>
38 #include <cstddef>
39 #include <cstdlib>
40 
41 #include <iostream>
42 #include <complex>
43 #include <type_traits>
44 #include <exception>
45 #include <stdexcept>
46 
49 
50 // get a demangle() function from Boost, either with boost::core::demangle() (boost >=
51 // 1.56) or boost::units::detail::demangle() (boost before that)
52 #include <boost/version.hpp>
53 #if BOOST_VERSION >= 105600
54 #include <boost/core/demangle.hpp>
55 #else
56 #include <boost/units/detail/utility.hpp>
57 namespace boost { namespace core { using boost::units::detail::demangle; } }
58 #endif
59 
60 #include <Eigen/Core>
61 
62 // -----------------------------------------------
63 
64 
65 namespace Tomographer
66 {
67 namespace Tools
68 {
69 
70 // taken from http://stackoverflow.com/a/25510879/1694896
71 
72 namespace tomo_internal {
73  template <typename F>
74  struct FinalAction {
75  FinalAction(F f) : clean_(f) {}
76  ~FinalAction() { clean_(); }
77  F clean_;
78  };
79 } // namespace tomo_internal
80 
92 template <typename F>
93 inline tomo_internal::FinalAction<F> finally(F f)
94 {
95  return tomo_internal::FinalAction<F>(f);
96 }
97 
98 
99 
100 // -----------------------------------------------------------------------------
101 
102 // see http://aherrmann.github.io/programming/2016/02/28/unpacking-tuples-in-cpp14/ and
103 // http://stackoverflow.com/questions/17424477/implementation-c14-make-integer-sequence/17426611#17426611
104 //
105 
106 template<typename T, T...> struct Sequence { typedef Sequence type; };
107 
108 template<typename T, typename S1, typename S2> struct Concatenate;
109 
110 template<typename T, T... I1, T... I2>
111 struct Concatenate<T, Sequence<T, I1...>, Sequence<T, I2...> >
112  : Sequence<T, I1..., (sizeof...(I1)+I2)...> {};
113 
114 template<typename T, T N, typename dummy = void>
116 
117 template<typename T, T N, typename >
118 struct GenerateSequence : Concatenate<T, typename GenerateSequence<T, N/2>::type,
119  typename GenerateSequence<T, N - N/2>::type>::type {};
120 
121 template<typename T, T N>
122 struct GenerateSequence<T, N, typename std::enable_if<(N==0),void>::type>
123  : Sequence<T> {};
124 
125 template<typename T, T N>
126 struct GenerateSequence<T, N, typename std::enable_if<(N==1),void>::type>
127  : Sequence<T, 0> {};
128 
129 
130 
131 
132 // -----------------------------------------------------------------------------
133 
134 
151 template<typename T_, bool IsDynamic_, T_ StaticValue_ = T_()>
152 class TOMOGRAPHER_EXPORT StaticOrDynamic
153 {
154 
155 public:
156  // definitions here are for the static case, the dynamic case will be specialized below.
157  TOMO_STATIC_ASSERT_EXPR(IsDynamic_ == false) ;
158 
160  typedef T_ T;
162  static constexpr bool IsDynamic = IsDynamic_;
164  static constexpr T StaticValue = StaticValue_;
165 
167  inline StaticOrDynamic() { }
173  inline explicit StaticOrDynamic(T val) {
174  tomographer_assert(val == StaticValue);
175  (void)val; // silence "unused parameter" warning if tomographer_assert() gets optimized out
176  }
177 
182  inline T value() const { return StaticValue; }
183 
188  inline T operator()() const { return StaticValue; }
189 };
190 // static properties
191 template<typename T_, bool IsDynamic_, T_ StaticValue_>
193 template<typename T_, bool IsDynamic_, T_ StaticValue_>
195 
200 template<typename T_, T_ StaticValue_>
201 class TOMOGRAPHER_EXPORT StaticOrDynamic<T_, true, StaticValue_>
202 {
203 public:
204 
206  typedef T_ T;
208  static constexpr bool IsDynamic = true;
209 
210 
212  StaticOrDynamic() = delete;
217  inline explicit StaticOrDynamic(T val) : _dyn_value(val) { }
218 
219 
221  inline T value() const { return _dyn_value; }
222 
224  inline T operator()() const { return value(); }
225 
226 private:
227 
229  const T _dyn_value;
230 };
231 // static properties
232 template<typename T_, T_ StaticValue_>
234 
235 
236 // -----------------------------------------------------------------------------
237 
238 
248 template<typename T_, bool enabled>
249 struct TOMOGRAPHER_EXPORT StoreIfEnabled
250 {
252  typedef T_ T;
254  static constexpr bool IsEnabled = false;
255 
257  template<typename... Args>
258  explicit StoreIfEnabled(Args...) { }
259 };
260 // static properties
261 template<typename T_, bool enabled>
267 template<typename T_>
268 struct TOMOGRAPHER_EXPORT StoreIfEnabled<T_, true>
269 {
271  typedef T_ T;
273  static constexpr bool IsEnabled = true;
274 
276  T value;
277 
279  template<typename... ArgTypes>
280  explicit StoreIfEnabled(const ArgTypes& ... args) : value(args...) { }
281 };
282 // static properties:
283 template<typename T_>
285 
293 template<typename T>
294 inline std::ostream & operator<<(std::ostream & str, const StoreIfEnabled<T, false>& /*val*/)
295 {
296  str << "[-]";
297  return str;
298 }
306 template<typename T>
307 inline std::ostream & operator<<(std::ostream & str, const StoreIfEnabled<T, true>& val)
308 {
309  str << val.value;
310  return str;
311 }
312 
313 
314 
315 // -----------------------------------------------------------------------------
316 
317 
320 template<typename IntType = int>
321 inline constexpr bool isPowerOfTwo(IntType N)
322 {
323  // taken from http://stackoverflow.com/q/10585450/1694896
324  return N && !(N & (N - 1));
325 }
326 
327 
328 // -----------------------------------------------------------------------------
329 
330 
339 template<typename Scalar>
341  typedef Scalar type;
342 };
343 
345 template<typename RealScalar>
346 struct ComplexRealScalar<std::complex<RealScalar> >
347 {
348  typedef RealScalar type;
349 };
350 
351 
352 
353 
359 template<typename X>
360 inline typename std::enable_if<std::is_unsigned<X>::value, bool>::type isPositive(const X /* val */)
361 {
362  return true;
363 }
365 template<typename X>
366 inline typename std::enable_if<!std::is_unsigned<X>::value, bool>::type isPositive(const X val)
367 {
368  return val >= 0;
369 }
370 
371 
372 
378 template<typename X>
379 inline bool isFinite(const X val)
380 {
381  return std::isfinite(val);
382 }
383 
384 
385 
394 template<typename IntType>
395 inline constexpr bool additionWillOverflow(IntType a, IntType b)
396 {
397  // see https://stackoverflow.com/a/1514309/1694896
399  return (b > 0 && a > std::numeric_limits<IntType>::max() - b) ||
400  (b < 0 && a < std::numeric_limits<IntType>::min() - b) ;
401 }
402 
408 template<typename IntType, typename ... IntTypes>
409 inline constexpr bool additionWillOverflow(IntType a, IntType b, IntType c, IntTypes ... rest)
410 {
411  return additionWillOverflow(a, b) || additionWillOverflow(IntType(a + b), c, IntTypes(rest)...) ;
412 }
413 
414 
415 // namespace tomo_internal {
416 // template<typename IntType>
417 // struct mult_will_overflow_helper {
418 // constexpr int NumBits = std::numeric_limits<IntType>::digits();
419 // constexpr int HalfNumBits = NumBits/2;
420 // constexpr IntType LoHalfBitsMask = (IntType(1) << HalfNumBits) - 1 ;
421 // inline constexpr bool calc(IntType a, IntType b)
422 // {
423 // return ( isPositive(a)
424 // ? ( isPositive(b)
425 // // a >= 0, b >= 0
426 // ? calc_parts(a >> HalfNumBits, a & LoHalfBitsMask,
427 // b >> HalfNumBits, b & LoHalfBitsMask)
428 // // a >= 0, b < 0
429 // : calc_parts(a >> HalfNumBits, a & LoHalfBitsMask,
430 // -(b / (2 << HalfNumBits)), b % (2 << HalfNumBits), true )
431 // }
432 // inline constexpr bool calc_parts(IntType ahi, IntType alo, IntType bhi, IntType blo, bool isneg = false)
433 // {
434 // return (!isneg
435 // ? ( (alo*bhi >= 1) ||
436 // additionWillOverflow((alo*bhi) << HalfNumBits, (ahi*blo) << HalfNumBits, alo*blo) )
437 // : ( ((alo*bhi > 0) &&
438 // additionWillOverflow((alo*bhi) << HalfNumBits, (ahi*blo) << HalfNumBits, alo*blo - 1) ||
439 // (alo*bhi ........??????????????
440 // }
441 // };
442 // }
443 
452 template<typename IntType>
453 inline constexpr bool multiplicationWillOverflow(IntType a, IntType b)
454 {
456  // see https://www.securecoding.cert.org/confluence/display/CINT/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow
457  return (
458  (a > 0)
459  ? ( (b > 0)
461  : (b < std::numeric_limits<IntType>::min() / a) )
462  : ( (b > 0)
464  : ((a != 0) && (b < std::numeric_limits<IntType>::max() / a)) )
465  ) ;
466 }
467 
468 
469 
470 
471 // -----------------------------------------------------------------------------
472 // Define functions with printf-safe arguments, with compiler-generated warnings
473 // -----------------------------------------------------------------------------
474 
475 
476 // The PRINTFX_ARGS_SAFE macros are defined here, so that in the future we may support a
477 // wider range of compilers which may not understand the __attribute__(format)
478 // instruction.
479 
480 
481 // g++ or clang++ (or doxygen :-) )
482 #if defined(__GNUC__) || defined(__clang__) || defined(TOMOGRAPHER_PARSED_BY_DOXGEN)
483 
502 # define PRINTF1_ARGS_SAFE __attribute__ ((__format__ (__printf__, 1, 2)))
503 # define PRINTF2_ARGS_SAFE __attribute__ ((__format__ (__printf__, 2, 3)))
505 # define PRINTF3_ARGS_SAFE __attribute__ ((__format__ (__printf__, 3, 4)))
507 # define PRINTF4_ARGS_SAFE __attribute__ ((__format__ (__printf__, 4, 5)))
509 #else
510 # define PRINTF1_ARGS_SAFE
511 # define PRINTF2_ARGS_SAFE
512 # define PRINTF3_ARGS_SAFE
513 # define PRINTF4_ARGS_SAFE
514 #endif
515 
516 
517 
518 
519 #if TOMOGRAPHER_PARSED_BY_DOXYGEN
520 
528 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN
529 #else // TOMOGRAPHER_PARSED_BY_DOXYGEN
530 //
531 #if defined(__GNUC__) || defined(__clang__)
532 # if defined(__MINGW32__) || defined(__MINGW64__)
533 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN __attribute__((force_align_arg_pointer,noinline))
534 # else
535 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN
536 # endif
537 #elif defined(__ICC)
538 // but ICC is fine
539 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN
540 #else
541 # warning "You are using an unknown compiler. You may run into memory alignment problems... Good luck!"
542 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN
543 #endif
544 //
545 #endif // TOMOGRAPHER_PARSED_BY_DOXYGEN
546 
547 
548 // Internal hacks...
549 // ---------------------------
550 
551 // these are useful when writing SFINAE C++/C++11 hacks
552 namespace tomo_internal {
553 template<typename Enabledtype = void> struct sfinae_no { typedef int no[1]; };
554 template<typename EnabledType = void> struct sfinae_yes { typedef int yes[2]; };
555 } // namespace tomo_internal
556 
557 
558 
559 
560 
569 inline int getWidthForTerminalOutput(int max_width = 0)
570 {
571  if (max_width > 0) {
572  return max_width;
573  }
574  // max_width <= 0:
575  const int offset = max_width;
576  // decide of a maximum width to display
577 #if defined(__MINGW32__) || defined(__MINGW64__)
578  max_width = 80; // Windows terminals are usually 80 chars wide
579 #else
580  max_width = 100; // default maximum width
581 #endif
582  // Note that $COLUMNS is not in the environment usually, so you have to set it manually
583  // with e.g.
584  // shell> export COLUMNS=$COLUMNS
585  const char * cols_s = std::getenv("COLUMNS");
586  if (cols_s != NULL) {
587  max_width = std::atoi(cols_s);
588  }
589  max_width += offset; // if we had given, e.g. maxwidth=-4
590  return max_width;
591 }
592 
593 
594 
595 
596 
597 
598 // -----------------------------------------------------------------------------
599 // Function Name-Related Stuff
600 // -----------------------------------------------------------------------------
601 
602 
603 
608 #define TOMO_FUNCTION __PRETTY_FUNCTION__
609 
610 
611 
612 namespace tomo_internal {
613 // logic taken from KLatexFormula/klftools: klfdefs.cpp / klfShortFuncSignature()
614 struct extractFuncName_helper {
615  struct extracted {
616  const std::size_t decl_pos;
617  const conststr extr;
618  constexpr extracted(std::size_t dp, const conststr& s) : decl_pos(dp), extr(s) { }
619  };
620  static constexpr conststr alltofirstparen(const conststr& s)
621  {
622  return s.substr(0, s.find(conststr("("), 0, s.size()));
623  }
624  static constexpr std::size_t declpos_from_found_spc(std::size_t found_pos)
625  {
626  return found_pos == std::string::npos ? 0 : found_pos + 1;
627  }
628  static constexpr std::size_t pos_decl(const conststr& s)
629  {
630  return ((s.size() > 2)
631  ? declpos_from_found_spc(s.rfind(conststr(" "), std::string::npos))
632  : 0);
633  }
634  static constexpr extracted allfromfirstspace(const conststr& s)
635  {
636  return extracted(pos_decl(s),
637  s.substr_e(pos_decl(s),
638  s.size()));
639  }
640  static constexpr extracted do_extract(const conststr& funcname)
641  {
642  return allfromfirstspace(alltofirstparen(funcname));
643  }
644  static constexpr conststr extract_choose(const extracted& do_extracted,
645  const conststr& funcname)
646  {
647  return (do_extracted.extr.substr(0,8) == conststr("operator")
648  ? funcname.substr(do_extracted.decl_pos)
649  : do_extracted.extr);
650  }
651  static constexpr conststr extract(const conststr& funcname)
652  {
653  return extract_choose(do_extract(funcname), funcname);
654  }
655 }; // helper struct
656 } // namespace tomo_internal
657 
658 
664 constexpr inline conststr extractFuncName(const conststr & funcname)
665 {
666  return tomo_internal::extractFuncName_helper::extract(funcname);
667 }
668 
669 
670 
671 } // namespace Tools
672 } // namespace Tomographer
673 
674 
675 
676 
712 #define TOMOGRAPHER_DEFINE_MSG_EXCEPTION(ClassName, ErrPrefix) \
713  class TOMOGRAPHER_EXPORT ClassName : public std::exception { \
714  std::string _msg; \
715  public: \
716  ClassName(std::string msg) : _msg(std::string(ErrPrefix) + std::move(msg)) { } \
717  virtual ~ClassName() throw() { } \
718  std::string msg() const { return _msg; } \
719  const char * what() const throw() { return _msg.c_str(); } \
720  };
721 
730 #define TOMOGRAPHER_DEFINE_MSG_EXCEPTION_BASE(ClassName, ErrPrefix, BaseClass) \
731  class TOMOGRAPHER_EXPORT ClassName : public BaseClass { \
732  public: \
733  ClassName(std::string msg) : BaseClass(std::string(ErrPrefix) + std::move(msg)) { } \
734  virtual ~ClassName() throw() { } \
735  };
736 
737 
738 
739 namespace Tomographer {
740 namespace Tools {
741 
754 template<typename ExceptionClass = std::runtime_error>
755 inline void tomographerEnsure(bool condition, std::string message) {
756  if (!condition) {
757  throw ExceptionClass(message);
758  }
759 }
760 
761 
762 
763 
764 
765 
766 } // namespace Tools
767 } // namespace Tomographer
768 
769 
770 
771 //
772 // boost.serialization of std::tuple -- needed e.g. in order to serialize
773 // MultipleMHRWStatsCollector::ResultType
774 //
775 namespace boost {
776 namespace serialization {
777 
778 template<typename Archive, typename... TupleArgs>
780  template<int I, TOMOGRAPHER_ENABLED_IF_TMPL(I < sizeof...(TupleArgs))>
781  static void go(Archive & a, std::tuple<TupleArgs...> & tuple, const unsigned int version)
782  {
783  a & std::get<I>(tuple);
784  go<I+1>(a, tuple, version);
785  }
786  template<int I, TOMOGRAPHER_ENABLED_IF_TMPL(I >= sizeof...(TupleArgs))>
787  static void go(Archive & , std::tuple<TupleArgs...> & , const unsigned int)
788  {
789  }
790 };
791 
792 template<typename Archive, typename... TupleArgs>
793 void serialize(Archive & a, std::tuple<TupleArgs...> & tuple, const unsigned int version)
794 {
795  serialize_tuple_helper<Archive, TupleArgs...>::go<0>(a, tuple, version);
796 }
797 
798 } // serialization
799 } // boost
800 
801 
802 #endif
Utility that stores a data type if a compile-time flag is enabled.
Definition: cxxutil.h:249
T atoi(T... args)
T value() const
See StaticOrDynamic<T_,IsDynamic_,StaticValue_>::value()
Definition: cxxutil.h:221
A type which stores a value possibly known at compile-time.
Definition: cxxutil.h:152
bool isFinite(const X val)
Test whether floating-point value is finite.
Definition: cxxutil.h:379
T operator()() const
See StaticOrDynamic<T_,IsDynamic_,StaticValue_>::operator()()
Definition: cxxutil.h:224
Base namespace for the Tomographer project.
Definition: densellh.h:45
T_ T
The type we&#39;re storing.
Definition: cxxutil.h:252
The Real scalar type corresponding to a std::complex type.
Definition: cxxutil.h:340
T value
This property keeps the value we&#39;re supposed to store.
Definition: cxxutil.h:276
STL namespace.
constexpr bool multiplicationWillOverflow(IntType a, IntType b)
Test whether a multiplication of two integers will cause an overflow/underflow for that integer type...
Definition: cxxutil.h:453
constexpr bool isPowerOfTwo(IntType N)
Return true if the argument is a power of two, false otherwise.
Definition: cxxutil.h:321
StaticOrDynamic(T val)
Constructor which initializes the value to val.
Definition: cxxutil.h:217
StaticOrDynamic(T val)
Constructor with an explicit value.
Definition: cxxutil.h:173
STL class.
T getenv(T... args)
#define TOMO_STATIC_ASSERT_EXPR(...)
Tool for static assertions without message.
Definition: cxxdefs.h:77
std::enable_if<!std::is_unsigned< X >::value, bool >::type isPositive(const X val)
See isPositive()
Definition: cxxutil.h:366
T_ T
The type we&#39;re storing.
Definition: cxxutil.h:271
T isfinite(T... args)
A constexpr string type, suitable for basic compile-time string processing.
StoreIfEnabled(const ArgTypes &... args)
Constructor. Any arguments are passed to the value&#39;s constructor.
Definition: cxxutil.h:280
StoreIfEnabled(Args...)
Constructor.
Definition: cxxutil.h:258
constexpr bool additionWillOverflow(IntType a, IntType b, IntType c, IntTypes ... rest)
Test whether the sum of several integers will cause an overflow/underflow for that integer type...
Definition: cxxutil.h:409
VarValueDecoder< T >::RetType value(const Var &var)
Access the value of the given variable, as a C++ type.
Definition: ezmatio.h:878
T_ T
Type of the value we are storing.
Definition: cxxutil.h:157
T_ T
Type of the value we are storing. See StaticOrDynamic<T_,IsDynamic_,StaticValue_>::T.
Definition: cxxutil.h:206
int getWidthForTerminalOutput(int max_width=0)
Return a suitable width for displaying stuff on the standard output.
Definition: cxxutil.h:569
void tomographerEnsure(bool condition, std::string message)
Ensure that a condition is met, or throw an exception.
Definition: cxxutil.h:755
StaticOrDynamic()
Default Constructor. Only if the value is stored at compile-time.
Definition: cxxutil.h:167
constexpr conststr extractFuncName(const conststr &funcname)
Extract the function name from its signature.
Definition: cxxutil.h:664
Basic definitions, which may have to be defined before any Eigen headers or further utilities are inc...
T operator()() const
Get the value stored.
Definition: cxxutil.h:188
A constexpr string type.
Definition: conststr.h:55
STL class.
#define tomographer_assert(...)
Assertion test macro.
Definition: cxxdefs.h:84
T value() const
Get the value stored.
Definition: cxxutil.h:182