mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-16 22:35:41 +00:00
Estimated hours taken: 4 Branches: main Improve the readability of float output from the debugger and io.print etc. by pruning redundant trailing zeroes. NEWS: Mention the change. library/string.m: runtime/mercury_float.c: Make string.float_to_string trim redundant trailing zeroes. The behaviour of string.format etc. is unchanged. tests/debugger/ambiguity.exp: tests/debugger/field_names.exp: tests/debugger/higher_order.exp: tests/debugger/print_table.exp: tests/hard_coded/common_type_cast.exp: tests/hard_coded/constant_prop_1.exp: tests/hard_coded/construct_test.exp: tests/hard_coded/deconstruct_arg.exp: tests/hard_coded/deep_copy.exp: tests/hard_coded/deep_copy_exist.exp: tests/hard_coded/dense_lookup_switch2.exp: tests/hard_coded/dense_lookup_switch_non.exp: tests/hard_coded/existential_float.exp: tests/hard_coded/expand.exp: tests/hard_coded/final_excp.exp: tests/hard_coded/float_field.exp: tests/hard_coded/float_gv.exp: tests/hard_coded/float_reg.exp: tests/hard_coded/float_rounding_bug.exp: tests/hard_coded/init_excp.exp: tests/hard_coded/mutable_excp.exp: tests/hard_coded/pragma_import.exp: tests/hard_coded/prince_frameopt.exp: tests/hard_coded/string_string.exp: tests/hard_coded/unused_float_box_test.exp: tests/hard_coded/write.exp: tests/hard_coded/write_binary.exp: tests/hard_coded/write_reg1.exp: tests/hard_coded/write_xml.exp: tests/hard_coded/sub-modules/non_word_mutable.exp: tests/hard_coded/typeclasses/arbitrary_constraint_class.exp: tests/hard_coded/typeclasses/arbitrary_constraint_pred_1.exp: tests/hard_coded/typeclasses/arbitrary_constraint_pred_2.exp: tests/hard_coded/typeclasses/existential_rtti.exp: tests/hard_coded/typeclasses/func_default_mode_bug.exp: tests/hard_coded/typeclasses/mode_decl_order_bug.exp: tests/hard_coded/typeclasses/module_test.exp: tests/hard_coded/typeclasses/typeclass_exist_method.exp: tests/invalid/error_in_list.err_exp: tests/invalid/errors2.err_exp: tests/invalid/purity/purity_type_error.err_exp: tests/mmc_make/complex_test.exp: tests/recompilation/add_type_re.exp.1: tests/recompilation/type_spec_rename_var_r.exp.1: tests/recompilation/type_spec_rename_var_r.exp.2: tests/recompilation/type_spec_unname_var_r.exp.1: tests/recompilation/type_spec_unname_var_r.exp.2: Updated expected test case output.
142 lines
3.4 KiB
C
142 lines
3.4 KiB
C
/*
|
|
** vim: ts=4 sw=4 expandtab
|
|
*/
|
|
/*
|
|
** Copyright (C) 1997, 2000, 2002, 2006-2007 The University of Melbourne.
|
|
** This file may only be copied under the terms of the GNU Library General
|
|
** Public License - see the file COPYING.LIB in the Mercury distribution.
|
|
*/
|
|
|
|
#include "mercury_imp.h"
|
|
#include <math.h>
|
|
|
|
/*
|
|
** The function `MR_hash_float()' is used by the library predicate
|
|
** `float__hash' and also for hashing floats for `pragma fact_table' indexing.
|
|
** It computes a non-negative MR_Integer hash value for a MR_Float.
|
|
** The exact hash function used depend on the relative sizes of MR_Float and
|
|
** MR_Integer.
|
|
*/
|
|
|
|
union MR_Float_Integer {
|
|
MR_Float f;
|
|
MR_Integer i;
|
|
MR_Integer j[(sizeof(MR_Float)/sizeof(MR_Integer) > 0
|
|
? sizeof(MR_Float)/sizeof(MR_Integer) : 1)];
|
|
char c[sizeof(MR_Float)/sizeof(char)];
|
|
};
|
|
|
|
MR_Integer
|
|
MR_hash_float(MR_Float f)
|
|
{
|
|
union MR_Float_Integer fi;
|
|
size_t i;
|
|
MR_Integer h = 0;
|
|
|
|
fi.i = 0;
|
|
fi.f = f;
|
|
|
|
if (sizeof(MR_Float) <= sizeof(MR_Integer)) {
|
|
h = fi.i;
|
|
} else if (sizeof(MR_Float) % sizeof(MR_Integer) == 0) {
|
|
for (i = 0; i < sizeof(MR_Float)/sizeof(MR_Integer); i++) {
|
|
h ^= fi.j[i];
|
|
}
|
|
} else {
|
|
for (i = 0; i < sizeof(MR_Float)/sizeof(char); i++) {
|
|
h ^= (h << 5);
|
|
h ^= fi.c[i];
|
|
}
|
|
}
|
|
return (h >= 0 ? h : -h);
|
|
}
|
|
|
|
/*
|
|
** MR_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
|
|
MR_sprintf_float(char *buf, MR_Float f)
|
|
{
|
|
MR_Float round_trip = 0.0;
|
|
int i = MR_FLT_MIN_PRECISION;
|
|
int n;
|
|
|
|
/*
|
|
** Print the float at increasing precisions until the float
|
|
** is round-trippable.
|
|
*/
|
|
do {
|
|
sprintf(buf, "%#.*g", i, f);
|
|
if (i >= MR_FLT_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, MR_FLT_FMT, &round_trip);
|
|
i++;
|
|
} while (round_trip != f);
|
|
|
|
/*
|
|
** Strip redundant trailing zeroes from the string (this behaviour
|
|
** for %g is suppressed by the # modifier).
|
|
*/
|
|
for (n = strlen(buf) - 1; n > 0; n--) {
|
|
switch (buf[n]) {
|
|
case '.':
|
|
buf[n + 2] = '\0';
|
|
return;
|
|
case '0':
|
|
continue;
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
buf[n + 1] = '\0';
|
|
return;
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
MR_bool
|
|
MR_is_nan(MR_Float Flt)
|
|
{
|
|
#if defined(MR_USE_SINGLE_PREC_FLOAT) && defined(MR_HAVE_ISNANF)
|
|
return isnanf(Flt);
|
|
#elif defined(MR_HAVE_ISNAN)
|
|
return isnan(Flt);
|
|
#else
|
|
return (Flt != Flt);
|
|
#endif
|
|
}
|
|
|
|
MR_bool
|
|
MR_is_inf(MR_Float Flt)
|
|
{
|
|
#if defined(MR_USE_SINGLE_PREC_FLOAT) && defined(MR_HAVE_ISINFF)
|
|
return isinff(Flt);
|
|
#elif defined(MR_HAVE_ISINF)
|
|
return isinf(Flt);
|
|
#else
|
|
return (Flt == Flt / 2.0 && Flt != 0.0);
|
|
#endif
|
|
}
|