Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does C standard's FE_TONEAREST rounding mode guarantee that halfway ties are rounded to even?

I am writing code that depends on halfway ties in C (specifically c11) rounding to even. When using rint with rounding mode as FE_TONEAREST, I have not found a guarantee in the C standard that states how ties are handled with FE_NEAREST. Page 509 of the ISO C standard states that

The fegetround and fesetround functions in <fenv.h> provide the facility to select among the IEC 60559 directed rounding modes represented by the rounding direction macros in <fenv.h> (FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO) and the values 0, 1, 2, and 3 of FLT_ROUNDS are the IEC 60559 directed rounding modes.

However, I cannot find any documentation in the IEC 60559 standard for rounding modes. While on my test machine, the behavior is that in FE_TONEAREST, ties are rounded to even, I want to be sure that this is enforced by the c11 standard and is not implementation defined.

like image 555
Benjie Avatar asked Sep 28 '21 16:09

Benjie


1 Answers

C11 Annex F says, in §F.1:

The IEC 60559 floating-point standard is specifically Binary floating-point arithmetic for microprocessor systems, second edition (IEC 60559:1989) [...]

and then later, in §F.3, paragraph 1 (as you already quoted in the question):

The fegetround and fesetround functions in <fenv.h> provide the facility to select among the IEC 60559 directed rounding modes represented by the rounding direction macros in <fenv.h> (FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO) and the values 0, 1, 2, and 3 of FLT_ROUNDS are the IEC 60559 directed rounding modes.

(Note: to be precise, I'm looking at the publicly available N1570 final draft for the C11 standard, but my understanding is that it's essentially identical to the final standard.)

So the reference to IEC 60559 here is actually a reference to the (now twice superseded) IEC 60559:1989 standard. I don't have access to that precise standard, but I do have a copy of IEEE 754-1985, and I believe that the content of those two standards (IEC 60559:1989 and IEEE 754-1985) is supposed to be essentially identical, though I observe that there are at least differences in capitalisation in the tables of contents of the respective standards. (Thanks to Michael Burr for confirming in a comment that the standards are identical in substance, if not word-for-word identical.)

IEEE 754-1985, in section 4, defines four rounding modes, which it terms "round to nearest", "round toward +∞", "round toward -∞", and "round toward zero". The latter three are described as "directed rounding modes". For "round to nearest" we have in §4.1 the text:

if the two nearest representable values are equally near, the one with its least significant bit zero shall be delivered

In other words, it's describing round-ties-to-even. (Later versions of the IEEE 754 standard introduce the names "roundTiesToEven", "roundTowardPositive", "roundTowardNegative" and "roundTowardZero" for the above rounding modes (now termed "attributes" rather than "modes", I believe because "mode" suggests some kind of persistent environmental setting), and define a fifth rounding attribute "roundTiesToAway". But C11 is explicit that it's referring to this earlier version of the standard.)

Now since C11 doesn't use the exact same terms as IEEE 754-1985, it's left to us to infer that the four rounding modes above correspond to "FE_TONEAREST", "FE_UPWARD", "FE_DOWNWARD" and "FE_TOWARDZERO", in that order, but there doesn't seem to be any reason to doubt that that's the intended matching. So assuming __STDC_IEC_559__ is defined, FE_TONEAREST should indeed correspond to "roundTiesToEven". Nate Eldredge's comment about C2x further reinforces that this is the intended matching.

So all in all, it's clear (to me at least) that the intent is that when __STDC_IEC_559__ is defined, the rounding mode FE_TONEAREST should correspond to "round to nearest", named in later versions of the IEEE 754 standard as "roundTiesToEven". The degree to which implementations of C honour that intent is, of course, a separate question (but I'd expect the vast majority of them to do so).

like image 70
Mark Dickinson Avatar answered Oct 25 '22 01:10

Mark Dickinson