Single-precision floats now print differently from their double-precision

counterparts.
This commit is contained in:
Vincent St-Amour 2011-01-14 12:47:28 -05:00
parent d220e0a10b
commit c997ae139b
2 changed files with 58 additions and 9 deletions

View File

@ -140,6 +140,17 @@
(test "+nan.0" number->string +nan.0)
(test "+nan.0" number->string +nan.0)
(test "+inf.f" number->string +inf.f)
(test "-inf.f" number->string -inf.f)
(test "+nan.f" number->string +nan.f)
(test "+nan.f" number->string +nan.f)
(test "0.0f0" number->string 0.0f0)
(test "0.0f0" number->string 0.0f1)
(test "0.0f0" number->string 0.0f17)
(test "13.25f0" number->string 13.25f0)
(test "13.25f0" number->string 1.325f1)
(test "-4.25f0" number->string -4.25f0)
(map (lambda (n)
;; test that fresh strings are generated:
(let ([n1 (number->string n)]

View File

@ -1521,27 +1521,54 @@ string_to_number (int argc, Scheme_Object *argv[])
}
static char *double_to_string (double d, int alloc)
static char *double_to_string (double d, int alloc, int was_single)
{
char buffer[100], *s;
int l, i, digits;
if (MZ_IS_NAN(d))
s = not_a_number_str;
#ifdef MZ_USE_SINGLE_FLOATS
if (was_single)
s = single_not_a_number_str;
else
#endif
s = not_a_number_str;
else if (MZ_IS_POS_INFINITY(d))
s = infinity_str;
#ifdef MZ_USE_SINGLE_FLOATS
if (was_single)
s = single_infinity_str;
else
#endif
s = infinity_str;
else if (MZ_IS_NEG_INFINITY(d))
s = minus_infinity_str;
#ifdef MZ_USE_SINGLE_FLOATS
if (was_single)
s = single_minus_infinity_str;
else
#endif
s = minus_infinity_str;
else if (d == 0.0) {
/* Check for -0.0, since some printers get it wrong. */
if (scheme_minus_zero_p(d))
s = "-0.0";
#ifdef MZ_USE_SINGLE_FLOATS
if (was_single)
/* The f0 suffix causes the string to be read as a single-
precision float. */
s = "-0.0f0";
else
#endif
s = "-0.0";
else
s = "0.0";
#ifdef MZ_USE_SINGLE_FLOATS
if (was_single)
s = "0.0f0";
else
#endif
s = "0.0";
} else {
/* Initial count for significant digits is 14. That's big enough to
get most right, small enough to avoid nonsense digits. But we'll
loop in case it's not precise enough to get read-write invariance: */
loop in case it's not precise enough to get read-write invariance: */
digits = 14;
while (digits < 30) {
double check;
@ -1568,6 +1595,17 @@ static char *double_to_string (double d, int alloc)
buffer[i + 2] = 0;
l += 2;
}
#ifdef MZ_USE_SINGLE_FLOATS
if (was_single) {
/* In case of a single-precision float, add the f0 suffix to
cause the string to be read back as a single-precision
float. */
buffer[l] = 'f';
buffer[l + 1] = '0';
buffer[l + 2] = 0;
l += 2;
}
#endif
s = (char *)scheme_malloc_atomic(strlen(buffer) + 1);
strcpy(s, buffer);
@ -1594,7 +1632,7 @@ static char *number_to_allocated_string(int radix, Scheme_Object *obj, int alloc
scheme_raise_exn(MZEXN_FAIL_CONTRACT,
"number->string: "
"inexact numbers can only be printed in base 10");
s = double_to_string(SCHEME_FLOAT_VAL(obj), alloc);
s = double_to_string(SCHEME_FLOAT_VAL(obj), alloc, SCHEME_FLTP(obj));
} else if (SCHEME_RATIONALP(obj)) {
Scheme_Object *n, *d;
char *ns, *ds;
@ -1659,7 +1697,7 @@ int scheme_check_double(const char *where, double d, const char *dest)
"%s: no %s representation for %s",
where,
dest,
double_to_string(d, 0));
double_to_string(d, 0, 0));
return 0;
}