[m-rev.] for review: fix bug in MR_sprintf_float
Ian MacLarty
maclarty at csse.unimelb.edu.au
Fri Jul 16 13:50:29 AEST 2010
Still bootchecking this, but it passes float_roundtrip and
test_pretty_print.
runtime/mercury_float.c:
Fix a bug in MR_sprintf_float where it would convert 1.8e-10
into "1.80000000000000e-1" instead of "1.8e-10".
The problem was that it was stripping the zeros off the end of the string
produced by sprintf without considering the case where the output
was in scientific notation.
The fix is to remove the `#' from the sprintf format string and then to
append ".0" to the string if there is no "." or "e".
tests/general/float_roundtrip.m:
tests/general/float_roundtrip.exp:
Add regression test.
Index: runtime/mercury_float.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_float.c,v
retrieving revision 1.10
diff -u -r1.10 mercury_float.c
--- runtime/mercury_float.c 15 Feb 2007 00:41:49 -0000 1.10
+++ runtime/mercury_float.c 16 Jul 2010 03:42:32 -0000
@@ -73,7 +73,7 @@
** is round-trippable.
*/
do {
- sprintf(buf, "%#.*g", i, f);
+ sprintf(buf, "%.*g", i, f);
if (i >= MR_FLT_MAX_PRECISION) {
/*
** This should be sufficient precision to round-trip any value.
@@ -87,30 +87,18 @@
} while (round_trip != f);
/*
- ** Strip redundant trailing zeroes from the string (this behaviour
- ** for %g is suppressed by the # modifier).
+ ** Append ".0" if there is no "e" or "." in the string.
*/
- for (n = strlen(buf) - 1; n > 0; n--) {
- switch (buf[n]) {
- case '.':
- buf[n + 2] = '\0';
- return;
- case '0':
- continue;
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- buf[n + 1] = '\0';
- return;
- default:
- return;
+ while (1) {
+ if (*buf == 'e' || *buf == '.') {
+ return;
}
+ if (*buf == '\0') {
+ /* We only get here if there is no '.' or 'e' in the string. */
+ strcpy(buf, ".0");
+ return;
+ }
+ buf++;
}
return;
Index: tests/general/float_roundtrip.exp
===================================================================
RCS file: /home/mercury1/repository/tests/general/float_roundtrip.exp,v
retrieving revision 1.1
diff -u -r1.1 float_roundtrip.exp
--- tests/general/float_roundtrip.exp 21 Nov 2002 08:00:58 -0000 1.1
+++ tests/general/float_roundtrip.exp 16 Jul 2010 03:42:33 -0000
@@ -2,3 +2,4 @@
0.123573124 : success.
0.987654321012345 : success.
0.12345678901234566 : success.
+1.8e-10 : success.
Index: tests/general/float_roundtrip.m
===================================================================
RCS file: /home/mercury1/repository/tests/general/float_roundtrip.m,v
retrieving revision 1.1
diff -u -r1.1 float_roundtrip.m
--- tests/general/float_roundtrip.m 21 Nov 2002 08:00:58 -0000 1.1
+++ tests/general/float_roundtrip.m 16 Jul 2010 03:42:33 -0000
@@ -14,7 +14,8 @@
test_float(7, 0.9092974),
test_float(9, 0.123573124),
test_float(15, 0.987654321012345),
- test_float(17, 0.12345678901234566).
+ test_float(17, 0.12345678901234566),
+ test_float_roundtrippable(1.8e-10).
:- pred test_float(int::in, float::in, io::di, io::uo) is det.
@@ -35,6 +36,16 @@
io__write_string(" digits of precision.\n")
).
+:- pred test_float_roundtrippable(float::in, io::di, io::uo) is det.
+
+test_float_roundtrippable(Flt, !IO) :-
+ ( roundtrip_float(Flt) ->
+ io.format("%-20s: ", [s(string.float_to_string(Flt))], !IO),
+ io.write_string("success.\n", !IO)
+ ;
+ io.format("failed to roundtrip %f\n", [f(Flt)], !IO)
+ ).
+
% Test that when we round-trip the float that we get the same float
% back.
:- pred roundtrip_float(float::in) is semidet.
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to: mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions: mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------
More information about the reviews
mailing list