summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/index/s2_key_generator_test.cpp25
-rwxr-xr-xsrc/third_party/s2/util/math/mathutil.cc13
-rwxr-xr-xsrc/third_party/s2/util/math/mathutil.h71
3 files changed, 30 insertions, 79 deletions
diff --git a/src/mongo/db/index/s2_key_generator_test.cpp b/src/mongo/db/index/s2_key_generator_test.cpp
index 23a321ddc68..d88c8e04919 100644
--- a/src/mongo/db/index/s2_key_generator_test.cpp
+++ b/src/mongo/db/index/s2_key_generator_test.cpp
@@ -27,12 +27,12 @@
* it in the license file.
*/
-
#include "mongo/platform/basic.h"
#include "mongo/db/index/expression_keys_private.h"
#include <algorithm>
+#include <s2.h>
#include "mongo/bson/bsonobjbuilder.h"
#include "mongo/bson/simple_bsonobj_comparator.h"
@@ -687,4 +687,27 @@ TEST_F(S2KeyGeneratorTest, MidPathSingleElementArrayIsConsideredMultikey) {
assertMultikeyPathsEqual(MultikeyPaths{{0U}, MultikeyComponents{}}, actualMultikeyPaths);
}
+// Test which verifies that the rounding functions used by s2 follow 'round to even' rounding
+// behavior.
+TEST_F(S2KeyGeneratorTest, VerifyS2RoundingBehavior) {
+ const double roundDownToEven = 2.5;
+ ASSERT_EQ(2, MathUtil::FastIntRound(roundDownToEven));
+ ASSERT_EQ(2LL, MathUtil::FastInt64Round(roundDownToEven));
+
+ const double roundUpToEven = 3.5;
+ ASSERT_EQ(4, MathUtil::FastIntRound(roundUpToEven));
+ ASSERT_EQ(4LL, MathUtil::FastInt64Round(roundUpToEven));
+
+ const double roundDownToEvenNegative = -3.5;
+ ASSERT_EQ(-4, MathUtil::FastIntRound(roundDownToEvenNegative));
+ ASSERT_EQ(-4LL, MathUtil::FastInt64Round(roundDownToEvenNegative));
+
+ const double roundUpToEvenNegative = -2.5;
+ ASSERT_EQ(-2, MathUtil::FastIntRound(roundUpToEvenNegative));
+ ASSERT_EQ(-2LL, MathUtil::FastInt64Round(roundUpToEvenNegative));
+
+ const double point = 944920918.5;
+ ASSERT_EQ(944920918, MathUtil::FastIntRound(point));
+ ASSERT_EQ(944920918LL, MathUtil::FastInt64Round(point));
+}
} // namespace
diff --git a/src/third_party/s2/util/math/mathutil.cc b/src/third_party/s2/util/math/mathutil.cc
index 7ca3b890f8a..35ab462027c 100755
--- a/src/third_party/s2/util/math/mathutil.cc
+++ b/src/third_party/s2/util/math/mathutil.cc
@@ -16,19 +16,6 @@ using std::vector;
#include "base/integral_types.h"
#include "base/logging.h"
- template <class IntOut, class FloatIn>
- IntOut MathUtil::Round(FloatIn x) {
- COMPILE_ASSERT(!MathLimits<FloatIn>::kIsInteger, FloatIn_is_integer);
- COMPILE_ASSERT(MathLimits<IntOut>::kIsInteger, IntOut_is_not_integer);
-
- // We don't use sgn(x) below because there is no need to distinguish the
- // (x == 0) case. Also note that there are specialized faster versions
- // of this function for Intel processors at the bottom of this file.
- return static_cast<IntOut>(x < 0 ? (x - 0.5) : (x + 0.5));
- }
-
-template int MathUtil::Round<int,double>(double x);
-
MathUtil::QuadraticRootType MathUtil::RealRootsForQuadratic(long double a,
long double b,
long double c,
diff --git a/src/third_party/s2/util/math/mathutil.h b/src/third_party/s2/util/math/mathutil.h
index bf607475b64..74ac26c5838 100755
--- a/src/third_party/s2/util/math/mathutil.h
+++ b/src/third_party/s2/util/math/mathutil.h
@@ -317,33 +317,6 @@ class MathUtil {
vector<bool>* shards_to_read);
// --------------------------------------------------------------------
- // Round, IntRound
- // These functions round a floating-point number to an integer. They
- // work for positive or negative numbers.
- //
- // Values that are halfway between two integers may be rounded up or
- // down, for example IntRound(0.5) == 0 and IntRound(1.5) == 2. This
- // allows these functions to be implemented efficiently on Intel
- // processors (see the template specializations at the bottom of this
- // file). You should not use these functions if you care about which
- // way such half-integers are rounded.
- //
- // Example usage:
- // double y, z;
- // int x = IntRound(y + 3.7);
- // int64 b = Round<int64>(0.3 * z);
- //
- // Note that the floating-point template parameter is typically inferred
- // from the argument type, i.e. there is no need to specify it explicitly.
- // --------------------------------------------------------------------
- template <class IntOut, class FloatIn>
- static IntOut Round(FloatIn x);
-
- // Example usage: IntRound(3.6) (no need for IntRound<double>(3.6)).
- template <class FloatIn>
- static int IntRound(FloatIn x) { return Round<int>(x); }
-
- // --------------------------------------------------------------------
// FastIntRound, FastInt64Round
// Fast routines for converting floating-point numbers to integers.
//
@@ -356,11 +329,10 @@ class MathUtil {
// floating-point pipeline (unless programs are compiled specifically
// for the Pentium 4, which has a new instruction to avoid this).
//
- // Numbers that are halfway between two integers may be rounded up or
- // down. This is because the conversion is done using the default
+ // Numbers that are halfway between two integers follow the deafult
// rounding mode, which rounds towards the closest even number in case
// of ties. So for example, FastIntRound(0.5) == 0, but
- // FastIntRound(1.5) == 2. These functions should only be used with
+ // FastIntRound(1.5) == 2. These functions should only be used with
// applications that don't care about which way such half-integers are
// rounded.
//
@@ -368,10 +340,8 @@ class MathUtil {
// functions (for "int" and "int64" only), but it's safer to call them
// directly.
//
- // This functions are equivalent to lrint() and llrint() as defined in
- // the ISO C99 standard. Unfortunately this standard does not seem to
- // widely adopted yet and these functions are not available by default.
- // --------------------------------------------------------------------
+ // This functions are equivalent to rint() and llrint().
+ // --------------------------------------------------------------------
static int32 FastIntRound(double x) {
// This function is not templatized because gcc doesn't seem to be able
@@ -399,7 +369,7 @@ class MathUtil {
return result;
#endif // if defined __x86_64__ || ...
#else
- return Round<int32, double>(x);
+ return static_cast<int32>(rint(x));
#endif // if defined __GNUC__ && ...
}
@@ -425,7 +395,7 @@ class MathUtil {
return result;
#endif // if defined __i386__
#else
- return Round<int64, double>(x);
+ return static_cast<int64>(llrint(x));
#endif // if defined __GNUC__ && ...
}
@@ -686,35 +656,6 @@ class MathUtil {
}
};
-// ========================================================================= //
-
-#if (defined __i386__ || defined __x86_64__) && defined __GNUC__
-
-// We define template specializations of Round() to get the more efficient
-// Intel versions when possible. Note that gcc does not currently support
-// partial specialization of templatized functions.
-template<>
-inline int32 MathUtil::Round<int32, double>(double x) {
- return FastIntRound(x);
-}
-
-template<>
-inline int32 MathUtil::Round<int32, float>(float x) {
- return FastIntRound(x);
-}
-
-template<>
-inline int64 MathUtil::Round<int64, double>(double x) {
- return FastInt64Round(x);
-}
-
-template<>
-inline int64 MathUtil::Round<int64, float>(float x) {
- return FastInt64Round(x);
-}
-
-#endif
-
template<typename T>
bool MathUtil::WithinFraction(const T x, const T y, const T fraction) {
// not just "0 <= fraction" to fool the compiler for unsigned types