On 8/7/07, James Y Knight <foom@...> wrote:
> On Aug 7, 2007, at 10:36 AM, G=E1bor Melis wrote:
> > (declaim (inline sigmoid))
> > (defun sigmoid (x)
> > (/ (1+ (exp ( x)))))
> >
> > (defun foo (x)
> > (declare (type doublefloat x))
> > (sigmoid x))
> >
> > (defun bar (x)
> > (sigmoid x))
> >
> > ;;; this returns 0.0d0
> > (foo 900d0)
> > ;;; this overflows
> > (bar 900d0)
>
> You should probably say what architecture. But I'll assume x86 (since
> it does happen there). The reason (i believe) is that the x87 FPU has
> 80 bit precision in registers, but when spilled to memory, only has
> 64 bits of precision. Disassembly of the two functions will show that
> the first just uses floating point instructions, while the second
> uses function calls.
Depending on x, the extra size of the exponent register in the x87 FPU
could make a difference, but it shouldn't really matter once x gets
big enough. The real issue is how SBCL handles floatingpoint
infinity: whether it signals a condition, or just lets the Inf pass
through. If FOO is just straight floatingpoint instructions, then
the Inf may not signal, which means you get 1/(1 + Inf) =3D=3D +0.0.
However, Lisp's EXP function may signal on Inf, which means you get
the overflow report.
SBCL should either leave Inf, NaN, etc. alone, or give users the
option to specify the semantics (and ensure that the semantics are
consistent, whether functions are inlined or not). Many C compilers
have flags that either ensure IEEE 754 semantics, or allow users to
relax them for the sake of performance. These could be exploited in
builtin functions.
mfh
