--- Objects/longobject.c.new 2008-11-10 14:15:00.000000000 +0100 +++ Objects/longobject.c 2008-11-10 14:45:26.000000000 +0100 @@ -202,22 +202,22 @@ } /* Fast path for single-digits ints */ - if (!(ival>>PyLong_SHIFT)) { + if (!(abs_ival>>PyLong_SHIFT)) { v = _PyLong_New(1); if (v) { Py_SIZE(v) = sign; - v->ob_digit[0] = ival; + v->ob_digit[0] = abs_ival; } return (PyObject*)v; } /* 2 digits */ - if (!(ival >> 2*PyLong_SHIFT)) { + if (!(abs_ival >> 2*PyLong_SHIFT)) { v = _PyLong_New(2); if (v) { Py_SIZE(v) = 2*sign; - v->ob_digit[0] = (digit)ival & PyLong_MASK; - v->ob_digit[1] = ival >> PyLong_SHIFT; + v->ob_digit[0] = abs_ival & PyLong_MASK; + v->ob_digit[1] = abs_ival >> PyLong_SHIFT; } return (PyObject*)v; } @@ -2009,17 +2009,39 @@ /* Long division with remainder, top-level routine */ static int +l_divmod_int(sdigit a, sdigit b, + PyLongObject **pdiv, PyLongObject **prem) +{ + if (pdiv) { + sdigit q = a / b; + if (((a < 0) != (b < 0)) && (a % b != 0)) + q -= 1; + *pdiv = (PyLongObject*) PyLong_FromLong(q); + if (*pdiv == NULL) + return -1; + } + if (prem) { + sdigit r = a % b; + if (r && (a < 0) != (b < 0)) + r += b; + *prem = (PyLongObject*) PyLong_FromLong(r); + if (*prem == NULL) { + if (pdiv) { + Py_DECREF(*pdiv); + } + return -1; + } + } + return 0; +} + +static int long_divrem(PyLongObject *a, PyLongObject *b, PyLongObject **pdiv, PyLongObject **prem) { Py_ssize_t size_a = PyLong_NDIGITS(a), size_b = PyLong_NDIGITS(b); PyLongObject *z; - if (size_b == 0) { - PyErr_SetString(PyExc_ZeroDivisionError, - "integer division or modulo by zero"); - return -1; - } if (size_a < size_b || (size_a == size_b && a->ob_digit[size_a-1] < b->ob_digit[size_b-1])) { @@ -2839,10 +2861,20 @@ { PyLongObject *div, *mod; + if (PyLong_EQUALS_ZERO(w)) { + PyErr_SetString(PyExc_ZeroDivisionError, + "integer division or modulo by zero"); + return -1; + } + + if (PyLong_FITS_INT(v) && PyLong_FITS_INT(w)) { + return l_divmod_int(PyLong_GET_INT(v), PyLong_GET_INT(w), pdiv, pmod); + } + if (long_divrem(v, w, &div, &mod) < 0) return -1; - if ((Py_SIZE(mod) < 0 && Py_SIZE(w) > 0) || - (Py_SIZE(mod) > 0 && Py_SIZE(w) < 0)) { + if ((PyLong_SIGN(mod) < 0 && PyLong_SIGN(w) > 0) || + (PyLong_SIGN(mod) > 0 && PyLong_SIGN(w) < 0)) { PyLongObject *temp; PyLongObject *one; temp = (PyLongObject *) long_add(mod, w); @@ -2895,6 +2927,20 @@ int failed, aexp = -1, bexp = -1; CHECK_BINOP(a, b); + + if (PyLong_EQUALS_ZERO(b)) { + PyErr_SetString(PyExc_ZeroDivisionError, + "int division or modulo by zero"); + return NULL; + } + + if (PyLong_FITS_INT(a) && PyLong_FITS_INT(b)) { + ad = PyLong_GET_INT((PyLongObject*)a); + bd = PyLong_GET_INT((PyLongObject*)b); + ad /= bd; + return PyFloat_FromDouble(ad); + } + ad = _PyLong_AsScaledDouble((PyObject *)a, &aexp); bd = _PyLong_AsScaledDouble((PyObject *)b, &bexp); failed = (ad == -1.0 || bd == -1.0) && PyErr_Occurred(); @@ -2905,12 +2951,6 @@ _PyLong_AsScaledDouble() */ assert(aexp >= 0 && bexp >= 0); - if (bd == 0.0) { - PyErr_SetString(PyExc_ZeroDivisionError, - "int division or modulo by zero"); - return NULL; - } - /* True value is very close to ad/bd * 2**(PyLong_SHIFT*(aexp-bexp)) */ ad /= bd; /* overflow/underflow impossible here */ aexp -= bexp; @@ -3159,7 +3199,7 @@ PyLongObject *w; if (PyLong_FITS_INT(v)) { sdigit invert = PyLong_GET_INT(v); - invert = -(invert + 1); + invert = ~invert; return PyLong_FromLong(invert); } w = (PyLongObject *)PyLong_FromLong(1L); @@ -3333,6 +3373,17 @@ digit diga, digb; PyObject *v; + if (PyLong_FITS_INT(a) && PyLong_FITS_INT(b)) { + sdigit aa = PyLong_GET_INT(a); + sdigit bb = PyLong_GET_INT(b); + switch (op) { + case '^': aa ^= bb; break; + case '&': aa &= bb; break; + case '|': aa |= bb; break; + } + return PyLong_FromLong(aa); + } + if (Py_SIZE(a) < 0) { a = (PyLongObject *) long_invert(a); if (a == NULL)