diff options
author | Siyuan Zhou <siyuan.zhou@mongodb.com> | 2015-02-03 18:40:35 -0500 |
---|---|---|
committer | Siyuan Zhou <siyuan.zhou@mongodb.com> | 2015-02-05 13:53:16 -0500 |
commit | 93e72f29f5d58dff1229c8db9db62b4f02324117 (patch) | |
tree | 975970f00278485ab112767e2758d290da588665 | |
parent | 68fe6570d19c744f84861b70d541e8b46ac24935 (diff) | |
download | mongo-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.h | 9 | ||||
-rw-r--r-- | src/mongo/base/parse_number_test.cpp | 8 | ||||
-rw-r--r-- | src/mongo/bson/bsonelement.cpp | 11 | ||||
-rw-r--r-- | src/mongo/bson/bsonelement.h | 4 | ||||
-rw-r--r-- | src/mongo/db/index/external_key_generator.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/matcher/expression_leaf.cpp | 5 | ||||
-rw-r--r-- | src/mongo/db/pipeline/value.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/query/index_bounds_builder.cpp | 9 | ||||
-rw-r--r-- | src/mongo/db/storage/key_string.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/storage/key_string_test.cpp | 10 | ||||
-rw-r--r-- | src/mongo/db/storage/mmap_v1/btree/key.cpp | 5 | ||||
-rw-r--r-- | src/mongo/dbtests/jsobjtests.cpp | 8 | ||||
-rw-r--r-- | src/mongo/platform/float_utils.h | 54 | ||||
-rw-r--r-- | src/third_party/s2/base/port.h | 11 |
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++ */ |