[m-rev.] for review: mercury implementation of float_to_string
Peter Ross
pro at missioncriticalit.com
Sat Nov 23 03:43:33 AEDT 2002
On Sat, Nov 23, 2002 at 02:44:33AM +1100, Simon Taylor wrote:
> You should document the difference between lowlevel_float_to_string
> and float_to_string, explaining why both are needed.
>
Estimated hours taken: 2
Branches: main
Provide a mercury implementation of string__float_to_string. This is
needed so that string__float_to_string returns the same output on all
backends.
library/string.m:
Implementation of string__float_to_string in Mercury by using
string__format.
inter diff:
diff -u library/string.m library/string.m
--- library/string.m
+++ library/string.m
@@ -96,6 +96,9 @@
:- pred string__float_to_string(float, string).
:- mode string__float_to_string(in, uo) is det.
% Convert an float to a string.
+% The resulting float will be in the form that it was printed using
+% the format string "%#.<prec>g" where <prec> is the required precision
+% needed to represent the string.
:- pred string__first_char(string, char, string).
:- mode string__first_char(in, in, in) is semidet. % implied
@@ -1866,6 +1869,12 @@
:- func max_precision = int.
max_precision = 17.
+% string__lowlevel_float_to_string differs from string__float_to_string in
+% that it must be implemented in a foreign language as this is the predicate
+% string__format uses to get the initial string representation of a float.
+% Also while its output must represent the float to sufficient precision, it
+% doesn't need to be in *exactly* the same format as if was formated with
+% "%#.<prec>g".
:- pred string__lowlevel_float_to_string(float, string).
:- mode string__lowlevel_float_to_string(in, uo) is det.
@@ -1873,7 +1882,7 @@
string__lowlevel_float_to_string(Flt::in, Str::uo),
[will_not_call_mercury, promise_pure, thread_safe], "{
/*
- ** Note anychanges here will require the same changes in
+ ** Note any changes here will require the same changes in
** string__float_to_string.
*/
char buf[ML_SPRINTF_FLOAT_BUF_SIZE];
full diff:
Index: library/string.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/string.m,v
retrieving revision 1.186
diff -u -r1.186 string.m
--- library/string.m 21 Nov 2002 09:21:33 -0000 1.186
+++ library/string.m 22 Nov 2002 16:41:20 -0000
@@ -96,6 +96,9 @@
:- pred string__float_to_string(float, string).
:- mode string__float_to_string(in, uo) is det.
% Convert an float to a string.
+% The resulting float will be in the form that it was printed using
+% the format string "%#.<prec>g" where <prec> is the required precision
+% needed to represent the string.
:- pred string__first_char(string, char, string).
:- mode string__first_char(in, in, in) is semidet. % implied
@@ -1829,13 +1832,66 @@
:- pragma foreign_proc("C",
string__float_to_string(Flt::in, Str::uo),
[will_not_call_mercury, promise_pure, thread_safe], "{
+ /*
+ ** For efficiency reasons we duplicate the C implementation
+ ** of string__lowlevel_float_to_string
+ */
+ char buf[ML_SPRINTF_FLOAT_BUF_SIZE];
+ ML_sprintf_float(buf, Flt);
+ MR_make_aligned_string_copy(Str, buf);
+}").
+
+ % XXX The unsafe_promise_unique is needed because in
+ % string__float_to_string_2 the call to string__to_float doesn't
+ % have a (ui, out) mode hence the output string cannot be unique.
+string__float_to_string(Float, unsafe_promise_unique(String)) :-
+ String = string__float_to_string_2(min_precision, Float).
+
+:- func string__float_to_string_2(int, float) = (string) is det.
+
+string__float_to_string_2(Prec, Float) = String :-
+ string__format("%#." ++ int_to_string(Prec) ++ "g", [f(Float)], Tmp),
+ ( Prec = max_precision ->
+ String = Tmp
+ ;
+ ( string__to_float(Tmp, Float) ->
+ String = Tmp
+ ;
+ String = float_to_string_2(Prec + 1, Float)
+ )
+ ).
+
+ % We assume that on non-C backends that we are using double
+ % precision floats.
+:- func min_precision = int.
+min_precision = 15.
+
+:- func max_precision = int.
+max_precision = 17.
+
+% string__lowlevel_float_to_string differs from string__float_to_string in
+% that it must be implemented in a foreign language as this is the predicate
+% string__format uses to get the initial string representation of a float.
+% Also while its output must represent the float to sufficient precision, it
+% doesn't need to be in *exactly* the same format as if was formated with
+% "%#.<prec>g".
+:- pred string__lowlevel_float_to_string(float, string).
+:- mode string__lowlevel_float_to_string(in, uo) is det.
+
+:- pragma foreign_proc("C",
+ string__lowlevel_float_to_string(Flt::in, Str::uo),
+ [will_not_call_mercury, promise_pure, thread_safe], "{
+ /*
+ ** Note any changes here will require the same changes in
+ ** string__float_to_string.
+ */
char buf[ML_SPRINTF_FLOAT_BUF_SIZE];
ML_sprintf_float(buf, Flt);
MR_make_aligned_string_copy(Str, buf);
}").
:- pragma foreign_proc("C#",
- string__float_to_string(FloatVal::in, FloatString::uo),
+ string__lowlevel_float_to_string(FloatVal::in, FloatString::uo),
[will_not_call_mercury, promise_pure, thread_safe], "
// The R format string prints the double out such that it
@@ -1846,10 +1902,10 @@
FloatString = FloatVal.ToString(""R"");
").
-string__float_to_string(_, _) :-
+string__lowlevel_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").
+ private_builtin__sorry("string__lowlevel_float_to_string").
:- pragma foreign_decl(c, "
#ifdef MR_USE_SINGLE_PREC_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