[m-rev.] for review: fix float_to_string so that roundtripping works

Peter Ross pro at missioncriticalit.com
Thu Nov 21 09:20:49 AEDT 2002


On Thu, Nov 21, 2002 at 04:20:04AM +1100, Fergus Henderson wrote:
> 
> Otherwise the interdiff looks good.
> But I'd like to double-check the full diff.
> 

Estimated hours taken: 8
Branches: main

Fix the I/O routines for floats so that can roundtrip.

library/string.m:
    Ensure that string__float_to_string returns a float that is
    round-trippable.  On the C backend we do that by starting at the min
    precision required and increasing it until the float roundtrips.
    This functionality is provided by ML_sprintf_float, so that it can
    be reused in io.m. On the IL backend the R flag guarantees that a
    double will be round-trippable, so we just use that.
    Change string__to_float so that it uses the format string for the
    precision float that we are using, and export this predicate for use
    by the trace system.
    Delete the unused string__float_to_f_string.

library/io.m:
    Print round-tripable floats in io__write_float.
    For the C backend use ML_sprintf_float to avoid unnecessary string
    allocation.  For other backends use string__float_to_string to
    generate a valid float.

trace/mercury_trace_util.c:
    Rather than duplicating the code from the library, call the code in
    the library.

tests/general/Mmakefile:
tests/general/float_roundtrip.exp:
tests/general/float_roundtrip.m:
    Test that floats roundtrip for different required miniumum
    precisions.

===============================================================================
diff -u library/io.m library/io.m
--- library/io.m	20 Nov 2002 16:25:52 -0000
+++ library/io.m	20 Nov 2002 21:05:51 -0000
@@ -1352,6 +1352,8 @@
 :- use_module table_builtin.
 :- use_module rtti_implementation.
 
+:- pragma foreign_import_module(c, string).
+
 :- type io__state ---> io__state(c_pointer).
 	% Values of type `io__state' are never really used:
 	% instead we store data in global variables.
diff -u library/string.m library/string.m
--- library/string.m	20 Nov 2002 16:42:19 -0000
+++ library/string.m	20 Nov 2002 21:29:54 -0000
@@ -1828,7 +1828,7 @@
 		[will_not_call_mercury, promise_pure, thread_safe], "{
 	char buf[ML_SPRINTF_FLOAT_BUF_SIZE];
 	ML_sprintf_float(buf, Flt);
-	MR_make_aligned_string(Str, buf);
+	MR_make_aligned_string_copy(Str, buf);
 }").
 
 :- pragma foreign_proc("C#",
@@ -1861,7 +1861,7 @@
 /*
 ** The size of the buffer to pass to ML_sprintf_float.
 **
-** Longest possible string for %.*g format is `-n.nnnnnnE-mmmm', which
+** Longest possible string for %#.*g format is `-n.nnnnnnE-mmmm', which
 ** has size  PRECISION + MAX_EXPONENT_DIGITS + 5 (for the `-', `.', `E',
 ** '-', and '\\0').  PRECISION is at most 20, and MAX_EXPONENT_DIGITS is
 ** at most 5, so we need at most 30 chars.  80 is way more than enough.
