Hi all,

This is a patch and bugreport rolled into one ;)

While testing the "numbers" egg I found out that programs
containing flonum literals can behave differently when compiled
or interpreted.

This turns out to be caused by the fact that Chicken just
uses [sf]printf or gcvt to print flonums while emitting C code.
When nothing else is specified, these use the default
"flonum-print-precision" of 15, which means that any number with
more _decimal_ digits than that get printed in exponential notation,
like this:

#;1> 123456789012345.0
123456789012345.0
#;2> 1234567890123456.0
1.23456789012346e+15

So after (read)ing the literal the compiler then later prints it
back again, but with less precision than was present when reading it.

This behavior can be tweaked by calling (flonum-print-precision N),
which is exactly what the compiler should be doing and what my patch
does.  You can also merge it from the "sjamaan-pending" branch,
it's changeset 6c39851e1504d01b2de05e014f5542913e3e5c5e.

PS: If someone with access to a Windows system is reading this,
there's a sort-of related bug in #691.  I've attached a patch that
needs to be tested to the ticket.

Cheers,
Peter
-- 
http://sjamaan.ath.cx
--
"The process of preparing programs for a digital computer
 is especially attractive, not only because it can be economically
 and scientifically rewarding, but also because it can be an aesthetic
 experience much like composing poetry or music."
                                                        -- Donald Knuth
>From 6c39851e1504d01b2de05e014f5542913e3e5c5e Mon Sep 17 00:00:00 2001
From: Peter Bex <peter....@xs4all.nl>
Date: Sat, 17 Sep 2011 17:41:58 +0200
Subject: [PATCH] Do not drop precision in flonums when compiling

---
 c-backend.scm            |    2 ++
 tests/compiler-tests.scm |   13 +++++++++++++
 2 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/c-backend.scm b/c-backend.scm
index 1571edb..5dbcadd 100644
--- a/c-backend.scm
+++ b/c-backend.scm
@@ -60,6 +60,8 @@
 ;;; Generate target code:
 
 (define (generate-code literals lliterals lambdas out source-file dynamic db)
+  ;; Don't truncate floating-point precision!
+  (flonum-print-precision (+ flonum-maximum-decimal-exponent 1))
   (let ()
 
     ;; Some helper procedures
diff --git a/tests/compiler-tests.scm b/tests/compiler-tests.scm
index 7395130..226c440 100644
--- a/tests/compiler-tests.scm
+++ b/tests/compiler-tests.scm
@@ -216,3 +216,16 @@
     (assert (zero? b))))
 
 (gp-test)
+
+;; Test that encode-literal doesn't drop digits for extreme flonum values.
+
+;; This number is 2^971 * (2^53 - 1), and is the positive "all ones" number for
+;; 64-bit flonums with precision 53 and significand/mantissa 10.
+;; If we want to support 32-bit flonums or flonums with different precision
+;; or significand, we need a cond-expand here or something.
+;; Technically, even larger decimal numbers can be represented by flonums.
+;; This number can correctly be compared exactly.
+(assert (= (* (- (expt 2 flonum-precision) 1)
+              (expt 2 (- flonum-maximum-exponent flonum-precision)))
+           
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0
+           (string->number 
"179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0")))
\ No newline at end of file
-- 
1.7.3.4

_______________________________________________
Chicken-hackers mailing list
Chicken-hackers@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-hackers

Reply via email to