lmi
[Top][All Lists]
Advanced

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

[lmi] feholdexcept() [Was: Better support for non-x87 platforms]


From: Greg Chicares
Subject: [lmi] feholdexcept() [Was: Better support for non-x87 platforms]
Date: Thu, 5 Jan 2017 12:01:31 +0000
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Icedove/45.4.0

On 2017-01-03 15:14, Vadim Zeitlin wrote:
[...]
>  Please let me know if you have any questions concerning any of this

I have a question on code unchanged since
  Initial checkin
  commit 73f326c348d063ae13dc93eb7ee77aee431857ea
which I believe I've answered correctly below.

In fenv_initialize(), if !defined LMI_X87, we do exactly this:
    fenv_t save_env;
    feholdexcept(&save_env);
    fesetround(FE_TONEAREST);
Reading that casually, I thought it might be an error not to use
'save_env' in some later call to std::fesetenv(). But now, after
studying the standard, I think that might be correct, though the
standard is confusing enough that I'd like your opinion. Here's
what it says about that function [C99 7.6.4.2/2]:

| The feholdexcept function saves the current floating-point environment
| in the object pointed to by [its argument], clears the floating-point
| status flags, and then installs a non-stop (continue on floating-point
| exceptions) mode, if available, for all floating-point exceptions.

and here's some relevant context [C99 7.6/1]:

| A 'floating-point status flag' is a system variable whose value is set
| (but never cleared) when a floating-point exception is raised, which
| occurs as a side effect of exceptional floating-point arithmetic to
| provide auxiliary information. A 'floating-point control mode' is a
| system variable whose value may be set by the user to affect the
| subsequent behavior of floating-point arithmetic.

So std::feholdexcept() does this [x87 instructions given for reference]:

| saves the current floating-point environment [FSAVE]
That's just a convenience feature that we don't need here: it doesn't
matter that we don't use the saved value later. [In x87 terms, the lack
of a subsequent FRSTOR shows that the FSAVE is wasted in our case.]

| clears the floating-point status flags [FCLEX]
I.e., in x87 terms, it clears the exception flags in the status word.
Thus, any FP exception that has been raised is ignored and wiped out.
[If FCLEX weren't used before FLDCW, an interrupt could occur.]

| non-stop (continue on floating-point exceptions) mode [FLDCW]
I.e., in x87 terms, it updates the control word to mask all exceptions.

Now I think I understand why the name suggests that this function's
purpose is to "hold exceptions": a later FRSTOR would restore any
exception flag that had been set in the status word. Actually, it holds
old exceptions and *masks* new exceptions: they simply figured that
feholdandmaskexcept() would be too long a name; and they didn't want to
make it the programmer's responsibility to call std::fegetenv() first.
But in the lmi code above, its only purpose is to mask exceptions;
apparently it's the only C99 function that can do that reliably.




reply via email to

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