]> git.eshelyaron.com Git - emacs.git/commitdiff
Refactor double integer scaling
authorPaul Eggert <eggert@cs.ucla.edu>
Sun, 10 Nov 2019 23:06:49 +0000 (15:06 -0800)
committerPaul Eggert <eggert@cs.ucla.edu>
Wed, 13 Nov 2019 21:10:08 +0000 (13:10 -0800)
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.

src/floatfns.c
src/lisp.h
src/timefns.c

index 3199d572138fdaa80cc38b666110b8b81bf314cb..7e77dbd16dc6073ecff8087439b24ce65359daf7 100644 (file)
@@ -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
index 04fa1d64eab2597af00030292e0125034ceed416..38e1891c894980ace7c6fbd698e133f08c8d8ffc 100644 (file)
@@ -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
index fe08efd4c10efd943ab94dfece96d253811af757..cf634a82b4eec024d611a2e26294fb81406e87f7 100644 (file)
@@ -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);