]> git.eshelyaron.com Git - emacs.git/commitdiff
* src/timefns.c: Add comments.
authorPaul Eggert <eggert@cs.ucla.edu>
Sun, 8 Mar 2020 23:43:54 +0000 (16:43 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Sun, 8 Mar 2020 23:44:49 +0000 (16:44 -0700)
src/timefns.c

index 8e2bb214ed8a2b7d4fda7648a8798814ce274d1d..4079358fc5d5d66ac90497f008108769a1fbdb9f 100644 (file)
@@ -421,6 +421,9 @@ decode_float_time (double t, struct lisp_time *result)
       else if (flt_radix_power_size <= scale)
        return isnan (t) ? EDOM : EOVERFLOW;
 
+      /* Compute TICKS, HZ such that TICKS / HZ exactly equals T, where HZ is
+        T's frequency or 1, whichever is greater.  Here, “frequency” means
+        1/precision.  Cache HZ values in flt_radix_power.  */
       double scaled = scalbn (t, scale);
       eassert (trunc (scaled) == scaled);
       ticks = double_to_integer (scaled);
@@ -442,6 +445,7 @@ decode_float_time (double t, struct lisp_time *result)
 static Lisp_Object
 ticks_hz_list4 (Lisp_Object ticks, Lisp_Object hz)
 {
+  /* mpz[0] = floor ((ticks * trillion) / hz).  */
   mpz_t const *zticks = bignum_integer (&mpz[0], ticks);
 #if FASTER_TIMEFNS && TRILLION <= ULONG_MAX
   mpz_mul_ui (mpz[0], *zticks, TRILLION);
@@ -449,6 +453,9 @@ ticks_hz_list4 (Lisp_Object ticks, Lisp_Object hz)
   mpz_mul (mpz[0], *zticks, ztrillion);
 #endif
   mpz_fdiv_q (mpz[0], mpz[0], *bignum_integer (&mpz[1], hz));
+
+  /* mpz[0] = floor (mpz[0] / trillion), with US = the high six digits of the
+     12-digit remainder, and PS = the low six digits.  */
 #if FASTER_TIMEFNS && TRILLION <= ULONG_MAX
   unsigned long int fullps = mpz_fdiv_q_ui (mpz[0], mpz[0], TRILLION);
   int us = fullps / 1000000;
@@ -458,11 +465,14 @@ ticks_hz_list4 (Lisp_Object ticks, Lisp_Object hz)
   int ps = mpz_fdiv_q_ui (mpz[1], mpz[1], 1000000);
   int us = mpz_get_ui (mpz[1]);
 #endif
+
+  /* mpz[0] = floor (mpz[0] / 1 << LO_TIME_BITS), with lo = remainder.  */
   unsigned long ulo = mpz_get_ui (mpz[0]);
   if (mpz_sgn (mpz[0]) < 0)
     ulo = -ulo;
   int lo = ulo & ((1 << LO_TIME_BITS) - 1);
   mpz_fdiv_q_2exp (mpz[0], mpz[0], LO_TIME_BITS);
+
   return list4 (make_integer_mpz (), make_fixnum (lo),
                make_fixnum (us), make_fixnum (ps));
 }
@@ -482,6 +492,7 @@ mpz_set_time (mpz_t rop, time_t t)
 static void
 timespec_mpz (struct timespec t)
 {
+  /* mpz[0] = sec * TIMESPEC_HZ + nsec.  */
   mpz_set_ui (mpz[0], t.tv_nsec);
   mpz_set_time (mpz[1], t.tv_sec);
   mpz_addmul_ui (mpz[0], mpz[1], TIMESPEC_HZ);
@@ -508,7 +519,9 @@ timespec_ticks (struct timespec t)
 static Lisp_Object
 lisp_time_hz_ticks (struct lisp_time t, Lisp_Object hz)
 {
-  /* For speed, just return TICKS if T is (TICKS . HZ).  */
+  /* The idea is to return the floor of ((T.ticks * HZ) / T.hz).  */
+
+  /* For speed, just return T.ticks if T.hz == HZ.  */
   if (FASTER_TIMEFNS && EQ (t.hz, hz))
     return t.ticks;
 
@@ -540,6 +553,8 @@ lisp_time_hz_ticks (struct lisp_time t, Lisp_Object hz)
 static Lisp_Object
 lisp_time_seconds (struct lisp_time t)
 {
+  /* The idea is to return the floor of T.ticks / T.hz.  */
+
   if (!FASTER_TIMEFNS)
     return lisp_time_hz_ticks (t, make_fixnum (1));
 
@@ -587,6 +602,7 @@ frac_to_double (Lisp_Object numerator, Lisp_Object denominator)
       && integer_to_intmax (numerator, &intmax_numerator))
     return intmax_numerator;
 
+  /* Compute number of base-FLT_RADIX digits in numerator and denominator.  */
   mpz_t const *n = bignum_integer (&mpz[0], numerator);
   mpz_t const *d = bignum_integer (&mpz[1], denominator);
   ptrdiff_t nbits = mpz_sizeinbase (*n, 2);
@@ -599,7 +615,8 @@ frac_to_double (Lisp_Object numerator, Lisp_Object denominator)
   /* Scale with SCALE when doing integer division.  That is, compute
      (N * FLT_RADIX**SCALE) / D [or, if SCALE is negative, N / (D *
      FLT_RADIX**-SCALE)] as a bignum, convert the bignum to double,
-     then divide the double by FLT_RADIX**SCALE.  */
+     then divide the double by FLT_RADIX**SCALE.  First scale N
+     N (or scale D, if SCALE is negative) ...  */
   ptrdiff_t scale = ddig - ndig + DBL_MANT_DIG + 1;
   if (scale < 0)
     {
@@ -614,12 +631,12 @@ frac_to_double (Lisp_Object numerator, Lisp_Object denominator)
       mpz_mul_2exp (mpz[0], *n, scale * LOG2_FLT_RADIX);
       n = &mpz[0];
     }
-
+  /* ... and then divide, with quotient Q and remainder R.  */
   mpz_t *q = &mpz[2];
   mpz_t *r = &mpz[3];
   mpz_tdiv_qr (*q, *r, *n, *d);
 
-  /* The amount to add to the absolute value of *Q so that truncating
+  /* The amount to add to the absolute value of Q so that truncating
      it to double will round correctly.  */
   int incr;
 
@@ -658,6 +675,7 @@ frac_to_double (Lisp_Object numerator, Lisp_Object denominator)
   if (!FASTER_TIMEFNS || incr != 0)
     (mpz_sgn (*n) < 0 ? mpz_sub_ui : mpz_add_ui) (*q, *q, incr);
 
+  /* Rescale the integer Q back to double.  This step does not round.  */
   return scalbn (mpz_get_d (*q), -scale);
 }
 
@@ -902,6 +920,10 @@ lisp_to_timespec (struct lisp_time t)
   mpz_t *q = &mpz[0];
   mpz_t const *qt = q;
 
+  /* Floor-divide (T.ticks * TIMESPEC_HZ) by T.hz,
+     yielding quotient Q (tv_sec) and remainder NS (tv_nsec).
+     Return an invalid timespec if Q does not fit in time_t.
+     For speed, prefer fixnum arithmetic if it works.  */
   if (FASTER_TIMEFNS && EQ (t.hz, timespec_hz))
     {
       if (FIXNUMP (t.ticks))
@@ -945,8 +967,8 @@ lisp_to_timespec (struct lisp_time t)
       ns = mpz_fdiv_q_ui (*q, *q, TIMESPEC_HZ);
     }
 
-  /* With some versions of MinGW, tv_sec is a 64-bit type, whereas
-     time_t is a 32-bit type.  */
+  /* Check that Q fits in time_t, not merely in T.tv_sec.  With some versions
+     of MinGW, tv_sec is a 64-bit type, whereas time_t is a 32-bit type.  */
   time_t sec;
   if (mpz_time (*qt, &sec))
     {
@@ -1026,10 +1048,14 @@ lispint_arith (Lisp_Object a, Lisp_Object b, bool subtract)
     {
       if (EQ (b, make_fixnum (0)))
        return a;
+
+      /* For speed, use EMACS_INT arithmetic if it will do.  */
       if (FIXNUMP (a))
        return make_int (subtract
                         ? XFIXNUM (a) - XFIXNUM (b)
                         : XFIXNUM (a) + XFIXNUM (b));
+
+      /* For speed, use mpz_add_ui/mpz_sub_ui if it will do.  */
       if (eabs (XFIXNUM (b)) <= ULONG_MAX)
        {
          ((XFIXNUM (b) < 0) == subtract ? mpz_add_ui : mpz_sub_ui)
@@ -1038,6 +1064,7 @@ lispint_arith (Lisp_Object a, Lisp_Object b, bool subtract)
        }
     }
 
+  /* Fall back on bignum arithmetic if necessary.  */
   if (!mpz_done)
     (subtract ? mpz_sub : mpz_add) (mpz[0],
                                    *bignum_integer (&mpz[0], a),
@@ -1221,6 +1248,8 @@ time_cmp (Lisp_Object a, Lisp_Object b)
   if (EQ (a, b))
     return 0;
 
+  /* Compare (ATICKS . AZ) to (BTICKS . BHZ) by comparing
+     ATICKS * BHZ to BTICKS * AHZ.  */
   struct lisp_time tb = lisp_time_struct (b, 0);
   mpz_t const *za = bignum_integer (&mpz[0], ta.ticks);
   mpz_t const *zb = bignum_integer (&mpz[1], tb.ticks);
@@ -1498,6 +1527,7 @@ SEC is always an integer between 0 and 59.)
 usage: (decode-time &optional TIME ZONE FORM)  */)
   (Lisp_Object specified_time, Lisp_Object zone, Lisp_Object form)
 {
+  /* Compute broken-down local time LOCAL_TM from SPECIFIED_TIME and ZONE.  */
   struct lisp_time lt = lisp_time_struct (specified_time, 0);
   struct timespec ts = lisp_to_timespec (lt);
   if (! timespec_valid_p (ts))
@@ -1512,6 +1542,7 @@ usage: (decode-time &optional TIME ZONE FORM)  */)
   if (!tm)
     time_error (localtime_errno);
 
+  /* Let YEAR = LOCAL_TM.tm_year + TM_YEAR_BASE.  */
   Lisp_Object year;
   if (FASTER_TIMEFNS
       && MOST_NEGATIVE_FIXNUM - TM_YEAR_BASE <= local_tm.tm_year
@@ -1528,12 +1559,15 @@ usage: (decode-time &optional TIME ZONE FORM)  */)
       year = make_integer_mpz ();
     }
 
+  /* Compute SEC from LOCAL_TM.tm_sec and HZ.  */
   Lisp_Object hz = lt.hz, sec;
   if (EQ (hz, make_fixnum (1)) || !EQ (form, Qt))
     sec = make_fixnum (local_tm.tm_sec);
   else
     {
-      Lisp_Object ticks; /* hz * tm_sec + mod (lt.ticks, hz) */
+      /* Let TICKS = HZ * LOCAL_TM.tm_sec + mod (LT.ticks, HZ)
+        and SEC = (TICKS . HZ).  */
+      Lisp_Object ticks;
       intmax_t n;
       if (FASTER_TIMEFNS && FIXNUMP (lt.ticks) && FIXNUMP (hz)
          && !INT_MULTIPLY_WRAPV (XFIXNUM (hz), local_tm.tm_sec, &n)
@@ -1663,6 +1697,7 @@ usage: (encode-time TIME &rest OBSOLESCENT-ARGUMENTS)  */)
       yeararg = args[5];
     }
 
+  /* Let SEC = floor (LT.ticks / HZ), with SUBSECTICKS the remainder.  */
   struct lisp_time lt;
   decode_lisp_time (secarg, 0, &lt, 0);
   Lisp_Object hz = lt.hz, sec, subsecticks;