<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;"><div><font size="2" face="Arial">This is an unfortunately late response to the discussion in the CFP thread, “Floating point rounding modes”. </font></div><div><font size="2" face="Arial"><br></font></div><div><font size="2" face="Arial">Below are thoughts about the 7 bullets in the Introduction in <a href="https://isocpp.org/files/papers/P2746R0.pdf" style="font-weight: bold; color: rgb(149, 79, 114);">https://isocpp.org/files/papers/P2746R0.pdf</a>, and other comments about the proposal and issues discussed in the thread. </font></div><div><br></div><div><font face="Arial" size="2">- Jim Thomas</font></div><div><font face="Arial" size="2"><br></font></div><blockquote type="cite"><div><font size="2" face="Arial">Introduction </font></div><div><font size="2" face="Arial"><br></font></div><blockquote type="cite"></blockquote></blockquote><blockquote type="cite"><div><font size="2" face="Arial">Currently floating point rounding modes are specified either dynamically, through the floating-point environment via fesetround() or, in C, statically, via #pragma STDC FENV_ROUND. As far as we can tell, fesetround(), in spite of its long history, has very few real use cases, and those are either not fully correct, or not portable across common implementations. There are many reasons for this:</font></div><div><font face="Arial" size="2"><br></font></div><div><p class="MsoNormal" style="margin: 0in;"><b><font size="2" face="Arial"> </font></b><span style="font-family: Arial; font-size: small;">1. Implementations can't be counted on to implement it correctly. Without the FENV_ACCESS pragma, compilers perform optimizations that do not preserve rounding behavior.</span><span style="font-family: Arial; font-size: small;"> </span><i><font size="2" face="Arial">That fenv.h pragma is explicitly not required to be supported in C++, and hence C++ provides no guarantee that fesetround() behaves reasonably.</font></i></p><p class="MsoNormal" style="margin: 0in;"><span style="font-family: Arial; color: rgb(192, 0, 0);"><br></span></p><p></p></div></blockquote><div><span style="font-family: Arial;">Some compilers also perform optimizations that don’t honor other language semantics (e.g. they reassociate, replace division by multiplication, distribute * over +, skip conversions). There’s a general problem of aligning optimizations and strict floating-point semantics. </span></div><div><p class="MsoNormal" style="margin: 0in;"><br></p><blockquote type="cite"><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial">2. In practice, it seems to be inconsistent, and somewhat unpredictable, what calls to standard math functions, and even more so, user-defined functions, do when invoked with non-standard rounding modes. (This is based on looking at some implementations. I didn't study this systematically) </font></p></blockquote><div><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial"><br></font></p></div><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial">C (even with Annex F support for IEC 60559) does not require all standard math function to honor rounding directions. This reflects history and the state of the art. The correctly rounded math functions for which C reserves cr_ prefix names are required to honor rounding directions. Regarding user-defined functions, see 7.6 #4 (in e.g. C23 draft N3054).<o:p></o:p></font></p><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial"><br></font></p><blockquote type="cite"><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial">3. If you really need to control rounding to guarantee specific properties of the result, rounding modes cannot just be specified for a region of code; they need to be carefully applied to each operation. </font><span style="font-family: Arial; font-size: small;">(What does it mean to set the rounding mode for cos(a + b)?)</span></p></blockquote><div><p class="MsoNormal" style="margin: 0in;"><span style="font-family: Arial; font-size: small;"><br></span></p></div><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial">This isn’t generally true. For example, an accumulated sum of squares can be computed with just one specification of the rounding direction. </font></p><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial"> <o:p></o:p></font></p><blockquote type="cite"><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial">4. As Jim Thomas points out, you could try to get some idea of floating point errors by trying with different rounding modes. But, by the same argument as (3), that seems to be at best a little better than randomly perturbing the results. And the whole approach can break either because the program logic relies on rounding mode, or if the code itself sets the rounding mode. </font></p></blockquote><div><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial"><br></font></p></div><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial">The technique I mentioned, and alternatives, are discussed at length by W Kahan in <a href="http://people.eecs.berkeley.edu/~wkahan/Mindless.pdf">http://people.eecs.berkeley.edu/~wkahan/Mindless.pdf</a>, which concludes</font></p><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial"> <o:p></o:p></font></p><p class="MsoNormal" style="margin: 0in 0in 0in 0.5in;"><font size="2" face="Arial">“At present only the second of the five schemes explored in these notes offers an economical way to diagnose anomalies caused by roundoff in precompiled software: Rerun the suspected module with exactly the same input but with default roundings (those not already directed by the author of the module) redirected. Though far from foolproof, this scheme has worked on over-zealous optimization in §3, on intermediate iterates xn in §5, on T(§6), on MATLAB’s log2(§7), acosh(§8) and acos(§8), on Gaussian Elimination (§9), on step H(§10) , on subtended angle ψ(§11), on subspace(§12) and on innumerable other examples upon which nothing else so inexpensive could possibly have worked so well.”<o:p></o:p></font></p><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial"><br></font></p><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial">The quote is in the context of debuggers, but the preferred technique is available to anyone who has the code they are debugging, provided dynamic rounding modes are available.<o:p></o:p></font></p><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial"><span style="color: rgb(192, 0, 0);"><br></span></font></p><blockquote type="cite"><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial">5. Compilers seem to commonly ignore rounding modes for compile-time evaluations, making it very hard for the programmer to predict what they are actually getting. (This is my reading anyway, though the current C standard seems to say otherwise?) </font></p></blockquote><div><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial"><br></font></p></div><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial">The intention in C (with Annex F) is that compile-time arithmetic is fully specified. Annex F supports </font><span style="font-family: Arial; font-size: small;">IEC 60559</span><font size="2" face="Arial">. The general C specification for floating point gives great flexibility to the implementation, largely to avoid breaking existing (including non portable) code.<o:p></o:p></font></p><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial"><span style="color: rgb(192, 0, 0);"><br></span></font></p><blockquote type="cite"><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial">6. If we really wanted to use rounding modes to bound results, constants would also have to be rounded according to the current rounding mode. This is explicitly disallowed, even by C: "All floating constants of the same source form(79) shall convert to the same internal format with the same value.” </font></p></blockquote><div><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial"><br></font></p></div><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial">This quote was a holdover from before static rounding modes (via rounding pragmas) were introduced for C23. It has been changed to reflect that static rounding modes do affect constants.<o:p></o:p></font></p><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial"><span style="color: rgb(192, 0, 0);"><br></span></font></p><blockquote type="cite"><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial">7. Especially in C++, it is unclear what the rounding modes mean for operations that are not correctly rounded to start with. Although IEEE requires correct rounding, basically no standard library implementations conform. </font></p></blockquote><div><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial"><br></font></p></div><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial">Right. But I don’t think this is relevant. The same situation will exist unless or until practical correctly-rounded versions of all the math functions are implemented and adopted—regardless of how rounding modes are supported. Quality implementations endeavor to honor (in one sense or another) the direction of directed rounding modes, along with other properties not required by C, like monotonicity, symmetry, and nearly correct rounding. <o:p></o:p></font></p><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial"><br></font></p><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial">General comments</font></p><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial"><br></font></p><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial">a. Would all the proposed functions raise floating-point exceptions (as required by </font><span style="font-family: Arial; font-size: small;">IEC 60559</span><font size="2" face="Arial">)? Could the current C features for test/clear/get/set exceptions be used? That would seem to defeat the goal of context independence. How would an over-aggressive optimizer be prevented from moving the function calls across accesses to the exception flags? With the current approach, if FENV_ACCESS is not “on”, optimizers are free to move the calls and do other transformations without regard to the floating-point environment, and even use faster versions of the functions that don’t raise exception “correctly”. A functions approach would need to include a way of managing exceptions, or say exceptions are not supported.</font></p><p class="MsoNormal" style="margin: 0in;"><font size="2" face="Arial"><br></font></p><p class="MsoNormal" style="margin: 0in;"><font face="Arial" size="2">b. The functions approach wouldn't satisfy the </font><span style="font-family: Arial; font-size: small;">IEC 60559</span><font face="Arial" size="2"> requirement for static rounding attributes, which apply to a program block. An IEEE 754 revision committee seems like an important forum for evaluating such a proposal. Note that CFP's role is to fit IEC 60559 as-is into C.</font></p><p class="MsoNormal" style="margin: 0in;"><font face="Arial" size="2"><br></font></p><p class="MsoNormal" style="margin: 0in;"><font face="Arial" size="2">c. Another consideration is performance. It would depend on how rounding modes are handled by the underlying hardware. If only dynamic rounding is supported in hardware, then how would the functions be implemented? Presumably, at some level with save/set/restore dynamic rounding mode. There’d still the performance overhead of dynamic modes plus a function call, for every operation. Inlining might allow some optimization but the functions approach is conceived to avoid bad optimization which inlining might facilitate.</font></p><p class="MsoNormal" style="margin: 0in;"><font face="Arial" size="2"><br></font></p><p class="MsoNormal" style="margin: 0in;"><font face="Arial" size="2">d. Part of the email discussion was about how code might look when written with the proposed functions vs with C23 static modes. For another example, h</font>ow would the functions approach look for</p><div><br></div><div>float z, x;</div><div>{</div><div>#pragma STDC FENV_ROUND FE_TOWARDZERO</div><div>z = x + 0.1;</div><div>}</div><div><br></div><div>This involves a translation-time evaluation of 0.1, a conversion of x to double, an add, and a conversion to float.</div><div><br></div><div><div>At this point, the proposal seems more for a direction than for a specific feature. It’s hard to really evaluate how it would be to write and read code without a more specific interface and details about what is or is not allowed.<span style="font-family: Arial; font-size: small;"> </span></div><div><br></div></div><div>e. How would the functions approach fit with the various evaluation methods C allows? Would there be functions to evaluate to wider formats?  I<span style="font-family: Arial; font-size: small;">EC 60559 recommends (block scoped) preferredWidthFormat attributes which specify the evaluation method (in C terminology). These are not supported in C23, but are in IEC TS 18661-5.</span></div><div><br></div><div>f. In [Cfp-interest 2638] is</div><div><br></div><div><blockquote type="cite"><pre style="margin: 0in 0in 0.0001pt; font-size: 10pt; font-family: "Courier New";"><span style="font-family: Arial, sans-serif;">The potential advantage of the functional notation is that it's much less<o:p></o:p></span></pre><pre style="margin: 0in 0in 0.0001pt; font-size: 10pt; font-family: "Courier New";"><span style="font-family: Arial, sans-serif;">intrusive on the implementation, though in C that argument may apply mostly<o:p></o:p></span></pre><pre style="margin: 0in 0in 0.0001pt; font-size: 10pt; font-family: "Courier New";"><span style="font-family: Arial, sans-serif;">to the version of the proposal that does not introduce a new type. We're<o:p></o:p></span></pre><pre style="margin: 0in 0in 0.0001pt; font-size: 10pt; font-family: "Courier New";"><span style="font-family: Arial, sans-serif;">potentially just adding some library code.<o:p></o:p></span></pre><pre style="margin: 0in 0in 0.0001pt; font-size: 10pt; font-family: "Courier New";"><span style="font-family: Arial, sans-serif;">AFAICT, a significant problem with the current and proposed facilities is<o:p></o:p></span></pre><pre style="margin: 0in 0in 0.0001pt; font-size: 10pt; font-family: "Courier New";"><span style="font-family: Arial, sans-serif;">that they are so rarely used that implementations commonly don't pay enough<o:p></o:p></span></pre><pre style="margin: 0in 0in 0.0001pt; font-size: 10pt; font-family: "Courier New";"><span style="font-family: Arial, sans-serif;">attention to them. I think many implementations don't properly handle<o:p></o:p></span></pre><pre style="margin: 0in 0in 0.0001pt; font-size: 10pt; font-family: "Courier New";"><span style="font-family: Arial, sans-serif;">FENV_ACCESS correctly, so I have relatively little confidence in<o:p></o:p></span></pre><pre style="margin: 0in 0in 0.0001pt; font-size: 10pt; font-family: "Courier New";"><span style="font-family: Arial, sans-serif;">FENV_ROUND, especially since I think we agree it still doesn't handle<o:p></o:p></span></pre><pre style="margin: 0in 0in 0.0001pt; font-size: 10pt; font-family: "Courier New";"><span style="font-family: Arial, sans-serif;">constants. I also have my doubts about FENV_ROUND in C++. I think there is<o:p></o:p></span></pre><pre style="margin: 0in 0in 0.0001pt; font-size: 10pt; font-family: "Courier New";"><span style="font-family: Arial, sans-serif;">currently not even a proposal to add it there?<o:p></o:p></span></pre></blockquote></div><div><br></div><blockquote type="cite" style="color: rgb(0, 0, 0);"><div></div></blockquote><p class="MsoNormal" style="margin: 0in;"><font face="Arial" size="2">Yes, the functions are less intrusive on the compiler implementation, assuming no new types. </font></p><p class="MsoNormal" style="margin: 0in;"><font face="Arial" size="2"><br></font></p><p class="MsoNormal" style="margin: 0in;"><font face="Arial" size="2">Partly it’s a “Which comes first: the chicken or the egg?” problem. Implementations don’t invest in features that aren’t used, and users don’t use features that aren’t well implement. But I think there are other reason too, maybe for discussion at another time.</font></p><p class="MsoNormal" style="margin: 0in;"><font face="Arial" size="2"><br></font></p><p class="MsoNormal" style="margin: 0in;"><font face="Arial" size="2">As noted above, FENV_ROUND does handle constants.</font></p><p class="MsoNormal" style="margin: 0in;"><font face="Arial" size="2"><br></font></p><p class="MsoNormal" style="margin: 0in;"><font face="Arial" size="2">g. </font><span style="font-family: Arial; font-size: small;">I think it’s difficult to assess how much a standard feature is used.</span><font face="Arial" size="2"> There have been statements like, AFAICT feature x is not implement/used. Do these assessments cover the range of C compilers and users (proprietary, university, etc.)? The proprietary compiler I last worked with (as a numerics engineer) had an excellent implementation of the C features for the floating-point environment. </font></p><p class="MsoNormal" style="margin: 0in;"><br></p></div><p class="MsoNormal" style="margin: 0in; font-size: medium; font-family: "Times New Roman", serif;"><b><span style="font-size: 10pt; font-family: Arial, sans-serif;"><o:p></o:p></span></b></p></body></html>