aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/timefns.c30
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. */
752static EMACS_INT
753emacs_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. */
753static Lisp_Object 762static 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);