Tomographer  v4.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 <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 
93 // -----------------------------------------------------------------------------
94 
95 
112 template<typename T_, bool IsDynamic_, T_ StaticValue_ = T_()>
113 TOMOGRAPHER_EXPORT class StaticOrDynamic
114 {
115 
116 public:
117  // definitions here are for the static case, the dynamic case will be specialized below.
118  TOMO_STATIC_ASSERT_EXPR(IsDynamic_ == false) ;
119 
121  typedef T_ T;
123  static constexpr bool IsDynamic = IsDynamic_;
125  static constexpr T StaticValue = StaticValue_;
126 
128  inline StaticOrDynamic() { }
134  inline explicit StaticOrDynamic(T val) {
135  tomographer_assert(val == StaticValue);
136  (void)val; // silence "unused parameter" warning if tomographer_assert() gets optimized out
137  }
138 
143  inline T value() const { return StaticValue; }
144 
149  inline T operator()() const { return StaticValue; }
150 };
151 // static properties
152 template<typename T_, bool IsDynamic_, T_ StaticValue_>
154 template<typename T_, bool IsDynamic_, T_ StaticValue_>
156 
161 template<typename T_, T_ StaticValue_>
162 TOMOGRAPHER_EXPORT class StaticOrDynamic<T_, true, StaticValue_>
163 {
164 public:
165 
167  typedef T_ T;
169  static constexpr bool IsDynamic = true;
170 
171 
173  StaticOrDynamic() = delete;
178  inline explicit StaticOrDynamic(T val) : _dyn_value(val) { }
179 
180 
182  inline T value() const { return _dyn_value; }
183 
185  inline T operator()() const { return value(); }
186 
187 private:
188 
190  const T _dyn_value;
191 };
192 // static properties
193 template<typename T_, T_ StaticValue_>
195 
196 
197 // -----------------------------------------------------------------------------
198 
199 
209 template<typename T_, bool enabled>
210 TOMOGRAPHER_EXPORT struct StoreIfEnabled
211 {
213  typedef T_ T;
215  static constexpr bool IsEnabled = false;
216 
218  template<typename... Args>
219  explicit StoreIfEnabled(Args...) { }
220 };
221 // static properties
222 template<typename T_, bool enabled>
228 template<typename T_>
229 TOMOGRAPHER_EXPORT struct StoreIfEnabled<T_, true>
230 {
232  typedef T_ T;
234  static constexpr bool IsEnabled = true;
235 
237  T value;
238 
240  template<typename... ArgTypes>
241  explicit StoreIfEnabled(const ArgTypes& ... args) : value(args...) { }
242 };
243 // static properties:
244 template<typename T_>
246 
254 template<typename T>
255 inline std::ostream & operator<<(std::ostream & str, const StoreIfEnabled<T, false>& /*val*/)
256 {
257  str << "[-]";
258  return str;
259 }
267 template<typename T>
268 inline std::ostream & operator<<(std::ostream & str, const StoreIfEnabled<T, true>& val)
269 {
270  str << val.value;
271  return str;
272 }
273 
274 
275 
276 // -----------------------------------------------------------------------------
277 
278 
281 template<typename IntType = int>
282 inline constexpr bool isPowerOfTwo(IntType N)
283 {
284  // taken from http://stackoverflow.com/q/10585450/1694896
285  return N && !(N & (N - 1));
286 }
287 
288 
289 // -----------------------------------------------------------------------------
290 
291 
300 template<typename Scalar>
302  typedef Scalar type;
303 };
304 
306 template<typename RealScalar>
307 struct ComplexRealScalar<std::complex<RealScalar> >
308 {
309  typedef RealScalar type;
310 };
311 
312 
313 
314 
320 template<typename X>
321 inline typename std::enable_if<std::is_unsigned<X>::value, bool>::type isPositive(const X /* val */)
322 {
323  return true;
324 }
326 template<typename X>
327 inline typename std::enable_if<!std::is_unsigned<X>::value, bool>::type isPositive(const X val)
328 {
329  return val >= 0;
330 }
331 
332 
333 
334 
335 
336 // -----------------------------------------------------------------------------
337 // Define functions with printf-safe arguments, with compiler-generated warnings
338 // -----------------------------------------------------------------------------
339 
340 
341 // The PRINTFX_ARGS_SAFE macros are defined here, so that in the future we may support a
342 // wider range of compilers which may not understand the __attribute__(format)
343 // instruction.
344 
345 
346 // g++ or clang++ (or doxygen :-) )
347 #if defined(__GNUC__) || defined(__clang__) || defined(TOMOGRAPHER_PARSED_BY_DOXGEN)
348 
367 # define PRINTF1_ARGS_SAFE __attribute__ ((__format__ (__printf__, 1, 2)))
368 # define PRINTF2_ARGS_SAFE __attribute__ ((__format__ (__printf__, 2, 3)))
370 # define PRINTF3_ARGS_SAFE __attribute__ ((__format__ (__printf__, 3, 4)))
372 # define PRINTF4_ARGS_SAFE __attribute__ ((__format__ (__printf__, 4, 5)))
374 #else
375 # define PRINTF1_ARGS_SAFE
376 # define PRINTF2_ARGS_SAFE
377 # define PRINTF3_ARGS_SAFE
378 # define PRINTF4_ARGS_SAFE
379 #endif
380 
381 
382 
383 
384 #if TOMOGRAPHER_PARSED_BY_DOXYGEN
385 
393 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN
394 #else // TOMOGRAPHER_PARSED_BY_DOXYGEN
395 //
396 #if defined(__GNUC__) || defined(__clang__)
397 # if defined(__MINGW32__) || defined(__MINGW64__)
398 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN __attribute__((force_align_arg_pointer,noinline))
399 # else
400 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN
401 # endif
402 #elif defined(__ICC)
403 // but ICC is fine
404 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN
405 #else
406 # warning "You are using an unknown compiler. You may run into memory alignment problems... Good luck!"
407 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN
408 #endif
409 //
410 #endif // TOMOGRAPHER_PARSED_BY_DOXYGEN
411 
412 
413 // Internal hacks...
414 // ---------------------------
415 
416 // these are useful when writing SFINAE C++/C++11 hacks
417 namespace tomo_internal {
418 template<typename Enabledtype = void> struct sfinae_no { typedef int no[1]; };
419 template<typename EnabledType = void> struct sfinae_yes { typedef int yes[2]; };
420 } // namespace tomo_internal
421 
422 
423 
424 
425 
434 inline int getWidthForTerminalOutput(int max_width = 0)
435 {
436  if (max_width > 0) {
437  return max_width;
438  }
439  // max_width <= 0:
440  const int offset = max_width;
441  // decide of a maximum width to display
442 #if defined(__MINGW32__) || defined(__MINGW64__)
443  max_width = 80; // Windows terminals are usually 80 chars wide
444 #else
445  max_width = 100; // default maximum width
446 #endif
447  // Note that $COLUMNS is not in the environment usually, so you have to set it manually
448  // with e.g.
449  // shell> export COLUMNS=$COLUMNS
450  const char * cols_s = std::getenv("COLUMNS");
451  if (cols_s != NULL) {
452  max_width = std::atoi(cols_s);
453  }
454  max_width += offset; // if we had given, e.g. maxwidth=-4
455  return max_width;
456 }
457 
458 
459 
460 
461 
462 
463 // -----------------------------------------------------------------------------
464 // Function Name-Related Stuff
465 // -----------------------------------------------------------------------------
466 
467 
468 
473 #define TOMO_FUNCTION __PRETTY_FUNCTION__
474 
475 
476 
477 namespace tomo_internal {
478 // logic taken from KLatexFormula/klftools: klfdefs.cpp / klfShortFuncSignature()
479 struct extractFuncName_helper {
480  struct extracted {
481  const std::size_t decl_pos;
482  const conststr extr;
483  constexpr extracted(std::size_t dp, const conststr& s) : decl_pos(dp), extr(s) { }
484  };
485  static constexpr conststr alltofirstparen(const conststr& s)
486  {
487  return s.substr(0, s.find(conststr("("), 0, s.size()));
488  }
489  static constexpr std::size_t declpos_from_found_spc(std::size_t found_pos)
490  {
491  return found_pos == std::string::npos ? 0 : found_pos + 1;
492  }
493  static constexpr std::size_t pos_decl(const conststr& s)
494  {
495  return ((s.size() > 2)
496  ? declpos_from_found_spc(s.rfind(conststr(" "), std::string::npos))
497  : 0);
498  }
499  static constexpr extracted allfromfirstspace(const conststr& s)
500  {
501  return extracted(pos_decl(s),
502  s.substr_e(pos_decl(s),
503  s.size()));
504  }
505  static constexpr extracted do_extract(const conststr& funcname)
506  {
507  return allfromfirstspace(alltofirstparen(funcname));
508  }
509  static constexpr conststr extract_choose(const extracted& do_extracted,
510  const conststr& funcname)
511  {
512  return (do_extracted.extr.substr(0,8) == conststr("operator")
513  ? funcname.substr(do_extracted.decl_pos)
514  : do_extracted.extr);
515  }
516  static constexpr conststr extract(const conststr& funcname)
517  {
518  return extract_choose(do_extract(funcname), funcname);
519  }
520 }; // helper struct
521 } // namespace tomo_internal
522 
523 
529 constexpr inline conststr extractFuncName(const conststr & funcname)
530 {
531  return tomo_internal::extractFuncName_helper::extract(funcname);
532 }
533 
534 
535 
536 } // namespace Tools
537 } // namespace Tomographer
538 
539 
540 
541 
577 #define TOMOGRAPHER_DEFINE_MSG_EXCEPTION(ClassName, ErrPrefix) \
578  TOMOGRAPHER_EXPORT class ClassName : public std::exception { \
579  std::string _msg; \
580  public: \
581  ClassName(std::string msg) : _msg(std::string(ErrPrefix) + std::move(msg)) { } \
582  virtual ~ClassName() throw() { } \
583  std::string msg() const { return _msg; } \
584  const char * what() const throw() { return _msg.c_str(); } \
585  };
586 
595 #define TOMOGRAPHER_DEFINE_MSG_EXCEPTION_BASE(ClassName, ErrPrefix, BaseClass) \
596  TOMOGRAPHER_EXPORT class ClassName : public BaseClass { \
597  public: \
598  ClassName(std::string msg) : BaseClass(std::string(ErrPrefix) + std::move(msg)) { } \
599  virtual ~ClassName() throw() { } \
600  };
601 
602 
603 
604 namespace Tomographer {
605 namespace Tools {
606 
619 template<typename ExceptionClass = std::runtime_error>
620 inline void tomographerEnsure(bool condition, std::string message) {
621  if (!condition) {
622  throw ExceptionClass(message);
623  }
624 }
625 
626 
627 } // namespace Tools
628 } // namespace Tomographer
629 
630 
631 
632 #endif
Utility that stores a data type if a compile-time flag is enabled.
Definition: cxxutil.h:210
T atoi(T... args)
T value() const
See StaticOrDynamic<T_,IsDynamic_,StaticValue_>::value()
Definition: cxxutil.h:182
A type which stores a value possibly known at compile-time.
Definition: cxxutil.h:113
T operator()() const
See StaticOrDynamic<T_,IsDynamic_,StaticValue_>::operator()()
Definition: cxxutil.h:185
Base namespace for the Tomographer project.
Definition: densellh.h:45
T_ T
The type we&#39;re storing.
Definition: cxxutil.h:213
The Real scalar type corresponding to a std::complex type.
Definition: cxxutil.h:301
T value
This property keeps the value we&#39;re supposed to store.
Definition: cxxutil.h:237
STL namespace.
constexpr bool isPowerOfTwo(IntType N)
Return true if the argument is a power of two, false otherwise.
Definition: cxxutil.h:282
StaticOrDynamic(T val)
Constructor which initializes the value to val.
Definition: cxxutil.h:178
StaticOrDynamic(T val)
Constructor with an explicit value.
Definition: cxxutil.h:134
STL class.
T getenv(T... args)
#define TOMO_STATIC_ASSERT_EXPR(...)
Tool for static assertions without message.
Definition: cxxdefs.h:76
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:321
T_ T
The type we&#39;re storing.
Definition: cxxutil.h:232
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:241
StoreIfEnabled(Args...)
Constructor.
Definition: cxxutil.h:219
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:118
T_ T
Type of the value we are storing. See StaticOrDynamic<T_,IsDynamic_,StaticValue_>::T.
Definition: cxxutil.h:167
int getWidthForTerminalOutput(int max_width=0)
Return a suitable width for displaying stuff on the standard output.
Definition: cxxutil.h:434
void tomographerEnsure(bool condition, std::string message)
Ensure that a condition is met, or throw an exception.
Definition: cxxutil.h:620
StaticOrDynamic()
Default Constructor. Only if the value is stored at compile-time.
Definition: cxxutil.h:128
constexpr conststr extractFuncName(const conststr &funcname)
Extract the function name from its signature.
Definition: cxxutil.h:529
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:149
A constexpr string type.
Definition: conststr.h:55
STL class.
#define tomographer_assert(...)
Assertion test macro.
Definition: cxxdefs.h:83
T value() const
Get the value stored.
Definition: cxxutil.h:143