diff options
Diffstat (limited to 'src/mongo/base/compare_numbers.h')
-rw-r--r-- | src/mongo/base/compare_numbers.h | 105 |
1 files changed, 56 insertions, 49 deletions
diff --git a/src/mongo/base/compare_numbers.h b/src/mongo/base/compare_numbers.h index ca42f5d1782..0049d5ba336 100644 --- a/src/mongo/base/compare_numbers.h +++ b/src/mongo/base/compare_numbers.h @@ -33,62 +33,69 @@ namespace mongo { - /** - * These functions compare numbers using the same rules as BSON. Care is taken to always give - * numerically correct results when comparing different types. Returns are always -1, 0, or 1 to - * ensure it is safe to negate the result to invert the direction of the comparison. - */ +/** + * These functions compare numbers using the same rules as BSON. Care is taken to always give + * numerically correct results when comparing different types. Returns are always -1, 0, or 1 to + * ensure it is safe to negate the result to invert the direction of the comparison. + */ - inline int compareInts(int lhs, int rhs) { - return lhs == rhs ? 0 : lhs < rhs ? -1 : 1; - } +inline int compareInts(int lhs, int rhs) { + return lhs == rhs ? 0 : lhs < rhs ? -1 : 1; +} - inline int compareLongs(long long lhs, long long rhs) { - return lhs == rhs ? 0 : lhs < rhs ? -1 : 1; - } +inline int compareLongs(long long lhs, long long rhs) { + return lhs == rhs ? 0 : lhs < rhs ? -1 : 1; +} - inline int compareDoubles(double lhs, double rhs) { - if (lhs == rhs) return 0; - if (lhs < rhs) return -1; - if (lhs > rhs) return 1; - - // If none of the above cases returned, lhs or rhs must be NaN. - if (std::isnan(lhs)) return std::isnan(rhs) ? 0 : -1; - dassert(std::isnan(rhs)); +inline int compareDoubles(double lhs, double rhs) { + if (lhs == rhs) + return 0; + if (lhs < rhs) + return -1; + if (lhs > rhs) return 1; - } - // This is the tricky one. Needs to support the following cases: - // * Doubles with a fractional component. - // * Longs that can't be precisely represented as a double. - // * Doubles outside of the range of Longs (including +/- Inf). - // * NaN (defined by us as less than all Longs) - // * Return value is always -1, 0, or 1 to ensure it is safe to negate. - inline int compareLongToDouble(long long lhs, double rhs) { - // All Longs are > NaN - if (std::isnan(rhs)) return 1; + // If none of the above cases returned, lhs or rhs must be NaN. + if (std::isnan(lhs)) + return std::isnan(rhs) ? 0 : -1; + dassert(std::isnan(rhs)); + return 1; +} - // Ints with magnitude <= 2**53 can be precisely represented as doubles. - // Additionally, doubles outside of this range can't have a fractional component. - static const long long kEndOfPreciseDoubles = 1ll << 53; - if (lhs <= kEndOfPreciseDoubles && lhs >= -kEndOfPreciseDoubles) { - return compareDoubles(lhs, rhs); - } - - // Large magnitude doubles (including +/- Inf) are strictly > or < all Longs. - static const double kBoundOfLongRange = -static_cast<double>(LLONG_MIN); // positive 2**63 - if (rhs >= kBoundOfLongRange) return -1; // Can't be represented in a Long. - if (rhs < -kBoundOfLongRange) return 1; // Can be represented in a Long. +// This is the tricky one. Needs to support the following cases: +// * Doubles with a fractional component. +// * Longs that can't be precisely represented as a double. +// * Doubles outside of the range of Longs (including +/- Inf). +// * NaN (defined by us as less than all Longs) +// * Return value is always -1, 0, or 1 to ensure it is safe to negate. +inline int compareLongToDouble(long long lhs, double rhs) { + // All Longs are > NaN + if (std::isnan(rhs)) + return 1; - // Remaining Doubles can have their integer component precisely represented as long longs. - // If they have a fractional component, they must be strictly > or < lhs even after - // truncation of the fractional component since low-magnitude lhs were handled above. - return compareLongs(lhs, rhs); + // Ints with magnitude <= 2**53 can be precisely represented as doubles. + // Additionally, doubles outside of this range can't have a fractional component. + static const long long kEndOfPreciseDoubles = 1ll << 53; + if (lhs <= kEndOfPreciseDoubles && lhs >= -kEndOfPreciseDoubles) { + return compareDoubles(lhs, rhs); } - inline int compareDoubleToLong(double lhs, long long rhs) { - // Only implement the real logic once. - return -compareLongToDouble(rhs, lhs); - } + // Large magnitude doubles (including +/- Inf) are strictly > or < all Longs. + static const double kBoundOfLongRange = -static_cast<double>(LLONG_MIN); // positive 2**63 + if (rhs >= kBoundOfLongRange) + return -1; // Can't be represented in a Long. + if (rhs < -kBoundOfLongRange) + return 1; // Can be represented in a Long. + + // Remaining Doubles can have their integer component precisely represented as long longs. + // If they have a fractional component, they must be strictly > or < lhs even after + // truncation of the fractional component since low-magnitude lhs were handled above. + return compareLongs(lhs, rhs); +} + +inline int compareDoubleToLong(double lhs, long long rhs) { + // Only implement the real logic once. + return -compareLongToDouble(rhs, lhs); +} -} // namespace mongo +} // namespace mongo |