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
30inline 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
60inline 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// ************************************************************************* //