mirror of git://gcc.gnu.org/git/gcc.git
Allow real_format to be passed to more real.h functions
Most real.h routines used machine modes to specify the format of an operation and converted that to a float_format * internally. Some also had alternative versions that accepted a float_format *. In an upcoming patch it seemed more convenient for the callers I was adding to use float_format directly, since the callers need to examine the format themselves for other reasons. This patch therefore replaces the machine_mode arguments with a new class that allows both machine modes and float_format pointers to be used. Tested on x86_64-linux-gnu, arm-linux-gnueabi and aarch64-linux-gnu. gcc/ * real.h (format_helper): New. (real_convert, exact_real_truncate, real_from_string3, real_to_target) (real_from_target, real_nan, real_2expN, real_value_truncate) (significand_size, real_from_string2, exact_real_inverse) (exact_real_inverse, real_powi, real_trunc, real_floor, real_ceil) (real_round, real_isinteger, real_from_integer): Replace machine_mode arguments with format_helper arguments. * real.c (exact_real_inverse, real_from_string2, real_from_string3) (real_from_integer, real_nan, real_2expN, real_convert) (real_value_truncate, exact_real_truncate, real_to_target) (real_from_target, significand_size, real_powi, real_trunc) (real_floor, real_ceil, real_round, real_isinteger): Replace machine_mode arguments with format_helper arguments. (real_to_target_fmt, real_from_target_fmt): Delete. * dfp.h (decimal_real_convert): Replace mode argument with real_format. * dfp.c (decimal_to_binary, decimal_real_convert): Replace mode argument with real_format. * builtins.c (do_real_to_int_conversion): Update type of fn argument. gcc/java/ * jcf-parse.c (get_constant): Use real_from_target rather than real_from_target_fmt. From-SVN: r229581
This commit is contained in:
parent
4ff7defd04
commit
f16e6077ea
|
|
@ -1,3 +1,24 @@
|
||||||
|
2015-10-30 Richard Sandiford <richard.sandiford@arm.com>
|
||||||
|
|
||||||
|
* real.h (format_helper): New.
|
||||||
|
(real_convert, exact_real_truncate, real_from_string3, real_to_target)
|
||||||
|
(real_from_target, real_nan, real_2expN, real_value_truncate)
|
||||||
|
(significand_size, real_from_string2, exact_real_inverse)
|
||||||
|
(exact_real_inverse, real_powi, real_trunc, real_floor, real_ceil)
|
||||||
|
(real_round, real_isinteger, real_from_integer): Replace
|
||||||
|
machine_mode arguments with format_helper arguments.
|
||||||
|
* real.c (exact_real_inverse, real_from_string2, real_from_string3)
|
||||||
|
(real_from_integer, real_nan, real_2expN, real_convert)
|
||||||
|
(real_value_truncate, exact_real_truncate, real_to_target)
|
||||||
|
(real_from_target, significand_size, real_powi, real_trunc)
|
||||||
|
(real_floor, real_ceil, real_round, real_isinteger): Replace
|
||||||
|
machine_mode arguments with format_helper arguments.
|
||||||
|
(real_to_target_fmt, real_from_target_fmt): Delete.
|
||||||
|
* dfp.h (decimal_real_convert): Replace mode argument with real_format.
|
||||||
|
* dfp.c (decimal_to_binary, decimal_real_convert): Replace mode
|
||||||
|
argument with real_format.
|
||||||
|
* builtins.c (do_real_to_int_conversion): Update type of fn argument.
|
||||||
|
|
||||||
2015-10-30 Richard Sandiford <richard.sandiford@arm.com>
|
2015-10-30 Richard Sandiford <richard.sandiford@arm.com>
|
||||||
|
|
||||||
* fixed-value.c (check_real_for_fixed_mode, fixed_from_string)
|
* fixed-value.c (check_real_for_fixed_mode, fixed_from_string)
|
||||||
|
|
|
||||||
|
|
@ -7273,7 +7273,7 @@ fold_builtin_strlen (location_t loc, tree type, tree arg)
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
do_real_to_int_conversion (tree itype, tree arg,
|
do_real_to_int_conversion (tree itype, tree arg,
|
||||||
void (*fn) (REAL_VALUE_TYPE *, machine_mode,
|
void (*fn) (REAL_VALUE_TYPE *, format_helper,
|
||||||
const REAL_VALUE_TYPE *))
|
const REAL_VALUE_TYPE *))
|
||||||
{
|
{
|
||||||
if (TREE_CODE (arg) != REAL_CST || TREE_OVERFLOW (arg))
|
if (TREE_CODE (arg) != REAL_CST || TREE_OVERFLOW (arg))
|
||||||
|
|
|
||||||
10
gcc/dfp.c
10
gcc/dfp.c
|
|
@ -343,13 +343,13 @@ decode_decimal128 (const struct real_format *fmt ATTRIBUTE_UNUSED,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
decimal_to_binary (REAL_VALUE_TYPE *to, const REAL_VALUE_TYPE *from,
|
decimal_to_binary (REAL_VALUE_TYPE *to, const REAL_VALUE_TYPE *from,
|
||||||
machine_mode mode)
|
const real_format *fmt)
|
||||||
{
|
{
|
||||||
char string[256];
|
char string[256];
|
||||||
const decimal128 *const d128 = (const decimal128 *) from->sig;
|
const decimal128 *const d128 = (const decimal128 *) from->sig;
|
||||||
|
|
||||||
decimal128ToString (d128, string);
|
decimal128ToString (d128, string);
|
||||||
real_from_string3 (to, string, mode);
|
real_from_string3 (to, string, fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -459,15 +459,13 @@ decimal_round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r)
|
||||||
binary and decimal types. */
|
binary and decimal types. */
|
||||||
|
|
||||||
void
|
void
|
||||||
decimal_real_convert (REAL_VALUE_TYPE *r, machine_mode mode,
|
decimal_real_convert (REAL_VALUE_TYPE *r, const real_format *fmt,
|
||||||
const REAL_VALUE_TYPE *a)
|
const REAL_VALUE_TYPE *a)
|
||||||
{
|
{
|
||||||
const struct real_format *fmt = REAL_MODE_FORMAT (mode);
|
|
||||||
|
|
||||||
if (a->decimal && fmt->b == 10)
|
if (a->decimal && fmt->b == 10)
|
||||||
return;
|
return;
|
||||||
if (a->decimal)
|
if (a->decimal)
|
||||||
decimal_to_binary (r, a, mode);
|
decimal_to_binary (r, a, fmt);
|
||||||
else
|
else
|
||||||
decimal_from_binary (r, a);
|
decimal_from_binary (r, a);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,8 @@ void encode_decimal128 (const struct real_format *fmt, long *, const REAL_VALUE_
|
||||||
int decimal_do_compare (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, int);
|
int decimal_do_compare (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, int);
|
||||||
void decimal_real_from_string (REAL_VALUE_TYPE *, const char *);
|
void decimal_real_from_string (REAL_VALUE_TYPE *, const char *);
|
||||||
void decimal_round_for_format (const struct real_format *, REAL_VALUE_TYPE *);
|
void decimal_round_for_format (const struct real_format *, REAL_VALUE_TYPE *);
|
||||||
void decimal_real_convert (REAL_VALUE_TYPE *, machine_mode, const REAL_VALUE_TYPE *);
|
void decimal_real_convert (REAL_VALUE_TYPE *, const real_format *,
|
||||||
|
const REAL_VALUE_TYPE *);
|
||||||
void decimal_real_to_decimal (char *, const REAL_VALUE_TYPE *, size_t, size_t, int);
|
void decimal_real_to_decimal (char *, const REAL_VALUE_TYPE *, size_t, size_t, int);
|
||||||
void decimal_do_fix_trunc (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
|
void decimal_do_fix_trunc (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
|
||||||
void decimal_real_maxval (REAL_VALUE_TYPE *, int, machine_mode);
|
void decimal_real_maxval (REAL_VALUE_TYPE *, int, machine_mode);
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
|
2015-10-30 Richard Sandiford <richard.sandiford@arm.com>
|
||||||
|
|
||||||
|
* jcf-parse.c (get_constant): Use real_from_target rather than
|
||||||
|
real_from_target_fmt.
|
||||||
|
|
||||||
2015-10-29 Andrew MacLeod <amacleod@redhat.com>
|
2015-10-29 Andrew MacLeod <amacleod@redhat.com>
|
||||||
|
|
||||||
* boehm.c: Reorder #include's and remove duplicates.
|
* boehm.c: Reorder #include's and remove duplicates.
|
||||||
|
|
|
||||||
|
|
@ -1058,7 +1058,7 @@ get_constant (JCF *jcf, int index)
|
||||||
long buf = num;
|
long buf = num;
|
||||||
REAL_VALUE_TYPE d;
|
REAL_VALUE_TYPE d;
|
||||||
|
|
||||||
real_from_target_fmt (&d, &buf, &ieee_single_format);
|
real_from_target (&d, &buf, &ieee_single_format);
|
||||||
value = build_real (float_type_node, d);
|
value = build_real (float_type_node, d);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1076,7 +1076,7 @@ get_constant (JCF *jcf, int index)
|
||||||
else
|
else
|
||||||
buf[0] = lo, buf[1] = hi;
|
buf[0] = lo, buf[1] = hi;
|
||||||
|
|
||||||
real_from_target_fmt (&d, buf, &ieee_double_format);
|
real_from_target (&d, buf, &ieee_double_format);
|
||||||
value = build_real (double_type_node, d);
|
value = build_real (double_type_node, d);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
163
gcc/real.c
163
gcc/real.c
|
|
@ -1266,11 +1266,11 @@ real_identical (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to change R into its exact multiplicative inverse in machine
|
/* Try to change R into its exact multiplicative inverse in format FMT.
|
||||||
mode MODE. Return true if successful. */
|
Return true if successful. */
|
||||||
|
|
||||||
bool
|
bool
|
||||||
exact_real_inverse (machine_mode mode, REAL_VALUE_TYPE *r)
|
exact_real_inverse (format_helper fmt, REAL_VALUE_TYPE *r)
|
||||||
{
|
{
|
||||||
const REAL_VALUE_TYPE *one = real_digit (1);
|
const REAL_VALUE_TYPE *one = real_digit (1);
|
||||||
REAL_VALUE_TYPE u;
|
REAL_VALUE_TYPE u;
|
||||||
|
|
@ -1286,9 +1286,9 @@ exact_real_inverse (machine_mode mode, REAL_VALUE_TYPE *r)
|
||||||
if (r->sig[SIGSZ-1] != SIG_MSB)
|
if (r->sig[SIGSZ-1] != SIG_MSB)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Find the inverse and truncate to the required mode. */
|
/* Find the inverse and truncate to the required format. */
|
||||||
do_divide (&u, one, r);
|
do_divide (&u, one, r);
|
||||||
real_convert (&u, mode, &u);
|
real_convert (&u, fmt, &u);
|
||||||
|
|
||||||
/* The rounding may have overflowed. */
|
/* The rounding may have overflowed. */
|
||||||
if (u.cl != rvc_normal)
|
if (u.cl != rvc_normal)
|
||||||
|
|
@ -2104,35 +2104,36 @@ real_from_string (REAL_VALUE_TYPE *r, const char *str)
|
||||||
/* Legacy. Similar, but return the result directly. */
|
/* Legacy. Similar, but return the result directly. */
|
||||||
|
|
||||||
REAL_VALUE_TYPE
|
REAL_VALUE_TYPE
|
||||||
real_from_string2 (const char *s, machine_mode mode)
|
real_from_string2 (const char *s, format_helper fmt)
|
||||||
{
|
{
|
||||||
REAL_VALUE_TYPE r;
|
REAL_VALUE_TYPE r;
|
||||||
|
|
||||||
real_from_string (&r, s);
|
real_from_string (&r, s);
|
||||||
if (mode != VOIDmode)
|
if (fmt)
|
||||||
real_convert (&r, mode, &r);
|
real_convert (&r, fmt, &r);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize R from string S and desired MODE. */
|
/* Initialize R from string S and desired format FMT. */
|
||||||
|
|
||||||
void
|
void
|
||||||
real_from_string3 (REAL_VALUE_TYPE *r, const char *s, machine_mode mode)
|
real_from_string3 (REAL_VALUE_TYPE *r, const char *s, format_helper fmt)
|
||||||
{
|
{
|
||||||
if (DECIMAL_FLOAT_MODE_P (mode))
|
if (fmt.decimal_p ())
|
||||||
decimal_real_from_string (r, s);
|
decimal_real_from_string (r, s);
|
||||||
else
|
else
|
||||||
real_from_string (r, s);
|
real_from_string (r, s);
|
||||||
|
|
||||||
if (mode != VOIDmode)
|
if (fmt)
|
||||||
real_convert (r, mode, r);
|
real_convert (r, fmt, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize R from the wide_int VAL_IN. The MODE is not VOIDmode,*/
|
/* Initialize R from the wide_int VAL_IN. Round it to format FMT if
|
||||||
|
FMT is nonnull. */
|
||||||
|
|
||||||
void
|
void
|
||||||
real_from_integer (REAL_VALUE_TYPE *r, machine_mode mode,
|
real_from_integer (REAL_VALUE_TYPE *r, format_helper fmt,
|
||||||
const wide_int_ref &val_in, signop sgn)
|
const wide_int_ref &val_in, signop sgn)
|
||||||
{
|
{
|
||||||
if (val_in == 0)
|
if (val_in == 0)
|
||||||
|
|
@ -2216,10 +2217,10 @@ real_from_integer (REAL_VALUE_TYPE *r, machine_mode mode,
|
||||||
normalize (r);
|
normalize (r);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DECIMAL_FLOAT_MODE_P (mode))
|
if (fmt.decimal_p ())
|
||||||
decimal_from_integer (r);
|
decimal_from_integer (r);
|
||||||
else if (mode != VOIDmode)
|
else if (fmt)
|
||||||
real_convert (r, mode, r);
|
real_convert (r, fmt, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Render R, an integral value, as a floating point constant with no
|
/* Render R, an integral value, as a floating point constant with no
|
||||||
|
|
@ -2448,13 +2449,8 @@ real_inf (REAL_VALUE_TYPE *r)
|
||||||
|
|
||||||
bool
|
bool
|
||||||
real_nan (REAL_VALUE_TYPE *r, const char *str, int quiet,
|
real_nan (REAL_VALUE_TYPE *r, const char *str, int quiet,
|
||||||
machine_mode mode)
|
format_helper fmt)
|
||||||
{
|
{
|
||||||
const struct real_format *fmt;
|
|
||||||
|
|
||||||
fmt = REAL_MODE_FORMAT (mode);
|
|
||||||
gcc_assert (fmt);
|
|
||||||
|
|
||||||
if (*str == 0)
|
if (*str == 0)
|
||||||
{
|
{
|
||||||
if (quiet)
|
if (quiet)
|
||||||
|
|
@ -2574,7 +2570,7 @@ real_maxval (REAL_VALUE_TYPE *r, int sign, machine_mode mode)
|
||||||
/* Fills R with 2**N. */
|
/* Fills R with 2**N. */
|
||||||
|
|
||||||
void
|
void
|
||||||
real_2expN (REAL_VALUE_TYPE *r, int n, machine_mode fmode)
|
real_2expN (REAL_VALUE_TYPE *r, int n, format_helper fmt)
|
||||||
{
|
{
|
||||||
memset (r, 0, sizeof (*r));
|
memset (r, 0, sizeof (*r));
|
||||||
|
|
||||||
|
|
@ -2589,8 +2585,8 @@ real_2expN (REAL_VALUE_TYPE *r, int n, machine_mode fmode)
|
||||||
SET_REAL_EXP (r, n);
|
SET_REAL_EXP (r, n);
|
||||||
r->sig[SIGSZ-1] = SIG_MSB;
|
r->sig[SIGSZ-1] = SIG_MSB;
|
||||||
}
|
}
|
||||||
if (DECIMAL_FLOAT_MODE_P (fmode))
|
if (fmt.decimal_p ())
|
||||||
decimal_real_convert (r, fmode, r);
|
decimal_real_convert (r, fmt, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2612,7 +2608,7 @@ round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r)
|
||||||
(e.g. -O0 on '_Decimal32 x = 1.0 + 2.0dd'), but have not
|
(e.g. -O0 on '_Decimal32 x = 1.0 + 2.0dd'), but have not
|
||||||
investigated whether this convert needs to be here, or
|
investigated whether this convert needs to be here, or
|
||||||
something else is missing. */
|
something else is missing. */
|
||||||
decimal_real_convert (r, DFmode, r);
|
decimal_real_convert (r, REAL_MODE_FORMAT (DFmode), r);
|
||||||
}
|
}
|
||||||
|
|
||||||
p2 = fmt->p;
|
p2 = fmt->p;
|
||||||
|
|
@ -2718,21 +2714,16 @@ round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r)
|
||||||
clear_significand_below (r, np2);
|
clear_significand_below (r, np2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Extend or truncate to a new mode. */
|
/* Extend or truncate to a new format. */
|
||||||
|
|
||||||
void
|
void
|
||||||
real_convert (REAL_VALUE_TYPE *r, machine_mode mode,
|
real_convert (REAL_VALUE_TYPE *r, format_helper fmt,
|
||||||
const REAL_VALUE_TYPE *a)
|
const REAL_VALUE_TYPE *a)
|
||||||
{
|
{
|
||||||
const struct real_format *fmt;
|
|
||||||
|
|
||||||
fmt = REAL_MODE_FORMAT (mode);
|
|
||||||
gcc_assert (fmt);
|
|
||||||
|
|
||||||
*r = *a;
|
*r = *a;
|
||||||
|
|
||||||
if (a->decimal || fmt->b == 10)
|
if (a->decimal || fmt->b == 10)
|
||||||
decimal_real_convert (r, mode, a);
|
decimal_real_convert (r, fmt, a);
|
||||||
|
|
||||||
round_for_format (fmt, r);
|
round_for_format (fmt, r);
|
||||||
|
|
||||||
|
|
@ -2744,32 +2735,28 @@ real_convert (REAL_VALUE_TYPE *r, machine_mode mode,
|
||||||
/* Legacy. Likewise, except return the struct directly. */
|
/* Legacy. Likewise, except return the struct directly. */
|
||||||
|
|
||||||
REAL_VALUE_TYPE
|
REAL_VALUE_TYPE
|
||||||
real_value_truncate (machine_mode mode, REAL_VALUE_TYPE a)
|
real_value_truncate (format_helper fmt, REAL_VALUE_TYPE a)
|
||||||
{
|
{
|
||||||
REAL_VALUE_TYPE r;
|
REAL_VALUE_TYPE r;
|
||||||
real_convert (&r, mode, &a);
|
real_convert (&r, fmt, &a);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return true if truncating to MODE is exact. */
|
/* Return true if truncating to FMT is exact. */
|
||||||
|
|
||||||
bool
|
bool
|
||||||
exact_real_truncate (machine_mode mode, const REAL_VALUE_TYPE *a)
|
exact_real_truncate (format_helper fmt, const REAL_VALUE_TYPE *a)
|
||||||
{
|
{
|
||||||
const struct real_format *fmt;
|
|
||||||
REAL_VALUE_TYPE t;
|
REAL_VALUE_TYPE t;
|
||||||
int emin2m1;
|
int emin2m1;
|
||||||
|
|
||||||
fmt = REAL_MODE_FORMAT (mode);
|
|
||||||
gcc_assert (fmt);
|
|
||||||
|
|
||||||
/* Don't allow conversion to denormals. */
|
/* Don't allow conversion to denormals. */
|
||||||
emin2m1 = fmt->emin - 1;
|
emin2m1 = fmt->emin - 1;
|
||||||
if (REAL_EXP (a) <= emin2m1)
|
if (REAL_EXP (a) <= emin2m1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* After conversion to the new mode, the value must be identical. */
|
/* After conversion to the new format, the value must be identical. */
|
||||||
real_convert (&t, mode, a);
|
real_convert (&t, fmt, a);
|
||||||
return real_identical (&t, a);
|
return real_identical (&t, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2780,8 +2767,8 @@ exact_real_truncate (machine_mode mode, const REAL_VALUE_TYPE *a)
|
||||||
Legacy: return word 0 for implementing REAL_VALUE_TO_TARGET_SINGLE. */
|
Legacy: return word 0 for implementing REAL_VALUE_TO_TARGET_SINGLE. */
|
||||||
|
|
||||||
long
|
long
|
||||||
real_to_target_fmt (long *buf, const REAL_VALUE_TYPE *r_orig,
|
real_to_target (long *buf, const REAL_VALUE_TYPE *r_orig,
|
||||||
const struct real_format *fmt)
|
format_helper fmt)
|
||||||
{
|
{
|
||||||
REAL_VALUE_TYPE r;
|
REAL_VALUE_TYPE r;
|
||||||
long buf1;
|
long buf1;
|
||||||
|
|
@ -2796,62 +2783,32 @@ real_to_target_fmt (long *buf, const REAL_VALUE_TYPE *r_orig,
|
||||||
return *buf;
|
return *buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Similar, but look up the format from MODE. */
|
|
||||||
|
|
||||||
long
|
|
||||||
real_to_target (long *buf, const REAL_VALUE_TYPE *r, machine_mode mode)
|
|
||||||
{
|
|
||||||
const struct real_format *fmt;
|
|
||||||
|
|
||||||
fmt = REAL_MODE_FORMAT (mode);
|
|
||||||
gcc_assert (fmt);
|
|
||||||
|
|
||||||
return real_to_target_fmt (buf, r, fmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read R from the given target format. Read the words of the result
|
/* Read R from the given target format. Read the words of the result
|
||||||
in target word order in BUF. There are always 32 bits in each
|
in target word order in BUF. There are always 32 bits in each
|
||||||
long, no matter the size of the host long. */
|
long, no matter the size of the host long. */
|
||||||
|
|
||||||
void
|
void
|
||||||
real_from_target_fmt (REAL_VALUE_TYPE *r, const long *buf,
|
real_from_target (REAL_VALUE_TYPE *r, const long *buf, format_helper fmt)
|
||||||
const struct real_format *fmt)
|
|
||||||
{
|
{
|
||||||
(*fmt->decode) (fmt, r, buf);
|
(*fmt->decode) (fmt, r, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Similar, but look up the format from MODE. */
|
|
||||||
|
|
||||||
void
|
|
||||||
real_from_target (REAL_VALUE_TYPE *r, const long *buf, machine_mode mode)
|
|
||||||
{
|
|
||||||
const struct real_format *fmt;
|
|
||||||
|
|
||||||
fmt = REAL_MODE_FORMAT (mode);
|
|
||||||
gcc_assert (fmt);
|
|
||||||
|
|
||||||
(*fmt->decode) (fmt, r, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the number of bits of the largest binary value that the
|
/* Return the number of bits of the largest binary value that the
|
||||||
significand of MODE will hold. */
|
significand of FMT will hold. */
|
||||||
/* ??? Legacy. Should get access to real_format directly. */
|
/* ??? Legacy. Should get access to real_format directly. */
|
||||||
|
|
||||||
int
|
int
|
||||||
significand_size (machine_mode mode)
|
significand_size (format_helper fmt)
|
||||||
{
|
{
|
||||||
const struct real_format *fmt;
|
|
||||||
|
|
||||||
fmt = REAL_MODE_FORMAT (mode);
|
|
||||||
if (fmt == NULL)
|
if (fmt == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (fmt->b == 10)
|
if (fmt->b == 10)
|
||||||
{
|
{
|
||||||
/* Return the size in bits of the largest binary value that can be
|
/* Return the size in bits of the largest binary value that can be
|
||||||
held by the decimal coefficient for this mode. This is one more
|
held by the decimal coefficient for this format. This is one more
|
||||||
than the number of bits required to hold the largest coefficient
|
than the number of bits required to hold the largest coefficient
|
||||||
of this mode. */
|
of this format. */
|
||||||
double log2_10 = 3.3219281;
|
double log2_10 = 3.3219281;
|
||||||
return fmt->p * log2_10;
|
return fmt->p * log2_10;
|
||||||
}
|
}
|
||||||
|
|
@ -4861,14 +4818,14 @@ const struct real_format real_internal_format =
|
||||||
"real_internal"
|
"real_internal"
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Calculate X raised to the integer exponent N in mode MODE and store
|
/* Calculate X raised to the integer exponent N in format FMT and store
|
||||||
the result in R. Return true if the result may be inexact due to
|
the result in R. Return true if the result may be inexact due to
|
||||||
loss of precision. The algorithm is the classic "left-to-right binary
|
loss of precision. The algorithm is the classic "left-to-right binary
|
||||||
method" described in section 4.6.3 of Donald Knuth's "Seminumerical
|
method" described in section 4.6.3 of Donald Knuth's "Seminumerical
|
||||||
Algorithms", "The Art of Computer Programming", Volume 2. */
|
Algorithms", "The Art of Computer Programming", Volume 2. */
|
||||||
|
|
||||||
bool
|
bool
|
||||||
real_powi (REAL_VALUE_TYPE *r, machine_mode mode,
|
real_powi (REAL_VALUE_TYPE *r, format_helper fmt,
|
||||||
const REAL_VALUE_TYPE *x, HOST_WIDE_INT n)
|
const REAL_VALUE_TYPE *x, HOST_WIDE_INT n)
|
||||||
{
|
{
|
||||||
unsigned HOST_WIDE_INT bit;
|
unsigned HOST_WIDE_INT bit;
|
||||||
|
|
@ -4910,27 +4867,27 @@ real_powi (REAL_VALUE_TYPE *r, machine_mode mode,
|
||||||
if (neg)
|
if (neg)
|
||||||
inexact |= do_divide (&t, &dconst1, &t);
|
inexact |= do_divide (&t, &dconst1, &t);
|
||||||
|
|
||||||
real_convert (r, mode, &t);
|
real_convert (r, fmt, &t);
|
||||||
return inexact;
|
return inexact;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Round X to the nearest integer not larger in absolute value, i.e.
|
/* Round X to the nearest integer not larger in absolute value, i.e.
|
||||||
towards zero, placing the result in R in mode MODE. */
|
towards zero, placing the result in R in format FMT. */
|
||||||
|
|
||||||
void
|
void
|
||||||
real_trunc (REAL_VALUE_TYPE *r, machine_mode mode,
|
real_trunc (REAL_VALUE_TYPE *r, format_helper fmt,
|
||||||
const REAL_VALUE_TYPE *x)
|
const REAL_VALUE_TYPE *x)
|
||||||
{
|
{
|
||||||
do_fix_trunc (r, x);
|
do_fix_trunc (r, x);
|
||||||
if (mode != VOIDmode)
|
if (fmt)
|
||||||
real_convert (r, mode, r);
|
real_convert (r, fmt, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Round X to the largest integer not greater in value, i.e. round
|
/* Round X to the largest integer not greater in value, i.e. round
|
||||||
down, placing the result in R in mode MODE. */
|
down, placing the result in R in format FMT. */
|
||||||
|
|
||||||
void
|
void
|
||||||
real_floor (REAL_VALUE_TYPE *r, machine_mode mode,
|
real_floor (REAL_VALUE_TYPE *r, format_helper fmt,
|
||||||
const REAL_VALUE_TYPE *x)
|
const REAL_VALUE_TYPE *x)
|
||||||
{
|
{
|
||||||
REAL_VALUE_TYPE t;
|
REAL_VALUE_TYPE t;
|
||||||
|
|
@ -4938,17 +4895,17 @@ real_floor (REAL_VALUE_TYPE *r, machine_mode mode,
|
||||||
do_fix_trunc (&t, x);
|
do_fix_trunc (&t, x);
|
||||||
if (! real_identical (&t, x) && x->sign)
|
if (! real_identical (&t, x) && x->sign)
|
||||||
do_add (&t, &t, &dconstm1, 0);
|
do_add (&t, &t, &dconstm1, 0);
|
||||||
if (mode != VOIDmode)
|
if (fmt)
|
||||||
real_convert (r, mode, &t);
|
real_convert (r, fmt, &t);
|
||||||
else
|
else
|
||||||
*r = t;
|
*r = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Round X to the smallest integer not less then argument, i.e. round
|
/* Round X to the smallest integer not less then argument, i.e. round
|
||||||
up, placing the result in R in mode MODE. */
|
up, placing the result in R in format FMT. */
|
||||||
|
|
||||||
void
|
void
|
||||||
real_ceil (REAL_VALUE_TYPE *r, machine_mode mode,
|
real_ceil (REAL_VALUE_TYPE *r, format_helper fmt,
|
||||||
const REAL_VALUE_TYPE *x)
|
const REAL_VALUE_TYPE *x)
|
||||||
{
|
{
|
||||||
REAL_VALUE_TYPE t;
|
REAL_VALUE_TYPE t;
|
||||||
|
|
@ -4956,8 +4913,8 @@ real_ceil (REAL_VALUE_TYPE *r, machine_mode mode,
|
||||||
do_fix_trunc (&t, x);
|
do_fix_trunc (&t, x);
|
||||||
if (! real_identical (&t, x) && ! x->sign)
|
if (! real_identical (&t, x) && ! x->sign)
|
||||||
do_add (&t, &t, &dconst1, 0);
|
do_add (&t, &t, &dconst1, 0);
|
||||||
if (mode != VOIDmode)
|
if (fmt)
|
||||||
real_convert (r, mode, &t);
|
real_convert (r, fmt, &t);
|
||||||
else
|
else
|
||||||
*r = t;
|
*r = t;
|
||||||
}
|
}
|
||||||
|
|
@ -4966,13 +4923,13 @@ real_ceil (REAL_VALUE_TYPE *r, machine_mode mode,
|
||||||
zero. */
|
zero. */
|
||||||
|
|
||||||
void
|
void
|
||||||
real_round (REAL_VALUE_TYPE *r, machine_mode mode,
|
real_round (REAL_VALUE_TYPE *r, format_helper fmt,
|
||||||
const REAL_VALUE_TYPE *x)
|
const REAL_VALUE_TYPE *x)
|
||||||
{
|
{
|
||||||
do_add (r, x, &dconsthalf, x->sign);
|
do_add (r, x, &dconsthalf, x->sign);
|
||||||
do_fix_trunc (r, r);
|
do_fix_trunc (r, r);
|
||||||
if (mode != VOIDmode)
|
if (fmt)
|
||||||
real_convert (r, mode, r);
|
real_convert (r, fmt, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the sign of R to the sign of X. */
|
/* Set the sign of R to the sign of X. */
|
||||||
|
|
@ -4986,11 +4943,11 @@ real_copysign (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *x)
|
||||||
/* Check whether the real constant value given is an integer. */
|
/* Check whether the real constant value given is an integer. */
|
||||||
|
|
||||||
bool
|
bool
|
||||||
real_isinteger (const REAL_VALUE_TYPE *c, machine_mode mode)
|
real_isinteger (const REAL_VALUE_TYPE *c, format_helper fmt)
|
||||||
{
|
{
|
||||||
REAL_VALUE_TYPE cint;
|
REAL_VALUE_TYPE cint;
|
||||||
|
|
||||||
real_trunc (&cint, mode, c);
|
real_trunc (&cint, fmt, c);
|
||||||
return real_identical (c, &cint);
|
return real_identical (c, &cint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
69
gcc/real.h
69
gcc/real.h
|
|
@ -193,6 +193,28 @@ extern const struct real_format *
|
||||||
(FLOAT_MODE_P (MODE) \
|
(FLOAT_MODE_P (MODE) \
|
||||||
&& FLOAT_MODE_FORMAT (MODE)->has_sign_dependent_rounding)
|
&& FLOAT_MODE_FORMAT (MODE)->has_sign_dependent_rounding)
|
||||||
|
|
||||||
|
/* This class allows functions in this file to accept a floating-point
|
||||||
|
format as either a mode or an explicit real_format pointer. In the
|
||||||
|
former case the mode must be VOIDmode (which means "no particular
|
||||||
|
format") or must satisfy SCALAR_FLOAT_MODE_P. */
|
||||||
|
class format_helper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
format_helper (const real_format *format) : m_format (format) {}
|
||||||
|
format_helper (machine_mode m);
|
||||||
|
const real_format *operator-> () const { return m_format; }
|
||||||
|
operator const real_format *() const { return m_format; }
|
||||||
|
|
||||||
|
bool decimal_p () const { return m_format && m_format->b == 10; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const real_format *m_format;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline format_helper::format_helper (machine_mode m)
|
||||||
|
: m_format (m == VOIDmode ? 0 : REAL_MODE_FORMAT (m))
|
||||||
|
{}
|
||||||
|
|
||||||
/* Declare functions in real.c. */
|
/* Declare functions in real.c. */
|
||||||
|
|
||||||
/* True if the given mode has a NaN representation and the treatment of
|
/* True if the given mode has a NaN representation and the treatment of
|
||||||
|
|
@ -254,12 +276,12 @@ extern bool real_identical (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
|
||||||
extern bool real_equal (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
|
extern bool real_equal (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
|
||||||
extern bool real_less (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
|
extern bool real_less (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
|
||||||
|
|
||||||
/* Extend or truncate to a new mode. */
|
/* Extend or truncate to a new format. */
|
||||||
extern void real_convert (REAL_VALUE_TYPE *, machine_mode,
|
extern void real_convert (REAL_VALUE_TYPE *, format_helper,
|
||||||
const REAL_VALUE_TYPE *);
|
const REAL_VALUE_TYPE *);
|
||||||
|
|
||||||
/* Return true if truncating to NEW is exact. */
|
/* Return true if truncating to NEW is exact. */
|
||||||
extern bool exact_real_truncate (machine_mode, const REAL_VALUE_TYPE *);
|
extern bool exact_real_truncate (format_helper, const REAL_VALUE_TYPE *);
|
||||||
|
|
||||||
/* Render R as a decimal floating point constant. */
|
/* Render R as a decimal floating point constant. */
|
||||||
extern void real_to_decimal (char *, const REAL_VALUE_TYPE *, size_t,
|
extern void real_to_decimal (char *, const REAL_VALUE_TYPE *, size_t,
|
||||||
|
|
@ -281,24 +303,20 @@ extern HOST_WIDE_INT real_to_integer (const REAL_VALUE_TYPE *);
|
||||||
the value underflows, +1 if overflows, and 0 otherwise. */
|
the value underflows, +1 if overflows, and 0 otherwise. */
|
||||||
extern int real_from_string (REAL_VALUE_TYPE *, const char *);
|
extern int real_from_string (REAL_VALUE_TYPE *, const char *);
|
||||||
/* Wrapper to allow different internal representation for decimal floats. */
|
/* Wrapper to allow different internal representation for decimal floats. */
|
||||||
extern void real_from_string3 (REAL_VALUE_TYPE *, const char *, machine_mode);
|
extern void real_from_string3 (REAL_VALUE_TYPE *, const char *, format_helper);
|
||||||
|
|
||||||
extern long real_to_target_fmt (long *, const REAL_VALUE_TYPE *,
|
extern long real_to_target (long *, const REAL_VALUE_TYPE *, format_helper);
|
||||||
const struct real_format *);
|
|
||||||
extern long real_to_target (long *, const REAL_VALUE_TYPE *, machine_mode);
|
|
||||||
|
|
||||||
extern void real_from_target_fmt (REAL_VALUE_TYPE *, const long *,
|
|
||||||
const struct real_format *);
|
|
||||||
extern void real_from_target (REAL_VALUE_TYPE *, const long *,
|
extern void real_from_target (REAL_VALUE_TYPE *, const long *,
|
||||||
machine_mode);
|
format_helper);
|
||||||
|
|
||||||
extern void real_inf (REAL_VALUE_TYPE *);
|
extern void real_inf (REAL_VALUE_TYPE *);
|
||||||
|
|
||||||
extern bool real_nan (REAL_VALUE_TYPE *, const char *, int, machine_mode);
|
extern bool real_nan (REAL_VALUE_TYPE *, const char *, int, format_helper);
|
||||||
|
|
||||||
extern void real_maxval (REAL_VALUE_TYPE *, int, machine_mode);
|
extern void real_maxval (REAL_VALUE_TYPE *, int, machine_mode);
|
||||||
|
|
||||||
extern void real_2expN (REAL_VALUE_TYPE *, int, machine_mode);
|
extern void real_2expN (REAL_VALUE_TYPE *, int, format_helper);
|
||||||
|
|
||||||
extern unsigned int real_hash (const REAL_VALUE_TYPE *);
|
extern unsigned int real_hash (const REAL_VALUE_TYPE *);
|
||||||
|
|
||||||
|
|
@ -370,15 +388,14 @@ extern const struct real_format arm_half_format;
|
||||||
#define REAL_VALUE_TO_TARGET_DECIMAL32(IN, OUT) \
|
#define REAL_VALUE_TO_TARGET_DECIMAL32(IN, OUT) \
|
||||||
((OUT) = real_to_target (NULL, &(IN), mode_for_size (32, MODE_DECIMAL_FLOAT, 0)))
|
((OUT) = real_to_target (NULL, &(IN), mode_for_size (32, MODE_DECIMAL_FLOAT, 0)))
|
||||||
|
|
||||||
extern REAL_VALUE_TYPE real_value_truncate (machine_mode,
|
extern REAL_VALUE_TYPE real_value_truncate (format_helper, REAL_VALUE_TYPE);
|
||||||
REAL_VALUE_TYPE);
|
|
||||||
|
|
||||||
extern REAL_VALUE_TYPE real_value_negate (const REAL_VALUE_TYPE *);
|
extern REAL_VALUE_TYPE real_value_negate (const REAL_VALUE_TYPE *);
|
||||||
extern REAL_VALUE_TYPE real_value_abs (const REAL_VALUE_TYPE *);
|
extern REAL_VALUE_TYPE real_value_abs (const REAL_VALUE_TYPE *);
|
||||||
|
|
||||||
extern int significand_size (machine_mode);
|
extern int significand_size (format_helper);
|
||||||
|
|
||||||
extern REAL_VALUE_TYPE real_from_string2 (const char *, machine_mode);
|
extern REAL_VALUE_TYPE real_from_string2 (const char *, format_helper);
|
||||||
|
|
||||||
#define REAL_VALUE_ATOF(s, m) \
|
#define REAL_VALUE_ATOF(s, m) \
|
||||||
real_from_string2 (s, m)
|
real_from_string2 (s, m)
|
||||||
|
|
@ -437,8 +454,8 @@ REAL_VALUE_TYPE real_value_from_int_cst (const_tree, const_tree);
|
||||||
/* Return a CONST_DOUBLE with value R and mode M. */
|
/* Return a CONST_DOUBLE with value R and mode M. */
|
||||||
extern rtx const_double_from_real_value (REAL_VALUE_TYPE, machine_mode);
|
extern rtx const_double_from_real_value (REAL_VALUE_TYPE, machine_mode);
|
||||||
|
|
||||||
/* Replace R by 1/R in the given machine mode, if the result is exact. */
|
/* Replace R by 1/R in the given format, if the result is exact. */
|
||||||
extern bool exact_real_inverse (machine_mode, REAL_VALUE_TYPE *);
|
extern bool exact_real_inverse (format_helper, REAL_VALUE_TYPE *);
|
||||||
|
|
||||||
/* Return true if arithmetic on values in IMODE that were promoted
|
/* Return true if arithmetic on values in IMODE that were promoted
|
||||||
from values in TMODE is equivalent to direct arithmetic on values
|
from values in TMODE is equivalent to direct arithmetic on values
|
||||||
|
|
@ -451,25 +468,25 @@ extern tree build_real (tree, REAL_VALUE_TYPE);
|
||||||
/* Likewise, but first truncate the value to the type. */
|
/* Likewise, but first truncate the value to the type. */
|
||||||
extern tree build_real_truncate (tree, REAL_VALUE_TYPE);
|
extern tree build_real_truncate (tree, REAL_VALUE_TYPE);
|
||||||
|
|
||||||
/* Calculate R as X raised to the integer exponent N in mode MODE. */
|
/* Calculate R as X raised to the integer exponent N in format FMT. */
|
||||||
extern bool real_powi (REAL_VALUE_TYPE *, machine_mode,
|
extern bool real_powi (REAL_VALUE_TYPE *, format_helper,
|
||||||
const REAL_VALUE_TYPE *, HOST_WIDE_INT);
|
const REAL_VALUE_TYPE *, HOST_WIDE_INT);
|
||||||
|
|
||||||
/* Standard round to integer value functions. */
|
/* Standard round to integer value functions. */
|
||||||
extern void real_trunc (REAL_VALUE_TYPE *, machine_mode,
|
extern void real_trunc (REAL_VALUE_TYPE *, format_helper,
|
||||||
const REAL_VALUE_TYPE *);
|
const REAL_VALUE_TYPE *);
|
||||||
extern void real_floor (REAL_VALUE_TYPE *, machine_mode,
|
extern void real_floor (REAL_VALUE_TYPE *, format_helper,
|
||||||
const REAL_VALUE_TYPE *);
|
const REAL_VALUE_TYPE *);
|
||||||
extern void real_ceil (REAL_VALUE_TYPE *, machine_mode,
|
extern void real_ceil (REAL_VALUE_TYPE *, format_helper,
|
||||||
const REAL_VALUE_TYPE *);
|
const REAL_VALUE_TYPE *);
|
||||||
extern void real_round (REAL_VALUE_TYPE *, machine_mode,
|
extern void real_round (REAL_VALUE_TYPE *, format_helper,
|
||||||
const REAL_VALUE_TYPE *);
|
const REAL_VALUE_TYPE *);
|
||||||
|
|
||||||
/* Set the sign of R to the sign of X. */
|
/* Set the sign of R to the sign of X. */
|
||||||
extern void real_copysign (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
|
extern void real_copysign (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
|
||||||
|
|
||||||
/* Check whether the real constant value given is an integer. */
|
/* Check whether the real constant value given is an integer. */
|
||||||
extern bool real_isinteger (const REAL_VALUE_TYPE *, machine_mode);
|
extern bool real_isinteger (const REAL_VALUE_TYPE *, format_helper);
|
||||||
extern bool real_isinteger (const REAL_VALUE_TYPE *, HOST_WIDE_INT *);
|
extern bool real_isinteger (const REAL_VALUE_TYPE *, HOST_WIDE_INT *);
|
||||||
|
|
||||||
/* Write into BUF the maximum representable finite floating-point
|
/* Write into BUF the maximum representable finite floating-point
|
||||||
|
|
@ -480,7 +497,7 @@ extern void get_max_float (const struct real_format *, char *, size_t);
|
||||||
#ifndef GENERATOR_FILE
|
#ifndef GENERATOR_FILE
|
||||||
/* real related routines. */
|
/* real related routines. */
|
||||||
extern wide_int real_to_integer (const REAL_VALUE_TYPE *, bool *, int);
|
extern wide_int real_to_integer (const REAL_VALUE_TYPE *, bool *, int);
|
||||||
extern void real_from_integer (REAL_VALUE_TYPE *, machine_mode,
|
extern void real_from_integer (REAL_VALUE_TYPE *, format_helper,
|
||||||
const wide_int_ref &, signop);
|
const wide_int_ref &, signop);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue