diff options
| author | Paul Eggert | 2024-07-10 02:37:55 +0200 |
|---|---|---|
| committer | Paul Eggert | 2024-07-11 16:01:41 +0200 |
| commit | 6ef052d9b23aef3f34d19e5d93d97884215d1465 (patch) | |
| tree | 0de5e670df5d238a0dde0b49559a23f705a29ae0 | |
| parent | 5e8a38ecb2a78c0e318892683dc0195084197c57 (diff) | |
| download | emacs-6ef052d9b23aef3f34d19e5d93d97884215d1465.tar.gz emacs-6ef052d9b23aef3f34d19e5d93d97884215d1465.zip | |
Reduce size of integer product in timefns
* src/timefns.c (emacs_gcd): New static function.
(ticks_hz_hz_ticks): Use it to reduce the size of the integer
product in the common case when converting from ns to ps. For
that, we need to multiply t.ticks only by 10³, not multiply by
10¹² and then divide by 10⁹. This avoids the need to use bignums
in a significant number of cases.
| -rw-r--r-- | src/timefns.c | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/src/timefns.c b/src/timefns.c index 0c5f3bf3ff1..0a34bda28c7 100644 --- a/src/timefns.c +++ b/src/timefns.c | |||
| @@ -748,6 +748,15 @@ timespec_ticks (struct timespec t) | |||
| 748 | return make_integer_mpz (); | 748 | return make_integer_mpz (); |
| 749 | } | 749 | } |
| 750 | 750 | ||
| 751 | /* Return greatest common divisor of positive A and B. */ | ||
| 752 | static EMACS_INT | ||
| 753 | emacs_gcd (EMACS_INT a, EMACS_INT b) | ||
| 754 | { | ||
| 755 | for (EMACS_INT r; (r = a % b) != 0; a = b, b = r) | ||
| 756 | continue; | ||
| 757 | return b; | ||
| 758 | } | ||
| 759 | |||
| 751 | /* Convert T to a Lisp integer counting HZ ticks, taking the floor. | 760 | /* Convert T to a Lisp integer counting HZ ticks, taking the floor. |
| 752 | Assume T is valid, but check HZ. */ | 761 | Assume T is valid, but check HZ. */ |
| 753 | static Lisp_Object | 762 | static Lisp_Object |
| @@ -766,11 +775,22 @@ ticks_hz_hz_ticks (struct ticks_hz t, Lisp_Object hz) | |||
| 766 | invalid_hz (hz); | 775 | invalid_hz (hz); |
| 767 | 776 | ||
| 768 | /* For speed, use intmax_t arithmetic if it will do. */ | 777 | /* For speed, use intmax_t arithmetic if it will do. */ |
| 769 | intmax_t ticks; | 778 | if (FASTER_TIMEFNS && FIXNUMP (t.ticks) && FIXNUMP (t.hz)) |
| 770 | if (FASTER_TIMEFNS && FIXNUMP (t.ticks) && FIXNUMP (t.hz) | 779 | { |
| 771 | && !ckd_mul (&ticks, XFIXNUM (t.ticks), XFIXNUM (hz))) | 780 | /* Reduce T.hz and HZ by their GCD, to avoid some intmax_t |
| 772 | return make_int (ticks / XFIXNUM (t.hz) | 781 | overflows that would occur in T.ticks * HZ. */ |
| 773 | - (ticks % XFIXNUM (t.hz) < 0)); | 782 | EMACS_INT ithz = XFIXNUM (t.hz), ihz = XFIXNUM (hz); |
| 783 | EMACS_INT d = emacs_gcd (ithz, ihz); | ||
| 784 | ithz /= d; | ||
| 785 | ihz /= d; | ||
| 786 | |||
| 787 | intmax_t ticks; | ||
| 788 | if (!ckd_mul (&ticks, XFIXNUM (t.ticks), ihz)) | ||
| 789 | return make_int (ticks / ithz - (ticks % ithz < 0)); | ||
| 790 | |||
| 791 | t.hz = make_fixnum (ithz); | ||
| 792 | hz = make_fixnum (ihz); | ||
| 793 | } | ||
| 774 | } | 794 | } |
| 775 | else if (! (BIGNUMP (hz) && 0 < mpz_sgn (*xbignum_val (hz)))) | 795 | else if (! (BIGNUMP (hz) && 0 < mpz_sgn (*xbignum_val (hz)))) |
| 776 | invalid_hz (hz); | 796 | invalid_hz (hz); |