Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo
Close
From: Paul Khuong <pkhuong@gm...>  20090728 18:05:02

On 28Jul09, at 1:12 PM, Nikodemus Siivola wrote: > Update of /cvsroot/sbcl/sbcl/src/compiler > In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvsserv7449/src/ > compiler > > Modified Files: > floattran.lisp > Log Message: > 1.0.30.5: optimize some floating point operations > > * Convert (/ <float> <one>) to (+ <float> <zero>), and similarly for > *. Multiplication and division by 1 preserve the sign of zeros, but addition doesn't. This one should probably depend on FLOATACCURACY, converting the division to a multiplication, which always preserves signs in the default case. In fact, the optimisation could be generalised to division by any number that can be exactly reciprocated, using something like the following. (defun maybeexactreciprocal (x) "Return the reciprocal of X if it can be represented exactly, NIL otherwise." (multiplevaluebind (significand exponent sign) (integerdecodefloat x) ; must special case infinities/zeros, and fail on NaNs (let ((expected (/ sign significand (expt 2 exponent)))) (let ((reciprocal (/ 1 x))) (multiplevaluebind (significand exponent sign) (integerdecodefloat reciprocal) (and (eql expected (* sign significand (expt 2 exponent))) reciprocal)))))) If FLOATACCURACY is 1, then (/ <float> <constantfloat>) can be converted to (* float (/ <constantfloat>)) if the above doesn't return NIL (if FLOATACCURACY is 0, then multiplication by reciprocal would probably always make sense, with a direct elimination of (* <float> <+/ one>)). I'm fairly certain the transformation can be extended to complex floats without breaking anything that isn't already broken, and even for nonconstant complexreal division. > * Convert (/ <float> <minusone>) to (+ (%negate <float>) <zero>), and > similarly for *. I don't see why that shouldn't be converted to (%negate <float>), which computes the sign of zeros correctly. As for FLOATACCURACY, since the "default" case is 1 and the minimal value 0, we're only left with a binary toggle... FLOATINACCURACY/ SPEED would give us a more useful range. Paul Khuong 
From: Nikodemus Siivola <nikodemus@ra...>  20090729 13:44:16

2009/7/28 Paul Khuong <pkhuong@...>: >> * Convert (/ <float> <one>) to (+ <float> <zero>), and similarly for *. > > Multiplication and division by 1 preserve the sign of zeros, but addition > doesn't. This one should probably depend on FLOATACCURACY, converting the Oops... > division to a multiplication, which always preserves signs in the default > case. In fact, the optimisation could be generalised to division by any > number that can be exactly reciprocated, using something like the following. > (defun maybeexactreciprocal (x) > If FLOATACCURACY is 1, then (/ <float> <constantfloat>) can be converted > to (* float (/ <constantfloat>)) if the above doesn't return NIL (if > FLOATACCURACY is 0, then multiplication by reciprocal would probably always > make sense, with a direct elimination of (* <float> <+/ one>)). I'm fairly > certain the transformation can be extended to complex floats without > breaking anything that isn't already broken, and even for nonconstant > complexreal division. I've implemented this (though not the extensions) in 1.0.30.8. >> * Convert (/ <float> <minusone>) to (+ (%negate <float>) <zero>), and >> similarly for *. > > I don't see why that shouldn't be converted to (%negate <float>), which > computes the sign of zeros correctly. I mentioned this on IRC, but for the record: I did that to catch SNaNs. > As for FLOATACCURACY, since the "default" case is 1 and the minimal value > 0, we're only left with a binary toggle... FLOATINACCURACY/SPEED would > give us a more useful range. Actually, the default is unintuitively 3, currently. The only thing it affected prior to this commit was the setting of FPU control word on x86 for alien calls: 53 bits for lisp, and 64 for C. (There's a bug there, actually: if the foreign function unwinds, the FPU is left in 64 bit mode for lisp.) Christophe pointed this out: http://gcc.gnu.org/wiki/FloatingPointMath I think most interesting toggles are: inexact results SNaN behaviour treatment of signed zeros For now these are all on FA=0, but perhaps they should be separate qualities? Cheers,  Nikodemus 