Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accounting for rounding mode in a constexpr function

I am trying to write a constexpr version of the exp function. I know that

  • The algorithm I'm using is designed for FE_TONEAREST rounding
  • Since C++11, it's possible to change the rounding mode via fesetround( int round ) (provided that #pragma STDC FENV_ACCESS is supported and is set to ON)
  • I am not allowed to call the non-constexpr function fesetround(int) within my own constexpr function

If my understanding is correct, this means that (within a compiler that supports #pragma STDC FENV_ACCESS), a user would be allowed to set the rounding mode before calling my function, but my function would not be allowed to un-do this change (even temporarily) and could therefore be excuted with the wrong rounding mode.

The best option that I can come up with for handling this is to have two functions:

  • Version A is marked constexpr and does not set the rounding mode
  • Version B is not marked constexpr and does 3 things:
    1. Set the rounding mode to FE_TONEAREST
    2. Call Version A
    3. Reset the rounding mode
    4. Return the result of Version A

To set a constexpr variable, one would have to call version A, but it would always be evaluated as though the rounding mode were FE_TONEAREST since (according to cppreference):

The current rounding mode does NOT affect .... results of floating-point arithmetic operators in constant expressions (always to nearest)

In non-constexpr contexts, Version A and Version B would agree so long as the rounding mode were FE_TONEAREST, but Version B would provide a superior result for any other rounding mode. The onus would be on the user to either use FE_TONEAREST rounding or make sure to call Version B.

Is there a better way of handling this, within standard C++? ... or does the standard have other things to say about rounding modes which make this entire question moot?

Edit: My goal isn't to respect the rounding mode; it's to ignore it so that the function's accuracy is consistent. I would prefer to use only Version B, but it's not possible to change the rounding mode in a constexpr function.

like image 241
user1476176 Avatar asked Feb 13 '26 03:02

user1476176


1 Answers

The FENV_ACCESS feature provided by C and C++ is a kludge and does not support the use sought in this question. Programs that modify the rounding mode are rare, and language support for them is poor.

Per the C standard (and inherited by C++ by reference), FENV_ACCESS informs the implementation the program might run under non-default floating-point control modes. If you allow your exp function to be called while in a non-default mode and it is not translated with FENV_ACCESS on, the standards do not tell us what the behavior will be.

Further, C++ does not provide any means by which different versions of a routine would be automatically called depending on the rounding mode or the state of FENV_ACCESS (although C++ implementations might do so as an extension to the language).

The statement you refer to from cppreference that the rounding mode does not affect arithmetic operations in constant expressions appears to be a conclusion derived by cppreference, not something explicitly stated in the C++ standard. Perhaps it follows from the fact that constant expressions are evaluated at translation time, so no modification of the floating-point environment could have been performed. However, it is not clear to me this is completely guaranteed by the standard—a note in the expr.const section says “Constant expressions can be evaluated during translation.” It does not say they must be evaluated during translation.

Generally, one would not want exp to behave the same way when the rounding mode is to-nearest as when it is toward-infinity or another setting. Instead, one would want exp to return a rounded-up result when the mode is toward-infinity, rounded-down when the mode is toward-negative-infinity, and rounded toward zero when the mode is toward-zero. (Obtaining these results requires having different implementations of exp for each mode, since merely applying rounding to each operation it does would not produce the required result.) So your request that exp return the same result regardless of rounding mode is a bit unusual. What purpose does it serve to return a rounded-to-nearest result when the program is evaluating floating-point operations with a different rounding mode? If a program is using toward-infinity to try to calculate an upper bound, a to-nearest exp would break that calculation.

like image 145
Eric Postpischil Avatar answered Feb 15 '26 16:02

Eric Postpischil



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!