diff options
| author | Paul Eggert | 2020-03-08 16:57:41 -0700 |
|---|---|---|
| committer | Paul Eggert | 2020-03-08 16:57:41 -0700 |
| commit | a461baae79af3cea8780e9d9a845a1e859e96e5e (patch) | |
| tree | 56d33aeaaf63999b415c9941772a2649ba6cbfdc | |
| parent | d00df0aaf9105128d80f6e395974474cf5975499 (diff) | |
| parent | cf223dc928119bb544c3370ad59fe3e175a8236e (diff) | |
| download | emacs-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.
| -rw-r--r-- | src/timefns.c | 49 |
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) | |||
| 442 | static Lisp_Object | 445 | static Lisp_Object |
| 443 | ticks_hz_list4 (Lisp_Object ticks, Lisp_Object hz) | 446 | ticks_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) | |||
| 482 | static void | 492 | static void |
| 483 | timespec_mpz (struct timespec t) | 493 | timespec_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) | |||
| 508 | static Lisp_Object | 519 | static Lisp_Object |
| 509 | lisp_time_hz_ticks (struct lisp_time t, Lisp_Object hz) | 520 | lisp_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) | |||
| 540 | static Lisp_Object | 553 | static Lisp_Object |
| 541 | lisp_time_seconds (struct lisp_time t) | 554 | lisp_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.) | |||
| 1504 | usage: (decode-time &optional TIME ZONE FORM) */) | 1533 | usage: (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, <, 0); | 1708 | decode_lisp_time (secarg, 0, <, 0); |
| 1674 | Lisp_Object hz = lt.hz, sec, subsecticks; | 1709 | Lisp_Object hz = lt.hz, sec, subsecticks; |