[cmucl-commit] [git] CMU Common Lisp branch 20f-branch updated. snapshot-2014-09-12-gab0a979
Raymond Toy
rtoy at common-lisp.net
Sat Sep 27 19:20:09 UTC 2014
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMU Common Lisp".
The branch, 20f-branch has been updated
via ab0a979db83310c64fcbbc13b178d5c31af9f5c9 (commit)
from 878f7c4337d04265d067a90d29acca0d868cd35d (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit ab0a979db83310c64fcbbc13b178d5c31af9f5c9
Author: Raymond Toy <toy.raymond at gmail.com>
Date: Fri Sep 26 20:20:54 2014 -0700
Fix incorrect value from INTEGER-DECODE-FLOAT for denormals.
This is a long standing bug where INTEGER-DECODE-FLOAT returned
incorrect values for denormal double-float numbers. The lower 32 bits
of the double were not shifted enough when creating the integer
result.
As a side-effect, DECODE-FLOAT decodes denormal double-float's
correctly and SCALE-FLOAT scales denormals correctly too.
* src/code/float.lisp:
* Shift the lower 32-bit of the fraction one more time to adjust
for the fact that the upper 20 bits were shifted an extra time.
* tests/float.lisp:
* Add several tests for INTEGER-DECODE-FLOAT, SCALE-FLOAT, and
DECODE-FLOAT.
* src/general-info/release-20f.txt:
* Add this bug fix to the notes.
Conflicts:
tests/float.lisp
diff --git a/src/code/float.lisp b/src/code/float.lisp
index cace1a4..3ac6512 100644
--- a/src/code/float.lisp
+++ b/src/code/float.lisp
@@ -581,7 +581,7 @@
(return))
(setq sig (ash sig 1))
(incf extra-bias))
- (values (logior (ash sig 32) (ash low-bits (1- extra-bias)))
+ (values (logior (ash sig 32) (ash low-bits (1+ extra-bias)))
(truly-the fixnum (- biased extra-bias))
sign)))))
diff --git a/src/general-info/release-20f.txt b/src/general-info/release-20f.txt
index 0327f5b..4fd57e3 100644
--- a/src/general-info/release-20f.txt
+++ b/src/general-info/release-20f.txt
@@ -123,6 +123,10 @@ New in this release:
* For linux, motifd is no longer a 64-bit app.
* (exp 1d0) now returns the correctly rounded value of
e. Previously, it was off by one bit.
+ * INTEGER-DECODE-FLOAT returns the correct values for denormal
+ doubles. As a side-effect of this fix, DECODE-FLOAT returns the
+ correct values for denormals, and SCALE-FLOAT scales denormals
+ correctly.
* Trac Tickets:
* Ticket #90 fixed.
diff --git a/tests/float.lisp b/tests/float.lisp
index 6fe1f50..454ab99 100644
--- a/tests/float.lisp
+++ b/tests/float.lisp
@@ -10,3 +10,77 @@
(declare (type (double-float (0d0)) x))
(decode-float x)))
1d0)))
+
+(define-test integer-decode-float.double
+ ;; Generate 100 random denormal values and compare what
+ ;; integer-decode-float returns against what it should return.
+ (dotimes (k 100)
+ (let ((x (random least-positive-normalized-double-float)))
+ (multiple-value-bind (hi lo)
+ (kernel:double-float-bits x)
+ ;; Verify that the exponent is 0, which it must be for a
+ ;; denormal number.
+ (assert-equal 0
+ (ldb vm:double-float-exponent-byte hi)
+ x)
+ ;; Print out the fraction bits, and the bits returned by
+ ;; INTEGER-DECODE-FLOAT. We could do this differently, but
+ ;; this has the nice side effect of making it easy to see what
+ ;; is expected and what went wrong.
+ (let* ((expected (format nil "~b~32,'0b" hi lo))
+ (actual (format nil "~b" (integer-decode-float x)))
+ (tail (subseq actual (length expected))))
+ ;; If everything is working correctly, the beginning of the
+ ;; actual bits must exactly match the expected bits.
+ (assert-true (every #'char=
+ expected
+ actual)
+ x
+ expected
+ actual)
+ ;; And finally, the trailing part of the actual bits must be
+ ;; all zeroes, but this is a denormal number.
+ (assert-true (every #'(lambda (c)
+ (char= c #\0))
+ tail)
+ x
+ tail))))))
+
+(define-test scale-float.double
+ ;; As a side-effect of fixing INTEGER-DECODE-FLOAT, SCALE-FLOAT
+ ;; should return the correct values now when scaling
+ ;; denormals. Check a few denormal values.
+ (dotimes (k 100)
+ (let* ((x (random least-positive-normalized-double-float))
+ (scaled (scale-float x 54))
+ (mult (* x (scale-float 1d0 54))))
+ ;; The result of SCALE-FLOAT and the multiplication should be
+ ;; exactly equal because the multiplication by 2^54 is exactly
+ ;; representable.
+ (assert-equal scaled
+ mult
+ x
+ scaled
+ mult)))
+ ;; Add the test caused the investigation of SCALE-FLOAT
+ (let* ((x 1d-310)
+ (scaled (scale-float x 54))
+ (mult (* x (scale-float 1d0 54))))
+ (assert-equal scaled
+ mult
+ x
+ scaled
+ mult)))
+
+(define-test decode-float.double
+ ;; As a side-effect of fixing INTEGER-DECODE-FLOAT, DECODE-FLOAT
+ ;; should return the correct values now. We just spot check one
+ ;; value here.
+ (dotimes (k 100)
+ (let ((x (random least-positive-normalized-double-float)))
+ (multiple-value-bind (f e)
+ (decode-float x)
+ (assert-equal x
+ (scale-float f e)
+ f
+ e)))))
-----------------------------------------------------------------------
Summary of changes:
src/code/float.lisp | 2 +-
src/general-info/release-20f.txt | 4 +++
tests/float.lisp | 74 ++++++++++++++++++++++++++++++++++++++
3 files changed, 79 insertions(+), 1 deletion(-)
hooks/post-receive
--
CMU Common Lisp
More information about the cmucl-commit
mailing list