aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2019-08-20 14:02:30 -0700
committerPaul Eggert2019-08-20 15:45:59 -0700
commit5a9552128296478ec74594b45d0728d87450197e (patch)
treef83d7409a2d62813ed4bb1d8b10215efefca29a3 /src
parenta13c64204c8ead966789abf8efe176e4f2d4f599 (diff)
downloademacs-5a9552128296478ec74594b45d0728d87450197e.tar.gz
emacs-5a9552128296478ec74594b45d0728d87450197e.zip
Support larger TIMEs in (time-convert TIME t)
Also, improve the doc to match current behavior. * doc/lispref/os.texi (Time Conversion): Document that time-convert signals an error for infinite or NaN args, and that (time-convert TIME t) is exact otherwise. Mention float-time as an alternative to time-convert. (Time Calculations): Document that time-add and time-subtract are exact and do not decrease HZ below the minimum of their args. * src/timefns.c (decode_float_time): Don’t signal an error for floating-point arguments whose base-FLT_RADIX exponent is not less than DBL_MANT_DIG. Instead, convert them to (TICKS . 1) values. Use two (instead of three) integer exponent comparisons in the typical case. * test/src/timefns-tests.el (time-arith-tests): Add more floating-point tests, including some tests that the old code fails.
Diffstat (limited to 'src')
-rw-r--r--src/timefns.c40
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);