https://github.com/python/cpython/commit/0d3ab6f17e1119095ce9c452cd14c15e60256b50 commit: 0d3ab6f17e1119095ce9c452cd14c15e60256b50 branch: main author: XiaohongGong <[email protected]> committer: eendebakpt <[email protected]> date: 2026-11-04T16:23:23+01:00 summary:
gh-156443: Keep PyLong loop carries as twodigits in shifts (#157060) * gh-156443: Keep PyLong loop carries as twodigits in shifts and division * 📜🤖 Added by blurb_it. * Update NEWS docs * Update NEWS.d doc * Update unit test and NEWS.d * Revert changes to x_divrem * Fix NEWS.d * Apply batched suggestions from code review Co-authored-by: Stan Ulbrych <[email protected]> --------- Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> Co-authored-by: Stan Ulbrych <[email protected]> files: A Misc/NEWS.d/next/Core_and_Builtins/2026-09-07-09-52-21.gh-issue-156443.tT40sm.rst M Lib/test/test_long.py M Objects/longobject.c diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py index 7c368e121024d2..c16bf1b1fe020e 100644 --- a/Lib/test/test_long.py +++ b/Lib/test/test_long.py @@ -204,7 +204,33 @@ def test_division(self): self.check_division(710031681576388032, 26769404391308) self.check_division(1933622614268221, 30212853348836) - + @support.requires_IEEE_754 + def test_intradigit_shift(self): + # Unit tests for v_lshift and v_rshift in longobject.c. + # These two functions are not used by Python << and >>, + # exercise them via float conversion and true division. + + # Full limb values. + two_limbs = (1 << (2 * SHIFT)) - 1 + three_limbs = (1 << (3 * SHIFT)) - 1 + four_limbs = (1 << (4 * SHIFT)) - 1 + # Multi-limb (not compact) but bit_length() still <= 55. + bits50 = (1 << 50) - 1 + + # _PyLong_Frexp (float(n)): + # v_lshift if n.bit_length() <= 55, else v_rshift. + self.check_float_conversion(bits50) + self.check_float_conversion(two_limbs) + self.check_float_conversion(four_limbs) + self.check_float_conversion(10**40) + + # long_true_divide (a / b): + # - (a.bit_length() - b.bit_length()) <= 55 => v_lshift, + # - (a.bit_length() - b.bit_length()) > 55 => v_rshift. + self.check_truediv(three_limbs, two_limbs) + self.check_truediv(four_limbs, two_limbs) + self.check_truediv(four_limbs, three_limbs) + self.check_truediv(10**40, 10**20) def test_karatsuba(self): digits = list(range(1, 5)) + list(range(KARATSUBA_CUTOFF, diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-09-07-09-52-21.gh-issue-156443.tT40sm.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-09-07-09-52-21.gh-issue-156443.tT40sm.rst new file mode 100644 index 00000000000000..54c345aad025ce --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-09-07-09-52-21.gh-issue-156443.tT40sm.rst @@ -0,0 +1 @@ +Speed up :func:`float` conversion and true division of large :class:`int` values. diff --git a/Objects/longobject.c b/Objects/longobject.c index 564f9601bbfde4..c96ed6a215b5a1 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -1905,15 +1905,15 @@ static digit v_lshift(digit *z, digit *a, Py_ssize_t m, int d) { Py_ssize_t i; - digit carry = 0; + twodigits carry = 0; assert(0 <= d && d < PyLong_SHIFT); for (i=0; i < m; i++) { twodigits acc = (twodigits)a[i] << d | carry; z[i] = (digit)acc & PyLong_MASK; - carry = (digit)(acc >> PyLong_SHIFT); + carry = acc >> PyLong_SHIFT; } - return carry; + return (digit)carry; } /* Shift digit vector a[0:m] d bits right, with 0 <= d < PyLong_SHIFT. Put @@ -1923,16 +1923,16 @@ static digit v_rshift(digit *z, digit *a, Py_ssize_t m, int d) { Py_ssize_t i; - digit carry = 0; - digit mask = ((digit)1 << d) - 1U; + twodigits carry = 0; + twodigits mask = ((twodigits)1 << d) - 1U; assert(0 <= d && d < PyLong_SHIFT); for (i=m; i-- > 0;) { - twodigits acc = (twodigits)carry << PyLong_SHIFT | a[i]; - carry = (digit)acc & mask; + twodigits acc = carry << PyLong_SHIFT | a[i]; + carry = acc & mask; z[i] = (digit)(acc >> d); } - return carry; + return (digit)carry; } /* Divide long pin, w/ size digits, by non-zero digit n, storing quotient _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: [email protected]
