diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/timefns.c | 40 |
1 files changed, 30 insertions, 10 deletions
diff --git a/src/timefns.c b/src/timefns.c index 2d545a4f905..3b686eb2265 100644 --- a/src/timefns.c +++ b/src/timefns.c | |||
| @@ -391,16 +391,36 @@ decode_float_time (double t, struct lisp_time *result) | |||
| 391 | else | 391 | else |
| 392 | { | 392 | { |
| 393 | int exponent = ilogb (t); | 393 | int exponent = ilogb (t); |
| 394 | if (exponent == FP_ILOGBNAN) | 394 | int scale; |
| 395 | return EINVAL; | 395 | if (exponent < DBL_MANT_DIG) |
| 396 | 396 | { | |
| 397 | /* An enormous or infinite T would make SCALE < 0 which would make | 397 | if (exponent < DBL_MIN_EXP - 1) |
| 398 | HZ < 1, which the (TICKS . HZ) representation does not allow. */ | 398 | { |
| 399 | if (DBL_MANT_DIG - 1 < exponent) | 399 | if (exponent == FP_ILOGBNAN |
| 400 | return EOVERFLOW; | 400 | && (FP_ILOGBNAN != FP_ILOGB0 || isnan (t))) |
| 401 | 401 | return EINVAL; | |
| 402 | /* min so we don't scale tiny numbers as if they were normalized. */ | 402 | /* T is tiny. SCALE must be less than FLT_RADIX_POWER_SIZE, |
| 403 | int scale = min (DBL_MANT_DIG - 1 - exponent, flt_radix_power_size - 1); | 403 | as otherwise T would be scaled as if it were normalized. */ |
| 404 | scale = flt_radix_power_size - 1; | ||
| 405 | } | ||
| 406 | else | ||
| 407 | { | ||
| 408 | /* The typical case. */ | ||
| 409 | scale = DBL_MANT_DIG - 1 - exponent; | ||
| 410 | } | ||
| 411 | } | ||
| 412 | else if (exponent < INT_MAX) | ||
| 413 | { | ||
| 414 | /* T is finite but so large that HZ would be less than 1 if | ||
| 415 | T's precision were represented exactly. SCALE must be | ||
| 416 | nonnegative, as the (TICKS . HZ) representation requires | ||
| 417 | HZ to be at least 1. So use SCALE = 0, which converts T to | ||
| 418 | (T . 1), which is the exact numeric value with too-large HZ, | ||
| 419 | which is typically better than signaling overflow. */ | ||
| 420 | scale = 0; | ||
| 421 | } | ||
| 422 | else | ||
| 423 | return FP_ILOGBNAN == INT_MAX && isnan (t) ? EINVAL : EOVERFLOW; | ||
| 404 | 424 | ||
| 405 | double scaled = scalbn (t, scale); | 425 | double scaled = scalbn (t, scale); |
| 406 | eassert (trunc (scaled) == scaled); | 426 | eassert (trunc (scaled) == scaled); |