egallesio / STklos

STklos Scheme
http://stklos.net
GNU General Public License v2.0
69 stars 17 forks source link

Portable, simpler and faster `decode-float` + a new `encode-float`, inspired by Gauche (and some tests) #517

Closed jpellegrini closed 1 year ago

jpellegrini commented 1 year ago

@egallesio even one more PR...

1. DECODE-FLOAT

decode-float, as implemented currently, will not work on at least one machine on which I have tried (this could be due to endianness or to the other machine not implementing IEEE doubles as expected).

This patch implements a new version of this procedure, using something similar to what ECL does for the Common Lisp function integer-decode-float.

It seems also that this version is faster than the previous one:

(let ((a 0))
  (time
    (repeat 10_000_000
      (set! a (decode-float 1.0001))))
  a)

With the current version in STklos, the average time to run this on my machine is 1151.116 ms. With the new version, it is 882.717 ms.

Also, the code does deal correctly with subnormal numbers (which ECL does not -- I have changed it a little bit).

It also returns #t and #f in the significand for NaNs and infinites, as the previous version did.

As a bonus, the code is now simpler.

2. ENCODE-FLOAT

Inspired by Gauche, I also implemented encode-float, and three auxiliary procedures:

These will give the range of possible values to be used when calling encode-float.

The encode-float function also interprets #t and #f in the significand to produce NaNs and infinities.

3. ENCODE-FLOAT AND DECODE-FLOAT TESTS

I have included a number of tests...

jpellegrini commented 1 year ago

average time to run this on my machine is 1151.116 ms. With the new version, it is 882.717 ms

Probably because I did not use Scheme arithmetic... Only conversion between doubles and reals is used (and that one is very cheap).

jpellegrini commented 1 year ago

Oh, there is one change from the previous version: Gauche (and STkos) return 0 -1074 1 for zero, but zero should be 0 0 1 according to the IEEE standards for floating point numbers. And everyone else returns 0 0 1 (Chez, Clisp, ECL, GCL, SBCL)... So I made this procedure return that too.

Correction:

I forgot the bias. A zero float is all bits zero, but with the IEEE bias, it becomes -1074, so that is the exponent for 0.0. But everyone except Gauche seems to prefer "0 0 1"... What do you think @egallesio ?

egallesio commented 1 year ago

Great! Thanks, @jpellegrini.