aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2019-11-10 15:06:49 -0800
committerPaul Eggert2019-11-13 13:10:08 -0800
commitff10e9517d98aa606e007d3aa4d5aef1c423ab77 (patch)
tree99d676a2ef88a024fdfd3fdafcdb7abb508e0f55 /src
parent65fb04801c59ac204790e0a5c0599c9b11151f32 (diff)
downloademacs-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.c23
-rw-r--r--src/lisp.h1
-rw-r--r--src/timefns.c27
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
360int
361double_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
353static Lisp_Object 376static 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);
3684extern void syms_of_fns (void); 3684extern void syms_of_fns (void);
3685 3685
3686/* Defined in floatfns.c. */ 3686/* Defined in floatfns.c. */
3687int double_integer_scale (double);
3687#ifndef HAVE_TRUNC 3688#ifndef HAVE_TRUNC
3688extern double trunc (double); 3689extern 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);