representing infinity and NAN independent of implementation
Asked Answered
L

3

11

Is there an implementation independent way of representing infinity or not a number (NAN) in Common Lisp? It would need to be a double float, and have both positive and negative values. In SBCL, the results of

(apropos "INFINITY")

include

SB-EXT:DOUBLE-FLOAT-NEGATIVE-INFINITY (bound)
SB-EXT:DOUBLE-FLOAT-POSITIVE-INFINITY (bound)

but I need it to be available in all implementations. I have an addendum to a package to write that runs on all platforms and it needs a representation of infinity and NAN. Even functions from another library would suffice.

I got iee-floats loaded and it's a part of my library now. I have a function that detects if a number is NaN and one that detects whether a number is infinity; I haven't tested NaN out but my infinity function needs the number to be a double-float. SBCL's SB-EXT:DOUBLE-FLOAT-POSITIVE-INFINITY works but I would need it to be implementation independent.

Litchi answered 14/10, 2013 at 15:15 Comment(1)
github.com/bytecurry/nonfiniteMuezzin
T
2

If you load GSLL (in quicklisp), you have gsl:+positive-infinity+, gsl:+negative-infinity+, and even gsl:+nan+. These should work anywhere that GSLL is installable.

Thornie answered 18/10, 2013 at 16:26 Comment(3)
from my ?..."my infinity function needs the number to be a double-float ....SBCL's SB-EXT:DOUBLE-FLOAT-POSITIVE-INFINITY works but i would need it to be implimentation independent" I would love if GSLL could fill that requirement been looking for an excuse to include it...also any way to cut down on the GSLL load times i don't load it all the time because its so big but i would love to have it loaded all the time.Litchi
I've been seeing a bug in ASDF where it recompiles everything I load. Perhaps that is what is causing your long load times? In any case, you can make a world with save-lisp-and-die with GSLL in it, and then your load time no more than the load of SBCL.Thornie
Be careful not to use GSL in code, you do not wish to open-source. GPL is viral and infects your code like Covid-19 on a cold winter night.Preternatural
R
14

Rosetta Code's entry on Common Lisp section on Infinity says:

Common Lisp does not specify an infinity value. Some implementations may have support for IEEE infinity, however. For instance, CMUCL supports IEEE Special Values. Common Lisp does specify that implementations define constants with most (and least) positive (and negative) values. These may vary between implementations.

Cliki lists an ieee-floats package that might help (but note what it says about :infinity):

IEEE-Floats provides a way of converting values of type float and double-float to and from their binary format representation as defined by IEEE 754 (which is commonly used by processors and network protocols).

The library defines encoding and decoding functions for the common 32-bit and 64-bit formats, and a macro for defining similar functions for other formats. The default functions do not detect the special cases for NaN or infinity, but functions can be generated which do, in which case the keywords :not-a-number, :positive-infinity, and :negative-infinity are used to represent them.

It sounds like your best best may be to find some IEEE values in the implementations that you want to support, and to write a cross-platform compatibility layer [which, of course, you should then publish and share with others :)].

Rankle answered 14/10, 2013 at 15:16 Comment(3)
@Litchi I marked the answer community wiki since I didn't really do much more than a quick Googling for some possible solutions, so anyone with at least 100 reputation can edit it). Hopefully we'll get some collaborative results about this.Rankle
Thanks..... is it out of curiosity just loading each implimentation then finding the double-float infinity representation the a simple if acl then infinity = "something" if sbcl then infinity = "something" kind of thingLitchi
@Litchi Are you asking about what the cross platform library would be like? It might have definitions in it like (defconstant common-numbers:+positive-infinity+ #+sbcl SB-EXT:DOUBLE-FLOAT-POSITIVE-INFINITY #+lispworks lispworks:pos-infinity ...). (The bit with LispWorks is a just an example; I don't know whether or how infinity is represented there.) Then people can use common-numbers:+positive-infinity+ in their code and it will work in all the supported implementations.Rankle
T
2

If you load GSLL (in quicklisp), you have gsl:+positive-infinity+, gsl:+negative-infinity+, and even gsl:+nan+. These should work anywhere that GSLL is installable.

Thornie answered 18/10, 2013 at 16:26 Comment(3)
from my ?..."my infinity function needs the number to be a double-float ....SBCL's SB-EXT:DOUBLE-FLOAT-POSITIVE-INFINITY works but i would need it to be implimentation independent" I would love if GSLL could fill that requirement been looking for an excuse to include it...also any way to cut down on the GSLL load times i don't load it all the time because its so big but i would love to have it loaded all the time.Litchi
I've been seeing a bug in ASDF where it recompiles everything I load. Perhaps that is what is causing your long load times? In any case, you can make a world with save-lisp-and-die with GSLL in it, and then your load time no more than the load of SBCL.Thornie
Be careful not to use GSL in code, you do not wish to open-source. GPL is viral and infects your code like Covid-19 on a cold winter night.Preternatural
B
2

The following requires that the float traps be disabled, but...since your are processing such values you need to disable traps anyway. I.e. consider this gem from the standard: "It is implementation-dependent whether floating point traps occur, and whether or how they may be enabled or disabled. Therefore, conforming code may establish handlers for this condition, but must not depend on its being signaled."

(eval-when (:compile-toplevel :load-toplevel :execute)
  #+sbcl (sb-int:set-floating-point-modes :traps nil)
  #+cmucl (ext:set-floating-point-modes :traps nil)
  #+linux (cffi:foreign-funcall "fedisableexcept" :int -1))

(defconstant +double+inf+ (* 2 most-positive-double-float))
(defconstant +double-inf+ (* 2 most-negative-double-float))
(defconstant +double-nan+ (/ 0d0 0d0))
Besmear answered 8/6, 2017 at 21:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.