• Convert inexact reals into binary IEEE 754 double format

    From =?UTF-8?Q?Marc_Nieper=2DWi=C3=9Fkir@21:1/5 to All on Mon Oct 7 13:17:38 2019
    Hi,

    does anyone know about an existing implementation of a procedure, say `real->binary64', that takes a Scheme real number `x' and returns a bytevector containing the binary64 representation (in any endianess) of an IEEE 754 double, which is closest to `x'?

    In particular, for a Scheme system whose inexact reals are implemented using IEEE doubles, this procedure should be a bijection (perhaps modulo NaNs).

    Thanks for looking into it.

    -- Marc

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From John Cowan@21:1/5 to All on Mon Oct 7 18:12:39 2019
    On Monday, October 7, 2019 at 4:17:41 PM UTC-4, Marc Nieper-Wißkirchen wrote:

    does anyone know about an existing implementation of a procedure, say `real->binary64', that takes a Scheme real number `x' and returns a bytevector containing the binary64 representation (in any endianess) of an IEEE 754 double, which is closest to `x'
    ?

    In particular, for a Scheme system whose inexact reals are implemented using IEEE doubles, this procedure should be a bijection (perhaps modulo NaNs).

    There's a portable implementation at https://github.com/scheme-requests-for-implementation/srfi-4/blob/master/contrib/cowan/r6rs/bytevectors-impl.scm. It's not very efficient unless you have a fast compiler, though. Chibi has a C implementation and so
    does Chicken; both of them are trivial.

    --
    John Cowan http://vrici.lojban.org/~cowan cowan@ccil.org
    One Word to write them all / One Access to find them,
    One Excel to count them all / And thus to Windows bind them.
    --Mike Champion

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Marc_Nieper=2DWi=C3=9Fkir@21:1/5 to All on Mon Oct 7 22:59:56 2019
    Am Dienstag, 8. Oktober 2019 03:12:41 UTC+2 schrieb John Cowan:
    On Monday, October 7, 2019 at 4:17:41 PM UTC-4, Marc Nieper-Wißkirchen wrote:

    does anyone know about an existing implementation of a procedure, say `real->binary64', that takes a Scheme real number `x' and returns a bytevector containing the binary64 representation (in any endianess) of an IEEE 754 double, which is closest to `
    x'?

    In particular, for a Scheme system whose inexact reals are implemented using IEEE doubles, this procedure should be a bijection (perhaps modulo NaNs).

    There's a portable implementation at https://github.com/scheme-requests-for-implementation/srfi-4/blob/master/contrib/cowan/r6rs/bytevectors-impl.scm. It's not very efficient unless you have a fast compiler, though. Chibi has a C implementation and
    so does Chicken; both of them are trivial.

    Dear John,

    thanks a lot. The portable implementation you called my attention for is exactly what I was looking for!

    Cheers,

    Marc


    --
    John Cowan http://vrici.lojban.org/~cowan cowan@ccil.org
    One Word to write them all / One Access to find them,
    One Excel to count them all / And thus to Windows bind them.
    --Mike Champion

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hans Aberg@21:1/5 to All on Tue Oct 8 22:07:17 2019
    On 2019-10-07 22:17, Marc Nieper-Wißkirchen wrote:

    does anyone know about an existing implementation of a procedure, say `real->binary64', that takes a Scheme real number `x' and returns a bytevector containing the binary64 representation (in any endianess) of an IEEE 754 double, which is closest to `x'
    ?

    Maybe implementations that use the GMP extension MPFR, which is a
    natural extension of IEEE P754 according to the GMP manual. Guile uses
    GMP at least and has a C interface that extracts the double.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dr.marc.feeley@gmail.com@21:1/5 to All on Sat Oct 26 14:57:14 2019
    On Monday, October 7, 2019 at 4:17:41 PM UTC-4, Marc Nieper-Wißkirchen wrote:
    Hi,

    does anyone know about an existing implementation of a procedure, say `real->binary64', that takes a Scheme real number `x' and returns a bytevector containing the binary64 representation (in any endianess) of an IEEE 754 double, which is closest to `x'
    ?

    In particular, for a Scheme system whose inexact reals are implemented using IEEE doubles, this procedure should be a bijection (perhaps modulo NaNs).

    Thanks for looking into it.

    -- Marc

    Here's some code from the Gambit compiler in vanilla Scheme.

    Marc

    ;; The following procedures convert floating point numbers into their
    ;; ANSI-IEEE Std 754-1985 representation (32 bit and 64 bit floats).
    ;; They perform bignum and flonum arithmetic.

    (define inexact-+2 (exact->inexact 2))
    (define inexact--2 (exact->inexact -2))
    (define inexact-+1 (exact->inexact 1))
    (define inexact-+1/2 (exact->inexact (/ 1 2)))
    (define inexact-+0 (exact->inexact 0))

    (define (float->inexact-exponential-format x f64?)
    (let* ((e-bits (if f64? 11 8))
    (e-bias (- (expt 2 (- e-bits 1)) 1)))

    (define (float-copysign x y)
    (if (negative? y)
    (- x)
    x))

    (define (exp-form-pos x y i)
    (let ((i*2 (+ i i)))
    (let ((z (if (and (not (< e-bias i*2))
    (not (< x y)))
    (exp-form-pos x (* y y) i*2)
    (vector x 0 1))))
    (let ((a (vector-ref z 0)) (b (vector-ref z 1)))
    (let ((i+b (+ i b)))
    (if (and (not (< e-bias i+b))
    (not (< a y)))
    (begin
    (vector-set! z 0 (/ a y))
    (vector-set! z 1 i+b)))
    z)))))

    (define (exp-form-neg x y i)
    (let ((i*2 (+ i i)))
    (let ((z (if (and (< i*2 (- e-bias 1))
    (< x y))
    (exp-form-neg x (* y y) i*2)
    (vector x 0 1))))
    (let ((a (vector-ref z 0)) (b (vector-ref z 1)))
    (let ((i+b (+ i b)))
    (if (and (< i+b (- e-bias 1))
    (< a y))
    (begin
    (vector-set! z 0 (/ a y))
    (vector-set! z 1 i+b)))
    z)))))

    (define (exp-form x)
    (if (< x inexact-+1)
    (let ((z (exp-form-neg x inexact-+1/2 1)))
    (vector-set! z 0 (* inexact-+2 (vector-ref z 0)))
    (vector-set! z 1 (- -1 (vector-ref z 1)))
    z)
    (exp-form-pos x inexact-+2 1)))

    (if (negative? (float-copysign inexact-+1 x))
    (let ((z (exp-form (float-copysign x inexact-+1))))
    (vector-set! z 2 -1)
    z)
    (exp-form x))))

    (define (float->exact-exponential-format x f64?)
    (let* ((z (float->inexact-exponential-format x f64?))
    (m-bits (if f64? 52 23))
    (e-bits (if f64? 11 8)))

    (let ((y (vector-ref z 0)))
    (if (not (< y inexact-+2)) ;; +inf.0 or +nan.0?
    (begin
    (if (< inexact-+0 y)
    (vector-set! z 0 (expt 2 m-bits)) ;; +inf.0
    (vector-set! z 0 (- (* (expt 2 m-bits) 2) 1))) ;; +nan.0
    (vector-set! z 1 (expt 2 (- e-bits 1))))
    (vector-set! z 0
    (truncate
    (inexact->exact
    (* (vector-ref z 0)
    (exact->inexact (expt 2 m-bits)))))))
    (vector-set! z 1 (- (vector-ref z 1) m-bits))
    z)))

    (define (float->bits x f64?)
    (let ((m-bits (if f64? 52 23))
    (e-bits (if f64? 11 8)))

    (define (bits a b)
    (let ((m-min (expt 2 m-bits)))
    (if (< a m-min)
    a
    (+ (- a m-min)
    (* (+ (+ b m-bits) (- (expt 2 (- e-bits 1)) 1))
    m-min)))))

    (let* ((z (float->exact-exponential-format x f64?))
    (y (bits (vector-ref z 0) (vector-ref z 1))))
    (if (negative? (vector-ref z 2))
    (+ (expt 2 (+ e-bits m-bits)) y)
    y))))

    (println (number->string (float->bits 1.5 #t) 16)) ;; 3ff8000000000000
    (println (number->string (float->bits 1.5 #f) 16)) ;; 3fc00000

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)