Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1dad6a8

Browse files
committed
SF bug 434186: 0x80000000/2 != 0x80000000>>1
i_divmod: New and simpler algorithm. Old one returned gibberish on most boxes when the numerator was -sys.maxint-1. Oddly enough, it worked in the release (not debug) build on Windows, because the compiler optimized away some tricky sign manipulations that were incorrect in this case. Makes you wonder <wink> ... Bugfix candidate.
1 parent 888aa26 commit 1dad6a8

2 files changed

Lines changed: 24 additions & 23 deletions

File tree

Lib/test/test_b1.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,13 @@ def f(): pass
367367
else:
368368
raise TestFailed, "int(%s)" % `s[1:]` + " should raise ValueError"
369369

370+
# SF bug 434186: 0x80000000/2 != 0x80000000>>1.
371+
# Worked by accident in Windows release build, but failed in debug build.
372+
# Failed in all Linux builds.
373+
x = -1-sys.maxint
374+
if x >> 1 != x/2:
375+
raise TestFailed("x >> 1 != x/2 when x == -1-sys.maxint")
376+
370377
print 'isinstance'
371378
class C:
372379
pass

Objects/intobject.c

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -434,38 +434,32 @@ int_mul(PyObject *v, PyObject *w)
434434
}
435435

436436
static int
437-
i_divmod(register long xi, register long yi,
437+
i_divmod(register long x, register long y,
438438
long *p_xdivy, long *p_xmody)
439439
{
440440
long xdivy, xmody;
441441

442-
if (yi == 0) {
442+
if (y == 0) {
443443
PyErr_SetString(PyExc_ZeroDivisionError,
444444
"integer division or modulo by zero");
445445
return -1;
446446
}
447-
if (yi < 0) {
448-
if (xi < 0) {
449-
if (yi == -1 && -xi < 0) {
450-
/* most negative / -1 */
451-
err_ovf("integer division");
452-
return -1;
453-
}
454-
xdivy = -xi / -yi;
455-
}
456-
else
457-
xdivy = - (xi / -yi);
458-
}
459-
else {
460-
if (xi < 0)
461-
xdivy = - (-xi / yi);
462-
else
463-
xdivy = xi / yi;
447+
/* (-sys.maxint-1)/-1 is the only overflow case. */
448+
if (y == -1 && x < 0 && x == -x) {
449+
err_ovf("integer division");
450+
return -1;
464451
}
465-
xmody = xi - xdivy*yi;
466-
if ((xmody < 0 && yi > 0) || (xmody > 0 && yi < 0)) {
467-
xmody += yi;
468-
xdivy -= 1;
452+
xdivy = x / y;
453+
xmody = x - xdivy * y;
454+
/* If the signs of x and y differ, and the remainder is non-0,
455+
* C89 doesn't define whether xdivy is now the floor or the
456+
* ceiling of the infinitely precise quotient. We want the floor,
457+
* and we have it iff the remainder's sign matches y's.
458+
*/
459+
if (xmody && ((y ^ xmody) < 0) /* i.e. and signs differ */) {
460+
xmody += y;
461+
--xdivy;
462+
assert(xmody && ((y ^ xmody) >= 0));
469463
}
470464
*p_xdivy = xdivy;
471465
*p_xmody = xmody;

0 commit comments

Comments
 (0)