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 10:59:49 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((PyObject*)a); + return (PyObject*)a; + } + if (b_size == 0) { + Py_INCREF((PyObject*)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((PyObject*)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((PyObject*)a); + return (PyObject*)a; + } else { + return long_neg(a); + } + } } z = k_mul(a, b);