lmi
[Top][All Lists]
Advanced

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

[lmi] fesetround() requirements and guarantees [Was: master a91cbc67: Ma


From: Greg Chicares
Subject: [lmi] fesetround() requirements and guarantees [Was: master a91cbc67: Make two comparisons work even for x87]
Date: Thu, 12 May 2022 09:06:42 +0000
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.8.0

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

True; however, instead of comparing floating-point values more carefully,
the real solution is to compare integral values. That's easier said than
done: here, for example, 'CumPmts' must be integral cents because it
represents actual payments, but 'CumSevenPP' can represent an irrational
number. I've postponed the currency-ization of tax-related code because
it's challenging, and because the existing implementation really needs
a thoroughgoing rewrite. I hope to get to that later in the year; until
then, I hesitate to beautify these ugly workarounds, because they should
soon be removed.

But there is one thing I've been tempted to beautify: this block...

    // Do not save and restore prior rounding direction, because lmi
    // generally expects rounding to nearest everywhere.
    std::fesetround(FE_TONEAREST);

...preceding every call to std::nearbyint(). Probably that ought to be
factored into a function that could be called instead. But first let me
ask a couple of questions:

 - Should the return code be checked? That is, can fesetround() ever
   realistically fail when it's called with one of its predefined macro
   arguments? I tend to think that checking it is useless: if it fails,
   we can't do anything about the failure; and if it fails because some
   variety of floating-point hardware lacks rounding control, then it
   would presumably round to nearest.

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

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


reply via email to

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