feexceptErsatz.H
Go to the documentation of this file.
1 // ============================================================================
2 // Generic handling of floating point exceptions
3 //
4 // 2018 Alexey Matveichev
5 // 2021 Tatsuya Shimizu - ARM64 support
6 // ----------------------------------------------------------------------------
7 //
8 // Original Author
9 // David N. Williams
10 //
11 // License
12 // Public Domain
13 //
14 // Description
15 // Alternate, nondefault handling of IEEE 754 floating-point exceptions
16 // in OS X, based on the GNU functions feenableexcept(), fedisableeexcept()
17 // and fegetexcept() [in libm]
18 //
19 // http://www-personal.umich.edu/~williams/archive/computation/fe-handling-example.c
20 // ============================================================================
21 
22 #ifndef feexceptErsatz_H
23 #define feexceptErsatz_H
24 
25 #ifdef __APPLE__
26 #include <fenv.h>
27 
28 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
29 
30 inline int feenableexcept(unsigned int excepts)
31 {
32  static fenv_t fenv;
33  unsigned int new_excepts = excepts & FE_ALL_EXCEPT;
34  unsigned int old_excepts; // previous masks
35 
36  if (fegetenv(&fenv))
37  {
38  return -1;
39  }
40 
41 #if defined __arm64__
42  old_excepts = fenv.__fpcr & FE_ALL_EXCEPT;
43 #else
44  old_excepts = fenv.__control & FE_ALL_EXCEPT;
45 #endif
46 
47  // unmask
48 #if defined __arm64__
49  fenv.__fpcr &= ~new_excepts;
50  fenv.__fpsr &= ~(new_excepts << 7);
51 #else
52  fenv.__control &= ~new_excepts;
53  fenv.__mxcsr &= ~(new_excepts << 7);
54 #endif
55 
56  return fesetenv(&fenv) ? -1 : old_excepts;
57 }
58 
59 
60 inline int fedisableexcept(unsigned int excepts)
61 {
62  static fenv_t fenv;
63  unsigned int new_excepts = excepts & FE_ALL_EXCEPT;
64  unsigned int old_excepts; // all previous masks
65 
66  if (fegetenv(&fenv))
67  {
68  return -1;
69  }
70 
71 #if defined __arm64__
72  old_excepts = fenv.__fpcr & FE_ALL_EXCEPT;
73 #else
74  old_excepts = fenv.__control & FE_ALL_EXCEPT;
75 #endif
76 
77  // mask
78 #if defined __arm64__
79  fenv.__fpcr |= new_excepts;
80  fenv.__fpsr |= new_excepts << 7;
81 #else
82  fenv.__control |= new_excepts;
83  fenv.__mxcsr |= new_excepts << 7;
84 #endif
85 
86  return fesetenv(&fenv) ? -1 : old_excepts;
87 }
88 
89 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
90 
91 #endif // __APPLE__
92 #endif
93 
94 // ************************************************************************* //