@@ -320,16 +320,35 @@ extern "C" Box* div_i64_i64(i64 lhs, i64 rhs) {
320
320
#if PYSTON_INT_MIN < -PYSTON_INT_MAX
321
321
static_assert (PYSTON_INT_MIN == -PYSTON_INT_MAX - 1 , " " );
322
322
323
- if (lhs == PYSTON_INT_MIN) {
324
- return longInt ( longDiv (boxLong (lhs), boxLong (rhs) ));
323
+ if (lhs == PYSTON_INT_MIN && rhs == - 1 ) {
324
+ return longDiv (boxLong (lhs), boxLong (rhs));
325
325
}
326
326
#endif
327
327
328
- if (lhs < 0 && rhs > 0 )
329
- return boxInt ((lhs - rhs + 1 ) / rhs);
330
- if (lhs > 0 && rhs < 0 )
331
- return boxInt ((lhs - rhs - 1 ) / rhs);
332
- return boxInt (lhs / rhs);
328
+ i64 div_result, mod_result;
329
+ div_result = lhs / rhs;
330
+ /* div_result * rhs can overflow on platforms where lhs/rhs gives floor(lhs/rhs)
331
+ * for lhs and rhs with differing signs. (This is unusual
332
+ * behaviour, and C99 prohibits it, but it's allowed by C89;
333
+ * for an example of overflow, take lhs = LONG_MIN, rhs = 5 or lhs =
334
+ * LONG_MAX, rhs = -5.) However, lhs - div_result*rhs is always
335
+ * representable as a long, since it lies strictly between
336
+ * -abs(rhs) and abs(rhs). We add casts to avoid intermediate
337
+ * overflow.
338
+ */
339
+ mod_result = (i64 )(lhs - (unsigned long )div_result * rhs);
340
+ /* If the signs of lhs and rhs differ, and the remainder is non-0,
341
+ * C89 doesn't define whether div_result is now the floor or the
342
+ * ceiling of the infinitely precise quotient. We want the floor,
343
+ * and we have it iff the remainder's sign matches rhs's.
344
+ */
345
+ if (mod_result && ((rhs ^ mod_result) < 0 ) /* i.e. and signs differ */ ) {
346
+ mod_result += rhs;
347
+ --div_result;
348
+ assert (mod_result && ((rhs ^ mod_result) >= 0 ));
349
+ }
350
+
351
+ return boxInt (div_result);
333
352
}
334
353
335
354
extern " C" i64 mod_i64_i64 (i64 lhs, i64 rhs) {
0 commit comments