-
-
Notifications
You must be signed in to change notification settings - Fork 32k
GH-101291: Rearrange the size bits in PyLongObject #102464
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
0ec07e4
292b9d0
5c54894
029aaa4
b56e6da
91269fc
c48e825
449c0e2
c5ba601
4b3a3e8
9ef9d2c
9c408c1
548d656
3e3fefd
391fb51
df8c7d3
bc14fa6
54c6f1b
ce6bfb2
4c1956b
301158b
1aa1891
bf2a9af
169f521
90f9072
f143443
a0d661e
145a2e4
638a98f
7f5acc0
b06bb6f
a19b0a7
87f49b2
f764aa8
9843ac0
d6cb917
469d26f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
…tCount().
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -3488,7 +3488,7 @@ x_mul(PyLongObject *a, PyLongObject *b) | |||
if (z == NULL) | ||||
return NULL; | ||||
|
||||
memset(z->long_value.ob_digit, 0, Py_SIZE(z) * sizeof(digit)); | ||||
memset(z->long_value.ob_digit, 0, _PyLong_UnsignedDigitCount(z) * sizeof(digit)); | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since
Suggested change
|
||||
if (a == b) { | ||||
/* Efficient squaring per HAC, Algorithm 14.16: | ||||
* http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf | ||||
|
@@ -3671,7 +3671,7 @@ k_mul(PyLongObject *a, PyLongObject *b) | |||
/* Split a & b into hi & lo pieces. */ | ||||
shift = bsize >> 1; | ||||
if (kmul_split(a, shift, &ah, &al) < 0) goto fail; | ||||
assert(Py_SIZE(ah) > 0); /* the split isn't degenerate */ | ||||
assert(_PyLong_UnsignedDigitCount(ah) > 0); /* the split isn't degenerate */ | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should just check the sign, right?
Suggested change
Same below several occurrences. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||
|
||||
if (a == b) { | ||||
bh = (PyLongObject*)Py_NewRef(ah); | ||||
|
@@ -3700,44 +3700,44 @@ k_mul(PyLongObject *a, PyLongObject *b) | |||
if (ret == NULL) goto fail; | ||||
#ifdef Py_DEBUG | ||||
/* Fill with trash, to catch reference to uninitialized digits. */ | ||||
memset(ret->long_value.ob_digit, 0xDF, Py_SIZE(ret) * sizeof(digit)); | ||||
memset(ret->long_value.ob_digit, 0xDF, _PyLong_UnsignedDigitCount(ret) * sizeof(digit)); | ||||
#endif | ||||
|
||||
/* 2. t1 <- ah*bh, and copy into high digits of result. */ | ||||
if ((t1 = k_mul(ah, bh)) == NULL) goto fail; | ||||
assert(Py_SIZE(t1) >= 0); | ||||
assert(2*shift + Py_SIZE(t1) <= Py_SIZE(ret)); | ||||
assert(_PyLong_UnsignedDigitCount(t1) >= 0); | ||||
assert(2*shift + _PyLong_UnsignedDigitCount(t1) <= _PyLong_UnsignedDigitCount(ret)); | ||||
memcpy(ret->long_value.ob_digit + 2*shift, t1->long_value.ob_digit, | ||||
Py_SIZE(t1) * sizeof(digit)); | ||||
_PyLong_UnsignedDigitCount(t1) * sizeof(digit)); | ||||
|
||||
/* Zero-out the digits higher than the ah*bh copy. */ | ||||
i = Py_SIZE(ret) - 2*shift - Py_SIZE(t1); | ||||
i = _PyLong_UnsignedDigitCount(ret) - 2*shift - _PyLong_UnsignedDigitCount(t1); | ||||
if (i) | ||||
memset(ret->long_value.ob_digit + 2*shift + Py_SIZE(t1), 0, | ||||
memset(ret->long_value.ob_digit + 2*shift + _PyLong_UnsignedDigitCount(t1), 0, | ||||
i * sizeof(digit)); | ||||
|
||||
/* 3. t2 <- al*bl, and copy into the low digits. */ | ||||
if ((t2 = k_mul(al, bl)) == NULL) { | ||||
Py_DECREF(t1); | ||||
goto fail; | ||||
} | ||||
assert(Py_SIZE(t2) >= 0); | ||||
assert(Py_SIZE(t2) <= 2*shift); /* no overlap with high digits */ | ||||
memcpy(ret->long_value.ob_digit, t2->long_value.ob_digit, Py_SIZE(t2) * sizeof(digit)); | ||||
assert(_PyLong_UnsignedDigitCount(t2) >= 0); | ||||
assert(_PyLong_UnsignedDigitCount(t2) <= 2*shift); /* no overlap with high digits */ | ||||
memcpy(ret->long_value.ob_digit, t2->long_value.ob_digit, _PyLong_UnsignedDigitCount(t2) * sizeof(digit)); | ||||
|
||||
/* Zero out remaining digits. */ | ||||
i = 2*shift - Py_SIZE(t2); /* number of uninitialized digits */ | ||||
i = 2*shift - _PyLong_UnsignedDigitCount(t2); /* number of uninitialized digits */ | ||||
if (i) | ||||
memset(ret->long_value.ob_digit + Py_SIZE(t2), 0, i * sizeof(digit)); | ||||
memset(ret->long_value.ob_digit + _PyLong_UnsignedDigitCount(t2), 0, i * sizeof(digit)); | ||||
|
||||
/* 4 & 5. Subtract ah*bh (t1) and al*bl (t2). We do al*bl first | ||||
* because it's fresher in cache. | ||||
*/ | ||||
i = Py_SIZE(ret) - shift; /* # digits after shift */ | ||||
(void)v_isub(ret->long_value.ob_digit + shift, i, t2->long_value.ob_digit, Py_SIZE(t2)); | ||||
i = _PyLong_UnsignedDigitCount(ret) - shift; /* # digits after shift */ | ||||
(void)v_isub(ret->long_value.ob_digit + shift, i, t2->long_value.ob_digit, _PyLong_UnsignedDigitCount(t2)); | ||||
_Py_DECREF_INT(t2); | ||||
|
||||
(void)v_isub(ret->long_value.ob_digit + shift, i, t1->long_value.ob_digit, Py_SIZE(t1)); | ||||
(void)v_isub(ret->long_value.ob_digit + shift, i, t1->long_value.ob_digit, _PyLong_UnsignedDigitCount(t1)); | ||||
_Py_DECREF_INT(t1); | ||||
|
||||
/* 6. t3 <- (ah+al)(bh+bl), and add into result. */ | ||||
|
@@ -3761,12 +3761,12 @@ k_mul(PyLongObject *a, PyLongObject *b) | |||
_Py_DECREF_INT(t1); | ||||
_Py_DECREF_INT(t2); | ||||
if (t3 == NULL) goto fail; | ||||
assert(Py_SIZE(t3) >= 0); | ||||
assert(_PyLong_UnsignedDigitCount(t3) >= 0); | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should really check the sign:
Suggested change
Same several times above. |
||||
|
||||
/* Add t3. It's not obvious why we can't run out of room here. | ||||
* See the (*) comment after this function. | ||||
*/ | ||||
(void)v_iadd(ret->long_value.ob_digit + shift, i, t3->long_value.ob_digit, Py_SIZE(t3)); | ||||
(void)v_iadd(ret->long_value.ob_digit + shift, i, t3->long_value.ob_digit, _PyLong_UnsignedDigitCount(t3)); | ||||
markshannon marked this conversation as resolved.
Show resolved
Hide resolved
|
||||
_Py_DECREF_INT(t3); | ||||
|
||||
return long_normalize(ret); | ||||
|
@@ -3849,7 +3849,7 @@ k_lopsided_mul(PyLongObject *a, PyLongObject *b) | |||
ret = _PyLong_New(asize + bsize); | ||||
if (ret == NULL) | ||||
return NULL; | ||||
memset(ret->long_value.ob_digit, 0, Py_SIZE(ret) * sizeof(digit)); | ||||
memset(ret->long_value.ob_digit, 0, _PyLong_UnsignedDigitCount(ret) * sizeof(digit)); | ||||
|
||||
/* Successive slices of b are copied into bslice. */ | ||||
bslice = _PyLong_New(asize); | ||||
|
@@ -3871,8 +3871,8 @@ k_lopsided_mul(PyLongObject *a, PyLongObject *b) | |||
goto fail; | ||||
|
||||
/* Add into result. */ | ||||
(void)v_iadd(ret->long_value.ob_digit + nbdone, Py_SIZE(ret) - nbdone, | ||||
product->long_value.ob_digit, Py_SIZE(product)); | ||||
(void)v_iadd(ret->long_value.ob_digit + nbdone, _PyLong_UnsignedDigitCount(ret) - nbdone, | ||||
product->long_value.ob_digit, _PyLong_UnsignedDigitCount(product)); | ||||
_Py_DECREF_INT(product); | ||||
|
||||
bsize -= nbtouse; | ||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not excited about this name; I keep having to look up how it differs from
_PyLong_DigitCount
, and it's not really related to_PyLong_SignedDigitCount
. :-( Maybe_PyLong_NonNegativeDigitCount
? Or perhaps better_PyLong_DigitCountOfNonNegative
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I needed this for the extra check during implementation.
_PyLong_UnsignedDigitCount
is now the same as_PyLong_DigitCount
, and should remain so.I'll remove it.