LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
FloatingPointControl.cc
Go to the documentation of this file.
2 // vim: set sw=2 expandtab :
3 
6 
7 using namespace std;
8 using namespace art::fp_detail;
9 
10 namespace art {
11 
12  namespace {
13 
14  void
15  echoState()
16  {
17  auto const femask{getFPCW()};
18  mf::LogVerbatim("FPE_Enable")
19  << "Floating point exception mask is " << std::showbase << std::hex
20  << femask << "\tDivByZero exception is"
21  << on_or_off(femask & FE_DIVBYZERO) << "\tInvalid exception is"
22  << on_or_off(femask & FE_INVALID) << "\tOverFlow exception is"
23  << on_or_off(femask & FE_OVERFLOW) << "\tUnderFlow exception is"
24  << on_or_off(femask & FE_UNDERFLOW);
25  }
26 
27  } // unnamed namespacde
28 
29  FloatingPointControl::FloatingPointControl(Parameters const& c,
30  ActivityRegistry& reg)
31  : enableDivByZeroEx_{c().enableDivByZeroEx()}
32  , enableInvalidEx_{c().enableInvalidEx()}
33  , enableOverFlowEx_{c().enableOverFlowEx()}
34  , enableUnderFlowEx_{c().enableUnderFlowEx()}
35  , setPrecisionDouble_{c().setPrecisionDouble()}
36  , reportSettings_{c().reportSettings()}
38  {
39  reg.sPostEndJob.watch(this, &FloatingPointControl::postEndJob);
40  if (reportSettings_) {
41  mf::LogVerbatim("FPE_Enable") << "\nOS's FP settings";
42  echoState();
43  }
44  // Update the state according to the user's configuration
45  {
46  // NB: We do not let users configure signaling of denormalized operand
47  // (fpControl_DENORMALOPERAND) or inexact (FE_INEXACT), both of which
48  // are suppressed.
49  unsigned short int enable_except{};
50  unsigned short int enable_sse{};
51  if (enableDivByZeroEx_) {
52  enable_except |= FE_DIVBYZERO;
53  enable_sse |= fpControl_ZM_MASK;
54  }
55  if (enableInvalidEx_) {
56  enable_except |= FE_INVALID;
57  enable_sse |= fpControl_IM_MASK;
58  }
59  if (enableOverFlowEx_) {
60  enable_except |= FE_OVERFLOW;
61  enable_sse |= fpControl_OM_MASK;
62  }
63  if (enableUnderFlowEx_) {
64  enable_except |= FE_UNDERFLOW;
65  enable_sse |= fpControl_UM_MASK;
66  }
67  auto fpControl = getFPControl();
68  // Reset exception mask before clearing the bits we care about.
69  fpControl.fpcw = (fpControl.fpcw | FE_ALL_EXCEPT) & (~enable_except);
70  if (setPrecisionDouble_) {
71  // Clear precision bits before setting only the ones we care about.
72  fpControl.fpcw =
73  (fpControl.fpcw & (~fpControl_ALL_PREC)) | fpControl_DOUBLE_PREC;
74  }
75 #ifdef fpControl_HAVE_MXCSR
76  // Reset exception mask before clearing the bits we care about.
77  fpControl.mxcsr =
78  (fpControl.mxcsr | fpControl_ALL_SSE_EXCEPT) & (~enable_sse);
79 #endif
80  // Write back.
81  (void)setFPControl(fpControl);
82  }
83  if (reportSettings_) {
84  mf::LogVerbatim("FPE_Enable")
85  << "\nUpdated FP settings per user's configuration";
86  if (reportSettings_) {
87  echoState();
88  }
89  }
90  }
91 
92  void
94  {
95  (void)setFPControl(OSdefault_);
96  if (reportSettings_) {
97  mf::LogVerbatim("FPE_Enable") << "\nRestored to OS's FPE settings";
98  echoState();
99  }
100  }
101 
102  auto
104  {
105  return static_cast<precision_t>(getFPCW() & fpControl_ALL_PREC);
106  }
107 
108  auto
110  {
111  return static_cast<mask_t>(getFPCW() & FE_ALL_EXCEPT);
112  }
113 
114 } // namespace art
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
fp_detail::fp_control_t OSdefault_
STL namespace.
precision_t getPrecision() const
char const * on_or_off(bool const b)
Definition: fpControl.h:154
fpcw_t getFPCW()
Definition: fpControl.cc:28
Definition: MVAAlg.h:12
fp_control_t getFPControl()
Definition: fpControl.h:130
fp_control_t setFPControl(fp_control_t const &fpControl)
Definition: fpControl.h:142