Tomographer  v5.1
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 #include <Eigen/Core>
51 
52 // -----------------------------------------------
53 
54 
55 namespace Tomographer
56 {
57 namespace Tools
58 {
59 
60 // taken from http://stackoverflow.com/a/25510879/1694896
61 
62 namespace tomo_internal {
63  template <typename F>
64  struct FinalAction {
65  FinalAction(F f) : clean_(f) {}
66  ~FinalAction() { clean_(); }
67  F clean_;
68  };
69 } // namespace tomo_internal
70 
82 template <typename F>
83 inline tomo_internal::FinalAction<F> finally(F f)
84 {
85  return tomo_internal::FinalAction<F>(f);
86 }
87 
88 
89 
90 // -----------------------------------------------------------------------------
91 
92 // see http://aherrmann.github.io/programming/2016/02/28/unpacking-tuples-in-cpp14/ and
93 // http://stackoverflow.com/questions/17424477/implementation-c14-make-integer-sequence/17426611#17426611
94 //
95 
96 template<typename T, T...> struct Sequence { typedef Sequence type; };
97 
98 template<typename T, typename S1, typename S2> struct Concatenate;
99 
100 template<typename T, T... I1, T... I2>
101 struct Concatenate<T, Sequence<T, I1...>, Sequence<T, I2...> >
102  : Sequence<T, I1..., (sizeof...(I1)+I2)...> {};
103 
104 template<typename T, T N, typename dummy = void>
106 
107 template<typename T, T N, typename >
108 struct GenerateSequence : Concatenate<T, typename GenerateSequence<T, N/2>::type,
109  typename GenerateSequence<T, N - N/2>::type>::type {};
110 
111 template<typename T, T N>
112 struct GenerateSequence<T, N, typename std::enable_if<(N==0),void>::type>
113  : Sequence<T> {};
114 
115 template<typename T, T N>
116 struct GenerateSequence<T, N, typename std::enable_if<(N==1),void>::type>
117  : Sequence<T, 0> {};
118 
119 
120 
121 
122 // -----------------------------------------------------------------------------
123 
124 
141 template<typename T_, bool IsDynamic_, T_ StaticValue_ = T_()>
142 class TOMOGRAPHER_EXPORT StaticOrDynamic
143 {
144 
145 public:
146  // definitions here are for the static case, the dynamic case will be specialized below.
147  TOMO_STATIC_ASSERT_EXPR(IsDynamic_ == false) ;
148 
150  typedef T_ T;
152  static constexpr bool IsDynamic = IsDynamic_;
154  static constexpr T StaticValue = StaticValue_;
155 
157  inline StaticOrDynamic() { }
163  inline explicit StaticOrDynamic(T val) {
164  tomographer_assert(val == StaticValue);
165  (void)val; // silence "unused parameter" warning if tomographer_assert() gets optimized out
166  }
167 
172  inline T value() const { return StaticValue; }
173 
178  inline T operator()() const { return StaticValue; }
179 };
180 // static properties
181 template<typename T_, bool IsDynamic_, T_ StaticValue_>
183 template<typename T_, bool IsDynamic_, T_ StaticValue_>
185 
190 template<typename T_, T_ StaticValue_>
191 class TOMOGRAPHER_EXPORT StaticOrDynamic<T_, true, StaticValue_>
192 {
193 public:
194 
196  typedef T_ T;
198  static constexpr bool IsDynamic = true;
199 
200 
202  StaticOrDynamic() = delete;
207  inline explicit StaticOrDynamic(T val) : _dyn_value(val) { }
208 
209 
211  inline T value() const { return _dyn_value; }
212 
214  inline T operator()() const { return value(); }
215 
216 private:
217 
219  const T _dyn_value;
220 };
221 // static properties
222 template<typename T_, T_ StaticValue_>
224 
225 
226 // -----------------------------------------------------------------------------
227 
228 
238 template<typename T_, bool enabled>
239 struct TOMOGRAPHER_EXPORT StoreIfEnabled
240 {
242  typedef T_ T;
244  static constexpr bool IsEnabled = false;
245 
247  template<typename... Args>
248  explicit StoreIfEnabled(Args...) { }
249 };
250 // static properties
251 template<typename T_, bool enabled>
257 template<typename T_>
258 struct TOMOGRAPHER_EXPORT StoreIfEnabled<T_, true>
259 {
261  typedef T_ T;
263  static constexpr bool IsEnabled = true;
264 
266  T value;
267 
269  template<typename... ArgTypes>
270  explicit StoreIfEnabled(const ArgTypes& ... args) : value(args...) { }
271 };
272 // static properties:
273 template<typename T_>
275 
283 template<typename T>
284 inline std::ostream & operator<<(std::ostream & str, const StoreIfEnabled<T, false>& /*val*/)
285 {
286  str << "[-]";
287  return str;
288 }
296 template<typename T>
297 inline std::ostream & operator<<(std::ostream & str, const StoreIfEnabled<T, true>& val)
298 {
299  str << val.value;
300  return str;
301 }
302 
303 
304 
305 // -----------------------------------------------------------------------------
306 
307 
310 template<typename IntType = int>
311 inline constexpr bool isPowerOfTwo(IntType N)
312 {
313  // taken from http://stackoverflow.com/q/10585450/1694896
314  return N && !(N & (N - 1));
315 }
316 
317 
318 // -----------------------------------------------------------------------------
319 
320 
329 template<typename Scalar>
331  typedef Scalar type;
332 };
333 
335 template<typename RealScalar>
336 struct ComplexRealScalar<std::complex<RealScalar> >
337 {
338  typedef RealScalar type;
339 };
340 
341 
342 
343 
349 template<typename X>
350 inline typename std::enable_if<std::is_unsigned<X>::value, bool>::type isPositive(const X /* val */)
351 {
352  return true;
353 }
355 template<typename X>
356 inline typename std::enable_if<!std::is_unsigned<X>::value, bool>::type isPositive(const X val)
357 {
358  return val >= 0;
359 }
360 
361 
362 
368 template<typename X>
369 inline bool isFinite(const X val)
370 {
371  return std::isfinite(val);
372 }
373 
374 
375 
376 // -----------------------------------------------------------------------------
377 // Define functions with printf-safe arguments, with compiler-generated warnings
378 // -----------------------------------------------------------------------------
379 
380 
381 // The PRINTFX_ARGS_SAFE macros are defined here, so that in the future we may support a
382 // wider range of compilers which may not understand the __attribute__(format)
383 // instruction.
384 
385 
386 // g++ or clang++ (or doxygen :-) )
387 #if defined(__GNUC__) || defined(__clang__) || defined(TOMOGRAPHER_PARSED_BY_DOXGEN)
388 
407 # define PRINTF1_ARGS_SAFE __attribute__ ((__format__ (__printf__, 1, 2)))
408 # define PRINTF2_ARGS_SAFE __attribute__ ((__format__ (__printf__, 2, 3)))
410 # define PRINTF3_ARGS_SAFE __attribute__ ((__format__ (__printf__, 3, 4)))
412 # define PRINTF4_ARGS_SAFE __attribute__ ((__format__ (__printf__, 4, 5)))
414 #else
415 # define PRINTF1_ARGS_SAFE
416 # define PRINTF2_ARGS_SAFE
417 # define PRINTF3_ARGS_SAFE
418 # define PRINTF4_ARGS_SAFE
419 #endif
420 
421 
422 
423 
424 #if TOMOGRAPHER_PARSED_BY_DOXYGEN
425 
433 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN
434 #else // TOMOGRAPHER_PARSED_BY_DOXYGEN
435 //
436 #if defined(__GNUC__) || defined(__clang__)
437 # if defined(__MINGW32__) || defined(__MINGW64__)
438 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN __attribute__((force_align_arg_pointer,noinline))
439 # else
440 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN
441 # endif
442 #elif defined(__ICC)
443 // but ICC is fine
444 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN
445 #else
446 # warning "You are using an unknown compiler. You may run into memory alignment problems... Good luck!"
447 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN
448 #endif
449 //
450 #endif // TOMOGRAPHER_PARSED_BY_DOXYGEN
451 
452 
453 // Internal hacks...
454 // ---------------------------
455 
456 // these are useful when writing SFINAE C++/C++11 hacks
457 namespace tomo_internal {
458 template<typename Enabledtype = void> struct sfinae_no { typedef int no[1]; };
459 template<typename EnabledType = void> struct sfinae_yes { typedef int yes[2]; };
460 } // namespace tomo_internal
461 
462 
463 
464 
465 
474 inline int getWidthForTerminalOutput(int max_width = 0)
475 {
476  if (max_width > 0) {
477  return max_width;
478  }
479  // max_width <= 0:
480  const int offset = max_width;
481  // decide of a maximum width to display
482 #if defined(__MINGW32__) || defined(__MINGW64__)
483  max_width = 80; // Windows terminals are usually 80 chars wide
484 #else
485  max_width = 100; // default maximum width
486 #endif
487  // Note that $COLUMNS is not in the environment usually, so you have to set it manually
488  // with e.g.
489  // shell> export COLUMNS=$COLUMNS
490  const char * cols_s = std::getenv("COLUMNS");
491  if (cols_s != NULL) {
492  max_width = std::atoi(cols_s);
493  }
494  max_width += offset; // if we had given, e.g. maxwidth=-4
495  return max_width;
496 }
497 
498 
499 
500 
501 
502 
503 // -----------------------------------------------------------------------------
504 // Function Name-Related Stuff
505 // -----------------------------------------------------------------------------
506 
507 
508 
513 #define TOMO_FUNCTION __PRETTY_FUNCTION__
514 
515 
516 
517 namespace tomo_internal {
518 // logic taken from KLatexFormula/klftools: klfdefs.cpp / klfShortFuncSignature()
519 struct extractFuncName_helper {
520  struct extracted {
521  const std::size_t decl_pos;
522  const conststr extr;
523  constexpr extracted(std::size_t dp, const conststr& s) : decl_pos(dp), extr(s) { }
524  };
525  static constexpr conststr alltofirstparen(const conststr& s)
526  {
527  return s.substr(0, s.find(conststr("("), 0, s.size()));
528  }
529  static constexpr std::size_t declpos_from_found_spc(std::size_t found_pos)
530  {
531  return found_pos == std::string::npos ? 0 : found_pos + 1;
532  }
533  static constexpr std::size_t pos_decl(const conststr& s)
534  {
535  return ((s.size() > 2)
536  ? declpos_from_found_spc(s.rfind(conststr(" "), std::string::npos))
537  : 0);
538  }
539  static constexpr extracted allfromfirstspace(const conststr& s)
540  {
541  return extracted(pos_decl(s),
542  s.substr_e(pos_decl(s),
543  s.size()));
544  }
545  static constexpr extracted do_extract(const conststr& funcname)
546  {
547  return allfromfirstspace(alltofirstparen(funcname));
548  }
549  static constexpr conststr extract_choose(const extracted& do_extracted,
550  const conststr& funcname)
551  {
552  return (do_extracted.extr.substr(0,8) == conststr("operator")
553  ? funcname.substr(do_extracted.decl_pos)
554  : do_extracted.extr);
555  }
556  static constexpr conststr extract(const conststr& funcname)
557  {
558  return extract_choose(do_extract(funcname), funcname);
559  }
560 }; // helper struct
561 } // namespace tomo_internal
562 
563 
569 constexpr inline conststr extractFuncName(const conststr & funcname)
570 {
571  return tomo_internal::extractFuncName_helper::extract(funcname);
572 }
573 
574 
575 
576 } // namespace Tools
577 } // namespace Tomographer
578 
579 
580 
581 
617 #define TOMOGRAPHER_DEFINE_MSG_EXCEPTION(ClassName, ErrPrefix) \
618  class TOMOGRAPHER_EXPORT ClassName : public std::exception { \
619  std::string _msg; \
620  public: \
621  ClassName(std::string msg) : _msg(std::string(ErrPrefix) + std::move(msg)) { } \
622  virtual ~ClassName() throw() { } \
623  std::string msg() const { return _msg; } \
624  const char * what() const throw() { return _msg.c_str(); } \
625  };
626 
635 #define TOMOGRAPHER_DEFINE_MSG_EXCEPTION_BASE(ClassName, ErrPrefix, BaseClass) \
636  class TOMOGRAPHER_EXPORT ClassName : public BaseClass { \
637  public: \
638  ClassName(std::string msg) : BaseClass(std::string(ErrPrefix) + std::move(msg)) { } \
639  virtual ~ClassName() throw() { } \
640  };
641 
642 
643 
644 namespace Tomographer {
645 namespace Tools {
646 
659 template<typename ExceptionClass = std::runtime_error>
660 inline void tomographerEnsure(bool condition, std::string message) {
661  if (!condition) {
662  throw ExceptionClass(message);
663  }
664 }
665 
666 
667 
668 
669 
670 
671 } // namespace Tools
672 } // namespace Tomographer
673 
674 
675 
676 #endif
Utility that stores a data type if a compile-time flag is enabled.
Definition: cxxutil.h:239
T atoi(T... args)
T value() const
See StaticOrDynamic<T_,IsDynamic_,StaticValue_>::value()
Definition: cxxutil.h:211
A type which stores a value possibly known at compile-time.
Definition: cxxutil.h:142
bool isFinite(const X val)
Test whether floating-point value is finite.
Definition: cxxutil.h:369
T operator()() const
See StaticOrDynamic<T_,IsDynamic_,StaticValue_>::operator()()
Definition: cxxutil.h:214
Base namespace for the Tomographer project.
Definition: densellh.h:45
T_ T
The type we&#39;re storing.
Definition: cxxutil.h:242
The Real scalar type corresponding to a std::complex type.
Definition: cxxutil.h:330
T value
This property keeps the value we&#39;re supposed to store.
Definition: cxxutil.h:266
STL namespace.
constexpr bool isPowerOfTwo(IntType N)
Return true if the argument is a power of two, false otherwise.
Definition: cxxutil.h:311
StaticOrDynamic(T val)
Constructor which initializes the value to val.
Definition: cxxutil.h:207
StaticOrDynamic(T val)
Constructor with an explicit value.
Definition: cxxutil.h:163
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)
Test whether the given value is positive or zero.
Definition: cxxutil.h:350
T_ T
The type we&#39;re storing.
Definition: cxxutil.h:261
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:270
StoreIfEnabled(Args...)
Constructor.
Definition: cxxutil.h:248
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:147
T_ T
Type of the value we are storing. See StaticOrDynamic<T_,IsDynamic_,StaticValue_>::T.
Definition: cxxutil.h:196
int getWidthForTerminalOutput(int max_width=0)
Return a suitable width for displaying stuff on the standard output.
Definition: cxxutil.h:474
void tomographerEnsure(bool condition, std::string message)
Ensure that a condition is met, or throw an exception.
Definition: cxxutil.h:660
StaticOrDynamic()
Default Constructor. Only if the value is stored at compile-time.
Definition: cxxutil.h:157
constexpr conststr extractFuncName(const conststr &funcname)
Extract the function name from its signature.
Definition: cxxutil.h:569
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:178
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:172