problem with numericalio: it writes 4 byte "unknowns" instead of 8 byte IEEE DP



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)))