I've got some piece of code calculating a vector of functions of a vector of independent variables (and parameters):
struct instance
{ double m_adParam1, m_adParam2;
std::array<double, OUTSIZE> calculate(const std::array<double, INSIZE>&x) const;
};
When any part of this code fails due to a division by (nearly) zero or due to a domain error, the entire code should fail and tell the caller, that it cannot calculate this function for the given input.
This should also apply for calculated values used for comparison only. So testing the result vector for NAN or infinity is not sufficient. Inserting tests after every fallible operation is infeasible.
How could one do this?
I read about fetestexcept(). But it is unclear what is resetting this state flag. SIGFPE is useless for anything other than debugging. Having the ability to convert this into C++ exceptions as on Windows would be great, but inserting a final check would be sufficient as well.
Inserting code to check for invalid inputs for the following code is also infeasible, as it would slow down the calculation dramatically.
I read about fetestexcept(). But it is unclear what is resetting this state flag.
That is what feclearexcept()
does. So you can do something like
std::feclearexcept(FE_INVALID | FE_OVERFLOW | FE_DIVBYZERO);
// do lots of calculations
// now check for exceptions
if (std::fetestexcept(FE_INVALID))
throw std::domain_error("argh");
else if (std::fetestexcept(FE_OVERFLOW))
throw std::overflow_error("eek");
// ...
The exception flags are "sticky" and no other operation, besides an explicit feclearexcept()
, should clear them.
The main benefits of using feenablexcept()
to force a SIGFPE are that you would detect the error immediately, without waiting until you happen to get around to testing the exception flag, and that you could pinpoint the exact instruction that caused the exception. It doesn't sound like either of those are needed in your use case.