lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lmi] fesetround() requirements and guarantees


From: Vadim Zeitlin
Subject: Re: [lmi] fesetround() requirements and guarantees
Date: Thu, 12 May 2022 16:49:49 +0200

On Thu, 12 May 2022 09:06:42 +0000 Greg Chicares <gchicares@sbcglobal.net> 
wrote:

GC> On 5/11/22 15:30, Vadim Zeitlin wrote:
GC> > On Wed, 11 May 2022 10:52:42 -0400 (EDT) Greg Chicares 
<gchicares@sbcglobal.net> wrote:
GC> [...]
GC> > GC> commit a91cbc67d7479e4b51a268748b9d1dabe2b66806
GC> [...]
GC> >  IMHO these checks would be more readable if we had a materially_less() or
GC> > its moral equivalent under some other name ("substantially_less" 
perhaps?).
GC> > 
GC> > GC> @@ -557,7 +557,12 @@ double Irc7702A::MaxNonMecPremium
GC> > GC>          {
GC> > GC>          if(TestPeriodDur < TestPeriodLen)
GC> > GC>              {
GC> > GC> -            LMI_ASSERT(CumPmts <= CumSevenPP);
GC> > GC> +            // Weird condition--see:
GC> > GC> +            //   
https://lists.nongnu.org/archive/html/lmi/2022-05/msg00006.html
GC> > GC> +            LMI_ASSERT
GC> > GC> +                (  CumPmts <= CumSevenPP
GC> > GC> +                || materially_equal(CumSevenPP, CumPmts)
GC> > GC> +                );
GC> > 
GC> >  And having such function would also allow to put this URL in a single
GC> > place instead of duplicating it wherever it's applicable.
GC> 
GC> True; however, instead of comparing floating-point values more carefully,
GC> the real solution is to compare integral values.

 Yes, absolutely, you won't hear any objections from me to this. But I
suspected, and you confirm, that this would be a bit more difficult to do.

GC> I hope to get to that later in the year; until then, I hesitate to
GC> beautify these ugly workarounds, because they should soon be removed.

 I did try leaving things deliberately ugly in order to force me to fix
them a.s.a.p. in the past but unfortunately this has rarely worked for me
and the end result was that things just remained ugly for a very long time
or maybe ever. You are much more disciplined about it than I am, however,
so I hope this works out for lmi.

GC> But there is one thing I've been tempted to beautify: this block...
GC> 
GC>     // Do not save and restore prior rounding direction, because lmi
GC>     // generally expects rounding to nearest everywhere.
GC>     std::fesetround(FE_TONEAREST);
GC> 
GC> ...preceding every call to std::nearbyint(). Probably that ought to be
GC> factored into a function that could be called instead. But first let me
GC> ask a couple of questions:
GC> 
GC>  - Should the return code be checked? That is, can fesetround() ever
GC>    realistically fail when it's called with one of its predefined macro
GC>    arguments? I tend to think that checking it is useless: if it fails,
GC>    we can't do anything about the failure; and if it fails because some
GC>    variety of floating-point hardware lacks rounding control, then it
GC>    would presumably round to nearest.

 On the platforms we use (meaning hardware/compiler/standard library)
combinations, fesetround() never fails if passed a valid argument, see the
implementations in glibc for x86-64 [1] and x86 [2] and MinGW-w64
implementation common to both of them [3].

[1]: 
https://github.com/bminor/glibc/blob/b92a49359f33a461db080a33940d73f47c756126/sysdeps/x86_64/fpu/fesetround.c#L22
[2]: 
https://github.com/bminor/glibc/blob/b92a49359f33a461db080a33940d73f47c756126/sysdeps/i386/fpu/fesetround.c#L29
[3]: 
https://github.com/ctaggart/mingw-w64/blob/cc47979ce5d0c28422a3967a2b12369d810b0afe/mingw-w64-crt/misc/fesetround.c#L18

 Looking at the other implementations, it seems that fesetround() can only
really fail when no FPU is available at all, but lmi is not going to run on
any platforms without FPU -- at least until the end of the centimization
work (but, realistically, not ever).

 Also, while I don't have source code for the MSVC implementation, it seems
to do something very similar from looking at its assembly code but,
interestingly, it ends by calling fegetround() and checking that the
returned value is equal to the one we just set and returns 1 if they
differ. AFAICS this still means that it always returns 0 because I don't
think setting the control word can fail but it's still a bit curious that
they decided they needed this check.

GC>  - How often should this be called? C++20 [cfenv.syn] specifies that the
GC>    floating-point environment has "thread storage duration" and that
GC>    child threads inherit the calling thread's environment, so shouldn't
GC>    it be sufficient to set it OAOO, at program startup? C++20 doesn't
GC>    seem to require that the compiler library restore the original state
GC>    when a library function changes it, AFAICT; can they really have
GC>    left that as a QOI issue?

 IMO there should be no reason to call it at all (which renders the
question above moot too, as a nice side effect) because FE_TONEAREST is
the default rounding mode anyhow, but if we do want to call it, there
should be no reason to call it more than once. I know that you were worried
about some rogue DLL, possibly loaded as an Explorer extension when using
the file open dialog, could change the process rounding mode but this kind
of things shouldn't happen accidentally any more -- and any DLL that wants
to intentionally skew lmi calculation results could still do it in a number
of creative ways not relying on the rounding mode.

GC>  - Given that 'long double' calculations on x86_64 depend on the x87
GC>    state, and 'double' on the SSE state, I'm somewhat surprised that the
GC>    standard implies that there's exactly one floating-point environment.
GC>    When setting the rounding direction, should we set both? or is it
GC>    reasonable to hope that any reasonable compiler would do that for us?

 Yes, as the links above show, they all set both the x87 and, if available,
SSE rounding modes.

 Regards,
VZ

Attachment: pgpeod2hXaXjw.pgp
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]