diff -r f494052eb476 Lib/test/test_long.py --- a/Lib/test/test_long.py Mon Feb 08 20:28:22 2016 +0200 +++ b/Lib/test/test_long.py Mon Feb 08 17:28:52 2016 -0500 @@ -689,6 +689,14 @@ self.assertRaises(OverflowError, int, float('-inf')) self.assertRaises(ValueError, int, float('nan')) + def test_mod_division(self): + with self.assertRaises(ZeroDivisionError): + _ = 1 % 0 + self.assertEqual(13 % 10, 3) + self.assertEqual(-13 % 10, 7) + self.assertEqual(13 % -10, -7) + self.assertEqual(-13 % -10, -3) + def test_true_division(self): huge = 1 << 40000 mhuge = -huge diff -r f494052eb476 Objects/longobject.c --- a/Objects/longobject.c Mon Feb 08 20:28:22 2016 +0200 +++ b/Objects/longobject.c Mon Feb 08 17:28:52 2016 -0500 @@ -3848,6 +3848,26 @@ CHECK_BINOP(a, b); + if (Py_ABS(Py_SIZE(a)) == 1 && Py_ABS(Py_SIZE(b)) == 1) { + /* Fast path for single-digit longs. See the comment for + l_divmod function, which explains the algorithm. */ + sdigit left = ((PyLongObject*)a)->ob_digit[0]; + sdigit right = ((PyLongObject*)b)->ob_digit[0]; + sdigit mod = left % right; + + if (Py_SIZE(a) < 0 || Py_SIZE(b) < 0) { + mod *= Py_SIZE(a); + if (mod < 0 && Py_SIZE(b) > 0) { + mod += right; + } + else if (mod > 0 && Py_SIZE(b) < 0) { + mod -= right; + } + } + + return PyLong_FromLong(mod); + } + if (l_divmod((PyLongObject*)a, (PyLongObject*)b, NULL, &mod) < 0) mod = NULL; return (PyObject *)mod;