ATLAS Offline Software
Toggle main menu visibility
Loading...
Searching...
No Matches
Control
AthenaServices
src
FPEControlSvc.cxx
Go to the documentation of this file.
1
/*
2
Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3
*/
10
11
#include "
FPEControlSvc.h
"
12
#include "
AthenaKernel/errorcheck.h
"
13
#include <fenv.h>
14
#include <cstring>
15
16
22
FPEControlSvc::FPEControlSvc
(
const
std::string& name, ISvcLocator* svc )
23
:
AthService
( name, svc ),
24
m_toolSvc
(
"ToolSvc"
, name),
25
m_env
(),
26
m_haveEnv
(false),
27
m_enabled
(0),
28
m_disabled
(0),
29
m_removeInFinalize
(false),
30
m_feSetRounding
(
""
)
31
{
32
declareProperty(
"Exceptions"
,
m_exceptions
);
33
declareProperty(
"ToolSvc"
,
m_toolSvc
);
34
declareProperty(
"FERoundingMode"
,
m_feSetRounding
);
35
m_exceptions
.declareUpdateHandler (&
FPEControlSvc::prophand
,
this
);
36
37
// Set up the default exceptions.
38
std::vector<std::string> defexc;
39
defexc.push_back (
"invalid"
);
40
defexc.push_back (
"divbyzero"
);
41
defexc.push_back (
"overflow"
);
42
m_exceptions
= defexc;
43
}
44
45
49
StatusCode
FPEControlSvc::initialize
()
50
{
51
// And change the exception mask.
52
prophand
(
m_exceptions
);
53
54
// Add ourself as an observer.
55
ATH_CHECK
(
m_toolSvc
.retrieve() );
56
m_toolSvc
->registerObserver (
this
);
57
58
if
(
m_feSetRounding
!=
""
)
59
{
60
ATH_MSG_INFO
(
"FE Rounding mode {} requested"
,
m_feSetRounding
);
61
if
(
m_feSetRounding
==
"FE_TONEAREST"
)
62
{
63
if
( fesetround(FE_TONEAREST) )
64
ATH_MSG_WARNING
(
"Couldn't change FE Rounding to mode FE_TONEAREST !"
);
65
}
66
else
if
(
m_feSetRounding
==
"FE_UPWARD"
)
67
{
68
if
( fesetround(FE_UPWARD) )
69
ATH_MSG_WARNING
(
"Couldn't change FE Rounding to mode FE_UPWARD !"
);
70
}
71
else
if
(
m_feSetRounding
==
"FE_DOWNWARD"
)
72
{
73
if
( fesetround(FE_DOWNWARD) )
74
ATH_MSG_WARNING
(
"Couldn't change FE Rounding to mode FE_DOWNWARD !"
);
75
}
76
else
if
(
m_feSetRounding
==
"FE_TOWARDZERO"
)
77
{
78
if
( fesetround(FE_TOWARDZERO) )
79
ATH_MSG_WARNING
(
"Couldn't change FE Rounding to mode FE_TOWARDZERO !"
);
80
}
81
else
82
ATH_MSG_WARNING
(
"Don't know FE Rounding to mode {}"
,
m_feSetRounding
);
83
}
84
85
return
StatusCode::SUCCESS;
86
}
87
88
92
StatusCode
FPEControlSvc::finalize
()
93
{
94
// remove only if requested
95
if
(
m_removeInFinalize
)
96
{
97
// Restore the FP environment to what is was before we ran.
98
fesetenv (&
m_env
);
99
}
100
101
return
StatusCode::SUCCESS;
102
}
103
104
115
void
FPEControlSvc::onCreate
(
const
IAlgTool*)
116
{
117
setFPU
();
118
}
119
120
121
namespace
{
122
123
128
std::string mask_to_string (
int
mask)
129
{
130
std::string out;
131
if
(mask & FE_INEXACT)
132
out +=
"inexact "
;
133
if
(mask & FE_DIVBYZERO)
134
out +=
"divbyzero "
;
135
if
(mask & FE_UNDERFLOW)
136
out +=
"underflow "
;
137
if
(mask & FE_OVERFLOW)
138
out +=
"overflow "
;
139
if
(mask & FE_INVALID)
140
out +=
"invalid "
;
141
if
(out.size() == 0)
142
out =
"(none) "
;
143
return
out;
144
}
145
146
147
}
// anonymous namespace
148
149
153
void
FPEControlSvc::prophand
(Gaudi::Details::PropertyBase&
/*prop*/
)
154
{
155
if
(!
m_haveEnv
) {
156
// Save the current FP environment.
157
fegetenv (&
m_env
);
158
m_haveEnv
=
true
;
159
}
160
else
{
161
// Reset to the FP environment before we started.
162
fesetenv (&
m_env
);
163
}
164
165
// Figure out which exceptions to enable/disable.
166
m_enabled
= 0;
167
m_disabled
= 0;
168
const
std::vector<std::string>& v =
m_exceptions
.value();
169
for
(
size_t
i = 0; i < v.size(); i++) {
170
bool
onoff =
true
;
171
const
char
* s = v[i].c_str();
172
if
(!s)
continue
;
173
if
(s[0] ==
'!'
) {
174
onoff =
false
;
175
++s;
176
}
177
int
thisexc = 0;
178
if
(strcasecmp (s,
"inexact"
) == 0)
179
thisexc = FE_INEXACT;
180
else
if
(strcasecmp (s,
"divbyzero"
) == 0)
181
thisexc = FE_DIVBYZERO;
182
else
if
(strcasecmp (s,
"underflow"
) == 0)
183
thisexc = FE_UNDERFLOW;
184
else
if
(strcasecmp (s,
"overflow"
) == 0)
185
thisexc = FE_OVERFLOW;
186
else
if
(strcasecmp (s,
"invalid"
) == 0)
187
thisexc = FE_INVALID;
188
else
{
189
ATH_MSG_INFO
(
"Unknown exception name: {}"
, v[i] );
190
continue
;
191
}
192
193
if
(onoff) {
194
m_enabled
|= thisexc;
195
m_disabled
&= ~thisexc;
196
}
197
else
{
198
m_disabled
|= thisexc;
199
m_enabled
&= ~thisexc;
200
}
201
}
202
203
// Say what we're doing, and change the masks.
204
REPORT_MESSAGE
(MSG::INFO)
205
<<
"Enable: "
<< mask_to_string (
m_enabled
)
206
<<
"Disable: "
<< mask_to_string (
m_disabled
);
207
208
setFPU
();
209
}
210
211
215
void
FPEControlSvc::setFPU
()
216
{
217
feclearexcept (
m_enabled
);
218
#ifdef __GLIBC__
219
feenableexcept (
m_enabled
);
220
fedisableexcept (
m_disabled
);
221
#elif defined __APPLE__
222
#include "
CxxUtils/excepts.h
"
223
feenableexcept (
m_enabled
);
224
fedisableexcept (
m_disabled
);
225
#else
226
// The functions above are gnu-specific.
227
// Without GNU, we do it the harder way.
228
fenv_t newval;
229
fegetenv(&newval);
230
231
// CSR bit on means that the exception is masked.
232
233
newval.__control_word &=
~m_enabled
;
234
newval.__control_word |=
m_disabled
;
235
# ifdef __x86_64
236
// SSE floating point uses separate exception masks.
237
newval.__mxcsr &= (
~m_enabled
) << 7;
238
newval.__mxcsr |= (
m_disabled
) << 7;
239
# endif
240
fesetenv(&newval);
241
#endif
242
}
ATH_CHECK
#define ATH_CHECK
Evaluate an expression and check for errors.
Definition
AthCheckMacros.h:40
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x,...)
Definition
AthMsgStreamMacros.h:46
ATH_MSG_INFO
#define ATH_MSG_INFO(x,...)
Definition
AthMsgStreamMacros.h:45
errorcheck.h
Helpers for checking error return status codes and reporting errors.
REPORT_MESSAGE
#define REPORT_MESSAGE(LVL)
Report a message.
Definition
Control/AthenaKernel/AthenaKernel/errorcheck.h:365
FPEControlSvc.h
Service to enable or disable floating-point exceptions.
AthService::AthService
AthService()
FPEControlSvc::m_toolSvc
ServiceHandle< IToolSvc > m_toolSvc
Tool service.
Definition
FPEControlSvc.h:80
FPEControlSvc::m_disabled
int m_disabled
Mask of disabled exceptions.
Definition
FPEControlSvc.h:92
FPEControlSvc::m_haveEnv
bool m_haveEnv
Flag that we've retrieved the environment.
Definition
FPEControlSvc.h:86
FPEControlSvc::m_feSetRounding
std::string m_feSetRounding
flag to decide on rounding mode (for stability tests)
Definition
FPEControlSvc.h:98
FPEControlSvc::setFPU
void setFPU()
Set the FPU exception masks from m_enabled and m_disabled.
Definition
FPEControlSvc.cxx:215
FPEControlSvc::prophand
void prophand(Gaudi::Details::PropertyBase &prop)
Property change handler.
Definition
FPEControlSvc.cxx:153
FPEControlSvc::m_removeInFinalize
bool m_removeInFinalize
boolean to decide to (not) remove the observer in finalize
Definition
FPEControlSvc.h:95
FPEControlSvc::m_exceptions
StringArrayProperty m_exceptions
Property specifying the desired exception mask.
Definition
FPEControlSvc.h:77
FPEControlSvc::m_enabled
int m_enabled
Mask of enabled exceptions.
Definition
FPEControlSvc.h:89
FPEControlSvc::finalize
virtual StatusCode finalize()
Standard finalize method.
Definition
FPEControlSvc.cxx:92
FPEControlSvc::FPEControlSvc
FPEControlSvc(const std::string &name, ISvcLocator *svcloc)
Constructor.
Definition
FPEControlSvc.cxx:22
FPEControlSvc::onCreate
virtual void onCreate(const IAlgTool *)
Called after each tool has been created.
Definition
FPEControlSvc.cxx:115
FPEControlSvc::initialize
virtual StatusCode initialize()
Standard initialize method.
Definition
FPEControlSvc.cxx:49
FPEControlSvc::m_env
fenv_t m_env
The FP environment before we initialize.
Definition
FPEControlSvc.h:83
excepts.h
Declarations of feenableexcept()/fedisableexcept() functions for MacOSX.
Generated on
for ATLAS Offline Software by
1.17.0