On May 20, 2005, at 11:29 AM, James Y Knight wrote:
> On May 19, 2005, at 4:47 AM, Christophe Rhodes wrote:
>> Something's not quite right...
>> (/ 1.0 0.0) => DIVISION-BY-ZERO ; fine
>> (/ 0.0 0.0) => DIVISION-BY-ZERO ; should be INVALID-OPERATION
>> (expt 1.2 10000) => +Inf.0 ; should be FLOATING-POINT-OVERFLOW
>> (defun fsqrt (x)
>> (declare (optimize speed (safety 0))
>> (type (single-float (0.0)) x))
>> (sqrt x))
>> (fsqrt -1.0) => DIVISION-BY-ZERO ; dunno what it should be, but
>> not that.
>> The new behaviour is definitely better than the old one, though.
> Indeed,something is still quite broken. Executing (/ 0.0 0.0) first
> thing properly throws a FLOATING-POINT-INVALID-OPERATION, but after
> having done a (/ 1.0 0.0), it subsequently throws a DIVISION-BY-
> ZERO. My guess is that some exception flags are not getting
> cleared, so in the next trap multiple flags are set and division by
> zero is just the first one it checks. I'll see what I can figure out.
Attached patch fixes up the flag handling, and also causes both the
SSE2 and x87 FPUs to be setup and checked. I moved the fp mode get/
set code into C instead of in a VOP because it was getting somewhat
complicated with setting both FPUs, and I didn't want to write that
whole thing out in asm. Setting up both FPUs did not help the error
below, but it's what the libc functions for manipulating the FPU
state do, and I think it's a good idea, anyways. (sidenote: it may be
possible to use the C99 standard fp manipulation functions, but that
looked harder to fit into the current way of doing things than just
> Interestingly, (expt 2.1d0 1000) does trap, but, (expt 2.1d0 1050)
> results in positive infinity. Very Weird.
> Ahh. SBCL is calling out to the libc implementation of pow, and
> it's simply returning +inf when it knows it can, since C doesn't
> really support trapping FP anyways. Also, it's using x87 fp
> instructions, whose trap flags I don't believe it even checks since
> it uses the xmm fp instructions. So really, that it *ever* catches
> exceptions from expt is amazing. I guess all the calls out to libm
> C functions need to explicitly check the return value for whether
> it should raise an fp exception.
One mistake above: glibc *is* using sse2 FP...most of the time.
There's still some x87 instrs mixed in in some places.
Also, I've read more, and C99 *does* support fp modes, but still
doesn't (ANSI C doesn't either) require math.h functions to raise fp
traps. They may either return ERANGE or EDOM in errno, or raise a fp
trap, or both. So sbcl needs to check errno after all libc math
calls. I believe the correct behavior is: cause an overflow exception
when errno==ERANGE and result != 0, an underflow exception when
errno==ERANGE and result == 0, and an invalid-operation exception
when errno=EDOM (all subject to the current fp exception mask, of
This error probably doesn't occur on x86 because in the x87 FPU, even
storing a value from register to memory causes FP traps to occur
(what a broken architecture). Testing shows that it does also happen
I have not fixed this issue.