summaryrefslogtreecommitdiff
path: root/src/third_party/s2
diff options
context:
space:
mode:
Diffstat (limited to 'src/third_party/s2')
-rwxr-xr-xsrc/third_party/s2/util/math/mathutil.cc13
-rwxr-xr-xsrc/third_party/s2/util/math/mathutil.h71
2 files changed, 78 insertions, 6 deletions
diff --git a/src/third_party/s2/util/math/mathutil.cc b/src/third_party/s2/util/math/mathutil.cc
index 35ab462027c..7ca3b890f8a 100755
--- a/src/third_party/s2/util/math/mathutil.cc
+++ b/src/third_party/s2/util/math/mathutil.cc
@@ -16,6 +16,19 @@ 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 74ac26c5838..bf607475b64 100755
--- a/src/third_party/s2/util/math/mathutil.h
+++ b/src/third_party/s2/util/math/mathutil.h
@@ -317,6 +317,33 @@ 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.
//
@@ -329,10 +356,11 @@ 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 follow the deafult
+ // Numbers that are halfway between two integers may be rounded up or
+ // down. This is because the conversion is done using the default
// 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.
//
@@ -340,8 +368,10 @@ class MathUtil {
// functions (for "int" and "int64" only), but it's safer to call them
// directly.
//
- // This functions are equivalent to rint() and llrint().
- // --------------------------------------------------------------------
+ // 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.
+ // --------------------------------------------------------------------
static int32 FastIntRound(double x) {
// This function is not templatized because gcc doesn't seem to be able
@@ -369,7 +399,7 @@ class MathUtil {
return result;
#endif // if defined __x86_64__ || ...
#else
- return static_cast<int32>(rint(x));
+ return Round<int32, double>(x);
#endif // if defined __GNUC__ && ...
}
@@ -395,7 +425,7 @@ class MathUtil {
return result;
#endif // if defined __i386__
#else
- return static_cast<int64>(llrint(x));
+ return Round<int64, double>(x);
#endif // if defined __GNUC__ && ...
}
@@ -656,6 +686,35 @@ 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