@@ -1872,12 +1872,25 @@
 ").
 
 :- pragma foreign_code(c, "
+/*
+** ML_sprintf_float(buf, f)
+**
+** fills buff with the string representation of the float, f, such that
+** the string representation has enough precision to represent the
+** float, f.
+**
+** Note that buf must have size at least ML_SPRINTF_FLOAT_BUF_SIZE.
+*/
 void
 ML_sprintf_float(char *buf, MR_Float f)
 {
 	MR_Float round;
 	int 	 i = ML_MIN_PRECISION;
 
+	/*
+	** Print the float at increasing precisions until the float
+	** is round-trippable.
+	*/
 	do {
 		sprintf(buf, ""%#.*g"", i, f);
 		if (i >= ML_MAX_PRECISION) {

===============================================================================
interdiff vs original:

diff -u library/io.m library/io.m
--- library/io.m	20 Nov 2002 10:43:29 -0000
+++ library/io.m	20 Nov 2002 21:05:51 -0000
@@ -1352,6 +1352,8 @@
 :- use_module table_builtin.
 :- use_module rtti_implementation.
 
+:- pragma foreign_import_module(c, string).
+
 :- type io__state ---> io__state(c_pointer).
 	% Values of type `io__state' are never really used:
 	% instead we store data in global variables.
@@ -4405,6 +4407,18 @@
 ").
 
 :- pragma foreign_proc("C",
+	io__write_float(Val::in, IO0::di, IO::uo),
+		[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+	char buf[ML_SPRINTF_FLOAT_BUF_SIZE];
+	ML_sprintf_float(buf, Val);
+	if (ML_fprintf(mercury_current_text_output, ""%s"", buf) < 0) {
+		mercury_output_error(mercury_current_text_output);
+	}
+	MR_update_io(IO0, IO);
+").
+
+:- pragma foreign_proc("C",
 	io__write_byte(Byte::in, IO0::di, IO::uo),
 		[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
 "
@@ -4659,6 +4673,19 @@
 }").
 
 :- pragma foreign_proc("C",
+	io__write_float(Stream::in, Val::in, IO0::di, IO::uo),
+		[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"{
+	MercuryFile *stream = (MercuryFile *) Stream;
+	char buf[ML_SPRINTF_FLOAT_BUF_SIZE];
+	ML_sprintf_float(buf, Val);
+	if (ML_fprintf(stream, ""%s"", buf) < 0) {
+		mercury_output_error(stream);
+	}
+	MR_update_io(IO0, IO);
+}").
+
+:- pragma foreign_proc("C",
 	io__write_byte(Stream::in, Byte::in, IO0::di, IO::uo),
 		[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
 "{
diff -u library/string.m library/string.m
--- library/string.m	20 Nov 2002 13:46:46 -0000
+++ library/string.m	20 Nov 2002 21:29:54 -0000
@@ -1826,45 +1826,21 @@
 :- pragma foreign_proc("C",
 	string__float_to_string(Flt::in, Str::uo),
 		[will_not_call_mercury, promise_pure, thread_safe], "{
-#ifdef MR_USE_SINGLE_PREC_FLOAT
-	#define MIN_PRECISION	7
-	const char *format = ""%f"";
-#else
-	#define MIN_PRECISION	15
-	const char *format = ""%lf"";
-#endif
-	int i = MIN_PRECISION;
-	MR_Float round;
-
-		/*
-		 * Round-trip the float to ensure the precision was 
-		 * sufficient, and if not then try with the next precision.
-		*/
-	Str = MR_make_string(MR_PROC_LABEL, ""%#.*g"", i, Flt);
-	sscanf(Str, format, &round);
-
-	while (round != Flt) {
-		i++;
-		Str = MR_make_string(MR_PROC_LABEL, ""#%.*g"", i, Flt);
-		sscanf(Str, format, &round);
-	}
+	char buf[ML_SPRINTF_FLOAT_BUF_SIZE];
+	ML_sprintf_float(buf, Flt);
+	MR_make_aligned_string_copy(Str, buf);
 }").
 
-:- pragma foreign_proc("il",
+:- pragma foreign_proc("C#",
 	string__float_to_string(FloatVal::in, FloatString::uo),
-	[will_not_call_mercury, promise_pure, thread_safe, max_stack_size(1)], "
-
-	ldloca	'FloatVal'
-	ldstr	""R""
+	[will_not_call_mercury, promise_pure, thread_safe], "
 
 		// The R format string prints the double out such that it
 		// can be round-tripped.
 		// XXX According to the documentation it tries the 15 digits of
 		// precision, then 17 digits skipping 16 digits of precision.
 		// unlike what we do for the C backend.
-	call instance string [mscorlib]System.Double::ToString(string)
-
-	stloc	'FloatString'
+	FloatString = FloatVal.ToString(""R"");
 ").
 
 string__float_to_string(_, _) :-
@@ -1872,21 +1848,80 @@
 	% matching foreign_proc version.
 	private_builtin__sorry("string__float_to_string").
 
+:- pragma foreign_decl(c, "
+#ifdef MR_USE_SINGLE_PREC_FLOAT
+  #define ML_MIN_PRECISION	7
+  #define ML_FMT		""%f""
+#else
+  #define ML_MIN_PRECISION	15
+  #define ML_FMT		""%lf""
+#endif
+#define ML_MAX_PRECISION	(ML_MIN_PRECISION + 2)
+
+/*
+** The size of the buffer to pass to ML_sprintf_float.
+**
+** Longest possible string for %#.*g format is `-n.nnnnnnE-mmmm', which
+** has size  PRECISION + MAX_EXPONENT_DIGITS + 5 (for the `-', `.', `E',
+** '-', and '\\0').  PRECISION is at most 20, and MAX_EXPONENT_DIGITS is
+** at most 5, so we need at most 30 chars.  80 is way more than enough.
+*/
+#define ML_SPRINTF_FLOAT_BUF_SIZE	80
+
+void ML_sprintf_float(char *buf, MR_Float f);
+").
+
+:- pragma foreign_code(c, "
+/*
+** ML_sprintf_float(buf, f)
+**
+** fills buff with the string representation of the float, f, such that
+** the string representation has enough precision to represent the
+** float, f.
+**
+** Note that buf must have size at least ML_SPRINTF_FLOAT_BUF_SIZE.
+*/
+void
+ML_sprintf_float(char *buf, MR_Float f)
+{
+	MR_Float round;
+	int 	 i = ML_MIN_PRECISION;
+
+	/*
+	** Print the float at increasing precisions until the float
+	** is round-trippable.
+	*/
+	do {
+		sprintf(buf, ""%#.*g"", i, f);
+		if (i >= ML_MAX_PRECISION) {
+			/*
+			** This should be sufficient precision to
+			** round-trip any value.  Don't bother checking
+			** whether it can actually be round-tripped,
+			** since if it can't, this is a bug in the C
+			** implementation.
+			*/
+			break;
+		}
+		sscanf(buf, ML_FMT, &round);
+		i++;
+	} while (round != f);
+}
+").
 
 :- pragma export(string__to_float(in, out), "ML_string_to_float").
 :- pragma foreign_proc("C",
 	string__to_float(FloatString::in, FloatVal::out),
 		[will_not_call_mercury, promise_pure, thread_safe], "{
-#ifdef MR_USE_SINGLE_PREC_FLOAT
-  #define FMT    """"
-#else
-  #define FMT    ""l""
-#endif
-
+	/*
+	** The %c checks for any erroneous characters appearing after
+	** the float; if there are then sscanf() will return 2 rather
+	** than 1.
+	*/
 	char   	tmpc;
 	SUCCESS_INDICATOR =
 		(!MR_isspace(FloatString[0])) &&
-		(sscanf(FloatString, ""%"" FMT ""f%c"", &FloatVal, &tmpc) == 1);
+		(sscanf(FloatString, ML_FMT ""%c"", &FloatVal, &tmpc) == 1);
 		/* MR_TRUE if sscanf succeeds, MR_FALSE otherwise */
 }").
 
===============================================================================
full diff:

Index: library/io.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/io.m,v
retrieving revision 1.276
diff -u -r1.276 io.m
--- library/io.m	6 Nov 2002 04:30:47 -0000	1.276
+++ library/io.m	20 Nov 2002 21:05:51 -0000
@@ -1352,6 +1352,8 @@
 :- use_module table_builtin.
 :- use_module rtti_implementation.
 
+:- pragma foreign_import_module(c, string).
+
 :- type io__state ---> io__state(c_pointer).
 	% Values of type `io__state' are never really used:
 	% instead we store data in global variables.
@@ -4408,7 +4410,9 @@
 	io__write_float(Val::in, IO0::di, IO::uo),
 		[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
 "
-	if (ML_fprintf(mercury_current_text_output, ""%#.15g"", Val) < 0) {
+	char buf[ML_SPRINTF_FLOAT_BUF_SIZE];
+	ML_sprintf_float(buf, Val);
+	if (ML_fprintf(mercury_current_text_output, ""%s"", buf) < 0) {
 		mercury_output_error(mercury_current_text_output);
 	}
 	MR_update_io(IO0, IO);
@@ -4501,14 +4505,6 @@
 ").
 
 :- pragma foreign_proc("MC++",
-	io__write_float(Val::in, IO0::di, IO::uo),
-		[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
-"
-	mercury_print_string(mercury_current_text_output, Val.ToString());
-	MR_update_io(IO0, IO);
-").
-
-:- pragma foreign_proc("MC++",
 	io__write_byte(Byte::in, IO0::di, IO::uo),
 		[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
 "
@@ -4555,10 +4551,8 @@
 	% matching foreign_proc version.
 	{ private_builtin__sorry("io__write_int") }.
 
-io__write_float(_) -->
-	% This version is only used for back-ends for which there is no
-	% matching foreign_proc version.
-	{ private_builtin__sorry("io__write_float") }.
+io__write_float(Float) -->
+	io__write_string(string__float_to_string(Float)).
 
 io__write_byte(_) -->
 	% This version is only used for back-ends for which there is no
@@ -4683,7 +4677,9 @@
 		[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
 "{
 	MercuryFile *stream = (MercuryFile *) Stream;
-	if (ML_fprintf(stream, ""%#.15g"", Val) < 0) {
+	char buf[ML_SPRINTF_FLOAT_BUF_SIZE];
+	ML_sprintf_float(buf, Val);
+	if (ML_fprintf(stream, ""%s"", buf) < 0) {
 		mercury_output_error(stream);
 	}
 	MR_update_io(IO0, IO);
@@ -4782,16 +4778,6 @@
 }").
 
 :- pragma foreign_proc("MC++",
-	io__write_float(Stream::in, Val::in, IO0::di, IO::uo),
-		[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
-"{
-	MR_MercuryFile stream = ML_DownCast(MR_MercuryFile, 
-		MR_word_to_c_pointer(Stream));
-	mercury_print_string(stream, Val.ToString());
-	MR_update_io(IO0, IO);
-}").
-
-:- pragma foreign_proc("MC++",
 	io__write_byte(Stream::in, Byte::in, IO0::di, IO::uo),
 		[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
 "{
@@ -4846,10 +4832,8 @@
 	% matching foreign_proc version.
 	{ private_builtin__sorry("io__write_int") }.
 
-io__write_float(_, _) -->
-	% This version is only used for back-ends for which there is no
-	% matching foreign_proc version.
-	{ private_builtin__sorry("io__write_float") }.
+io__write_float(Stream, Float) -->
+	io__write_string(Stream, string__float_to_string(Float)).
 
 io__write_byte(_, _) -->
 	% This version is only used for back-ends for which there is no
Index: library/string.m
===================================================================
RCS file: /home/staff/zs/imp/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	20 Nov 2002 21:29:54 -0000
@@ -1824,76 +1824,105 @@
 %-----------------------------------------------------------------------------%
 
 :- 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);
+	char buf[ML_SPRINTF_FLOAT_BUF_SIZE];
+	ML_sprintf_float(buf, Flt);
+	MR_make_aligned_string_copy(Str, buf);
 }").
 
-:- 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);
-}").
+	[will_not_call_mercury, promise_pure, thread_safe], "
+
+		// The R format string prints the double out such that it
+		// can be round-tripped.
+		// XXX According to the documentation it tries the 15 digits of
+		// precision, then 17 digits skipping 16 digits of precision.
+		// unlike what we do for the C backend.
+	FloatString = FloatVal.ToString(""R"");
+").
 
 string__float_to_string(_, _) :-
 	% This version is only used for back-ends for which there is no
 	% matching foreign_proc version.
 	private_builtin__sorry("string__float_to_string").
 
+:- pragma foreign_decl(c, "
+#ifdef MR_USE_SINGLE_PREC_FLOAT
+  #define ML_MIN_PRECISION	7
+  #define ML_FMT		""%f""
+#else
+  #define ML_MIN_PRECISION	15
+  #define ML_FMT		""%lf""
+#endif
+#define ML_MAX_PRECISION	(ML_MIN_PRECISION + 2)
+
+/*
+** The size of the buffer to pass to ML_sprintf_float.
+**
+** Longest possible string for %#.*g format is `-n.nnnnnnE-mmmm', which
+** has size  PRECISION + MAX_EXPONENT_DIGITS + 5 (for the `-', `.', `E',
+** '-', and '\\0').  PRECISION is at most 20, and MAX_EXPONENT_DIGITS is
+** at most 5, so we need at most 30 chars.  80 is way more than enough.
+*/
+#define ML_SPRINTF_FLOAT_BUF_SIZE	80
+
+void ML_sprintf_float(char *buf, MR_Float f);
+").
+
+:- pragma foreign_code(c, "
+/*
+** ML_sprintf_float(buf, f)
+**
+** fills buff with the string representation of the float, f, such that
+** the string representation has enough precision to represent the
+** float, f.
+**
+** Note that buf must have size at least ML_SPRINTF_FLOAT_BUF_SIZE.
+*/
+void
+ML_sprintf_float(char *buf, MR_Float f)
+{
+	MR_Float round;
+	int 	 i = ML_MIN_PRECISION;
 
-	% Beware that the implementation of string__format depends
-	% on the details of what string__float_to_f_string/2 outputs.
-
-:- pred string__float_to_f_string(float::in, string::out) is det.
-
-:- pragma foreign_proc("C",
-	string__float_to_f_string(FloatVal::in, FloatString::out),
-		[will_not_call_mercury, promise_pure, thread_safe], "{
-	char buf[500];
-	sprintf(buf, ""%.15f"", FloatVal);
-	MR_allocate_aligned_string_msg(FloatString, strlen(buf), MR_PROC_LABEL);
-	strcpy(FloatString, buf);
-}").
-
-:- pragma foreign_proc("MC++",
-	string__float_to_f_string(FloatVal::in, FloatString::out),
-		[will_not_call_mercury, promise_pure, thread_safe], "{
-	FloatString = System::Convert::ToString(FloatVal);
-}").
-
-string__float_to_f_string(_, _) :-
-	% This version is only used for back-ends for which there is no
-	% matching foreign_proc version.
-	private_builtin__sorry("string__float_to_f_string").
+	/*
+	** Print the float at increasing precisions until the float
+	** is round-trippable.
+	*/
+	do {
+		sprintf(buf, ""%#.*g"", i, f);
+		if (i >= ML_MAX_PRECISION) {
+			/*
+			** This should be sufficient precision to
+			** round-trip any value.  Don't bother checking
+			** whether it can actually be round-tripped,
+			** since if it can't, this is a bug in the C
+			** implementation.
+			*/
+			break;
+		}
+		sscanf(buf, ML_FMT, &round);
+		i++;
+	} while (round != f);
+}
+").
 
+:- pragma export(string__to_float(in, out), "ML_string_to_float").
 :- pragma foreign_proc("C",
 	string__to_float(FloatString::in, FloatVal::out),
 		[will_not_call_mercury, promise_pure, thread_safe], "{
 	/*
-	** Use a temporary, since we can't don't know whether FloatVal is a
-	** double or float.  The %c checks for any erroneous characters
-	** appearing after the float; if there are then sscanf() will
-	** return 2 rather than 1.
-	**
-	** The logic used here is duplicated in the function MR_trace_is_float
-	** in trace/mercury_trace_util.c.
+	** The %c checks for any erroneous characters appearing after
+	** the float; if there are then sscanf() will return 2 rather
+	** than 1.
 	*/
-	double tmpf;
-	char   tmpc;
+	char   	tmpc;
 	SUCCESS_INDICATOR =
 		(!MR_isspace(FloatString[0])) &&
-		(sscanf(FloatString, ""%lf%c"", &tmpf, &tmpc) == 1);
+		(sscanf(FloatString, ML_FMT ""%c"", &FloatVal, &tmpc) == 1);
 		/* MR_TRUE if sscanf succeeds, MR_FALSE otherwise */
-	FloatVal = tmpf;
-}").
-
-:- pragma foreign_proc("MC++",
-	string__float_to_f_string(FloatVal::in, FloatString::out),
-		[will_not_call_mercury, promise_pure, thread_safe], "{
-	FloatString = System::Convert::ToString(FloatVal);
 }").
 
 :- pragma foreign_proc("MC++",
Index: tests/general/Mmakefile
===================================================================
RCS file: /home/staff/zs/imp/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	20 Nov 2002 10:43:30 -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	20 Nov 2002 10:43:30 -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	20 Nov 2002 16:42:19 -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).
Index: trace/mercury_trace_util.c
===================================================================
RCS file: /home/staff/zs/imp/mercury/trace/mercury_trace_util.c,v
retrieving revision 1.9
diff -u -r1.9 mercury_trace_util.c
--- trace/mercury_trace_util.c	15 Nov 2002 04:50:49 -0000	1.9
+++ trace/mercury_trace_util.c	20 Nov 2002 10:43:30 -0000
@@ -15,6 +15,8 @@
 #include "mercury_trace_util.h"
 #include "mercury_file.h"
 
+#include "string.mh"
+
 #include <ctype.h>
 
 void
@@ -74,17 +76,7 @@
 MR_bool
 MR_trace_is_float(const char *word, MR_Float *value)
 {
-	double	tmpf;
-	char   	tmpc;
-	MR_bool	success;
-
-	/* this duplicates the logic of string__to_float */
-	success =
-		(!MR_isspace(word[0])) &&
-		(sscanf(word, "%lf%c", &tmpf, &tmpc) == 1);
-		/* MR_TRUE if sscanf succeeds, MR_FALSE otherwise */
-	*value = tmpf;
-	return success;
+	return ML_string_to_float((MR_String) word, value);
 }
 
 void

--------------------------------------------------------------------------
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