Skip to content
Open
32 changes: 28 additions & 4 deletions Objects/longobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -3387,16 +3387,29 @@ x_add(PyLongObject *a, PyLongObject *b)
Py_ssize_t i;
digit carry = 0;

/* There are fast paths for cases where a and b both have at most a single
digit, so if we end up here then at least one of them is multi-digit. */
assert(size_a >= 2 || size_b >= 2);

/* Ensure a is the larger of the two: */
if (size_a < size_b) {
{ PyLongObject *temp = a; a = b; b = temp; }
{ Py_ssize_t size_temp = size_a;
size_a = size_b;
size_b = size_temp; }
}
z = _PyLong_New(size_a+1);

/* Allocate sufficient space for the result. In the majority of cases
we allocate exactly the right number of digits, but in the (relatively
rare) case where the sum of the topmost digits is exactly PyLong_MASK,
we'll sometimes end up overallocating by a single digit. */
digit top_sum = a->ob_digit[size_a-1]
+ (size_b == size_a ? b->ob_digit[size_b-1] : (digit)0);
int extra_digit = top_sum >= PyLong_MASK;
z = _PyLong_New(size_a+extra_digit);
if (z == NULL)
return NULL;

for (i = 0; i < size_b; ++i) {
carry += a->ob_digit[i] + b->ob_digit[i];
z->ob_digit[i] = carry & PyLong_MASK;
Expand All @@ -3407,8 +3420,16 @@ x_add(PyLongObject *a, PyLongObject *b)
z->ob_digit[i] = carry & PyLong_MASK;
carry >>= PyLong_SHIFT;
}
z->ob_digit[i] = carry;
return long_normalize(z);
if (extra_digit) {
if (carry) {
z->ob_digit[i] = carry;
}
else {
/* rare case: we didn't need the extra digit after all */
Py_SET_SIZE(z, size_a);
}
}
return z;
}

/* Subtract the absolute values of two integers. */
Expand Down Expand Up @@ -5879,7 +5900,10 @@ int___sizeof___impl(PyObject *self)
{
Py_ssize_t res;

res = offsetof(PyLongObject, ob_digit) + Py_ABS(Py_SIZE(self))*sizeof(digit);
res = offsetof(PyLongObject, ob_digit)
/* using Py_MAX(..., 1) because we always allocate space for at least
one digit, even though the integer zero has a Py_SIZE of 0 */
+ Py_MAX(Py_ABS(Py_SIZE(self)), 1)*sizeof(digit);
return res;
}

Expand Down