Tomographer  v3.0
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 <type_traits>
42 #include <exception>
43 #include <stdexcept>
44 
45 #include <Eigen/Core> // NumTraits
46 
48 
49 
50 
51 // -----------------------------------------------------------------------------
52 // Some C++ helpers
53 // -----------------------------------------------------------------------------
54 
55 
56 
62 #define TOMO_STATIC_ASSERT_EXPR(...) \
63  static_assert(__VA_ARGS__, #__VA_ARGS__)
64 
65 
66 #ifndef tomographer_assert
67 #define tomographer_assert(...) eigen_assert((__VA_ARGS__) && "assert: " #__VA_ARGS__)
68 #endif
69 
70 
71 
72 #ifndef TOMOGRAPHER_PARSED_BY_DOXYGEN
73 // WARNING!!! CHECK OUT http://stackoverflow.com/q/29363532/1694896
74 // FOR VERY SUBTLE BUGS :( :( -- TEST WITH INTEL ICC!!
75 #define TOMOGRAPHER_ENABLED_IF(...) \
76  template<bool _dummy__enabledif = false, \
77  typename std::enable_if<_dummy__enabledif || (__VA_ARGS__), bool>::type \
78  _dummy__enabledif2 = false>
79 #define TOMOGRAPHER_ENABLED_IF_TMPL(...) \
80  bool _dummy__enabledif = false, \
81  typename std::enable_if<_dummy__enabledif || (__VA_ARGS__), bool>::type \
82  _dummy__enabledif2 = true
83 
90 #define TOMOGRAPHER_ENABLED_IF_TMPL_REPEAT(...) \
91  bool _dummy__enabledif, \
92  typename std::enable_if<_dummy__enabledif || (__VA_ARGS__), bool>::type \
93  _dummy__enabledifAlt2 = true
94 #endif
95 
96 
97 
98 // -----------------------------------------------
99 
100 
101 namespace Tomographer
102 {
103 namespace Tools
104 {
105 
106 // taken from http://stackoverflow.com/a/25510879/1694896
107 
108 namespace tomo_internal {
109  template <typename F>
110  struct FinalAction {
111  FinalAction(F f) : clean_{f} {}
112  ~FinalAction() { clean_(); }
113  F clean_;
114  };
115 } // namespace tomo_internal
116 
128 template <typename F>
129 inline tomo_internal::FinalAction<F> finally(F f)
130 {
131  return tomo_internal::FinalAction<F>(f);
132 }
133 
134 
135 
136 
137 
138 
139 // -----------------------------------------------------------------------------
140 
141 
158 template<typename T_, bool IsDynamic_, T_ StaticValue_ = T_()>
160 {
161 
162 public:
163  // definitions here are for the static case, the dynamic case will be specialized below.
164  TOMO_STATIC_ASSERT_EXPR(IsDynamic_ == false) ;
165 
167  typedef T_ T;
169  static constexpr bool IsDynamic = IsDynamic_;
171  static constexpr T StaticValue = StaticValue_;
172 
174  inline StaticOrDynamic() { }
180  inline explicit StaticOrDynamic(T val) {
181  tomographer_assert(val == StaticValue);
182  (void)val; // silence "unused parameter" warning if tomographer_assert() gets optimized out
183  }
184 
189  inline T value() const { return StaticValue; }
190 
195  inline T operator()() const { return StaticValue; }
196 };
197 // static properties
198 template<typename T_, bool IsDynamic_, T_ StaticValue_>
200 template<typename T_, bool IsDynamic_, T_ StaticValue_>
202 
207 template<typename T_, T_ StaticValue_>
208 class StaticOrDynamic<T_, true, StaticValue_>
209 {
210 public:
211 
213  typedef T_ T;
215  static constexpr bool IsDynamic = true;
216 
217 
219  StaticOrDynamic() = delete;
224  inline explicit StaticOrDynamic(T val) : _dyn_value(val) { }
225 
226 
228  inline T value() const { return _dyn_value; }
229 
231  inline T operator()() const { return value(); }
232 
233 private:
234 
236  const T _dyn_value;
237 };
238 // static properties
239 template<typename T_, T_ StaticValue_>
241 
242 
243 // -----------------------------------------------------------------------------
244 
245 
255 template<typename T_, bool enabled>
257 {
259  typedef T_ T;
261  static constexpr bool IsEnabled = false;
262 
264  template<typename... Args>
265  explicit StoreIfEnabled(Args...) { }
266 };
267 // static properties
268 template<typename T_, bool enabled>
274 template<typename T_>
275 struct StoreIfEnabled<T_, true>
276 {
278  typedef T_ T;
280  static constexpr bool IsEnabled = true;
281 
283  T value;
284 
286  template<typename... ArgTypes>
287  explicit StoreIfEnabled(const ArgTypes& ... args) : value(args...) { }
288 };
289 // static properties:
290 template<typename T_>
292 
300 template<typename T>
301 inline std::ostream & operator<<(std::ostream & str, const StoreIfEnabled<T, false>& /*val*/)
302 {
303  str << "[-]";
304  return str;
305 }
313 template<typename T>
314 inline std::ostream & operator<<(std::ostream & str, const StoreIfEnabled<T, true>& val)
315 {
316  str << val.value;
317  return str;
318 }
319 
320 
321 
322 // -----------------------------------------------------------------------------
323 
324 
327 template<typename IntType = int>
328 inline constexpr bool isPowerOfTwo(IntType N)
329 {
330  // taken from http://stackoverflow.com/q/10585450/1694896
331  return N && !(N & (N - 1));
332 }
333 
334 
335 // -----------------------------------------------------------------------------
336 
337 
343 template<typename Scalar>
344 struct isComplex {
345  // use Eigen's existing implementation
347 };
348 
349 
358 template<typename Scalar>
360  typedef Scalar type;
361 };
362 
364 template<typename RealScalar>
365 struct ComplexRealScalar<std::complex<RealScalar> >
366 {
367  typedef RealScalar type;
368 };
369 
370 
371 
372 
378 template<typename X>
379 inline typename std::enable_if<std::is_unsigned<X>::value, bool>::type isPositive(const X /* val */)
380 {
381  return true;
382 }
384 template<typename X>
385 inline typename std::enable_if<!std::is_unsigned<X>::value, bool>::type isPositive(const X val)
386 {
387  return val >= 0;
388 }
389 
390 
391 
392 
393 
394 // -----------------------------------------------------------------------------
395 // Define functions with printf-safe arguments, with compiler-generated warnings
396 // -----------------------------------------------------------------------------
397 
398 
399 // The PRINTFX_ARGS_SAFE macros are defined here, so that in the future we may support a
400 // wider range of compilers which may not understand the __attribute__(format)
401 // instruction.
402 
403 
404 // g++ or clang++ (or doxygen :-) )
405 #if defined(__GNUC__) || defined(__clang__) || defined(TOMOGRAPHER_PARSED_BY_DOXGEN)
406 
425 # define PRINTF1_ARGS_SAFE __attribute__ ((__format__ (__printf__, 1, 2)))
426 # define PRINTF2_ARGS_SAFE __attribute__ ((__format__ (__printf__, 2, 3)))
428 # define PRINTF3_ARGS_SAFE __attribute__ ((__format__ (__printf__, 3, 4)))
430 # define PRINTF4_ARGS_SAFE __attribute__ ((__format__ (__printf__, 4, 5)))
432 #else
433 # define PRINTF1_ARGS_SAFE
434 # define PRINTF2_ARGS_SAFE
435 # define PRINTF3_ARGS_SAFE
436 # define PRINTF4_ARGS_SAFE
437 #endif
438 
439 
440 
441 
442 #if TOMOGRAPHER_PARSED_BY_DOXYGEN
443 
451 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN
452 #else // TOMOGRAPHER_PARSED_BY_DOXYGEN
453 //
454 #if defined(__GNUC__) || defined(__clang__)
455 # if defined(__MINGW32__) || defined(__MINGW64__)
456 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN __attribute__((force_align_arg_pointer,noinline))
457 # else
458 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN
459 # endif
460 #elif defined(__ICC)
461 // but ICC is fine
462 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN
463 #else
464 # warning "You are using an unknown compiler. You may run into memory alignment problems... Good luck!"
465 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN
466 #endif
467 //
468 #endif // TOMOGRAPHER_PARSED_BY_DOXYGEN
469 
470 
471 // Internal hacks...
472 // ---------------------------
473 
474 // these are useful when writing SFINAE C++/C++11 hacks
475 namespace tomo_internal {
476 template<typename Enabledtype = void> struct sfinae_no { typedef int no[1]; };
477 template<typename EnabledType = void> struct sfinae_yes { typedef int yes[2]; };
478 } // namespace tomo_internal
479 
480 
481 
482 
483 
492 inline int getWidthForTerminalOutput(int max_width = 0)
493 {
494  if (max_width > 0) {
495  return max_width;
496  }
497  // max_width <= 0:
498  const int offset = max_width;
499  // decide of a maximum width to display
500 #if defined(__MINGW32__) || defined(__MINGW64__)
501  max_width = 80; // Windows terminals are usually 80 chars wide
502 #else
503  max_width = 100; // default maximum width
504 #endif
505  // Note that $COLUMNS is not in the environment usually, so you have to set it manually
506  // with e.g.
507  // shell> export COLUMNS=$COLUMNS
508  const char * cols_s = std::getenv("COLUMNS");
509  if (cols_s != NULL) {
510  max_width = std::atoi(cols_s);
511  }
512  max_width += offset; // if we had given, e.g. maxwidth=-4
513  return max_width;
514 }
515 
516 
517 
518 
519 
520 
521 // -----------------------------------------------------------------------------
522 // Function Name-Related Stuff
523 // -----------------------------------------------------------------------------
524 
525 
526 
531 #define TOMO_FUNCTION __PRETTY_FUNCTION__
532 
533 
534 
535 namespace tomo_internal {
536 // logic taken from KLatexFormula/klftools: klfdefs.cpp / klfShortFuncSignature()
537 struct extractFuncName_helper {
538  struct extracted {
539  const std::size_t decl_pos;
540  const conststr extr;
541  constexpr extracted(std::size_t dp, const conststr& s) : decl_pos(dp), extr(s) { }
542  };
543  static constexpr conststr alltofirstparen(const conststr& s)
544  {
545  return s.substr(0, s.find(conststr("("), 0, s.size()));
546  }
547  static constexpr std::size_t declpos_from_found_spc(std::size_t found_pos)
548  {
549  return found_pos == std::string::npos ? 0 : found_pos + 1;
550  }
551  static constexpr std::size_t pos_decl(const conststr& s)
552  {
553  return ((s.size() > 2)
554  ? declpos_from_found_spc(s.rfind(conststr(" "), std::string::npos))
555  : 0);
556  }
557  static constexpr extracted allfromfirstspace(const conststr& s)
558  {
559  return extracted(pos_decl(s),
560  s.substr_e(pos_decl(s),
561  s.size()));
562  }
563  static constexpr extracted do_extract(const conststr& funcname)
564  {
565  return allfromfirstspace(alltofirstparen(funcname));
566  }
567  static constexpr conststr extract_choose(const extracted& do_extracted,
568  const conststr& funcname)
569  {
570  return (do_extracted.extr.substr(0,8) == conststr("operator")
571  ? funcname.substr(do_extracted.decl_pos)
572  : do_extracted.extr);
573  }
574  static constexpr conststr extract(const conststr& funcname)
575  {
576  return extract_choose(do_extract(funcname), funcname);
577  }
578 }; // helper struct
579 } // namespace tomo_internal
580 
581 
587 constexpr inline conststr extractFuncName(const conststr & funcname)
588 {
589  return tomo_internal::extractFuncName_helper::extract(funcname);
590 }
591 
592 
593 
594 } // namespace Tools
595 } // namespace Tomographer
596 
597 
598 
599 
635 #define TOMOGRAPHER_DEFINE_MSG_EXCEPTION(ClassName, ErrPrefix) \
636  class ClassName : public std::exception { \
637  std::string _msg; \
638  public: \
639  ClassName(std::string msg) : _msg(std::string(ErrPrefix) + std::move(msg)) { } \
640  virtual ~ClassName() throw() { } \
641  std::string msg() const { return _msg; } \
642  const char * what() const throw() { return _msg.c_str(); } \
643  };
644 
653 #define TOMOGRAPHER_DEFINE_MSG_EXCEPTION_BASE(ClassName, ErrPrefix, BaseClass) \
654  class ClassName : public BaseClass { \
655  public: \
656  ClassName(std::string msg) : BaseClass(std::string(ErrPrefix) + std::move(msg)) { } \
657  virtual ~ClassName() throw() { } \
658  };
659 
660 
661 
662 namespace Tomographer {
663 namespace Tools {
664 
677 template<typename ExceptionClass = std::runtime_error>
678 inline void tomographerEnsure(bool condition, std::string message) {
679  if (!condition) {
680  throw ExceptionClass(message);
681  }
682 }
683 
684 
685 } // namespace Tools
686 } // namespace Tomographer
687 
688 
689 
690 #endif
Utility that stores a data type if a compile-time flag is enabled.
Definition: cxxutil.h:256
#define TOMO_STATIC_ASSERT_EXPR(...)
Tool for static assertions without message.
Definition: cxxutil.h:62
T atoi(T... args)
T value() const
See StaticOrDynamic<T_,IsDynamic_,StaticValue_>::value()
Definition: cxxutil.h:228
A type which stores a value possibly known at compile-time.
Definition: cxxutil.h:159
T operator()() const
See StaticOrDynamic<T_,IsDynamic_,StaticValue_>::operator()()
Definition: cxxutil.h:231
Base namespace for the Tomographer project.
Definition: densellh.h:45
T_ T
The type we&#39;re storing.
Definition: cxxutil.h:259
The Real scalar type corresponding to a std::complex type.
Definition: cxxutil.h:359
T value
This property keeps the value we&#39;re supposed to store.
Definition: cxxutil.h:283
STL namespace.
statically determine whether a type is complex
Definition: cxxutil.h:344
constexpr bool isPowerOfTwo(IntType N)
Return true if the argument is a power of two, false otherwise.
Definition: cxxutil.h:328
StaticOrDynamic(T val)
Constructor which initializes the value to val.
Definition: cxxutil.h:224
StaticOrDynamic(T val)
Constructor with an explicit value.
Definition: cxxutil.h:180
STL class.
T getenv(T... args)
std::enable_if< std::is_unsigned< X >::value, bool >::type isPositive(const X)
Test whether the given value is positive or zero.
Definition: cxxutil.h:379
T_ T
The type we&#39;re storing.
Definition: cxxutil.h:278
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:287
StoreIfEnabled(Args...)
Constructor.
Definition: cxxutil.h:265
VarValueDecoder< T >::RetType value(const Var &var)
Access the value of the given variable, as a C++ type.
Definition: ezmatio.h:871
T_ T
Type of the value we are storing.
Definition: cxxutil.h:164
T_ T
Type of the value we are storing. See StaticOrDynamic<T_,IsDynamic_,StaticValue_>::T.
Definition: cxxutil.h:213
int getWidthForTerminalOutput(int max_width=0)
Return a suitable width for displaying stuff on the standard output.
Definition: cxxutil.h:492
void tomographerEnsure(bool condition, std::string message)
Ensure that a condition is met, or throw an exception.
Definition: cxxutil.h:678
StaticOrDynamic()
Default Constructor. Only if the value is stored at compile-time.
Definition: cxxutil.h:174
constexpr conststr extractFuncName(const conststr &funcname)
Extract the function name from its signature.
Definition: cxxutil.h:587
T operator()() const
Get the value stored.
Definition: cxxutil.h:195
A constexpr string type.
Definition: conststr.h:55
STL class.
T value() const
Get the value stored.
Definition: cxxutil.h:189