From cd9625fc3cacb4efd0da57d9f5780671f5c1310f Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 6 Jan 2016 14:40:50 +0100 Subject: Correct floordiv() to cope with implementation-defined division. Irrelevant once we get to C++11 (so we can revert this in 5.7), but division's rounding direction is implementation defined when either operand is negative [0]. The prior code assumed C++11's truncation (a.k.a. round towards zero), but rounding may be downwards instead. [0] http://en.cppreference.com/w/cpp/language/operator_arithmetic#Multiplicative_operators Change-Id: I2b6b27e1cf629def48b25433e81b9ed8230d8795 Reviewed-by: Thiago Macieira --- src/corelib/tools/qdatetime.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index fa4ac2b00f..ff20c57166 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -90,14 +90,25 @@ static inline QDate fixedDate(int y, int m, int d) return result; } +/* + Until C++11, rounding direction is implementation-defined. + + For negative operands, implementations may chose to round down instead of + towards zero (truncation). We only actually care about the case a < 0, as all + uses of floordiv have b > 0. In this case, if rounding is down we have a % b + >= 0 and simple division works fine; but a % b = a - (a / b) * b always, so + rounding towards zero gives a % b <= 0; when < 0, we need to adjust. + + Once we assume C++11, we can safely test a < 0 instead of a % b < 0. + */ static inline qint64 floordiv(qint64 a, int b) { - return (a - (a < 0 ? b-1 : 0)) / b; + return (a - (a % b < 0 ? b - 1 : 0)) / b; } static inline int floordiv(int a, int b) { - return (a - (a < 0 ? b-1 : 0)) / b; + return (a - (a % b < 0 ? b - 1 : 0)) / b; } static inline qint64 julianDayFromDate(int year, int month, int day) -- cgit v1.2.3