From d4028f953bee3eb33fddd9a8cd7ba8cb7d181292 Mon Sep 17 00:00:00 2001 From: Alex Shinn Date: Sun, 2 Jun 2024 22:31:25 +0900 Subject: [PATCH] Tentatively manually encoding non-finite f16 values. Issue #988. --- lib/srfi/160/mini-test.sld | 8 ++++++-- sexp.c | 19 +++++++++++++------ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/lib/srfi/160/mini-test.sld b/lib/srfi/160/mini-test.sld index a0d7cd1b..661184d4 100644 --- a/lib/srfi/160/mini-test.sld +++ b/lib/srfi/160/mini-test.sld @@ -1,6 +1,6 @@ (define-library (srfi 160 mini-test) - (import (scheme base) + (import (scheme base) (scheme inexact) (srfi 160 base) (srfi 160 f8) (srfi 160 f16) (chibi test)) (export run-tests) @@ -82,7 +82,11 @@ (test '#f16(1 2) (vector->f16vector '#(0 1 2 3) 1 3)) (test '#(1.0 2.0) - (f16vector->vector '#f16(0 1 2 3) 1 3)) + (f16vector->vector '#f16(0 1 2 3) 1 3)) + (test '(-inf.0 -1.0 -0.0 0.0 1.0 +inf.0) + (f16vector->list + '#f16(-inf.0 -1.0 -0.0 0.0 1.0 +inf.0))) + (test-assert (nan? (f16vector-ref '#f16(+nan.0) 0))) ) (test-end)))) diff --git a/sexp.c b/sexp.c index 1b6be3c0..9f809758 100644 --- a/sexp.c +++ b/sexp.c @@ -3206,16 +3206,23 @@ static float int_as_float(const unsigned int n) { /* https://arxiv.org/abs/2112.08926 */ double sexp_half_to_double(unsigned short x) { - unsigned int e = (x&0x7C00)>>10, - m = (x&0x03FF)<<13, - v = float_as_int((float)m)>>23; + unsigned int e, m, v; + if (x == 31744) return INFINITY; + if (x == 32767) return NAN; + if (x == 64512) return -INFINITY; + e = (x&0x7C00)>>10; + m = (x&0x03FF)<<13; + v = float_as_int((float)m)>>23; return int_as_float((x&0x8000)<<16 | (e!=0)*((e+112)<<23|m) | ((e==0)&(m!=0))*((v-37)<<23|((m<<(150-v))&0x007FE000))); } unsigned short sexp_double_to_half(double x) { - unsigned int b = float_as_int(x)+0x00001000, - e = (b&0x7F800000)>>23, - m = b&0x007FFFFF; + unsigned int b, e, m; + if (isnan(x)) return 32767; + if (isinf(x)) return x < 0 ? 64512 : 31744; + b = float_as_int(x)+0x00001000; + e = (b&0x7F800000)>>23; + m = b&0x007FFFFF; return (b&0x80000000)>>16 | (e>112)*((((e-112)<<10)&0x7C00)|m>>13) | ((e<113)&(e>101))*((((0x007FF000+m)>>(125-e))+1)>>1) | (e>143)*0x7FFF; } #endif