summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSiyuan Zhou <siyuan.zhou@mongodb.com>2015-02-03 18:40:35 -0500
committerSiyuan Zhou <siyuan.zhou@mongodb.com>2015-02-05 13:53:16 -0500
commit93e72f29f5d58dff1229c8db9db62b4f02324117 (patch)
tree975970f00278485ab112767e2758d290da588665
parent68fe6570d19c744f84861b70d541e8b46ac24935 (diff)
downloadmongo-93e72f29f5d58dff1229c8db9db62b4f02324117.tar.gz
SERVER-8944 Use C++11 standard library functions for double NaN and Infinity detection
-rw-r--r--src/mongo/base/compare_numbers.h9
-rw-r--r--src/mongo/base/parse_number_test.cpp8
-rw-r--r--src/mongo/bson/bsonelement.cpp11
-rw-r--r--src/mongo/bson/bsonelement.h4
-rw-r--r--src/mongo/db/index/external_key_generator.cpp4
-rw-r--r--src/mongo/db/matcher/expression_leaf.cpp5
-rw-r--r--src/mongo/db/pipeline/value.cpp3
-rw-r--r--src/mongo/db/query/index_bounds_builder.cpp9
-rw-r--r--src/mongo/db/storage/key_string.cpp6
-rw-r--r--src/mongo/db/storage/key_string_test.cpp10
-rw-r--r--src/mongo/db/storage/mmap_v1/btree/key.cpp5
-rw-r--r--src/mongo/dbtests/jsobjtests.cpp8
-rw-r--r--src/mongo/platform/float_utils.h54
-rw-r--r--src/third_party/s2/base/port.h11
14 files changed, 46 insertions, 101 deletions
diff --git a/src/mongo/base/compare_numbers.h b/src/mongo/base/compare_numbers.h
index c086f87fb7a..ca42f5d1782 100644
--- a/src/mongo/base/compare_numbers.h
+++ b/src/mongo/base/compare_numbers.h
@@ -27,7 +27,8 @@
#pragma once
-#include "mongo/platform/float_utils.h"
+#include <cmath>
+
#include "mongo/util/assert_util.h"
namespace mongo {
@@ -52,8 +53,8 @@ namespace mongo {
if (lhs > rhs) return 1;
// If none of the above cases returned, lhs or rhs must be NaN.
- if (isNaN(lhs)) return isNaN(rhs) ? 0 : -1;
- dassert(isNaN(rhs));
+ if (std::isnan(lhs)) return std::isnan(rhs) ? 0 : -1;
+ dassert(std::isnan(rhs));
return 1;
}
@@ -65,7 +66,7 @@ namespace mongo {
// * 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 (isNaN(rhs)) return 1;
+ if (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.
diff --git a/src/mongo/base/parse_number_test.cpp b/src/mongo/base/parse_number_test.cpp
index ecbad5086e9..3f30448d26d 100644
--- a/src/mongo/base/parse_number_test.cpp
+++ b/src/mongo/base/parse_number_test.cpp
@@ -28,12 +28,12 @@
#include "mongo/platform/basic.h"
+#include <cmath>
#include <limits>
#include "mongo/base/parse_number.h"
#include "mongo/base/status.h"
#include "mongo/platform/cstdint.h"
-#include "mongo/platform/float_utils.h"
#include "mongo/util/mongoutils/str.h" // for str::stream()!
#include "mongo/unittest/unittest.h"
@@ -275,16 +275,16 @@ namespace {
TEST(Double, TestParsingNan) {
double d = 0;
ASSERT_OK(parseNumberFromString("NaN", &d));
- ASSERT_TRUE(isNaN(d));
+ ASSERT_TRUE(std::isnan(d));
}
TEST(Double, TestParsingInfinity) {
double d = 0;
ASSERT_OK(parseNumberFromString("infinity", &d));
- ASSERT_TRUE(isInf(d));
+ ASSERT_TRUE(std::isinf(d));
d = 0;
ASSERT_OK(parseNumberFromString("-Infinity", &d));
- ASSERT_TRUE(isInf(d));
+ ASSERT_TRUE(std::isinf(d));
}
TEST(Double, TestParsingNormal) {
diff --git a/src/mongo/bson/bsonelement.cpp b/src/mongo/bson/bsonelement.cpp
index 0502038e668..7960209963b 100644
--- a/src/mongo/bson/bsonelement.cpp
+++ b/src/mongo/bson/bsonelement.cpp
@@ -31,6 +31,7 @@
#include "mongo/bson/bsonelement.h"
+#include <cmath>
#include <boost/functional/hash.hpp>
#include "mongo/base/compare_numbers.h"
@@ -49,8 +50,6 @@ namespace mongo {
using std::string;
string BSONElement::jsonString( JsonStringFormat format, bool includeFieldNames, int pretty ) const {
- int sign;
-
std::stringstream s;
if ( includeFieldNames )
s << '"' << escape( fieldName() ) << "\" : ";
@@ -81,11 +80,11 @@ namespace mongo {
// This is not valid JSON, but according to RFC-4627, "Numeric values that cannot be
// represented as sequences of digits (such as Infinity and NaN) are not permitted." so
// we are accepting the fact that if we have such values we cannot output valid JSON.
- else if ( mongo::isNaN(number()) ) {
+ else if ( std::isnan(number()) ) {
s << "NaN";
}
- else if ( mongo::isInf(number(), &sign) ) {
- s << ( sign == 1 ? "Infinity" : "-Infinity");
+ else if ( std::isinf(number()) ) {
+ s << ( number() > 0 ? "Infinity" : "-Infinity");
}
else {
StringBuilder ss;
@@ -973,7 +972,7 @@ namespace mongo {
// equal numbers and is still likely to be different for different numbers.
// SERVER-16851
const double dbl = elem.numberDouble();
- if (isNaN(dbl)) {
+ if (std::isnan(dbl)) {
boost::hash_combine(hash, std::numeric_limits<double>::quiet_NaN());
}
else {
diff --git a/src/mongo/bson/bsonelement.h b/src/mongo/bson/bsonelement.h
index a5937349399..386d2ac0020 100644
--- a/src/mongo/bson/bsonelement.h
+++ b/src/mongo/bson/bsonelement.h
@@ -29,6 +29,7 @@
#pragma once
+#include <cmath>
#include <string.h> // strlen
#include <string>
#include <vector>
@@ -38,7 +39,6 @@
#include "mongo/bson/oid.h"
#include "mongo/client/export_macros.h"
#include "mongo/platform/cstdint.h"
-#include "mongo/platform/float_utils.h"
namespace mongo {
class OpTime;
@@ -641,7 +641,7 @@ namespace mongo {
switch( type() ) {
case NumberDouble:
d = numberDouble();
- if ( isNaN( d ) ){
+ if ( std::isnan( d ) ){
return 0;
}
if ( d > (double) std::numeric_limits<long long>::max() ){
diff --git a/src/mongo/db/index/external_key_generator.cpp b/src/mongo/db/index/external_key_generator.cpp
index 9f2e053e848..31289e04883 100644
--- a/src/mongo/db/index/external_key_generator.cpp
+++ b/src/mongo/db/index/external_key_generator.cpp
@@ -28,6 +28,8 @@
#include "mongo/db/index/external_key_generator.h"
+#include <cmath>
+
#include "mongo/db/fts/fts_index_format.h"
#include "mongo/db/index/s2_common.h"
#include "mongo/db/index_names.h"
@@ -170,7 +172,7 @@ namespace {
case NumberDouble:
{
double d = e._numberDouble();
- if (isNaN(d)) {
+ if (std::isnan(d)) {
return traditionalSize;
}
size += 1;
diff --git a/src/mongo/db/matcher/expression_leaf.cpp b/src/mongo/db/matcher/expression_leaf.cpp
index 22ad65ebbca..01e42775531 100644
--- a/src/mongo/db/matcher/expression_leaf.cpp
+++ b/src/mongo/db/matcher/expression_leaf.cpp
@@ -30,6 +30,7 @@
#include "mongo/db/matcher/expression_leaf.h"
+#include <cmath>
#include <pcrecpp.h>
#include "mongo/bson/bsonobjiterator.h"
@@ -121,8 +122,8 @@ namespace mongo {
// Special case handling for NaN. NaN is equal to NaN but
// otherwise always compares to false.
- if (isNaN(e.numberDouble()) || isNaN(_rhs.numberDouble())) {
- bool bothNaN = isNaN(e.numberDouble()) && isNaN(_rhs.numberDouble());
+ if (std::isnan(e.numberDouble()) || std::isnan(_rhs.numberDouble())) {
+ bool bothNaN = std::isnan(e.numberDouble()) && std::isnan(_rhs.numberDouble());
switch ( matchType() ) {
case LT:
return false;
diff --git a/src/mongo/db/pipeline/value.cpp b/src/mongo/db/pipeline/value.cpp
index b37bc1cb6d3..5c371a1f2cb 100644
--- a/src/mongo/db/pipeline/value.cpp
+++ b/src/mongo/db/pipeline/value.cpp
@@ -30,6 +30,7 @@
#include "mongo/db/pipeline/value.h"
+#include <cmath>
#include <boost/functional/hash.hpp>
#include <boost/scoped_array.hpp>
@@ -719,7 +720,7 @@ namespace mongo {
case NumberLong:
case NumberInt: {
const double dbl = getDouble();
- if (isNaN(dbl)) {
+ if (std::isnan(dbl)) {
boost::hash_combine(seed, numeric_limits<double>::quiet_NaN());
}
else {
diff --git a/src/mongo/db/query/index_bounds_builder.cpp b/src/mongo/db/query/index_bounds_builder.cpp
index b22d5c70158..afad4491bab 100644
--- a/src/mongo/db/query/index_bounds_builder.cpp
+++ b/src/mongo/db/query/index_bounds_builder.cpp
@@ -30,6 +30,7 @@
#include "mongo/db/query/index_bounds_builder.h"
+#include <cmath>
#include <limits>
#include "mongo/base/string_data.h"
@@ -359,7 +360,7 @@ namespace mongo {
}
// Only NaN is <= NaN.
- if (isNaN(dataElt.numberDouble())) {
+ if (std::isnan(dataElt.numberDouble())) {
double nan = dataElt.numberDouble();
oilOut->intervals.push_back(makePointInterval(nan));
*tightnessOut = IndexBoundsBuilder::EXACT;
@@ -398,7 +399,7 @@ namespace mongo {
}
// Nothing is < NaN.
- if (isNaN(dataElt.numberDouble())) {
+ if (std::isnan(dataElt.numberDouble())) {
*tightnessOut = IndexBoundsBuilder::EXACT;
return;
}
@@ -441,7 +442,7 @@ namespace mongo {
}
// Nothing is > NaN.
- if (isNaN(dataElt.numberDouble())) {
+ if (std::isnan(dataElt.numberDouble())) {
*tightnessOut = IndexBoundsBuilder::EXACT;
return;
}
@@ -483,7 +484,7 @@ namespace mongo {
}
// Only NaN is >= NaN.
- if (isNaN(dataElt.numberDouble())) {
+ if (std::isnan(dataElt.numberDouble())) {
double nan = dataElt.numberDouble();
oilOut->intervals.push_back(makePointInterval(nan));
*tightnessOut = IndexBoundsBuilder::EXACT;
diff --git a/src/mongo/db/storage/key_string.cpp b/src/mongo/db/storage/key_string.cpp
index 7e0bfa1f153..13e7711a217 100644
--- a/src/mongo/db/storage/key_string.cpp
+++ b/src/mongo/db/storage/key_string.cpp
@@ -451,7 +451,7 @@ namespace mongo {
// no special cases needed for Inf,
// see http://en.wikipedia.org/wiki/IEEE_754-1985#Positive_and_negative_infinity
- if (isNaN(num)) {
+ if (std::isnan(num)) {
_append(CType::kNumericNaN, invert);
return;
}
@@ -596,7 +596,7 @@ namespace mongo {
}
void KeyString::_appendSmallDouble(double value, bool invert) {
- dassert(!isNaN(value));
+ dassert(!std::isnan(value));
dassert(value != 0.0);
uint64_t data;
@@ -613,7 +613,7 @@ namespace mongo {
}
void KeyString::_appendLargeDouble(double value, bool invert) {
- dassert(!isNaN(value));
+ dassert(!std::isnan(value));
dassert(value != 0.0);
uint64_t data;
diff --git a/src/mongo/db/storage/key_string_test.cpp b/src/mongo/db/storage/key_string_test.cpp
index dab32fa0a15..55acef635ae 100644
--- a/src/mongo/db/storage/key_string_test.cpp
+++ b/src/mongo/db/storage/key_string_test.cpp
@@ -30,6 +30,8 @@
#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kStorage
+#include <cmath>
+
#include "mongo/platform/basic.h"
#include "mongo/db/storage/key_string.h"
#include "mongo/unittest/unittest.h"
@@ -701,10 +703,10 @@ TEST(KeyStringTest, NaNs) {
ASSERT_EQ(ks1a, ks2a);
ASSERT_EQ(ks1d, ks2d);
- ASSERT(isNaN(toBson(ks1a, ONE_ASCENDING)[""].Double()));
- ASSERT(isNaN(toBson(ks2a, ONE_ASCENDING)[""].Double()));
- ASSERT(isNaN(toBson(ks1d, ONE_DESCENDING)[""].Double()));
- ASSERT(isNaN(toBson(ks2d, ONE_DESCENDING)[""].Double()));
+ ASSERT(std::isnan(toBson(ks1a, ONE_ASCENDING)[""].Double()));
+ ASSERT(std::isnan(toBson(ks2a, ONE_ASCENDING)[""].Double()));
+ ASSERT(std::isnan(toBson(ks1d, ONE_DESCENDING)[""].Double()));
+ ASSERT(std::isnan(toBson(ks2d, ONE_DESCENDING)[""].Double()));
}
TEST(KeyStringTest, NumberOrderLots) {
std::vector<BSONObj> numbers;
diff --git a/src/mongo/db/storage/mmap_v1/btree/key.cpp b/src/mongo/db/storage/mmap_v1/btree/key.cpp
index d1bae1d4b33..0ee18f614ac 100644
--- a/src/mongo/db/storage/mmap_v1/btree/key.cpp
+++ b/src/mongo/db/storage/mmap_v1/btree/key.cpp
@@ -30,8 +30,9 @@
#include "mongo/db/storage/mmap_v1/btree/key.h"
+#include <cmath>
+
#include "mongo/bson/util/builder.h"
-#include "mongo/platform/float_utils.h"
#include "mongo/util/log.h"
#include "mongo/util/startup_test.h"
@@ -348,7 +349,7 @@ namespace mongo {
case NumberDouble:
{
double d = e._numberDouble();
- if( isNaN(d) ) {
+ if( std::isnan(d) ) {
traditional(obj);
return;
}
diff --git a/src/mongo/dbtests/jsobjtests.cpp b/src/mongo/dbtests/jsobjtests.cpp
index 401f4648c80..ff99677170a 100644
--- a/src/mongo/dbtests/jsobjtests.cpp
+++ b/src/mongo/dbtests/jsobjtests.cpp
@@ -33,6 +33,7 @@
#include "mongo/platform/basic.h"
+#include <cmath>
#include <iostream>
#include "mongo/bson/util/builder.h"
@@ -40,7 +41,6 @@
#include "mongo/db/json.h"
#include "mongo/db/storage/mmap_v1/btree/key.h"
#include "mongo/dbtests/dbtests.h"
-#include "mongo/platform/float_utils.h"
#include "mongo/util/allocator.h"
#include "mongo/util/embedded_builder.h"
#include "mongo/util/log.h"
@@ -458,9 +458,9 @@ namespace JsobjTests {
double inf = numeric_limits< double >::infinity();
double nan = numeric_limits< double >::quiet_NaN();
double nan2 = numeric_limits< double >::signaling_NaN();
- ASSERT( isNaN(nan) );
- ASSERT( isNaN(nan2) );
- ASSERT( !isNaN(inf) );
+ ASSERT( std::isnan(nan) );
+ ASSERT( std::isnan(nan2) );
+ ASSERT( !std::isnan(inf) );
ASSERT( BSON( "a" << inf ).woCompare( BSON( "a" << inf ) ) == 0 );
ASSERT( BSON( "a" << inf ).woCompare( BSON( "a" << 1 ) ) > 0 );
diff --git a/src/mongo/platform/float_utils.h b/src/mongo/platform/float_utils.h
deleted file mode 100644
index 035d31da3bb..00000000000
--- a/src/mongo/platform/float_utils.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2009 10gen Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the GNU Affero General Public License in all respects
- * for all of the code used other than as permitted herein. If you modify
- * file(s) with this exception, you may extend this exception to your
- * version of the file(s), but you are not obligated to do so. If you do not
- * wish to do so, delete this exception statement from your version. If you
- * delete this exception statement from all source files in the program,
- * then also delete it in the license file.
- */
-
-#pragma once
-
-namespace mongo {
-
- inline bool isNaN(double d) {
- return d != d;
- }
-
- inline bool isInf(double d, int* sign = 0) {
- volatile double tmp = d;
-
- if ((tmp == d) && ((tmp - d) != 0.0)) {
- if ( sign ) {
- *sign = (d < 0.0 ? -1 : 1);
- }
- return true;
- }
-
- if ( sign ) {
- *sign = 0;
- }
-
- return false;
- }
-
-}
diff --git a/src/third_party/s2/base/port.h b/src/third_party/s2/base/port.h
index 54a6cbe2ebe..6731c175d01 100644
--- a/src/third_party/s2/base/port.h
+++ b/src/third_party/s2/base/port.h
@@ -716,17 +716,8 @@ inline void va_copy(va_list& a, va_list& b) {
a = b;
}
#endif
-using namespace std;
-#define isnan _isnan
+
#define snprintf _snprintf
-#include "float.h"
-inline double sqrt(int x) { return sqrt((double)x); }
-inline int isinf(double x) {
- const int float_point_class =_fpclass(x);
- if (float_point_class == _FPCLASS_PINF) return 1;
- if (float_point_class == _FPCLASS_NINF) return -1;
- return 0;
-}
#endif
#ifdef COMPILER_MSVC /* if Visual C++ */