MongoDB C++ Driver  legacy-1.1.2
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 
20 namespace mongo {
21 
28 inline int compareInts(int lhs, int rhs) {
29  return lhs == rhs ? 0 : lhs < rhs ? -1 : 1;
30 }
31 
32 inline int compareLongs(long long lhs, long long rhs) {
33  return lhs == rhs ? 0 : lhs < rhs ? -1 : 1;
34 }
35 
36 inline 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.
56 inline 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 
81 inline 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