diff -r fd0c02c3df31 Objects/longobject.c --- a/Objects/longobject.c Fri Sep 26 09:04:19 2014 +0300 +++ b/Objects/longobject.c Fri Sep 26 12:23:01 2014 +0200 @@ -2372,6 +2372,7 @@ static PyLongObject *x_divrem (PyLongObject *, PyLongObject *, PyLongObject **); static PyObject *long_long(PyObject *v); +static PyObject *long_neg(PyLongObject *v); /* Int division with remainder, top-level routine */ @@ -3402,23 +3403,53 @@ long_mul(PyLongObject *a, PyLongObject *b) { PyLongObject *z; + const Py_ssize_t a_size = Py_ABS(Py_SIZE(a)), b_size = Py_ABS(Py_SIZE(b)); CHECK_BINOP(a, b); + if (a_size == 0) { + Py_INCREF(a); + return (PyObject*)a; + } + if (b_size == 0) { + Py_INCREF(b); + return (PyObject*)b; + } + /* fast path for single-digit multiplication */ - if (Py_ABS(Py_SIZE(a)) <= 1 && Py_ABS(Py_SIZE(b)) <= 1) { - stwodigits v = (stwodigits)(MEDIUM_VALUE(a)) * MEDIUM_VALUE(b); + if (a_size == 1) { + if (a->ob_digit[0] == 1) { + if (Py_SIZE(a) == 1) { + Py_INCREF(b); + return (PyObject*)b; + } else { + return long_neg(b); + } + } + else if (b_size == 1) { + stwodigits v = (stwodigits)(MEDIUM_VALUE(a)) * MEDIUM_VALUE(b); #ifdef HAVE_LONG_LONG - return PyLong_FromLongLong((PY_LONG_LONG)v); + return PyLong_FromLongLong((PY_LONG_LONG)v); #else - /* if we don't have long long then we're almost certainly - using 15-bit digits, so v will fit in a long. In the - unlikely event that we're using 30-bit digits on a platform - without long long, a large v will just cause us to fall - through to the general multiplication code below. */ - if (v >= LONG_MIN && v <= LONG_MAX) - return PyLong_FromLong((long)v); + /* if we don't have long long then we're almost certainly + using 15-bit digits, so v will fit in a long. In the + unlikely event that we're using 30-bit digits on a platform + without long long, a large v will just cause us to fall + through to the general multiplication code below. */ + if (v >= LONG_MIN && v <= LONG_MAX) + return PyLong_FromLong((long)v); #endif + } + } + else if (b_size == 1) { + if (b->ob_digit[0] == 1) { + if (Py_SIZE(b) == 1) { + Py_INCREF(a); + return (PyObject*)a; + } else { + return long_neg(a); + } + } } z = k_mul(a, b); @@ -3458,6 +3489,33 @@ { PyLongObject *div, *mod; + /* Fast path for division by 1 or -1 */ + if (Py_ABS(Py_SIZE(w)) == 1 && w->ob_digit[0] == 1) { + if (pdiv != NULL) { + if (Py_SIZE(w) == 1) { + Py_INCREF(v); + div = v; + } else { + div = (PyLongObject*)long_neg(v); + if (div == NULL) + return -1; + } + } else { + div = NULL; + } + if (pmod != NULL) { + mod = (PyLongObject*)PyLong_FromLong(0); + if (mod == NULL) { + Py_XDECREF(div); + return -1; + } + *pmod = mod; + } + if (pdiv != NULL) + *pdiv = div; + return 0; + } + if (long_divrem(v, w, &div, &mod) < 0) return -1; if ((Py_SIZE(mod) < 0 && Py_SIZE(w) > 0) || @@ -3624,6 +3682,16 @@ if (a_size == 0) goto underflow_or_zero; + /* Fast path for division by 1 or -1 */ + if (b_size == 1 && b->ob_digit[0] == 1) { + result = PyLong_AsDouble(v); + if (result == -1.0 && PyErr_Occurred()) + return NULL; + if (Py_SIZE(b) == -1) + result = -result; + return PyFloat_FromDouble(result); + } + /* Fast path for a and b small (exactly representable in a double). Relies on floating-point division being correctly rounded; results may be subject to double rounding on x86 machines that operate with