Module Name:    src
Committed By:   bouyer
Date:           Thu Mar 15 11:24:46 UTC 2018

Modified Files:
        src/tests/lib/libc/locale [netbsd-8]: t_sprintf.c

Log Message:
Pull up following revision(s) (requested by martin in ticket #631):
        tests/lib/libc/locale/t_sprintf.c: revision 1.4
        tests/lib/libc/locale/t_sprintf.c: revision 1.5
        tests/lib/libc/locale/t_sprintf.c: revision 1.6
        tests/lib/libc/locale/t_sprintf.c: revision 1.7
Add some diagnostics to the strto test, so I can see why this
fails on i386 (on qemu) - will probably keep them when done.
When comparing doubles (any floating point values) which have been
computed using different methods, don't expect to achieve identical
results (here, one constant is perhaps converted to binary from a string by
a cross compiler, the other is converted at run time).   Allow them to
have a small difference (for now, small is < 1e-7 - the constant is ~ 1e5,
so this is 12 orders of magnitude less) before failing (and include the
actual difference in the error message if it does fail.)
Revert 1.4 (perhaps temporarily) and add even more diagnostics to those
added in 1.3 to see if it is possible to determine why the strict equality
test fails on i386, yet succeeds elsewhere.
Since the C standard allows for intermediate floating results to contain
more precision bits than the data type expects, but (kind of obviously)
does not allow such values to be stored in memory, expecting the value
returned from strtod() (an intermediate result) to be identical (that is,
equal) to a stored value is incorrect.
So instead go back to checking that the two numbers are very very close.
See comments added to the test for more explanation.


To generate a diff of this commit:
cvs rdiff -u -r1.1.2.2 -r1.1.2.3 src/tests/lib/libc/locale/t_sprintf.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/tests/lib/libc/locale/t_sprintf.c
diff -u src/tests/lib/libc/locale/t_sprintf.c:1.1.2.2 src/tests/lib/libc/locale/t_sprintf.c:1.1.2.3
--- src/tests/lib/libc/locale/t_sprintf.c:1.1.2.2	Thu Mar 15 09:55:23 2018
+++ src/tests/lib/libc/locale/t_sprintf.c	Thu Mar 15 11:24:46 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: t_sprintf.c,v 1.1.2.2 2018/03/15 09:55:23 martin Exp $ */
+/* $NetBSD: t_sprintf.c,v 1.1.2.3 2018/03/15 11:24:46 bouyer Exp $ */
 
 /*-
  * Copyright (c) 2017 The NetBSD Foundation, Inc.
@@ -32,9 +32,10 @@
 #include <sys/cdefs.h>
 __COPYRIGHT("@(#) Copyright (c) 2017\
  The NetBSD Foundation, inc. All rights reserved.");
-__RCSID("$NetBSD: t_sprintf.c,v 1.1.2.2 2018/03/15 09:55:23 martin Exp $");
+__RCSID("$NetBSD: t_sprintf.c,v 1.1.2.3 2018/03/15 11:24:46 bouyer Exp $");
 
 #include <locale.h>
+#include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -125,12 +126,51 @@ h_sprintf(const struct test *t)
 static void
 h_strto(const struct test *t)
 {
+	double d, diff;
+
 	ATF_REQUIRE_STREQ(setlocale(LC_ALL, "C"), "C");
 	printf("Trying locale %s...\n", t->locale);
 	ATF_REQUIRE(setlocale(LC_NUMERIC, t->locale) != NULL);
 
 	ATF_REQUIRE_EQ((int)strtol(t->int_input, NULL, 10), t->int_value);
-	ATF_REQUIRE_EQ(strtod(t->double_input, NULL), t->double_value);
+
+	/*
+	 * Note that the C standard permits function values to be
+	 * returned with more precision than is expected by (floating)
+	 * data types, and on i386 (and potentially other implementations)
+	 * that is exactly what happens, meaning that the result from
+	 * strtod() is not identical to the expected value - it turns out
+	 * that it is the same if the value is constrained to the number
+	 * of mantissa bits in a double (so the %a values printed below
+	 * show the exact same bit patterns) and on i386 -ffloat-store
+	 * will cause gcc to constrain the result that way, but nothing
+	 * demands that be true, so instead, we simply test that the
+	 * value returned is very very close to that expected.
+	 *
+	 * 1e-12 is chosen as the allowable delta, as we know (from
+	 * the data in the "struct test" earlier in this file) that
+	 * its magnitude is ~ 10^5, with values of that magnitude,
+	 * 10^-12 difference is a 10^-17 relative difference, and
+	 * with a 56 bit mantissa (standard IEEE "double") a difference
+	 * that small vanishes (requires at least 57 mantissa bits to
+	 * be representable).   If the data values were to change, then
+	 * so might this delta (if they were not all the same, we would
+	 * move the delta into the struct rather than having it a constant
+	 * here.).
+	 *
+	 * Finally, note that our purpose here is not to test floating
+	 * point arithmetic, we're testing locale dependent string to
+	 * binary conversions.
+	 */
+
+	d = (double)strtod(t->double_input, NULL);
+	diff = fabs(d - t->double_value);
+	if (diff >= 1e-12)
+		ATF_REQUIRE_EQ_MSG(d, t->double_value, "In %s: " 
+		    "d=strtod(t->double_input[%s], NULL)[%.12g = %a] != "
+		    "t->double_value[%.12g = %a]: diff=%g", t->locale,
+		    t->double_input, d, d, t->double_value, t->double_value,
+		    diff);
 }
 
 static void

Reply via email to