aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2020-03-08 16:43:54 -0700
committerPaul Eggert2020-03-08 16:44:49 -0700
commit20d3d3a9509ed24b4fb701919bf4a677c7d9e249 (patch)
tree592b600f20e0f115128893129f3046f694e1b815 /src
parent0a3682a566d5563e3d57defe49359cee236e0274 (diff)
downloademacs-20d3d3a9509ed24b4fb701919bf4a677c7d9e249.tar.gz
emacs-20d3d3a9509ed24b4fb701919bf4a677c7d9e249.zip
* src/timefns.c: Add comments.
Diffstat (limited to 'src')
-rw-r--r--src/timefns.c49
1 files changed, 42 insertions, 7 deletions
diff --git a/src/timefns.c b/src/timefns.c
index 8e2bb214ed8..4079358fc5d 100644
--- a/src/timefns.c
+++ b/src/timefns.c
@@ -421,6 +421,9 @@ decode_float_time (double t, struct lisp_time *result)
421 else if (flt_radix_power_size <= scale) 421 else if (flt_radix_power_size <= scale)
422 return isnan (t) ? EDOM : EOVERFLOW; 422 return isnan (t) ? EDOM : EOVERFLOW;
423 423
424 /* Compute TICKS, HZ such that TICKS / HZ exactly equals T, where HZ is
425 T's frequency or 1, whichever is greater. Here, “frequency” means
426 1/precision. Cache HZ values in flt_radix_power. */
424 double scaled = scalbn (t, scale); 427 double scaled = scalbn (t, scale);
425 eassert (trunc (scaled) == scaled); 428 eassert (trunc (scaled) == scaled);
426 ticks = double_to_integer (scaled); 429 ticks = double_to_integer (scaled);
@@ -442,6 +445,7 @@ decode_float_time (double t, struct lisp_time *result)
442static Lisp_Object 445static Lisp_Object
443ticks_hz_list4 (Lisp_Object ticks, Lisp_Object hz) 446ticks_hz_list4 (Lisp_Object ticks, Lisp_Object hz)
444{ 447{
448 /* mpz[0] = floor ((ticks * trillion) / hz). */
445 mpz_t const *zticks = bignum_integer (&mpz[0], ticks); 449 mpz_t const *zticks = bignum_integer (&mpz[0], ticks);
446#if FASTER_TIMEFNS && TRILLION <= ULONG_MAX 450#if FASTER_TIMEFNS && TRILLION <= ULONG_MAX
447 mpz_mul_ui (mpz[0], *zticks, TRILLION); 451 mpz_mul_ui (mpz[0], *zticks, TRILLION);
@@ -449,6 +453,9 @@ ticks_hz_list4 (Lisp_Object ticks, Lisp_Object hz)
449 mpz_mul (mpz[0], *zticks, ztrillion); 453 mpz_mul (mpz[0], *zticks, ztrillion);
450#endif 454#endif
451 mpz_fdiv_q (mpz[0], mpz[0], *bignum_integer (&mpz[1], hz)); 455 mpz_fdiv_q (mpz[0], mpz[0], *bignum_integer (&mpz[1], hz));
456
457 /* mpz[0] = floor (mpz[0] / trillion), with US = the high six digits of the
458 12-digit remainder, and PS = the low six digits. */
452#if FASTER_TIMEFNS && TRILLION <= ULONG_MAX 459#if FASTER_TIMEFNS && TRILLION <= ULONG_MAX
453 unsigned long int fullps = mpz_fdiv_q_ui (mpz[0], mpz[0], TRILLION); 460 unsigned long int fullps = mpz_fdiv_q_ui (mpz[0], mpz[0], TRILLION);
454 int us = fullps / 1000000; 461 int us = fullps / 1000000;
@@ -458,11 +465,14 @@ ticks_hz_list4 (Lisp_Object ticks, Lisp_Object hz)
458 int ps = mpz_fdiv_q_ui (mpz[1], mpz[1], 1000000); 465 int ps = mpz_fdiv_q_ui (mpz[1], mpz[1], 1000000);
459 int us = mpz_get_ui (mpz[1]); 466 int us = mpz_get_ui (mpz[1]);
460#endif 467#endif
468
469 /* mpz[0] = floor (mpz[0] / 1 << LO_TIME_BITS), with lo = remainder. */
461 unsigned long ulo = mpz_get_ui (mpz[0]); 470 unsigned long ulo = mpz_get_ui (mpz[0]);
462 if (mpz_sgn (mpz[0]) < 0) 471 if (mpz_sgn (mpz[0]) < 0)
463 ulo = -ulo; 472 ulo = -ulo;
464 int lo = ulo & ((1 << LO_TIME_BITS) - 1); 473 int lo = ulo & ((1 << LO_TIME_BITS) - 1);
465 mpz_fdiv_q_2exp (mpz[0], mpz[0], LO_TIME_BITS); 474 mpz_fdiv_q_2exp (mpz[0], mpz[0], LO_TIME_BITS);
475
466 return list4 (make_integer_mpz (), make_fixnum (lo), 476 return list4 (make_integer_mpz (), make_fixnum (lo),
467 make_fixnum (us), make_fixnum (ps)); 477 make_fixnum (us), make_fixnum (ps));
468} 478}
@@ -482,6 +492,7 @@ mpz_set_time (mpz_t rop, time_t t)
482static void 492static void
483timespec_mpz (struct timespec t) 493timespec_mpz (struct timespec t)
484{ 494{
495 /* mpz[0] = sec * TIMESPEC_HZ + nsec. */
485 mpz_set_ui (mpz[0], t.tv_nsec); 496 mpz_set_ui (mpz[0], t.tv_nsec);
486 mpz_set_time (mpz[1], t.tv_sec); 497 mpz_set_time (mpz[1], t.tv_sec);
487 mpz_addmul_ui (mpz[0], mpz[1], TIMESPEC_HZ); 498 mpz_addmul_ui (mpz[0], mpz[1], TIMESPEC_HZ);
@@ -508,7 +519,9 @@ timespec_ticks (struct timespec t)
508static Lisp_Object 519static Lisp_Object
509lisp_time_hz_ticks (struct lisp_time t, Lisp_Object hz) 520lisp_time_hz_ticks (struct lisp_time t, Lisp_Object hz)
510{ 521{
511 /* For speed, just return TICKS if T is (TICKS . HZ). */ 522 /* The idea is to return the floor of ((T.ticks * HZ) / T.hz). */
523
524 /* For speed, just return T.ticks if T.hz == HZ. */
512 if (FASTER_TIMEFNS && EQ (t.hz, hz)) 525 if (FASTER_TIMEFNS && EQ (t.hz, hz))
513 return t.ticks; 526 return t.ticks;
514 527
@@ -540,6 +553,8 @@ lisp_time_hz_ticks (struct lisp_time t, Lisp_Object hz)
540static Lisp_Object 553static Lisp_Object
541lisp_time_seconds (struct lisp_time t) 554lisp_time_seconds (struct lisp_time t)
542{ 555{
556 /* The idea is to return the floor of T.ticks / T.hz. */
557
543 if (!FASTER_TIMEFNS) 558 if (!FASTER_TIMEFNS)
544 return lisp_time_hz_ticks (t, make_fixnum (1)); 559 return lisp_time_hz_ticks (t, make_fixnum (1));
545 560
@@ -587,6 +602,7 @@ frac_to_double (Lisp_Object numerator, Lisp_Object denominator)
587 && integer_to_intmax (numerator, &intmax_numerator)) 602 && integer_to_intmax (numerator, &intmax_numerator))
588 return intmax_numerator; 603 return intmax_numerator;
589 604
605 /* Compute number of base-FLT_RADIX digits in numerator and denominator. */
590 mpz_t const *n = bignum_integer (&mpz[0], numerator); 606 mpz_t const *n = bignum_integer (&mpz[0], numerator);
591 mpz_t const *d = bignum_integer (&mpz[1], denominator); 607 mpz_t const *d = bignum_integer (&mpz[1], denominator);
592 ptrdiff_t nbits = mpz_sizeinbase (*n, 2); 608 ptrdiff_t nbits = mpz_sizeinbase (*n, 2);
@@ -599,7 +615,8 @@ frac_to_double (Lisp_Object numerator, Lisp_Object denominator)
599 /* Scale with SCALE when doing integer division. That is, compute 615 /* Scale with SCALE when doing integer division. That is, compute
600 (N * FLT_RADIX**SCALE) / D [or, if SCALE is negative, N / (D * 616 (N * FLT_RADIX**SCALE) / D [or, if SCALE is negative, N / (D *
601 FLT_RADIX**-SCALE)] as a bignum, convert the bignum to double, 617 FLT_RADIX**-SCALE)] as a bignum, convert the bignum to double,
602 then divide the double by FLT_RADIX**SCALE. */ 618 then divide the double by FLT_RADIX**SCALE. First scale N
619 N (or scale D, if SCALE is negative) ... */
603 ptrdiff_t scale = ddig - ndig + DBL_MANT_DIG + 1; 620 ptrdiff_t scale = ddig - ndig + DBL_MANT_DIG + 1;
604 if (scale < 0) 621 if (scale < 0)
605 { 622 {
@@ -614,12 +631,12 @@ frac_to_double (Lisp_Object numerator, Lisp_Object denominator)
614 mpz_mul_2exp (mpz[0], *n, scale * LOG2_FLT_RADIX); 631 mpz_mul_2exp (mpz[0], *n, scale * LOG2_FLT_RADIX);
615 n = &mpz[0]; 632 n = &mpz[0];
616 } 633 }
617 634 /* ... and then divide, with quotient Q and remainder R. */
618 mpz_t *q = &mpz[2]; 635 mpz_t *q = &mpz[2];
619 mpz_t *r = &mpz[3]; 636 mpz_t *r = &mpz[3];
620 mpz_tdiv_qr (*q, *r, *n, *d); 637 mpz_tdiv_qr (*q, *r, *n, *d);
621 638
622 /* The amount to add to the absolute value of *Q so that truncating 639 /* The amount to add to the absolute value of Q so that truncating
623 it to double will round correctly. */ 640 it to double will round correctly. */
624 int incr; 641 int incr;
625 642
@@ -658,6 +675,7 @@ frac_to_double (Lisp_Object numerator, Lisp_Object denominator)
658 if (!FASTER_TIMEFNS || incr != 0) 675 if (!FASTER_TIMEFNS || incr != 0)
659 (mpz_sgn (*n) < 0 ? mpz_sub_ui : mpz_add_ui) (*q, *q, incr); 676 (mpz_sgn (*n) < 0 ? mpz_sub_ui : mpz_add_ui) (*q, *q, incr);
660 677
678 /* Rescale the integer Q back to double. This step does not round. */
661 return scalbn (mpz_get_d (*q), -scale); 679 return scalbn (mpz_get_d (*q), -scale);
662} 680}
663 681
@@ -902,6 +920,10 @@ lisp_to_timespec (struct lisp_time t)
902 mpz_t *q = &mpz[0]; 920 mpz_t *q = &mpz[0];
903 mpz_t const *qt = q; 921 mpz_t const *qt = q;
904 922
923 /* Floor-divide (T.ticks * TIMESPEC_HZ) by T.hz,
924 yielding quotient Q (tv_sec) and remainder NS (tv_nsec).
925 Return an invalid timespec if Q does not fit in time_t.
926 For speed, prefer fixnum arithmetic if it works. */
905 if (FASTER_TIMEFNS && EQ (t.hz, timespec_hz)) 927 if (FASTER_TIMEFNS && EQ (t.hz, timespec_hz))
906 { 928 {
907 if (FIXNUMP (t.ticks)) 929 if (FIXNUMP (t.ticks))
@@ -945,8 +967,8 @@ lisp_to_timespec (struct lisp_time t)
945 ns = mpz_fdiv_q_ui (*q, *q, TIMESPEC_HZ); 967 ns = mpz_fdiv_q_ui (*q, *q, TIMESPEC_HZ);
946 } 968 }
947 969
948 /* With some versions of MinGW, tv_sec is a 64-bit type, whereas 970 /* Check that Q fits in time_t, not merely in T.tv_sec. With some versions
949 time_t is a 32-bit type. */ 971 of MinGW, tv_sec is a 64-bit type, whereas time_t is a 32-bit type. */
950 time_t sec; 972 time_t sec;
951 if (mpz_time (*qt, &sec)) 973 if (mpz_time (*qt, &sec))
952 { 974 {
@@ -1026,10 +1048,14 @@ lispint_arith (Lisp_Object a, Lisp_Object b, bool subtract)
1026 { 1048 {
1027 if (EQ (b, make_fixnum (0))) 1049 if (EQ (b, make_fixnum (0)))
1028 return a; 1050 return a;
1051
1052 /* For speed, use EMACS_INT arithmetic if it will do. */
1029 if (FIXNUMP (a)) 1053 if (FIXNUMP (a))
1030 return make_int (subtract 1054 return make_int (subtract
1031 ? XFIXNUM (a) - XFIXNUM (b) 1055 ? XFIXNUM (a) - XFIXNUM (b)
1032 : XFIXNUM (a) + XFIXNUM (b)); 1056 : XFIXNUM (a) + XFIXNUM (b));
1057
1058 /* For speed, use mpz_add_ui/mpz_sub_ui if it will do. */
1033 if (eabs (XFIXNUM (b)) <= ULONG_MAX) 1059 if (eabs (XFIXNUM (b)) <= ULONG_MAX)
1034 { 1060 {
1035 ((XFIXNUM (b) < 0) == subtract ? mpz_add_ui : mpz_sub_ui) 1061 ((XFIXNUM (b) < 0) == subtract ? mpz_add_ui : mpz_sub_ui)
@@ -1038,6 +1064,7 @@ lispint_arith (Lisp_Object a, Lisp_Object b, bool subtract)
1038 } 1064 }
1039 } 1065 }
1040 1066
1067 /* Fall back on bignum arithmetic if necessary. */
1041 if (!mpz_done) 1068 if (!mpz_done)
1042 (subtract ? mpz_sub : mpz_add) (mpz[0], 1069 (subtract ? mpz_sub : mpz_add) (mpz[0],
1043 *bignum_integer (&mpz[0], a), 1070 *bignum_integer (&mpz[0], a),
@@ -1221,6 +1248,8 @@ time_cmp (Lisp_Object a, Lisp_Object b)
1221 if (EQ (a, b)) 1248 if (EQ (a, b))
1222 return 0; 1249 return 0;
1223 1250
1251 /* Compare (ATICKS . AZ) to (BTICKS . BHZ) by comparing
1252 ATICKS * BHZ to BTICKS * AHZ. */
1224 struct lisp_time tb = lisp_time_struct (b, 0); 1253 struct lisp_time tb = lisp_time_struct (b, 0);
1225 mpz_t const *za = bignum_integer (&mpz[0], ta.ticks); 1254 mpz_t const *za = bignum_integer (&mpz[0], ta.ticks);
1226 mpz_t const *zb = bignum_integer (&mpz[1], tb.ticks); 1255 mpz_t const *zb = bignum_integer (&mpz[1], tb.ticks);
@@ -1498,6 +1527,7 @@ SEC is always an integer between 0 and 59.)
1498usage: (decode-time &optional TIME ZONE FORM) */) 1527usage: (decode-time &optional TIME ZONE FORM) */)
1499 (Lisp_Object specified_time, Lisp_Object zone, Lisp_Object form) 1528 (Lisp_Object specified_time, Lisp_Object zone, Lisp_Object form)
1500{ 1529{
1530 /* Compute broken-down local time LOCAL_TM from SPECIFIED_TIME and ZONE. */
1501 struct lisp_time lt = lisp_time_struct (specified_time, 0); 1531 struct lisp_time lt = lisp_time_struct (specified_time, 0);
1502 struct timespec ts = lisp_to_timespec (lt); 1532 struct timespec ts = lisp_to_timespec (lt);
1503 if (! timespec_valid_p (ts)) 1533 if (! timespec_valid_p (ts))
@@ -1512,6 +1542,7 @@ usage: (decode-time &optional TIME ZONE FORM) */)
1512 if (!tm) 1542 if (!tm)
1513 time_error (localtime_errno); 1543 time_error (localtime_errno);
1514 1544
1545 /* Let YEAR = LOCAL_TM.tm_year + TM_YEAR_BASE. */
1515 Lisp_Object year; 1546 Lisp_Object year;
1516 if (FASTER_TIMEFNS 1547 if (FASTER_TIMEFNS
1517 && MOST_NEGATIVE_FIXNUM - TM_YEAR_BASE <= local_tm.tm_year 1548 && MOST_NEGATIVE_FIXNUM - TM_YEAR_BASE <= local_tm.tm_year
@@ -1528,12 +1559,15 @@ usage: (decode-time &optional TIME ZONE FORM) */)
1528 year = make_integer_mpz (); 1559 year = make_integer_mpz ();
1529 } 1560 }
1530 1561
1562 /* Compute SEC from LOCAL_TM.tm_sec and HZ. */
1531 Lisp_Object hz = lt.hz, sec; 1563 Lisp_Object hz = lt.hz, sec;
1532 if (EQ (hz, make_fixnum (1)) || !EQ (form, Qt)) 1564 if (EQ (hz, make_fixnum (1)) || !EQ (form, Qt))
1533 sec = make_fixnum (local_tm.tm_sec); 1565 sec = make_fixnum (local_tm.tm_sec);
1534 else 1566 else
1535 { 1567 {
1536 Lisp_Object ticks; /* hz * tm_sec + mod (lt.ticks, hz) */ 1568 /* Let TICKS = HZ * LOCAL_TM.tm_sec + mod (LT.ticks, HZ)
1569 and SEC = (TICKS . HZ). */
1570 Lisp_Object ticks;
1537 intmax_t n; 1571 intmax_t n;
1538 if (FASTER_TIMEFNS && FIXNUMP (lt.ticks) && FIXNUMP (hz) 1572 if (FASTER_TIMEFNS && FIXNUMP (lt.ticks) && FIXNUMP (hz)
1539 && !INT_MULTIPLY_WRAPV (XFIXNUM (hz), local_tm.tm_sec, &n) 1573 && !INT_MULTIPLY_WRAPV (XFIXNUM (hz), local_tm.tm_sec, &n)
@@ -1663,6 +1697,7 @@ usage: (encode-time TIME &rest OBSOLESCENT-ARGUMENTS) */)
1663 yeararg = args[5]; 1697 yeararg = args[5];
1664 } 1698 }
1665 1699
1700 /* Let SEC = floor (LT.ticks / HZ), with SUBSECTICKS the remainder. */
1666 struct lisp_time lt; 1701 struct lisp_time lt;
1667 decode_lisp_time (secarg, 0, &lt, 0); 1702 decode_lisp_time (secarg, 0, &lt, 0);
1668 Lisp_Object hz = lt.hz, sec, subsecticks; 1703 Lisp_Object hz = lt.hz, sec, subsecticks;