Oops. Meant to reply to all. ---------- Forwarded message ---------- From: Raymond Toy <toy.raymond@gmail.com> Date: Sun, Jan 8, 2017 at 10:00 AM Subject: Re: [cmucl-help] NaN To: Marco Antoniotti <marcoxa@cs.nyu.edu> On Sat, Jan 7, 2017 at 3:44 PM, Marco Antoniotti <marcoxa@cs.nyu.edu> wrote:
Hi
I am fiddling around with some IEEE floating points.
I see that the following code produces a (almost nice) “quiet” NaN.
CL-USER> (ext:with-float-traps-masked (:invalid) (* 0.0 ext:double-float-positive-infinity)) #<DOUBLE-FLOAT Quiet NaN>
Alas, there seem to be no way to tell the compiler that we are actually executing the multiplication within the ext:with-float-traps-masked. This prevents us, for example to do things like
(defparameter NAN (ext:with-float-traps-masked (:invalid) (* 0.0 ext:double-float-positive-infinity))
in a file and having it compiled “nicely”. The compiler complains (warns) about a FLOATING-POINT-INVALID-OPERATION
; In: DEFPARAMETER NAN
; (* 0.0 EXTENSIONS:DOUBLE-FLOAT-POSITIVE-INFINITY) ; Warning: Lisp error during constant folding: ; Arithmetic error FLOATING-POINT-INVALID-OPERATION signalled. ; Operation was *, operands (0.0d0 #.EXT:DOUBLE-FLOAT-POSITIVE-INFINITY).
What version? I don't get any warnings from snapshot-2017-01.
Note that the value is then assigned correctly, but it seems very hard (at least I did not figure out how to do it) to get to the constant folding time to catch and muffle the warning.
Any ideas?
Since you're using cmucl-specific functions, you could always just construct the NaN directly using kernel:make-double-float. Something like (kernel:make-double-float -524288 0) -- Ray -- Ray
Hi Ray maybe we can just have this discussion here. I am not a person who knows all that much about the IEEE fine details, but I would like to have a “higher level” portable API to access IEEE NaNs, infinities, and rounding modes. I am kind of familiar with the C99 API. Would you like to have an API consisting of something like (given a package “M”, not its real name) the following? Assuming all “quiet” NaNs. Parameter NaN Constant <float-length>-float-positive-infinity Constant <float-length>-float-negative-infinity Type rounding-mode (member :positive :negative :toward-zero :to-nearest) Struct floating-point-configuration Function current-floating-point-configuration Function (setf current-floating-point-configuration) Macro with-floating-point-configuration Function current-rounding-mode Function (setf current-rounding-mode) Macro with-rounding-mode Details to be filled… This covers CMUCL and SBCL and (mostly) LW. CCL could be bent to comply. For ECL and ABCL pressures can be made; ACL is another story. What do you think? MA
On Jan 8, 2017, at 23:58 , Raymond Toy <toy.raymond@gmail.com> wrote:
Oops. Meant to reply to all.
---------- Forwarded message ---------- From: Raymond Toy <toy.raymond@gmail.com> Date: Sun, Jan 8, 2017 at 10:00 AM Subject: Re: [cmucl-help] NaN To: Marco Antoniotti <marcoxa@cs.nyu.edu>
On Sat, Jan 7, 2017 at 3:44 PM, Marco Antoniotti <marcoxa@cs.nyu.edu> wrote:
Hi
I am fiddling around with some IEEE floating points.
I see that the following code produces a (almost nice) “quiet” NaN.
CL-USER> (ext:with-float-traps-masked (:invalid) (* 0.0 ext:double-float-positive-infinity)) #<DOUBLE-FLOAT Quiet NaN>
Alas, there seem to be no way to tell the compiler that we are actually executing the multiplication within the ext:with-float-traps-masked. This prevents us, for example to do things like
(defparameter NAN (ext:with-float-traps-masked (:invalid) (* 0.0 ext:double-float-positive-infinity))
in a file and having it compiled “nicely”. The compiler complains (warns) about a FLOATING-POINT-INVALID-OPERATION
; In: DEFPARAMETER NAN
; (* 0.0 EXTENSIONS:DOUBLE-FLOAT-POSITIVE-INFINITY) ; Warning: Lisp error during constant folding: ; Arithmetic error FLOATING-POINT-INVALID-OPERATION signalled. ; Operation was *, operands (0.0d0 #.EXT:DOUBLE-FLOAT-POSITIVE-INFINITY).
What version? I don't get any warnings from snapshot-2017-01.
Note that the value is then assigned correctly, but it seems very hard (at least I did not figure out how to do it) to get to the constant folding time to catch and muffle the warning.
Any ideas?
Since you're using cmucl-specific functions, you could always just construct the NaN directly using kernel:make-double-float. Something like (kernel:make-double-float -524288 0)
-- Ray
-- Ray _______________________________________________ cmucl-imp mailing list cmucl-imp@lists.zs64.net https://lists.zs64.net/mailman/listinfo/cmucl-imp
-- Marco Antoniotti
"Marco" == Marco Antoniotti <marcoxa@cs.nyu.edu> writes:
Marco> Hi Ray Marco> maybe we can just have this discussion here. Marco> I am not a person who knows all that much about the IEEE fine details, but I would like to have a “higher level” portable API to access IEEE NaNs, infinities, and rounding modes. I am kind of familiar with the C99 API. Marco> Would you like to have an API consisting of something like (given a package “M”, not its real name) the following? Assuming all “quiet” NaNs. Marco> Parameter NaN Marco> Constant <float-length>-float-positive-infinity Marco> Constant <float-length>-float-negative-infinity Marco> Type rounding-mode (member :positive :negative :toward-zero :to-nearest) Marco> Struct floating-point-configuration What does that mean? Marco> Function current-floating-point-configuration Marco> Function (setf current-floating-point-configuration) Marco> Macro with-floating-point-configuration Marco> Function current-rounding-mode Marco> Function (setf current-rounding-mode) Marco> Macro with-rounding-mode Coincidentally, I was looking at ieeefp-tests (https://gitlab.common-lisp.net/ieeefp-tests/ieeefp-tests) last night. It might satisfy your needs because it provides at least some of the things you're looking for. And it looks like it abcl, cmucl, and sbcl. Not bad. I'm curious, though. Can you explain your use case for having such an interface? -- Ray
On Jan 9, 2017, at 17:16 , Raymond Toy <toy.raymond@gmail.com> wrote:
"Marco" == Marco Antoniotti <marcoxa@cs.nyu.edu> writes:
Marco> Hi Ray Marco> maybe we can just have this discussion here.
Marco> I am not a person who knows all that much about the IEEE fine details, but I would like to have a “higher level” portable API to access IEEE NaNs, infinities, and rounding modes. I am kind of familiar with the C99 API.
Marco> Would you like to have an API consisting of something like (given a package “M”, not its real name) the following? Assuming all “quiet” NaNs.
Marco> Parameter NaN
Marco> Constant <float-length>-float-positive-infinity Marco> Constant <float-length>-float-negative-infinity
Marco> Type rounding-mode (member :positive :negative :toward-zero :to-nearest)
Marco> Struct floating-point-configuration
What does that mean?
Marco> Function current-floating-point-configuration Marco> Function (setf current-floating-point-configuration)
Marco> Macro with-floating-point-configuration
Marco> Function current-rounding-mode Marco> Function (setf current-rounding-mode)
Marco> Macro with-rounding-mode
Coincidentally, I was looking at ieeefp-tests (https://gitlab.common-lisp.net/ieeefp-tests/ieeefp-tests) last night. It might satisfy your needs because it provides at least some of the things you're looking for. And it looks like it abcl, cmucl, and sbcl. Not bad.
Thanks for the pointer to IEEEFP-TESTS.
I'm curious, though. Can you explain your use case for having such an interface?
Well. I have been fooling around (read: veered off a tangent) with interval arithmetic, where it looks like you need to ensure that your rounding modes are set to positive or negative infinity when using an end points representation. That’s were it all started. Next I am always for defining compatible layers whenever possible. Which is the other bit of my idiosyncrasies. After all, I am one of the most prolific (YMMV) CDR producer :) Cheers Marco
-- Ray
_______________________________________________ cmucl-imp mailing list cmucl-imp@lists.zs64.net https://lists.zs64.net/mailman/listinfo/cmucl-imp
-- Marco Antoniotti
"Marco" == Marco Antoniotti <marcoxa@cs.nyu.edu> writes:
>> On Jan 9, 2017, at 17:16 , Raymond Toy <toy.raymond@gmail.com> wrote: >> >>>>>>> "Marco" == Marco Antoniotti <marcoxa@cs.nyu.edu> writes: [snip] >> >> Coincidentally, I was looking at ieeefp-tests >> (https://gitlab.common-lisp.net/ieeefp-tests/ieeefp-tests) last >> night. It might satisfy your needs because it provides at least some >> of the things you're looking for. And it looks like it abcl, cmucl, >> and sbcl. Not bad. Marco> Thanks for the pointer to IEEEFP-TESTS. >> I'm curious, though. Can you explain your use case for having such an >> interface? Marco> Well. I have been fooling around (read: veered off a Marco> tangent) with interval arithmetic, where it looks like you Marco> need to ensure that your rounding modes are set to positive Marco> or negative infinity when using an end points Marco> representation. That’s were it all started. That's one way. I vaguely recall some Fortran TOMS package that included interval arithmetic, but I think it just did something simple like multiply by 1+e for some tiny e. Setting the rounding modes twice (up and down) for every operation is pretty expensive. -- Ray
On Jan 10, 2017, at 16:46 , Raymond Toy <toy.raymond@gmail.com> wrote: ...
Marco> Well. I have been fooling around (read: veered off a Marco> tangent) with interval arithmetic, where it looks like you Marco> need to ensure that your rounding modes are set to positive Marco> or negative infinity when using an end points Marco> representation. That’s were it all started.
That's one way. I vaguely recall some Fortran TOMS package that included interval arithmetic, but I think it just did something simple like multiply by 1+e for some tiny e.
Setting the rounding modes twice (up and down) for every operation is pretty expensive.
Ok. I presume that the references talk of rounding modes only because they assume some “very-close-to-the-metal” implementation. In any case, the need for NaNs and infinities is there. And right now CL is lacking in this respect. Cheers -- Marco Antoniotti
Since we are on the subject… I am looking at ieeefp-tests. The code for CMUCL (the relevant one, I assume) looks like this: (defun make-single-float (x) (declare (type (or (unsigned-byte 32) (signed-byte 32)) x)) (typecase x ((signed-byte 32) (kernel:make-single-float x)) (t (kernel:make-single-float (dpb x (byte 32 0) -1))))) (defun make-double-float (x) (declare (type (or (unsigned-byte 64) (signed-byte 64)) x)) (typecase x ((signed-byte 64) (kernel:make-double-float (ldb (byte 32 32) x) (ldb (byte 32 0) x))) (t (kernel:make-double-float (dpb (ldb (byte 32 32) x) (byte 32 0) -1) (ldb (byte 32 0) x))))) (defun single-float-bits (x) (declare (type single-float x)) (ldb (byte 32 0) (kernel:single-float-bits x))) (defun double-float-bits (x) (declare (type double-float x)) (ldb (byte 64 0) (logior (ash (kernel:double-float-high-bits x) 32) (kernel:double-float-low-bits x)))) (defun set-floating-point-modes (&rest args &key traps accrued-exceptions current-exceptions rounding-mode precision) (declare (ignore traps accrued-exceptions current-exceptions rounding-mode precision)) (apply #'ext:set-floating-point-modes args)) (defun get-floating-point-modes () (ext:get-floating-point-modes)) Now. I am trying to produce a version for LW that, at a minimum, implemented the following (defun make-single-float (x) (float x 1.0f0)) ; Would this “just work”? (defun make-double-float (x) (float x 1.0d0)) ; Would this “just work”? (defun single-float-bits (x) (declare (type single-float x)) ;; Wrong for LW. No KERNEL:SINGLE-FLOAT-BITS. (ldb (byte 32 0) (kernel:single-float-bits x))) (defun double-float-bits (x) (declare (type double-float x)) ;; Wrong for LW. No KERNEL:DOUBLE-FLOAT-HIGH-BITS and KERNEL:DOUBLE-FLOAT-LOW-BITS. (ldb (byte 64 0) (logior (ash (kernel:double-float-high-bits x) 32) (kernel:double-float-low-bits x)))) What do the two missing function actually do? Sorry. I tried to read the sources, but (1) I am too lazy and (2) I am way too rusty in deep lisping (cfr., functions that just call themselves :) ) Do they just get the actual bitwise representation of the floats assuming a Lisp representation? Cheers — MA
On Jan 10, 2017, at 21:42 , Marco Antoniotti <marcoxa@cs.nyu.edu> wrote:
On Jan 10, 2017, at 16:46 , Raymond Toy <toy.raymond@gmail.com> wrote: ...
Marco> Well. I have been fooling around (read: veered off a Marco> tangent) with interval arithmetic, where it looks like you Marco> need to ensure that your rounding modes are set to positive Marco> or negative infinity when using an end points Marco> representation. That’s were it all started.
That's one way. I vaguely recall some Fortran TOMS package that included interval arithmetic, but I think it just did something simple like multiply by 1+e for some tiny e.
Setting the rounding modes twice (up and down) for every operation is pretty expensive.
Ok. I presume that the references talk of rounding modes only because they assume some “very-close-to-the-metal” implementation.
In any case, the need for NaNs and infinities is there. And right now CL is lacking in this respect.
Cheers
-- Marco Antoniotti
_______________________________________________ cmucl-imp mailing list cmucl-imp@lists.zs64.net https://lists.zs64.net/mailman/listinfo/cmucl-imp
-- Marco Antoniotti
"Marco" == Marco Antoniotti <marcoxa@cs.nyu.edu> writes:
Marco> Now. I am trying to produce a version for LW that, at a minimum, implemented the following Marco> (defun make-single-float (x) Marco> (float x 1.0f0)) ; Would this “just work”? Nope. x is an integer, basically equal to the bits in a float. You want to take those bits and interpret them as a float. Something akin to the C code union { int n; float f; } var; var.n = x; /* Some integer */ printf("%g\n", var.f): /* Magically a floating point number */ Analogous union for doubles. Marco> (defun single-float-bits (x) Marco> (declare (type single-float x)) Marco> ;; Wrong for LW. No KERNEL:SINGLE-FLOAT-BITS. Marco> (ldb (byte 32 0) (kernel:single-float-bits x))) Using the union above, it's something like var.f = x; printf("%d\n", var.n); Marco> What do the two missing function actually do? Sorry. I Marco> tried to read the sources, but (1) I am too lazy and (2) I Marco> am way too rusty in deep lisping (cfr., functions that just Marco> call themselves :) ) Marco> Do they just get the actual bitwise representation of the Marco> floats assuming a Lisp representation? Pretty much. These functions basically give you a way to produce exactly a float value from the bit representation of the float and to extract the bit representation of a float. In cmucl for architectures that don't let you transfer a value between float register and an integer register, cmucl basically write out the float to memory and reads it back in, into an integer register, and vice versa. You will have to figure out how to get LW or your favorite impl to do something similar. -- Ray
Since we are on the subject…
I am looking at ieeefp-tests.
The code for CMUCL (the relevant one, I assume) looks like this:
(defun make-single-float (x) (declare (type (or (unsigned-byte 32) (signed-byte 32)) x)) (typecase x ((signed-byte 32) (kernel:make-single-float x)) (t (kernel:make-single-float (dpb x (byte 32 0) -1)))))
(defun make-single-float (x) (declare (type (or (unsigned-byte 32) (signed-byte 32)) x)) (cffi:with-foreign-object (p :uint32) (setf (cffi:mem-ref p :uint32) x) (cffi:mem-ref p :float))) Definitely portable across Lisps and probably across CPUs. If you don't care about the former, use LW's own FFI. -- Stelian Ionescu a.k.a. fe[nl]ix Quidquid latine dictum sit, altum videtur.
participants (3)
-
Marco Antoniotti -
Raymond Toy -
Stelian Ionescu