CMUCL commit: src (code/float.lisp compiler/float-tran.lisp)
Raymond Toy
rtoy at common-lisp.net
Fri Feb 5 19:10:59 CET 2010
Date: Friday, February 5, 2010 @ 13:10:59
Author: rtoy
Path: /project/cmucl/cvsroot/src
Modified: code/float.lisp compiler/float-tran.lisp
Implement a fast fround for single and double floats. This is enabled
everywhere except for x87 builds since there is a possible roundoff
issue due to the 80-bit registers for x87.
This is some 2-3 times faster than the existing fround function.
code/float.lisp:
o Implementations of %unary-fround/single-float,
%unary-fround/double-float, and %unary-fround. Declare the first
two as inline too.
compiler/float-tran.lisp:
o Tell compiler about %unary-fround.
o Transform fround to a call to %unary-fround.
o Transform %unary-fround to special versions for single and double
float arguments.
--------------------------+
code/float.lisp | 54 +++++++++++++++++++++++++++++++++++++++++++--
compiler/float-tran.lisp | 28 ++++++++++++++++++++++-
2 files changed, 79 insertions(+), 3 deletions(-)
Index: src/code/float.lisp
diff -u src/code/float.lisp:1.43 src/code/float.lisp:1.44
--- src/code/float.lisp:1.43 Mon Dec 22 18:24:28 2008
+++ src/code/float.lisp Fri Feb 5 13:10:58 2010
@@ -5,7 +5,7 @@
;;; Carnegie Mellon University, and has been placed in the public domain.
;;;
(ext:file-comment
- "$Header: /project/cmucl/cvsroot/src/code/float.lisp,v 1.43 2008-12-22 23:24:28 rtoy Rel $")
+ "$Header: /project/cmucl/cvsroot/src/code/float.lisp,v 1.44 2010-02-05 18:10:58 rtoy Exp $")
;;;
;;; **********************************************************************
;;;
@@ -20,6 +20,9 @@
(export '(%unary-truncate %unary-round %unary-ftruncate
%unary-ftruncate/single-float %unary-ftruncate/double-float))
+#-x87
+(export '(%unary-fround/single-float %unary-fround/double-float))
+
(in-package "LISP")
(export '(least-positive-normalized-short-float
least-positive-normalized-single-float
@@ -1412,9 +1415,56 @@
#+double-double
((double-double-float)
(%unary-ftruncate/double-double-float number))))
-
+;; %UNARY-FROUND not implemented for x87. I think there are potential
+;; roundoff problems due to the 80-bit FPU registers.
+#-x87
+(progn
+(declaim (inline %unary-fround/single-float %unary-fround/double-float))
+
+;; %UNARY-FROUND/DOUBLE-FLOAT
+;;
+;; Basically the same as fround, but specialized to handle only
+;; double-floats and to return the first value. This is the algorithm
+;; given by Anton Ertl in comp.arch.arithmetic, Oct 26, 2002.
+(defun %unary-fround/double-float (x)
+ (declare (double-float x))
+ (let ((const (scale-float 1d0 53)))
+ (if (>= x 0)
+ (+ (- x const) const)
+ (- (+ x const) const))))
+
+
+;; %UNARY-FROUND/SINLGE-FLOAT
+;;
+;; Same as %UNARY-FROUND/DOUBLE-FLOAT, except specialized for single-float.
+(defun %unary-fround/single-float (x)
+ (declare (single-float x))
+ (let ((const (scale-float 1f0 24)))
+ (if (>= x 0)
+ (+ (- x const) const)
+ (- (+ x const) const))))
+
+;;; %UNARY-FROUND -- Interface
+;;;
+;;; This function is called when we are doing an fround without any
+;;; funky divisor. Note that we do *not* return the second value of
+;;; round, so it must be computed by the caller if needed.
+;;;
+(defun %unary-fround (number)
+ (number-dispatch ((number real))
+ ((integer)
+ (float number))
+ ((ratio)
+ (float (round (numerator number) (denominator number))))
+ ((single-float)
+ (%unary-fround/single-float number))
+ ((double-float)
+ (%unary-fround/double-float number))))
+
+) ; not x87
+
(defun rational (x)
"RATIONAL produces a rational number for any real numeric argument. This is
more efficient than RATIONALIZE, but it assumes that floating-point is
Index: src/compiler/float-tran.lisp
diff -u src/compiler/float-tran.lisp:1.135 src/compiler/float-tran.lisp:1.136
--- src/compiler/float-tran.lisp:1.135 Mon Nov 2 10:05:06 2009
+++ src/compiler/float-tran.lisp Fri Feb 5 13:10:59 2010
@@ -5,7 +5,7 @@
;;; Carnegie Mellon University, and has been placed in the public domain.
;;;
(ext:file-comment
- "$Header: /project/cmucl/cvsroot/src/compiler/float-tran.lisp,v 1.135 2009-11-02 15:05:06 rtoy Exp $")
+ "$Header: /project/cmucl/cvsroot/src/compiler/float-tran.lisp,v 1.136 2010-02-05 18:10:59 rtoy Exp $")
;;;
;;; **********************************************************************
;;;
@@ -235,6 +235,32 @@
(frob single-float %unary-ftruncate/single-float)
(frob double-float %unary-ftruncate/double-float))
+;;; FROUND
+#-x87
+(progn
+(deftransform fround ((x &optional (y 1))
+ ((or single-float double-float)
+ &optional (or single-float double-float integer)))
+ '(let ((res (%unary-fround (/ x y))))
+ (values res (- x (* y res)))))
+
+(defknown %unary-fround (real) float
+ (movable foldable flushable))
+
+(defknown %unary-fround/single-float (single-float) single-float
+ (movable foldable flushable))
+
+(defknown %unary-fround/double-float (double-float) double-float
+ (movable foldable flushable))
+
+(deftransform %unary-fround ((x) (single-float))
+ '(%unary-fround/single-float x))
+
+(deftransform %unary-fround ((x) (double-float))
+ '(%unary-fround/double-float x))
+
+); not x87
+
;;; Random:
;;;
(macrolet ((frob (fun type)
More information about the cmucl-commit
mailing list