FloatExceptions.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // Copyright (c) 2012 Cygnus Software
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy of
  4. // this software and associated documentation files (the "Software"), to deal in
  5. // the Software without restriction, including without limitation the rights to use,
  6. // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
  7. // Software, and to permit persons to whom the Software is furnished to do so,
  8. // subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included in all
  11. // copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  15. // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  16. // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  17. // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  18. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  19. //
  20. // For more details see the original blog post at:
  21. // http://randomascii.wordpress.com/2012/04/21/exceptional-floating-point/
  22. #ifdef _WIN32
  23. #include <float.h> // For _clearfp and _controlfp_s
  24. //#define ENABLE_FP_EXCEPTIONS 1
  25. // Declare an object of this type in a scope in order to suppress
  26. // all floating-point exceptions temporarily. The old exception
  27. // state will be reset at the end.
  28. // From http://randomascii.wordpress.com/2012/04/21/exceptional-floating-point/
  29. class FPExceptionDisabler
  30. {
  31. public:
  32. FPExceptionDisabler()
  33. {
  34. // Retrieve the current state of the exception flags. This
  35. // must be done before changing them.
  36. _controlfp_s(&mOldValues, 0, 0);
  37. // Set all of the exception flags, which suppresses FP
  38. // exceptions on the x87 and SSE units. _MCW_EM is a bit
  39. // mask representing all available exception masks.
  40. _controlfp_s(0, _MCW_EM, _MCW_EM);
  41. }
  42. ~FPExceptionDisabler()
  43. {
  44. // Clear any pending FP exceptions. This must be done
  45. // prior to enabling FP exceptions since otherwise there
  46. // may be a 'deferred crash' as soon the exceptions are
  47. // enabled.
  48. _clearfp();
  49. // Reset (possibly enabling) the exception status.
  50. _controlfp_s(0, mOldValues, _MCW_EM);
  51. }
  52. private:
  53. unsigned int mOldValues;
  54. // Make the copy constructor and assignment operator private
  55. // and unimplemented to prohibit copying.
  56. FPExceptionDisabler(const FPExceptionDisabler&);
  57. FPExceptionDisabler& operator=(const FPExceptionDisabler&);
  58. };
  59. // Declare an object of this type in a scope in order to enable a
  60. // specified set of floating-point exceptions temporarily. The old
  61. // exception state will be reset at the end.
  62. // This class can be nested.
  63. // From http://randomascii.wordpress.com/2012/04/21/exceptional-floating-point/
  64. class FPExceptionEnabler
  65. {
  66. public:
  67. // Overflow, divide-by-zero, and invalid-operation are the FP
  68. // exceptions most frequently associated with bugs.
  69. FPExceptionEnabler(unsigned int enableBits = _EM_OVERFLOW |
  70. _EM_ZERODIVIDE | _EM_INVALID)
  71. {
  72. // Retrieve the current state of the exception flags. This
  73. // must be done before changing them.
  74. _controlfp_s(&mOldValues, 0, 0);
  75. // Make sure no non-exception flags have been specified,
  76. // to avoid accidental changing of rounding modes, etc.
  77. enableBits &= _MCW_EM;
  78. // Clear any pending FP exceptions. This must be done
  79. // prior to enabling FP exceptions since otherwise there
  80. // may be a 'deferred crash' as soon the exceptions are
  81. // enabled. _MCW_EM is a bit
  82. // mask representing all available exception masks.
  83. _clearfp();
  84. // Zero out the specified bits, leaving other bits alone.
  85. _controlfp_s(0, ~enableBits, enableBits);
  86. }
  87. ~FPExceptionEnabler()
  88. {
  89. // Reset the exception state.
  90. _controlfp_s(0, mOldValues, _MCW_EM);
  91. }
  92. private:
  93. unsigned int mOldValues;
  94. // Make the copy constructor and assignment operator private
  95. // and unimplemented to prohibit copying.
  96. FPExceptionEnabler(const FPExceptionEnabler&);
  97. FPExceptionEnabler& operator=(const FPExceptionEnabler&);
  98. };
  99. #endif