diff options
| author | Paul Eggert | 2019-11-10 15:06:49 -0800 |
|---|---|---|
| committer | Paul Eggert | 2019-11-13 13:10:08 -0800 |
| commit | ff10e9517d98aa606e007d3aa4d5aef1c423ab77 (patch) | |
| tree | 99d676a2ef88a024fdfd3fdafcdb7abb508e0f55 /src | |
| parent | 65fb04801c59ac204790e0a5c0599c9b11151f32 (diff) | |
| download | emacs-ff10e9517d98aa606e007d3aa4d5aef1c423ab77.tar.gz emacs-ff10e9517d98aa606e007d3aa4d5aef1c423ab77.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/floatfns.c | 23 | ||||
| -rw-r--r-- | src/lisp.h | 1 | ||||
| -rw-r--r-- | src/timefns.c | 27 |
3 files changed, 29 insertions, 22 deletions
diff --git a/src/floatfns.c b/src/floatfns.c index 3199d572138..7e77dbd16dc 100644 --- a/src/floatfns.c +++ b/src/floatfns.c | |||
| @@ -348,6 +348,29 @@ integer_value (Lisp_Object a) | |||
| 348 | return true; | 348 | return true; |
| 349 | } | 349 | } |
| 350 | 350 | ||
| 351 | /* Return the integer exponent E such that D * FLT_RADIX**E (i.e., | ||
| 352 | scalbn (D, E)) is an integer that has precision equal to D and is | ||
| 353 | representable as a double. | ||
| 354 | |||
| 355 | Return DBL_MANT_DIG - DBL_MIN_EXP (the maximum possible valid | ||
| 356 | scale) if D is zero or tiny. Return a value greater than | ||
| 357 | DBL_MANT_DIG - DBL_MIN_EXP if there is conversion trouble; on all | ||
| 358 | current platforms this can happen only if D is infinite or a NaN. */ | ||
| 359 | |||
| 360 | int | ||
| 361 | double_integer_scale (double d) | ||
| 362 | { | ||
| 363 | int exponent = ilogb (d); | ||
| 364 | return (DBL_MIN_EXP - 1 <= exponent && exponent < INT_MAX | ||
| 365 | ? DBL_MANT_DIG - 1 - exponent | ||
| 366 | : (DBL_MANT_DIG - DBL_MIN_EXP | ||
| 367 | + (exponent == INT_MAX | ||
| 368 | || (exponent == FP_ILOGBNAN | ||
| 369 | && (FP_ILOGBNAN != FP_ILOGB0 || isnan (d))) | ||
| 370 | || (!IEEE_FLOATING_POINT && exponent == INT_MIN | ||
| 371 | && (FP_ILOGB0 != INT_MIN || d != 0))))); | ||
| 372 | } | ||
| 373 | |||
| 351 | /* the rounding functions */ | 374 | /* the rounding functions */ |
| 352 | 375 | ||
| 353 | static Lisp_Object | 376 | static Lisp_Object |
diff --git a/src/lisp.h b/src/lisp.h index 04fa1d64eab..38e1891c894 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -3684,6 +3684,7 @@ extern Lisp_Object string_make_unibyte (Lisp_Object); | |||
| 3684 | extern void syms_of_fns (void); | 3684 | extern void syms_of_fns (void); |
| 3685 | 3685 | ||
| 3686 | /* Defined in floatfns.c. */ | 3686 | /* Defined in floatfns.c. */ |
| 3687 | int double_integer_scale (double); | ||
| 3687 | #ifndef HAVE_TRUNC | 3688 | #ifndef HAVE_TRUNC |
| 3688 | extern double trunc (double); | 3689 | extern double trunc (double); |
| 3689 | #endif | 3690 | #endif |
diff --git a/src/timefns.c b/src/timefns.c index fe08efd4c10..cf634a82b4e 100644 --- a/src/timefns.c +++ b/src/timefns.c | |||
| @@ -406,26 +406,9 @@ decode_float_time (double t, struct lisp_time *result) | |||
| 406 | } | 406 | } |
| 407 | else | 407 | else |
| 408 | { | 408 | { |
| 409 | int exponent = ilogb (t); | 409 | int scale = double_integer_scale (t); |
| 410 | int scale; | 410 | |
| 411 | if (exponent < DBL_MANT_DIG) | 411 | if (scale < 0) |
| 412 | { | ||
| 413 | if (exponent < DBL_MIN_EXP - 1) | ||
| 414 | { | ||
| 415 | if (exponent == FP_ILOGBNAN | ||
| 416 | && (FP_ILOGBNAN != FP_ILOGB0 || isnan (t))) | ||
| 417 | return EINVAL; | ||
| 418 | /* T is tiny. SCALE must be less than FLT_RADIX_POWER_SIZE, | ||
| 419 | as otherwise T would be scaled as if it were normalized. */ | ||
| 420 | scale = flt_radix_power_size - 1; | ||
| 421 | } | ||
| 422 | else | ||
| 423 | { | ||
| 424 | /* The typical case. */ | ||
| 425 | scale = DBL_MANT_DIG - 1 - exponent; | ||
| 426 | } | ||
| 427 | } | ||
| 428 | else if (exponent < INT_MAX) | ||
| 429 | { | 412 | { |
| 430 | /* T is finite but so large that HZ would be less than 1 if | 413 | /* T is finite but so large that HZ would be less than 1 if |
| 431 | T's precision were represented exactly. SCALE must be | 414 | T's precision were represented exactly. SCALE must be |
| @@ -435,8 +418,8 @@ decode_float_time (double t, struct lisp_time *result) | |||
| 435 | which is typically better than signaling overflow. */ | 418 | which is typically better than signaling overflow. */ |
| 436 | scale = 0; | 419 | scale = 0; |
| 437 | } | 420 | } |
| 438 | else | 421 | else if (flt_radix_power_size <= scale) |
| 439 | return FP_ILOGBNAN == INT_MAX && isnan (t) ? EINVAL : EOVERFLOW; | 422 | return isnan (t) ? EDOM : EOVERFLOW; |
| 440 | 423 | ||
| 441 | double scaled = scalbn (t, scale); | 424 | double scaled = scalbn (t, scale); |
| 442 | eassert (trunc (scaled) == scaled); | 425 | eassert (trunc (scaled) == scaled); |