MongoDB C++ Driver legacy-1.1.2
Loading...
Searching...
No Matches
compare_numbers.h
1/* Copyright 2015 MongoDB Inc.
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#pragma once
17
18#include "mongo/platform/float_utils.h"
19
20namespace mongo {
21
28inline int compareInts(int lhs, int rhs) {
29 return lhs == rhs ? 0 : lhs < rhs ? -1 : 1;
30}
31
32inline int compareLongs(long long lhs, long long rhs) {
33 return lhs == rhs ? 0 : lhs < rhs ? -1 : 1;
34}
35
36inline int compareDoubles(double lhs, double rhs) {
37 if (lhs == rhs)
38 return 0;
39 if (lhs < rhs)
40 return -1;
41 if (lhs > rhs)
42 return 1;
43
44 // If none of the above cases returned, lhs or rhs must be NaN.
45 if (isNaN(lhs))
46 return isNaN(rhs) ? 0 : -1;
47 return 1;
48}
49
50// This is the tricky one. Needs to support the following cases:
51// * Doubles with a fractional component.
52// * Longs that can't be precisely represented as a double.
53// * Doubles outside of the range of Longs (including +/- Inf).
54// * NaN (defined by us as less than all Longs)
55// * Return value is always -1, 0, or 1 to ensure it is safe to negate.
56inline int compareLongToDouble(long long lhs, double rhs) {
57 // All Longs are > NaN
58 if (isNaN(rhs))
59 return 1;
60
61 // Ints with magnitude <= 2**53 can be precisely represented as doubles.
62 // Additionally, doubles outside of this range can't have a fractional component.
63 static const long long kEndOfPreciseDoubles = 1ll << 53;
64 if (lhs <= kEndOfPreciseDoubles && lhs >= -kEndOfPreciseDoubles) {
65 return compareDoubles(lhs, rhs);
66 }
67
68 // Large magnitude doubles (including +/- Inf) are strictly > or < all Longs.
69 static const double kBoundOfLongRange = -static_cast<double>(LLONG_MIN); // positive 2**63
70 if (rhs >= kBoundOfLongRange)
71 return -1; // Can't be represented in a Long.
72 if (rhs < -kBoundOfLongRange)
73 return 1; // Can be represented in a Long.
74
75 // Remaining Doubles can have their integer component precisely represented as long longs.
76 // If they have a fractional component, they must be strictly > or < lhs even after
77 // truncation of the fractional component since low-magnitude lhs were handled above.
78 return compareLongs(lhs, rhs);
79}
80
81inline int compareDoubleToLong(double lhs, long long rhs) {
82 // Only implement the real logic once.
83 return -compareLongToDouble(rhs, lhs);
84}
85
86} // namespace mongo
Utility functions for parsing numbers from strings.
Definition compare_numbers.h:20
int compareInts(int lhs, int rhs)
These functions compare numbers using the same rules as BSON.
Definition compare_numbers.h:28