diff options
| author | Paul Eggert | 2020-03-08 16:43:54 -0700 |
|---|---|---|
| committer | Paul Eggert | 2020-03-08 16:44:49 -0700 |
| commit | 20d3d3a9509ed24b4fb701919bf4a677c7d9e249 (patch) | |
| tree | 592b600f20e0f115128893129f3046f694e1b815 /src | |
| parent | 0a3682a566d5563e3d57defe49359cee236e0274 (diff) | |
| download | emacs-20d3d3a9509ed24b4fb701919bf4a677c7d9e249.tar.gz emacs-20d3d3a9509ed24b4fb701919bf4a677c7d9e249.zip | |
* src/timefns.c: Add comments.
Diffstat (limited to 'src')
| -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 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) | |||
| 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 | ||
| @@ -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.) | |||
| 1498 | usage: (decode-time &optional TIME ZONE FORM) */) | 1527 | usage: (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, <, 0); | 1702 | decode_lisp_time (secarg, 0, <, 0); |
| 1668 | Lisp_Object hz = lt.hz, sec, subsecticks; | 1703 | Lisp_Object hz = lt.hz, sec, subsecticks; |