aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2020-03-08 16:57:41 -0700
committerPaul Eggert2020-03-08 16:57:41 -0700
commita461baae79af3cea8780e9d9a845a1e859e96e5e (patch)
tree56d33aeaaf63999b415c9941772a2649ba6cbfdc /src
parentd00df0aaf9105128d80f6e395974474cf5975499 (diff)
parentcf223dc928119bb544c3370ad59fe3e175a8236e (diff)
downloademacs-a461baae79af3cea8780e9d9a845a1e859e96e5e.tar.gz
emacs-a461baae79af3cea8780e9d9a845a1e859e96e5e.zip
Merge from origin/emacs-27
cf223dc928 ; * src/timefns.c: Fix typo in previous change. 20d3d3a950 * 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 6dd6e1611a4..404ce4973b7 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
@@ -590,6 +605,7 @@ frac_to_double (Lisp_Object numerator, Lisp_Object denominator)
590 && intmax_numerator % intmax_denominator == 0) 605 && intmax_numerator % intmax_denominator == 0)
591 return intmax_numerator / intmax_denominator; 606 return intmax_numerator / intmax_denominator;
592 607
608 /* Compute number of base-FLT_RADIX digits in numerator and denominator. */
593 mpz_t const *n = bignum_integer (&mpz[0], numerator); 609 mpz_t const *n = bignum_integer (&mpz[0], numerator);
594 mpz_t const *d = bignum_integer (&mpz[1], denominator); 610 mpz_t const *d = bignum_integer (&mpz[1], denominator);
595 ptrdiff_t ndig = mpz_sizeinbase (*n, FLT_RADIX); 611 ptrdiff_t ndig = mpz_sizeinbase (*n, FLT_RADIX);
@@ -601,7 +617,8 @@ frac_to_double (Lisp_Object numerator, Lisp_Object denominator)
601 /* Scale with SCALE when doing integer division. That is, compute 617 /* Scale with SCALE when doing integer division. That is, compute
602 (N * FLT_RADIX**SCALE) / D [or, if SCALE is negative, N / (D * 618 (N * FLT_RADIX**SCALE) / D [or, if SCALE is negative, N / (D *
603 FLT_RADIX**-SCALE)] as a bignum, convert the bignum to double, 619 FLT_RADIX**-SCALE)] as a bignum, convert the bignum to double,
604 then divide the double by FLT_RADIX**SCALE. */ 620 then divide the double by FLT_RADIX**SCALE. First scale N
621 (or scale D, if SCALE is negative) ... */
605 ptrdiff_t scale = ddig - ndig + DBL_MANT_DIG; 622 ptrdiff_t scale = ddig - ndig + DBL_MANT_DIG;
606 if (scale < 0) 623 if (scale < 0)
607 { 624 {
@@ -616,12 +633,12 @@ frac_to_double (Lisp_Object numerator, Lisp_Object denominator)
616 mpz_mul_2exp (mpz[0], *n, scale * LOG2_FLT_RADIX); 633 mpz_mul_2exp (mpz[0], *n, scale * LOG2_FLT_RADIX);
617 n = &mpz[0]; 634 n = &mpz[0];
618 } 635 }
619 636 /* ... and then divide, with quotient Q and remainder R. */
620 mpz_t *q = &mpz[2]; 637 mpz_t *q = &mpz[2];
621 mpz_t *r = &mpz[3]; 638 mpz_t *r = &mpz[3];
622 mpz_tdiv_qr (*q, *r, *n, *d); 639 mpz_tdiv_qr (*q, *r, *n, *d);
623 640
624 /* The amount to add to the absolute value of *Q so that truncating 641 /* The amount to add to the absolute value of Q so that truncating
625 it to double will round correctly. */ 642 it to double will round correctly. */
626 int incr; 643 int incr;
627 644
@@ -660,6 +677,7 @@ frac_to_double (Lisp_Object numerator, Lisp_Object denominator)
660 if (!FASTER_TIMEFNS || incr != 0) 677 if (!FASTER_TIMEFNS || incr != 0)
661 (mpz_sgn (*n) < 0 ? mpz_sub_ui : mpz_add_ui) (*q, *q, incr); 678 (mpz_sgn (*n) < 0 ? mpz_sub_ui : mpz_add_ui) (*q, *q, incr);
662 679
680 /* Rescale the integer Q back to double. This step does not round. */
663 return scalbn (mpz_get_d (*q), -scale); 681 return scalbn (mpz_get_d (*q), -scale);
664} 682}
665 683
@@ -908,6 +926,10 @@ lisp_to_timespec (struct lisp_time t)
908 mpz_t *q = &mpz[0]; 926 mpz_t *q = &mpz[0];
909 mpz_t const *qt = q; 927 mpz_t const *qt = q;
910 928
929 /* Floor-divide (T.ticks * TIMESPEC_HZ) by T.hz,
930 yielding quotient Q (tv_sec) and remainder NS (tv_nsec).
931 Return an invalid timespec if Q does not fit in time_t.
932 For speed, prefer fixnum arithmetic if it works. */
911 if (FASTER_TIMEFNS && EQ (t.hz, timespec_hz)) 933 if (FASTER_TIMEFNS && EQ (t.hz, timespec_hz))
912 { 934 {
913 if (FIXNUMP (t.ticks)) 935 if (FIXNUMP (t.ticks))
@@ -951,8 +973,8 @@ lisp_to_timespec (struct lisp_time t)
951 ns = mpz_fdiv_q_ui (*q, *q, TIMESPEC_HZ); 973 ns = mpz_fdiv_q_ui (*q, *q, TIMESPEC_HZ);
952 } 974 }
953 975
954 /* With some versions of MinGW, tv_sec is a 64-bit type, whereas 976 /* Check that Q fits in time_t, not merely in T.tv_sec. With some versions
955 time_t is a 32-bit type. */ 977 of MinGW, tv_sec is a 64-bit type, whereas time_t is a 32-bit type. */
956 time_t sec; 978 time_t sec;
957 if (mpz_time (*qt, &sec)) 979 if (mpz_time (*qt, &sec))
958 { 980 {
@@ -1032,10 +1054,14 @@ lispint_arith (Lisp_Object a, Lisp_Object b, bool subtract)
1032 { 1054 {
1033 if (EQ (b, make_fixnum (0))) 1055 if (EQ (b, make_fixnum (0)))
1034 return a; 1056 return a;
1057
1058 /* For speed, use EMACS_INT arithmetic if it will do. */
1035 if (FIXNUMP (a)) 1059 if (FIXNUMP (a))
1036 return make_int (subtract 1060 return make_int (subtract
1037 ? XFIXNUM (a) - XFIXNUM (b) 1061 ? XFIXNUM (a) - XFIXNUM (b)
1038 : XFIXNUM (a) + XFIXNUM (b)); 1062 : XFIXNUM (a) + XFIXNUM (b));
1063
1064 /* For speed, use mpz_add_ui/mpz_sub_ui if it will do. */
1039 if (eabs (XFIXNUM (b)) <= ULONG_MAX) 1065 if (eabs (XFIXNUM (b)) <= ULONG_MAX)
1040 { 1066 {
1041 ((XFIXNUM (b) < 0) == subtract ? mpz_add_ui : mpz_sub_ui) 1067 ((XFIXNUM (b) < 0) == subtract ? mpz_add_ui : mpz_sub_ui)
@@ -1044,6 +1070,7 @@ lispint_arith (Lisp_Object a, Lisp_Object b, bool subtract)
1044 } 1070 }
1045 } 1071 }
1046 1072
1073 /* Fall back on bignum arithmetic if necessary. */
1047 if (!mpz_done) 1074 if (!mpz_done)
1048 (subtract ? mpz_sub : mpz_add) (mpz[0], 1075 (subtract ? mpz_sub : mpz_add) (mpz[0],
1049 *bignum_integer (&mpz[0], a), 1076 *bignum_integer (&mpz[0], a),
@@ -1227,6 +1254,8 @@ time_cmp (Lisp_Object a, Lisp_Object b)
1227 if (EQ (a, b)) 1254 if (EQ (a, b))
1228 return 0; 1255 return 0;
1229 1256
1257 /* Compare (ATICKS . AZ) to (BTICKS . BHZ) by comparing
1258 ATICKS * BHZ to BTICKS * AHZ. */
1230 struct lisp_time tb = lisp_time_struct (b, 0); 1259 struct lisp_time tb = lisp_time_struct (b, 0);
1231 mpz_t const *za = bignum_integer (&mpz[0], ta.ticks); 1260 mpz_t const *za = bignum_integer (&mpz[0], ta.ticks);
1232 mpz_t const *zb = bignum_integer (&mpz[1], tb.ticks); 1261 mpz_t const *zb = bignum_integer (&mpz[1], tb.ticks);
@@ -1504,6 +1533,7 @@ SEC is always an integer between 0 and 59.)
1504usage: (decode-time &optional TIME ZONE FORM) */) 1533usage: (decode-time &optional TIME ZONE FORM) */)
1505 (Lisp_Object specified_time, Lisp_Object zone, Lisp_Object form) 1534 (Lisp_Object specified_time, Lisp_Object zone, Lisp_Object form)
1506{ 1535{
1536 /* Compute broken-down local time LOCAL_TM from SPECIFIED_TIME and ZONE. */
1507 struct lisp_time lt = lisp_time_struct (specified_time, 0); 1537 struct lisp_time lt = lisp_time_struct (specified_time, 0);
1508 struct timespec ts = lisp_to_timespec (lt); 1538 struct timespec ts = lisp_to_timespec (lt);
1509 if (! timespec_valid_p (ts)) 1539 if (! timespec_valid_p (ts))
@@ -1518,6 +1548,7 @@ usage: (decode-time &optional TIME ZONE FORM) */)
1518 if (!tm) 1548 if (!tm)
1519 time_error (localtime_errno); 1549 time_error (localtime_errno);
1520 1550
1551 /* Let YEAR = LOCAL_TM.tm_year + TM_YEAR_BASE. */
1521 Lisp_Object year; 1552 Lisp_Object year;
1522 if (FASTER_TIMEFNS 1553 if (FASTER_TIMEFNS
1523 && MOST_NEGATIVE_FIXNUM - TM_YEAR_BASE <= local_tm.tm_year 1554 && MOST_NEGATIVE_FIXNUM - TM_YEAR_BASE <= local_tm.tm_year
@@ -1534,12 +1565,15 @@ usage: (decode-time &optional TIME ZONE FORM) */)
1534 year = make_integer_mpz (); 1565 year = make_integer_mpz ();
1535 } 1566 }
1536 1567
1568 /* Compute SEC from LOCAL_TM.tm_sec and HZ. */
1537 Lisp_Object hz = lt.hz, sec; 1569 Lisp_Object hz = lt.hz, sec;
1538 if (EQ (hz, make_fixnum (1)) || !EQ (form, Qt)) 1570 if (EQ (hz, make_fixnum (1)) || !EQ (form, Qt))
1539 sec = make_fixnum (local_tm.tm_sec); 1571 sec = make_fixnum (local_tm.tm_sec);
1540 else 1572 else
1541 { 1573 {
1542 Lisp_Object ticks; /* hz * tm_sec + mod (lt.ticks, hz) */ 1574 /* Let TICKS = HZ * LOCAL_TM.tm_sec + mod (LT.ticks, HZ)
1575 and SEC = (TICKS . HZ). */
1576 Lisp_Object ticks;
1543 intmax_t n; 1577 intmax_t n;
1544 if (FASTER_TIMEFNS && FIXNUMP (lt.ticks) && FIXNUMP (hz) 1578 if (FASTER_TIMEFNS && FIXNUMP (lt.ticks) && FIXNUMP (hz)
1545 && !INT_MULTIPLY_WRAPV (XFIXNUM (hz), local_tm.tm_sec, &n) 1579 && !INT_MULTIPLY_WRAPV (XFIXNUM (hz), local_tm.tm_sec, &n)
@@ -1669,6 +1703,7 @@ usage: (encode-time TIME &rest OBSOLESCENT-ARGUMENTS) */)
1669 yeararg = args[5]; 1703 yeararg = args[5];
1670 } 1704 }
1671 1705
1706 /* Let SEC = floor (LT.ticks / HZ), with SUBSECTICKS the remainder. */
1672 struct lisp_time lt; 1707 struct lisp_time lt;
1673 decode_lisp_time (secarg, 0, &lt, 0); 1708 decode_lisp_time (secarg, 0, &lt, 0);
1674 Lisp_Object hz = lt.hz, sec, subsecticks; 1709 Lisp_Object hz = lt.hz, sec, subsecticks;