From: <mega@re...>  20070807 14:36:37

I'm puzzled by this: (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) 
From: James Y Knight <foom@fu...>  20070807 14:48:21

On Aug 7, 2007, at 10:36 AM, G=E1bor Melis wrote: > I'm puzzled by this: > > (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 =20= it does happen there). The reason (i believe) is that the x87 FPU has =20= 80 bit precision in registers, but when spilled to memory, only has =20 64 bits of precision. Disassembly of the two functions will show that =20= the first just uses floating point instructions, while the second =20 uses function calls. I believe you'll run into the same issue with gcc if you rewrite it =20 in C. James= 
From: Mark Hoemmen <mark.hoemmen@gm...>  20070807 18:00:48

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 