problem with numericalio: it writes 4 byte "unknowns" instead of 8 byte IEEE DP
Subject: problem with numericalio: it writes 4 byte "unknowns" instead of 8 byte IEEE DP
From: Robert Dodier
Date: Sat, 29 Sep 2012 20:09:01 +0000 (UTC)
On 2012-09-29, drgst web de <drgst at web.de> wrote:
> load("numericalio");
> assume_external_byte_order:msb;
> a:1.0;b:2.0;ip:float(%pi);
> lst:[a/b,a,b,ip/b,ip,a];
> write_binary_data(lst,"filename goes in here");
>
> is executed on a system described by :
>
> build_info("5.28.0-2","2012-08-27 23:16:48","i686-pc-mingw32","GNU
> Common Lisp (GCL)","GCL 2.6.8")
>
> the output file looks like this when displayed in a hex editor:
>
> 30 80 00 00 31 00 00 00 31 80 00 00 31 44 2D 18 31 C4 2D 18 31 00 00
> 00
GCL doesn't distinguish single floats and double floats (which is OK by
the Common Lisp spec) but numericalio assumed they were distinct --
that's a bug in numericalio.
I have committed a patch for numericalio as shown below. You can can
also get the current version of the relevant Lisp code from Git:
http://maxima.git.sourceforge.net/git/gitweb.cgi?p=maxima/maxima;a=blob_plain;f=share/numericalio/encode-decode-float.lisp
Just replace that file in your Maxima installation. You don't need to
rebuild Maxima for the change to take effect.
I think this fixes the problem you observed. Sorry for the bother.
best,
Robert Dodier
PS.
diff --git a/share/numericalio/encode-decode-float.lisp b/share/numericalio/encode-decode-float.lisp
index cd79465..07a3303 100644
--- a/share/numericalio/encode-decode-float.lisp
+++ b/share/numericalio/encode-decode-float.lisp
@@ -26,9 +26,11 @@
(multiple-value-bind
(significand exponent sign)
(integer-decode-float x)
- (if (typep x 'single-float)
- (smash-decoded-float-32-into-integer significand exponent sign)
- (smash-decoded-float-64-into-integer significand exponent sign))))
+ ;; This logic cannot be guaranteed to work -- there is no necessary
+ ;; correlation between IEEE 754 and CL floats. Oh well.
+ (if (or (typep x 'double-float) (typep x 'long-float))
+ (smash-decoded-float-64-into-integer significand exponent sign)
+ (smash-decoded-float-32-into-integer significand exponent sign))))
(defun smash-decoded-float-32-into-integer (significand exponent sign)
(if (= significand 0)
@@ -77,7 +79,7 @@
(write-unsigned-integer (smash-float-into-integer x) (size-in-bytes x) s))
(defun size-in-bytes (x)
- (if (typep x 'single-float) 4 8)) ;; AUGHHHH!! THIS IS TERRIBLE!
+ (if (or (typep x 'double-float) (typep x 'long-float)) 8 4)) ;; AUGHHHH!! THIS IS TERRIBLE!
(defun read-float-64 (s)
(let ((x (read-unsigned-integer 8 s)))