Tomographer  v2.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) 2015 ETH Zurich, Institute for Theoretical Physics, Philippe Faist
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  */
26 
27 #ifndef TOMOGRAPHER_TOOLS_UTILS_H
28 #define TOMOGRAPHER_TOOLS_UTILS_H
29 
36 #include <cassert>
37 #include <cstddef>
38 #include <cstdlib>
39 
40 #include <type_traits>
41 
42 #include <Eigen/Core> // NumTraits
43 
45 
46 
47 
48 // -----------------------------------------------------------------------------
49 // Some C++ helpers
50 // -----------------------------------------------------------------------------
51 
52 
53 
59 #define TOMO_STATIC_ASSERT_EXPR(...) \
60  static_assert(__VA_ARGS__, #__VA_ARGS__)
61 
62 
63 #ifndef tomographer_assert
64 #define tomographer_assert(...) eigen_assert((__VA_ARGS__) && "assert: " #__VA_ARGS__)
65 #endif
66 
67 
68 
69 #ifndef TOMOGRAPHER_PARSED_BY_DOXYGEN
70 // WARNING!!! CHECK OUT http://stackoverflow.com/q/29363532/1694896
71 // FOR VERY SUBTLE BUGS....... :( :( -- TEST WITH INTEL ICC!!
72 #define TOMOGRAPHER_ENABLED_IF(...) \
73  template<bool _dummy__enabledif = false, \
74  typename std::enable_if<_dummy__enabledif || (__VA_ARGS__), bool>::type \
75  _dummy__enabledif2 = false>
76 #define TOMOGRAPHER_ENABLED_IF_TMPL(...) \
77  bool _dummy__enabledif = false, \
78  typename std::enable_if<_dummy__enabledif || (__VA_ARGS__), bool>::type \
79  _dummy__enabledif2 = true
80 
87 #define TOMOGRAPHER_ENABLED_IF_TMPL_REPEAT(...) \
88  bool _dummy__enabledif, \
89  typename std::enable_if<_dummy__enabledif || (__VA_ARGS__), bool>::type \
90  _dummy__enabledifAlt2 = true
91 #endif
92 
93 
94 
95 // -----------------------------------------------
96 
97 
98 namespace Tomographer
99 {
100 namespace Tools
101 {
102 
103 // taken from http://stackoverflow.com/a/25510879/1694896
104 
105 namespace tomo_internal {
106  template <typename F>
107  struct FinalAction {
108  FinalAction(F f) : clean_{f} {}
109  ~FinalAction() { clean_(); }
110  F clean_;
111  };
112 } // namespace tomo_internal
113 
125 template <typename F>
126 inline tomo_internal::FinalAction<F> finally(F f)
127 {
128  return tomo_internal::FinalAction<F>(f);
129 }
130 
131 
132 
133 
134 
135 
136 // -----------------------------------------------------------------------------
137 
138 
155 template<typename T_, bool IsDynamic_, T_ StaticValue_ = T_()>
157 {
158 
159 public:
160  // definitions here are for the static case, the dynamic case will be specialized below.
161  TOMO_STATIC_ASSERT_EXPR(IsDynamic_ == false) ;
162 
164  typedef T_ T;
166  static constexpr bool IsDynamic = IsDynamic_;
168  static constexpr T StaticValue = StaticValue_;
169 
171  inline StaticOrDynamic() { }
177  inline explicit StaticOrDynamic(T val) {
178  tomographer_assert(val == StaticValue);
179  (void)val; // silence "unused parameter" warning if tomographer_assert() gets optimized out
180  }
181 
186  inline T value() const { return StaticValue; }
187 
192  inline T operator()() const { return StaticValue; }
193 };
194 // static properties
195 template<typename T_, bool IsDynamic_, T_ StaticValue_>
197 template<typename T_, bool IsDynamic_, T_ StaticValue_>
199 
204 template<typename T_, T_ StaticValue_>
205 class StaticOrDynamic<T_, true, StaticValue_>
206 {
207 public:
208 
210  typedef T_ T;
212  static constexpr bool IsDynamic = true;
213 
214 
216  StaticOrDynamic() = delete;
221  inline explicit StaticOrDynamic(T val) : _dyn_value(val) { }
222 
223 
225  inline T value() const { return _dyn_value; }
226 
228  inline T operator()() const { return value(); }
229 
230 private:
231 
233  const T _dyn_value;
234 };
235 // static properties
236 template<typename T_, T_ StaticValue_>
238 
239 
240 // -----------------------------------------------------------------------------
241 
242 
252 template<typename T_, bool enabled>
254 {
256  typedef T_ T;
258  static constexpr bool IsEnabled = false;
259 
261  template<typename... Args>
262  explicit StoreIfEnabled(Args...) { }
263 };
264 // static properties
265 template<typename T_, bool enabled>
271 template<typename T_>
272 struct StoreIfEnabled<T_, true>
273 {
275  typedef T_ T;
277  static constexpr bool IsEnabled = true;
278 
280  T value;
281 
283  template<typename... ArgTypes>
284  explicit StoreIfEnabled(const ArgTypes& ... args) : value(args...) { }
285 };
286 // static properties:
287 template<typename T_>
289 
297 template<typename T>
298 inline std::ostream & operator<<(std::ostream & str, const StoreIfEnabled<T, false>& /*val*/)
299 {
300  str << "[-]";
301  return str;
302 }
310 template<typename T>
311 inline std::ostream & operator<<(std::ostream & str, const StoreIfEnabled<T, true>& val)
312 {
313  str << val.value;
314  return str;
315 }
316 
317 
318 
319 // -----------------------------------------------------------------------------
320 
321 
324 template<typename IntType = int>
325 inline constexpr bool isPowerOfTwo(IntType N)
326 {
327  // taken from http://stackoverflow.com/q/10585450/1694896
328  return N && !(N & (N - 1));
329 }
330 
331 
332 // -----------------------------------------------------------------------------
333 
334 
340 template<typename Scalar>
341 struct isComplex {
342  // use Eigen's existing implementation
344 };
345 
346 
355 template<typename Scalar>
357  typedef Scalar type;
358 };
359 
361 template<typename RealScalar>
362 struct ComplexRealScalar<std::complex<RealScalar> >
363 {
364  typedef RealScalar type;
365 };
366 
367 
368 
369 
375 template<typename X>
376 inline typename std::enable_if<std::is_unsigned<X>::value, bool>::type isPositive(const X /* val */)
377 {
378  return true;
379 }
381 template<typename X>
382 inline typename std::enable_if<!std::is_unsigned<X>::value, bool>::type isPositive(const X val)
383 {
384  return val >= 0;
385 }
386 
387 
388 
389 
390 
391 // -----------------------------------------------------------------------------
392 // Define functions with printf-safe arguments, with compiler-generated warnings
393 // -----------------------------------------------------------------------------
394 
395 
396 // The PRINTFX_ARGS_SAFE macros are defined here, so that in the future we may support a
397 // wider range of compilers which may not understand the __attribute__(format)
398 // instruction.
399 
400 
401 // g++ or clang++ (or doxygen :-) )
402 #if defined(__GNUC__) || defined(__clang__) || defined(TOMOGRAPHER_PARSED_BY_DOXGEN)
403 
422 # define PRINTF1_ARGS_SAFE __attribute__ ((__format__ (__printf__, 1, 2)))
423 # define PRINTF2_ARGS_SAFE __attribute__ ((__format__ (__printf__, 2, 3)))
425 # define PRINTF3_ARGS_SAFE __attribute__ ((__format__ (__printf__, 3, 4)))
427 # define PRINTF4_ARGS_SAFE __attribute__ ((__format__ (__printf__, 4, 5)))
429 #else
430 # define PRINTF1_ARGS_SAFE
431 # define PRINTF2_ARGS_SAFE
432 # define PRINTF3_ARGS_SAFE
433 # define PRINTF4_ARGS_SAFE
434 #endif
435 
436 
437 
438 
439 #if TOMOGRAPHER_PARSED_BY_DOXYGEN
440 
448 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN
449 #else // TOMOGRAPHER_PARSED_BY_DOXYGEN
450 //
451 #if defined(__GNUC__) || defined(__clang__)
452 # if defined(__MINGW32__) || defined(__MINGW64__)
453 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN __attribute__((force_align_arg_pointer,noinline))
454 # else
455 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN
456 # endif
457 #elif defined(__ICC)
458 // but ICC is fine
459 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN
460 #else
461 # warning "You are using an unknown compiler. You may run into memory alignment problems... Good luck!"
462 # define TOMOGRAPHER_CXX_STACK_FORCE_REALIGN
463 #endif
464 //
465 #endif // TOMOGRAPHER_PARSED_BY_DOXYGEN
466 
467 
468 // Internal hacks...
469 // ---------------------------
470 
471 // these are useful when writing SFINAE C++/C++11 hacks
472 namespace tomo_internal {
473 template<typename Enabledtype = void> struct sfinae_no { typedef int no[1]; };
474 template<typename EnabledType = void> struct sfinae_yes { typedef int yes[2]; };
475 } // namespace tomo_internal
476 
477 
478 
479 
480 
489 inline int getWidthForTerminalOutput(int max_width = 0)
490 {
491  if (max_width > 0) {
492  return max_width;
493  }
494  // max_width <= 0:
495  const int offset = max_width;
496  // decide of a maximum width to display
497 #if defined(__MINGW32__) || defined(__MINGW64__)
498  max_width = 80; // Windows terminals are usually 80 chars wide
499 #else
500  max_width = 100; // default maximum width
501 #endif
502  // Note that $COLUMNS is not in the environment usually, so you have to set it manually
503  // with e.g.
504  // shell> export COLUMNS=$COLUMNS
505  const char * cols_s = std::getenv("COLUMNS");
506  if (cols_s != NULL) {
507  max_width = std::atoi(cols_s);
508  }
509  max_width += offset; // if we had given, e.g. maxwidth=-4
510  return max_width;
511 }
512 
513 
514 
515 
516 
517 
518 // -----------------------------------------------------------------------------
519 // Function Name-Related Stuff
520 // -----------------------------------------------------------------------------
521 
522 
523 
528 #define TOMO_FUNCTION __PRETTY_FUNCTION__
529 
530 
531 
532 namespace tomo_internal {
533 // logic taken from KLatexFormula/klftools: klfdefs.cpp / klfShortFuncSignature()
534 struct extractFuncName_helper {
535  struct extracted {
536  const std::size_t decl_pos;
537  const conststr extr;
538  constexpr extracted(std::size_t dp, const conststr& s) : decl_pos(dp), extr(s) { }
539  };
540  static constexpr conststr alltofirstparen(const conststr& s)
541  {
542  return s.substr(0, s.find(conststr("("), 0, s.size()));
543  }
544  static constexpr std::size_t declpos_from_found_spc(std::size_t found_pos)
545  {
546  return found_pos == std::string::npos ? 0 : found_pos + 1;
547  }
548  static constexpr std::size_t pos_decl(const conststr& s)
549  {
550  return ((s.size() > 2)
551  ? declpos_from_found_spc(s.rfind(conststr(" "), std::string::npos))
552  : 0);
553  }
554  static constexpr extracted allfromfirstspace(const conststr& s)
555  {
556  return extracted(pos_decl(s),
557  s.substr_e(pos_decl(s),
558  s.size()));
559  }
560  static constexpr extracted do_extract(const conststr& funcname)
561  {
562  return allfromfirstspace(alltofirstparen(funcname));
563  }
564  static constexpr conststr extract_choose(const extracted& do_extracted,
565  const conststr& funcname)
566  {
567  return (do_extracted.extr.substr(0,8) == conststr("operator")
568  ? funcname.substr(do_extracted.decl_pos)
569  : do_extracted.extr);
570  }
571  static constexpr conststr extract(const conststr& funcname)
572  {
573  return extract_choose(do_extract(funcname), funcname);
574  }
575 }; // helper struct
576 } // namespace tomo_internal
577 
578 
584 constexpr inline conststr extractFuncName(const conststr & funcname)
585 {
586  return tomo_internal::extractFuncName_helper::extract(funcname);
587 }
588 
589 
590 
591 
592 
593 
594 
595 } // namespace Tools
596 } // namespace Tomographer
597 
598 
599 
600 #endif
Utility that stores a data type if a compile-time flag is enabled.
Definition: cxxutil.h:253
#define TOMO_STATIC_ASSERT_EXPR(...)
Tool for static assertions without message.
Definition: cxxutil.h:59
T atoi(T...args)
A type which stores a value possibly known at compile-time.
Definition: cxxutil.h:156
Base namespace for the Tomographer project.
Definition: densellh.h:44
T_ T
The type we&#39;re storing.
Definition: cxxutil.h:256
The Real scalar type corresponding to a std::complex type.
Definition: cxxutil.h:356
T value
This property keeps the value we&#39;re supposed to store.
Definition: cxxutil.h:280
STL namespace.
statically determine whether a type is complex
Definition: cxxutil.h:341
constexpr bool isPowerOfTwo(IntType N)
Return true if the argument is a power of two, false otherwise.
Definition: cxxutil.h:325
StaticOrDynamic(T val)
Constructor which initializes the value to val.
Definition: cxxutil.h:221
StaticOrDynamic(T val)
Constructor with an explicit value.
Definition: cxxutil.h:177
T operator()() const
Get the value stored.
Definition: cxxutil.h:192
T getenv(T...args)
StoreIfEnabled(const ArgTypes &...args)
Constructor. Any arguments are passed to the value&#39;s constructor.
Definition: cxxutil.h:284
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:376
T_ T
The type we&#39;re storing.
Definition: cxxutil.h:275
A constexpr string type, suitable for basic compile-time string processing.
T value() const
Get the value stored.
Definition: cxxutil.h:186
StoreIfEnabled(Args...)
Constructor.
Definition: cxxutil.h:262
T operator()() const
See StaticOrDynamic<T_,IsDynamic_,StaticValue_>::operator()()
Definition: cxxutil.h:228
VarValueDecoder< T >::RetType value(const Var &var)
Access the value of the given variable, as a C++ type.
Definition: ezmatio.h:854
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:210
int getWidthForTerminalOutput(int max_width=0)
Return a suitable width for displaying stuff on the standard output.
Definition: cxxutil.h:489
StaticOrDynamic()
Default Constructor. Only if the value is stored at compile-time.
Definition: cxxutil.h:171
constexpr conststr extractFuncName(const conststr &funcname)
Extract the function name from its signature.
Definition: cxxutil.h:584
T value() const
See StaticOrDynamic<T_,IsDynamic_,StaticValue_>::value()
Definition: cxxutil.h:225
A constexpr string type.
Definition: conststr.h:54
STL class.