diff -r b2802d3427a4 Objects/longobject.c --- a/Objects/longobject.c Sat Sep 10 04:27:56 2016 -0400 +++ b/Objects/longobject.c Sat Sep 10 11:42:04 2016 +0100 @@ -3593,46 +3593,74 @@ static PyObject * fast_mod(PyLongObject *a, PyLongObject *b) { - sdigit left = a->ob_digit[0]; - sdigit right = b->ob_digit[0]; - sdigit mod; - - assert(Py_ABS(Py_SIZE(a)) == 1); - assert(Py_ABS(Py_SIZE(b)) == 1); - - if (Py_SIZE(a) == Py_SIZE(b)) { - /* 'a' and 'b' have the same sign. */ + sdigit mod, left, right; + assert(Py_ABS(Py_SIZE(a)) <= 1); + assert(Py_SIZE(b) == 1); + + right = b->ob_digit[0]; + if (Py_SIZE(a) >= 0) { + left = Py_SIZE(a) == 0 ? 0 : a->ob_digit[0]; mod = left % right; } else { - /* Either 'a' or 'b' is negative. */ + left = a->ob_digit[0]; mod = right - 1 - (left - 1) % right; } - - return PyLong_FromLong(mod * (sdigit)Py_SIZE(b)); + return PyLong_FromLong((long)mod); } /* Fast floor division for single-digit longs. */ static PyObject * fast_floor_div(PyLongObject *a, PyLongObject *b) { - sdigit left = a->ob_digit[0]; - sdigit right = b->ob_digit[0]; - sdigit div; - - assert(Py_ABS(Py_SIZE(a)) == 1); - assert(Py_ABS(Py_SIZE(b)) == 1); - - if (Py_SIZE(a) == Py_SIZE(b)) { - /* 'a' and 'b' have the same sign. */ + sdigit div, left, right; + assert(Py_ABS(Py_SIZE(a)) <= 1); + assert(Py_SIZE(b) == 1); + + right = b->ob_digit[0]; + if (Py_SIZE(a) >= 0) { + left = Py_SIZE(a) == 0 ? 0 : a->ob_digit[0]; div = left / right; } else { - /* Either 'a' or 'b' is negative. */ + left = a->ob_digit[0]; div = -1 - (left - 1) / right; } - - return PyLong_FromLong(div); + return PyLong_FromLong((long)div); +} + +/* Fast divmod operation for single-digit longs. */ +static int +fast_divmod(PyLongObject *a, PyLongObject *b, + PyLongObject **pdiv, PyLongObject **pmod) +{ + sdigit div, mod, left, right; + assert(Py_ABS(Py_SIZE(a)) <= 1); + assert(Py_SIZE(b) == 1); + + right = b->ob_digit[0]; + if (Py_SIZE(a) >= 0) { + left = Py_SIZE(a) == 0 ? 0 : a->ob_digit[0]; + div = left / right; + mod = left % right; + } + else { + left = a->ob_digit[0]; + div = -1 - (left - 1) / right; + mod = right - 1 - (left - 1) % right; + } + + *pdiv = (PyLongObject *)PyLong_FromLong((long)div); + if (*pdiv == NULL) { + return -1; + } + + *pmod = (PyLongObject *)PyLong_FromLong((long)mod); + if (*pmod == NULL) { + Py_CLEAR(*pdiv); + return -1; + } + return 0; } /* The / and % operators are now defined in terms of divmod(). @@ -3662,30 +3690,6 @@ { PyLongObject *div, *mod; - if (Py_ABS(Py_SIZE(v)) == 1 && Py_ABS(Py_SIZE(w)) == 1) { - /* Fast path for single-digit longs */ - div = NULL; - if (pdiv != NULL) { - div = (PyLongObject *)fast_floor_div(v, w); - if (div == NULL) { - return -1; - } - } - if (pmod != NULL) { - mod = (PyLongObject *)fast_mod(v, w); - if (mod == NULL) { - Py_XDECREF(div); - return -1; - } - *pmod = mod; - } - if (pdiv != NULL) { - /* We only want to set `*pdiv` when `*pmod` is - set successfully. */ - *pdiv = div; - } - return 0; - } if (long_divrem(v, w, &div, &mod) < 0) return -1; if ((Py_SIZE(mod) < 0 && Py_SIZE(w) > 0) || @@ -3731,7 +3735,7 @@ CHECK_BINOP(a, b); - if (Py_ABS(Py_SIZE(a)) == 1 && Py_ABS(Py_SIZE(b)) == 1) { + if (Py_ABS(Py_SIZE(a)) <= 1 && Py_SIZE(b) == 1) { return fast_floor_div((PyLongObject*)a, (PyLongObject*)b); } @@ -4010,12 +4014,13 @@ CHECK_BINOP(a, b); - if (Py_ABS(Py_SIZE(a)) == 1 && Py_ABS(Py_SIZE(b)) == 1) { + if (Py_ABS(Py_SIZE(a)) <= 1 && Py_SIZE(b) == 1) { return fast_mod((PyLongObject*)a, (PyLongObject*)b); } - if (l_divmod((PyLongObject*)a, (PyLongObject*)b, NULL, &mod) < 0) + if (l_divmod((PyLongObject*)a, (PyLongObject*)b, NULL, &mod) < 0) { mod = NULL; + } return (PyObject *)mod; } @@ -4024,10 +4029,17 @@ { PyLongObject *div, *mod; PyObject *z; + int error; CHECK_BINOP(a, b); - if (l_divmod((PyLongObject*)a, (PyLongObject*)b, &div, &mod) < 0) { + if (Py_ABS(Py_SIZE(a)) <= 1 && Py_SIZE(b) == 1) { + error = fast_divmod((PyLongObject*)a, (PyLongObject*)b, &div, &mod); + } + else { + error = l_divmod((PyLongObject*)a, (PyLongObject*)b, &div, &mod); + } + if (error < 0) { return NULL; } z = PyTuple_New(2);