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 11:45:09 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); @@ -3502,6 +3533,19 @@ PyLongObject *div; CHECK_BINOP(a, b); + + /* Fast path for division by 1 or -1 */ + if (Py_SIZE(b) == 1) { + if (((PyLongObject*)b)->ob_digit[0] == 1) { + Py_INCREF(a); + return a; + } + } + else if (Py_SIZE(b) == -1) { + if (((PyLongObject*)b)->ob_digit[0] == 1) + return long_neg((PyLongObject*)a); + } + if (l_divmod((PyLongObject*)a, (PyLongObject*)b, &div, NULL) < 0) div = NULL; return (PyObject *)div; @@ -3624,6 +3668,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