[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