Version: SMASH-3.4
fpenvironment.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2015,2017-2018,2020
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #ifndef SRC_INCLUDE_SMASH_FPENVIRONMENT_H_
11 #define SRC_INCLUDE_SMASH_FPENVIRONMENT_H_
12 
13 #include <cfenv>
14 
15 namespace smash {
16 
17 #if defined _GNU_SOURCE && !defined __clang__
18 /**
19  * Standard C/C++ don't have a function to modify the trapping behavior. You
20  * can only save and restore the setup. With glibc you can change it via
21  * feenableexcept and fedisableexcept. Without glibc inline asm and SSE
22  * intrinsics can do it (for x86).
23  *
24  * It is important that the used compiler supports floating-point traps, other-
25  * wise it might break them by reordering floating-point operations when
26  * optimizing. Currently floating-point traps are disabled for Clang, because
27  * it does not support them.
28  *
29  * \param mask A bitwise of the traps you want to keep enabled.
30  * \return Whether the trap was successfully set.
31  *
32  * glibc specific implementation
33  */
34 inline bool enable_float_traps(int mask) { return -1 != feenableexcept(mask); }
35 #elif defined __SSE__ && !defined __clang__
36 /// Directly program the trap on the SSE unit
37 bool enable_float_traps(int mask);
38 #else
39 /// Fallback that fails to set the trap
40 inline bool enable_float_traps(int) { return false; }
41 #endif
42 
43 /**
44  * Setup the floating-point traps used throughout SMASH.
45  *
46  * If possible, this function additionally installs a signal handler that prints
47  * what kind of condition triggered the trap. This requires POSIX.1-2001 to
48  * work.
49  */
51 
52 /**
53  * Guard type that safely disables floating point traps for the scope in which
54  * it is placed.
55  *
56  * Example:
57  * \code
58  * {
59  * // some code where FPEs will trap
60  * DisableFloatTraps guard;
61  * // all code up to the closing brace will not trap anymore.
62  * }
63  * \endcode
64  *
65  * You can also keep some traps enabled. E.g. FE_DIVBYZERO is a candidate you
66  * might want to keep enabled, whereas FE_UNDERFLOW and FE_OVERFLOW are the ones
67  * that you really need to get rid of:
68  * \code
69  * DisableFloatTraps guard(FE_DIVBYZERO | FE_INVALID);
70  * \endcode
71  *
72  * \note There is no guarantee about the complexity of modifying the floating
73  * point environment. This could be very expensive. Therefore it is always
74  * preferable to fix your code to not require underflow or overflow.
75  *
76  * \see http://en.cppreference.com/w/cpp/numeric/fenv/FE_exceptions for a
77  * complete list of flags.
78  */
80  public:
81  /**
82  * Constructs the guard object.
83  *
84  * \param mask A bitwise of the traps you want to keep enabled.
85  * \return The constructed object.
86  */
87  explicit DisableFloatTraps(int mask = 0) {
88  std::feholdexcept(&environment_);
89  if (mask != 0) {
90  reenable_traps(mask);
91  }
92  }
93 
94  /**
95  * When the guard goes out of scope the floating point environment is
96  * restored.
97  */
98  ~DisableFloatTraps() { std::fesetenv(&environment_); }
99 
100  private:
101  /**
102  * Reenables the given traps.
103  * \param mask A bitwise of the traps you want to keep enabled.
104  */
105  void reenable_traps(int mask);
106 
107  /// The stored environment that the destructor will restore.
108  std::fenv_t environment_;
109 };
110 
111 /**
112  * Convenience function to create a scope where all floating point traps are
113  * disabled.
114  *
115  * Example:
116  * \code
117  * // some code where FPEs will trap
118  * without_float_traps([&] {
119  * // all code up to the closing brace will not trap anymore.
120  * });
121  * // more code where FPEs will trap
122  * \endcode
123  *
124  * \param f A functor (e.g. lambda) that is executed in the cleared floating
125  * point environment.
126  * \tparam F type of the functor
127  */
128 template <typename F>
129 void without_float_traps(F &&f) {
130  DisableFloatTraps guard;
131  f();
132 }
133 
134 } // namespace smash
135 
136 #endif // SRC_INCLUDE_SMASH_FPENVIRONMENT_H_
Guard type that safely disables floating point traps for the scope in which it is placed.
Definition: fpenvironment.h:79
~DisableFloatTraps()
When the guard goes out of scope the floating point environment is restored.
Definition: fpenvironment.h:98
DisableFloatTraps(int mask=0)
Constructs the guard object.
Definition: fpenvironment.h:87
void reenable_traps(int mask)
Reenables the given traps.
std::fenv_t environment_
The stored environment that the destructor will restore.
Definition: action.h:24
bool enable_float_traps(int)
Fallback that fails to set the trap.
Definition: fpenvironment.h:40
void without_float_traps(F &&f)
Convenience function to create a scope where all floating point traps are disabled.
void setup_default_float_traps()
Setup the floating-point traps used throughout SMASH.