Refine QRoundingDown::qDiv() to avoid underflow
Subtracting denominator - 1 from the numerator ran into trouble if the numerator was close to its type's minimum representable value. Adding 1 before division, then subtracting it after, avoids that underflow while getting the same answer. Change-Id: I0bb85deaa2ad36f8744ed6dbfdb4817442dddebe Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
4222d117d2
commit
93125d3a05
@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Copyright (C) 2022 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
@ -62,10 +62,17 @@ namespace QRoundingDown {
|
||||
From C++11 onwards, integer division is defined to round towards zero, so we
|
||||
can rely on that when implementing this. This is only used with denominator b
|
||||
> 0, so we only have to treat negative numerator, a, specially.
|
||||
|
||||
If a is a multiple of b, adding 1 before and subtracting it after dividing by
|
||||
b gets us to where we should be (albeit by an eccentric path), since the
|
||||
adding caused rounding up, undone by the subtracting. Otherwise, adding 1
|
||||
doesn't change the result of dividing by b; and we want one less than that
|
||||
result. This is equivalent to subtracting b - 1 and simply dividing, except
|
||||
when that subtraction would underflow.
|
||||
*/
|
||||
|
||||
template<typename Int> constexpr Int qDiv(Int a, unsigned b)
|
||||
{ return (a - (a < 0 ? int(b - 1) : 0)) / int(b); }
|
||||
{ return a < 0 ? (a + 1) / int(b) - 1 : a / int(b); }
|
||||
|
||||
template<typename Int> constexpr Int qMod(Int a, unsigned b)
|
||||
{ return a - qDiv(a, b) * b; }
|
||||
|
Loading…
x
Reference in New Issue
Block a user