[Nickle] nickle: Branch 'master' - 2 commits

Keith Packard keithp at keithp.com
Sun Dec 8 14:11:21 PST 2024


 float.c          |    3 +++
 test/Makefile.am |    1 +
 test/fround.5c   |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 test/meson.build |    1 +
 4 files changed, 51 insertions(+)

New commits:
commit 9d6a3a79eef447420dbad2a0c17bd7dfcbc8f0f0
Author: Keith Packard <keithp at keithp.com>
Date:   Sun Dec 8 14:10:42 2024 -0800

    test: Add test for correct rounding when reducing float precision
    
    Make sure that reducing float precision rounds to even.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/test/Makefile.am b/test/Makefile.am
index 7748aab..94e9b76 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -11,6 +11,7 @@ check_SCRIPTS=\
 	hashtest.5c \
 	signal.5c \
 	round.5c \
+	fround.5c \
 	math.5c \
 	factorial.5c \
 	is_type.5c \
diff --git a/test/fround.5c b/test/fround.5c
new file mode 100644
index 0000000..efb4a97
--- /dev/null
+++ b/test/fround.5c
@@ -0,0 +1,46 @@
+exception bad_round (int last_bits, int prec, int dist, real computed, rational actual);
+
+void imprecise_check(int last_bits, int prec, int dist)
+{
+    int		power = prec - 1;
+    real	i = imprecise(1, prec + dist + 100);
+    real	f = 0;
+
+    /* add in the last bits */
+    f += last_bits * 2**(-power);
+
+    /* add in a bit just past the value */
+    f += 0.5 * 2**(-power);
+
+    /* Add in a bit far past the value if specified */
+    if (dist > 0)
+	f += 2**(-(power + dist));
+
+    real	computed = imprecise(i + f, prec);
+
+    rational	actual = 1;
+    bool	do_round = false;
+    int		last_actual_bits = last_bits;
+
+    if ((last_bits & 1) == 0) {
+	/* If the last bits are even, then round only if the frac is > 0.5 */
+	do_round = dist > 0;
+    } else {
+	/* Otherwise, always round */
+	do_round = true;
+    }
+    if (do_round)
+	last_actual_bits++;
+
+    actual += last_actual_bits * 2 ** (-power);
+
+    if (computed != actual) {
+	printf("computed %a actual %a\n", computed, actual);
+	raise bad_round(last_bits, prec, dist, computed, actual);
+    }
+}
+
+for(int last_bits = 0; last_bits < 8; last_bits++)
+    for(prec = 24; prec <= 57; prec++)
+	for (dist = 0; dist <= 64; dist++)
+	    imprecise_check(last_bits, prec, dist);
diff --git a/test/meson.build b/test/meson.build
index 04e32b6..963c4de 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -17,6 +17,7 @@ tests = [
   'hashtest.5c',
   'signal.5c',
   'round.5c',
+  'fround.5c',
   'math.5c',
   'factorial.5c',
   'is_type.5c',
commit 8165252d35460a57dafff2ae8b5a3b465bccca34
Author: Keith Packard <keithp at keithp.com>
Date:   Sun Dec 8 14:09:21 2024 -0800

    float: Check bits in the last chunk during round even
    
    Missed the last few bits of the value when checking for > 0.5
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/float.c b/float.c
index 9752578..4821f99 100644
--- a/float.c
+++ b/float.c
@@ -214,6 +214,9 @@ FpartRound (Fpart *a, int shift)
 	if (shift < 0) {
 	    last <<= 1;
 	    shift = 0;
+	} else {
+	    if (last & ((1 << shift) - 1))
+		round |= 1;
 	}
 	round |= (last >> shift) & 3;
     }


More information about the Nickle mailing list