mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-16 17:24:23 +00:00
Refactor double integer scaling
This doesn’t alter behavior, and simplifies a future commit. * src/floatfns.c (double_integer_scale): New function, with body adapted from the old timefns.c. * src/timefns.c (decode_float_time): Use it.
This commit is contained in:
parent
65fb04801c
commit
ff10e9517d
3 changed files with 29 additions and 22 deletions
|
|
@ -348,6 +348,29 @@ integer_value (Lisp_Object a)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Return the integer exponent E such that D * FLT_RADIX**E (i.e.,
|
||||
scalbn (D, E)) is an integer that has precision equal to D and is
|
||||
representable as a double.
|
||||
|
||||
Return DBL_MANT_DIG - DBL_MIN_EXP (the maximum possible valid
|
||||
scale) if D is zero or tiny. Return a value greater than
|
||||
DBL_MANT_DIG - DBL_MIN_EXP if there is conversion trouble; on all
|
||||
current platforms this can happen only if D is infinite or a NaN. */
|
||||
|
||||
int
|
||||
double_integer_scale (double d)
|
||||
{
|
||||
int exponent = ilogb (d);
|
||||
return (DBL_MIN_EXP - 1 <= exponent && exponent < INT_MAX
|
||||
? DBL_MANT_DIG - 1 - exponent
|
||||
: (DBL_MANT_DIG - DBL_MIN_EXP
|
||||
+ (exponent == INT_MAX
|
||||
|| (exponent == FP_ILOGBNAN
|
||||
&& (FP_ILOGBNAN != FP_ILOGB0 || isnan (d)))
|
||||
|| (!IEEE_FLOATING_POINT && exponent == INT_MIN
|
||||
&& (FP_ILOGB0 != INT_MIN || d != 0)))));
|
||||
}
|
||||
|
||||
/* the rounding functions */
|
||||
|
||||
static Lisp_Object
|
||||
|
|
|
|||
|
|
@ -3684,6 +3684,7 @@ extern Lisp_Object string_make_unibyte (Lisp_Object);
|
|||
extern void syms_of_fns (void);
|
||||
|
||||
/* Defined in floatfns.c. */
|
||||
int double_integer_scale (double);
|
||||
#ifndef HAVE_TRUNC
|
||||
extern double trunc (double);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -406,26 +406,9 @@ decode_float_time (double t, struct lisp_time *result)
|
|||
}
|
||||
else
|
||||
{
|
||||
int exponent = ilogb (t);
|
||||
int scale;
|
||||
if (exponent < DBL_MANT_DIG)
|
||||
{
|
||||
if (exponent < DBL_MIN_EXP - 1)
|
||||
{
|
||||
if (exponent == FP_ILOGBNAN
|
||||
&& (FP_ILOGBNAN != FP_ILOGB0 || isnan (t)))
|
||||
return EINVAL;
|
||||
/* T is tiny. SCALE must be less than FLT_RADIX_POWER_SIZE,
|
||||
as otherwise T would be scaled as if it were normalized. */
|
||||
scale = flt_radix_power_size - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The typical case. */
|
||||
scale = DBL_MANT_DIG - 1 - exponent;
|
||||
}
|
||||
}
|
||||
else if (exponent < INT_MAX)
|
||||
int scale = double_integer_scale (t);
|
||||
|
||||
if (scale < 0)
|
||||
{
|
||||
/* T is finite but so large that HZ would be less than 1 if
|
||||
T's precision were represented exactly. SCALE must be
|
||||
|
|
@ -435,8 +418,8 @@ decode_float_time (double t, struct lisp_time *result)
|
|||
which is typically better than signaling overflow. */
|
||||
scale = 0;
|
||||
}
|
||||
else
|
||||
return FP_ILOGBNAN == INT_MAX && isnan (t) ? EINVAL : EOVERFLOW;
|
||||
else if (flt_radix_power_size <= scale)
|
||||
return isnan (t) ? EDOM : EOVERFLOW;
|
||||
|
||||
double scaled = scalbn (t, scale);
|
||||
eassert (trunc (scaled) == scaled);
|
||||
|
|
|
|||
Loading…
Reference in a new issue