[m-rev.] for review: fix float_to_string so that roundtripping works
Peter Ross
pro at missioncriticalit.com
Wed Nov 20 03:53:51 AEDT 2002
Hi,
===================================================================
Estimated hours taken: 5
Branches: main
Fix a bug where floats couldn't be roundtripped via a string.
library/string.m:
When converting a string to a float check before returning the
string that it can be roundtripped, if not then output it with
an increased precision.
tests/general/Mmakefile:
tests/general/float_roundtrip.exp:
tests/general/float_roundtrip.m:
A test case.
Index: library/string.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/string.m,v
retrieving revision 1.184
diff -u -r1.184 string.m
--- library/string.m 15 Nov 2002 04:50:37 -0000 1.184
+++ library/string.m 19 Nov 2002 16:47:37 -0000
@@ -1824,18 +1824,36 @@
%-----------------------------------------------------------------------------%
:- pragma foreign_proc("C",
- string__float_to_string(FloatVal::in, FloatString::uo),
+ string__float_to_string(Flt::in, Str::uo),
[will_not_call_mercury, promise_pure, thread_safe], "{
- char buf[500];
- sprintf(buf, ""%#.15g"", FloatVal);
- MR_allocate_aligned_string_msg(FloatString, strlen(buf), MR_PROC_LABEL);
- strcpy(FloatString, buf);
+#ifdef MR_USE_SINGLE_PREC_FLOAT
+ const char *format_a = ""%.7g"";
+ const char *format_b = ""%.9g"";
+ const char *format_r = ""%f"";
+ float round;
+#else
+ const char *format_a = ""%.15g"";
+ const char *format_b = ""%.17g"";
+ const char *format_r = ""%lf"";
+ double round;
+#endif
+ Str = MR_make_string(MR_PROC_LABEL, format_a, Flt);
+
+ /*
+ * Round-trip the float to ensure the precision was
+ * sufficient, and if not try with the next precision.
+ */
+ sscanf(Str, format_r, &round);
+ if (round != Flt)
+ {
+ Str = MR_make_string(MR_PROC_LABEL, format_b, Flt);
+ }
}").
-:- pragma foreign_proc("MC++",
+:- pragma foreign_proc("C#",
string__float_to_string(FloatVal::in, FloatString::uo),
[will_not_call_mercury, promise_pure, thread_safe], "{
- FloatString = System::Convert::ToString(FloatVal);
+ FloatString = FloatVal.ToString(""R"");
}").
string__float_to_string(_, _) :-
Index: tests/general/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/general/Mmakefile,v
retrieving revision 1.46
diff -u -r1.46 Mmakefile
--- tests/general/Mmakefile 19 Nov 2002 09:42:14 -0000 1.46
+++ tests/general/Mmakefile 19 Nov 2002 16:47:42 -0000
@@ -21,6 +21,7 @@
duplicate_label \
environment \
fail_detism \
+ float_roundtrip \
float_test \
frameopt_mkframe_bug \
hello_again \
Index: tests/general/float_roundtrip.exp
===================================================================
RCS file: tests/general/float_roundtrip.exp
diff -N tests/general/float_roundtrip.exp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/general/float_roundtrip.exp 19 Nov 2002 16:47:43 -0000
@@ -0,0 +1,4 @@
+0.9092974 : success.
+0.123573124 : success.
+0.987654321012345 : success.
+0.12345678901234566 : success.
Index: tests/general/float_roundtrip.m
===================================================================
RCS file: tests/general/float_roundtrip.m
diff -N tests/general/float_roundtrip.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/general/float_roundtrip.m 19 Nov 2002 16:47:43 -0000
@@ -0,0 +1,44 @@
+% Test that we roundtrip floats.
+:- module float_roundtrip.
+
+:- interface.
+
+:- import_module io.
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module int, list, string.
+
+main -->
+ test_float(7, 0.9092974),
+ test_float(9, 0.123573124),
+ test_float(15, 0.987654321012345),
+ test_float(17, 0.12345678901234566).
+
+:- pred test_float(int::in, float::in, io::di, io::uo) is det.
+
+test_float(ReqPrecision, Float) -->
+ { FloatStr = string__format("%." ++ int_to_string(ReqPrecision) ++ "g",
+ [f(Float)]) },
+ { Precision = string__length(FloatStr) - 2 },
+ io__format("%-20s: ", [s(FloatStr)]),
+ ( { Precision = ReqPrecision } ->
+ ( { roundtrip_float(Float) } ->
+ io__write_string("success.\n")
+ ;
+ io__write_string("failed.\n")
+ )
+ ;
+ io__write_string("failed as only "),
+ io__write_int(Precision),
+ io__write_string(" digits of precision.\n")
+ ).
+
+ % Test that when we round-trip the float that we get the same float
+ % back.
+:- pred roundtrip_float(float::in) is semidet.
+
+roundtrip_float(Float) :-
+ float_to_string(Float, String),
+ string__to_float(String, Float).
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list