From f4bdeedaba71200b999804d9ce388dc528a636d7 Mon Sep 17 00:00:00 2001 From: Henning Baldersheim Date: Tue, 2 Jan 2024 13:02:45 +0000 Subject: Use std::from_chars instead of strtod. Also improve handling of float vs double. --- searchlib/src/tests/query/streaming_query_test.cpp | 54 ++++---- .../vespa/searchlib/query/query_term_simple.cpp | 138 ++++++++++++--------- .../src/vespa/searchlib/query/query_term_simple.h | 59 ++++----- 3 files changed, 134 insertions(+), 117 deletions(-) (limited to 'searchlib/src') diff --git a/searchlib/src/tests/query/streaming_query_test.cpp b/searchlib/src/tests/query/streaming_query_test.cpp index 0a751e96222..e1acb3b467f 100644 --- a/searchlib/src/tests/query/streaming_query_test.cpp +++ b/searchlib/src/tests/query/streaming_query_test.cpp @@ -38,7 +38,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, 7); EXPECT_EQ(ib, 7); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, 7); EXPECT_EQ(db, 7); } @@ -48,7 +48,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, -7); EXPECT_EQ(ib, -7); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, -7); EXPECT_EQ(db, -7); } @@ -56,7 +56,7 @@ TEST(StreamingQueryTest, test_query_language) { QueryTerm q(factory.create(), "7.5", "index", TermType::WORD); EXPECT_TRUE(!q.getAsIntegerTerm(ia, ib)); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, 7.5); EXPECT_EQ(db, 7.5); } @@ -64,7 +64,7 @@ TEST(StreamingQueryTest, test_query_language) { QueryTerm q(factory.create(), "-7.5", "index", TermType::WORD); EXPECT_TRUE(!q.getAsIntegerTerm(ia, ib)); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, -7.5); EXPECT_EQ(db, -7.5); } @@ -74,7 +74,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, std::numeric_limits::min()); EXPECT_EQ(ib, 6); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, -std::numeric_limits::max()); EXPECT_LT(db, 7); EXPECT_GT(db, 6.99); @@ -85,7 +85,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, std::numeric_limits::min()); EXPECT_EQ(ib, 7); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, -std::numeric_limits::max()); EXPECT_EQ(db, 7); } @@ -95,7 +95,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, 8); EXPECT_EQ(ib, std::numeric_limits::max()); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_GT(da, 7); EXPECT_LT(da, 7.01); EXPECT_EQ(db, std::numeric_limits::max()); @@ -106,7 +106,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, 7); EXPECT_EQ(ib, std::numeric_limits::max()); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, 7); EXPECT_EQ(db, std::numeric_limits::max()); } @@ -116,7 +116,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, -7); EXPECT_EQ(ib, 7); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, -7); EXPECT_EQ(db, 7); } @@ -126,7 +126,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_FALSE(q.getAsIntegerTerm(ia, ib)); // This is dubious and perhaps a regression. EXPECT_EQ(ia, std::numeric_limits::min()); EXPECT_EQ(ib, std::numeric_limits::max()); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, -7.1); EXPECT_EQ(db, 7.1); } @@ -136,7 +136,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_FALSE(q.getAsIntegerTerm(ia, ib)); // This is dubious and perhaps a regression. EXPECT_EQ(ia, std::numeric_limits::min()); EXPECT_EQ(ib, std::numeric_limits::max()); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, 500.0); EXPECT_EQ(db, std::numeric_limits::max()); } @@ -147,8 +147,8 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, -6); EXPECT_EQ(ib, 7); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); - EXPECT_EQ(da, std::nextafterf(minusSeven, seven)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); + EXPECT_EQ(da, std::nextafter(minusSeven, seven)); EXPECT_EQ(db, seven); } @@ -157,9 +157,9 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, -6); EXPECT_EQ(ib, 6); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); - EXPECT_EQ(da, std::nextafterf(minusSeven, seven)); - EXPECT_EQ(db, std::nextafterf(seven, minusSeven)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); + EXPECT_EQ(da, std::nextafter(minusSeven, seven)); + EXPECT_EQ(db, std::nextafter(seven, minusSeven)); } { @@ -174,9 +174,9 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, -7); EXPECT_EQ(ib, 6); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, minusSeven); - EXPECT_EQ(db, std::nextafterf(seven, minusSeven)); + EXPECT_EQ(db, std::nextafter(seven, minusSeven)); } { @@ -184,7 +184,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, std::numeric_limits::min()); EXPECT_EQ(ib, -8); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, -std::numeric_limits::max()); EXPECT_LT(db, -7); EXPECT_GT(db, -7.01); @@ -195,7 +195,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, std::numeric_limits::min()); EXPECT_EQ(ib, -7); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, -std::numeric_limits::max()); EXPECT_EQ(db, -7); } @@ -205,7 +205,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, std::numeric_limits::min()); EXPECT_EQ(ib, -7); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, -std::numeric_limits::max()); EXPECT_EQ(db, -7); } @@ -215,7 +215,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, -6); EXPECT_EQ(ib, std::numeric_limits::max()); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_GT(da, -7); EXPECT_LT(da, -6.99); EXPECT_EQ(db, std::numeric_limits::max()); @@ -226,7 +226,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, -7); EXPECT_EQ(ib, std::numeric_limits::max()); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, -7); EXPECT_EQ(db, std::numeric_limits::max()); } @@ -236,7 +236,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); EXPECT_EQ(ia, -7); EXPECT_EQ(ib, std::numeric_limits::max()); - EXPECT_TRUE(q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, -7); EXPECT_EQ(db, std::numeric_limits::max()); } @@ -244,7 +244,7 @@ TEST(StreamingQueryTest, test_query_language) { QueryTerm q(factory.create(), "a", "index", TermType::WORD); EXPECT_TRUE(!q.getAsIntegerTerm(ia, ib)); - EXPECT_TRUE(!q.getAsDoubleTerm(da, db)); + EXPECT_TRUE(!q.getAsFloatTerm(da, db)); } { @@ -645,7 +645,7 @@ TEST(StreamingQueryTest, require_that_ascending_range_can_be_specified_with_limi QueryTerm ascending_query(eqnr.create(), "[;;500]", "index", TermType::WORD); EXPECT_TRUE(ascending_query.getAsIntegerTerm(low_integer, high_integer)); - EXPECT_TRUE(ascending_query.getAsDoubleTerm(low_double, high_double)); + EXPECT_TRUE(ascending_query.getAsFloatTerm(low_double, high_double)); EXPECT_EQ(std::numeric_limits::min(), low_integer); EXPECT_EQ(std::numeric_limits::max(), high_integer); EXPECT_EQ(-std::numeric_limits::max(), low_double); @@ -664,7 +664,7 @@ TEST(StreamingQueryTest, require_that_descending_range_can_be_specified_with_lim QueryTerm descending_query(eqnr.create(), "[;;-500]", "index", TermType::WORD); EXPECT_TRUE(descending_query.getAsIntegerTerm(low_integer, high_integer)); - EXPECT_TRUE(descending_query.getAsDoubleTerm(low_double, high_double)); + EXPECT_TRUE(descending_query.getAsFloatTerm(low_double, high_double)); EXPECT_EQ(std::numeric_limits::min(), low_integer); EXPECT_EQ(std::numeric_limits::max(), high_integer); EXPECT_EQ(-std::numeric_limits::max(), low_double); diff --git a/searchlib/src/vespa/searchlib/query/query_term_simple.cpp b/searchlib/src/vespa/searchlib/query/query_term_simple.cpp index fb2be58c536..77e245c3b7d 100644 --- a/searchlib/src/vespa/searchlib/query/query_term_simple.cpp +++ b/searchlib/src/vespa/searchlib/query/query_term_simple.cpp @@ -4,7 +4,6 @@ #include "base.h" #include #include -#include #include #include #include @@ -12,11 +11,59 @@ namespace { template -bool isValidInteger(int64_t value) +constexpr bool isValidInteger(int64_t value) noexcept { - return value >= std::numeric_limits::min() && value <= std::numeric_limits::max(); + return (value >= std::numeric_limits::min()) && + (value <= std::numeric_limits::max()); } +constexpr bool isRepresentableByInt64(double d) noexcept { + return (d > double(std::numeric_limits::min())) && + (d < double(std::numeric_limits::max())); +} + +bool isFullRange(vespalib::stringref s) noexcept { + const size_t sz(s.size()); + return (sz >= 3u) && + (s[0] == '<' || s[0] == '[') && + (s[sz-1] == '>' || s[sz-1] == ']'); +} + +struct IntDecoder { + static int64_t fromstr(const char * q, const char * qend, const char ** end) noexcept { + int64_t v(0); + for (;q < qend && isspace(*q); q++); + std::from_chars_result err = std::from_chars(q, qend, v, 10); + if (err.ec == std::errc::result_out_of_range) { + v = (*q == '-') ? std::numeric_limits::min() : std::numeric_limits::max(); + } + *end = err.ptr; + return v; + } + static int64_t nearestDownwd(int64_t n, int64_t min) noexcept { return (n > min ? n - 1 : n); } + static int64_t nearestUpward(int64_t n, int64_t max) noexcept { return (n < max ? n + 1 : n); } +}; + +template +struct FloatDecoder { + static T fromstr(const char * q, const char * qend, const char ** end) noexcept { + T v(0); + for (;q < qend && isspace(*q); q++); + std::from_chars_result err = std::from_chars(q, qend, v); + if (err.ec == std::errc::result_out_of_range) { + v = (*q == '-') ? std::numeric_limits::min() : std::numeric_limits::max(); + } + *end = err.ptr; + return v; + } + static T nearestDownwd(T n, T min) noexcept { + return std::nextafter(n, min); + } + static T nearestUpward(T n, T max) noexcept { + return std::nextafter(n, max); + } +}; + } namespace search { @@ -30,10 +77,10 @@ QueryTermSimple::visitMembers(vespalib::ObjectVisitor & visitor) const template QueryTermSimple::RangeResult -QueryTermSimple::getFloatRange() const +QueryTermSimple::getFloatRange() const noexcept { - double lowRaw, highRaw; - bool valid = getAsDoubleTerm(lowRaw, highRaw); + N lowRaw, highRaw; + bool valid = getAsFloatTerm(lowRaw, highRaw); RangeResult res; res.valid = valid; if (!valid) { @@ -47,25 +94,16 @@ QueryTermSimple::getFloatRange() const return res; } -namespace { - -bool isRepresentableByInt64(double d) { - return (d > double(std::numeric_limits::min())) - && (d < double(std::numeric_limits::max())); -} - -} - bool -QueryTermSimple::getRangeInternal(int64_t & low, int64_t & high) const +QueryTermSimple::getRangeInternal(int64_t & low, int64_t & high) const noexcept { bool valid = getAsIntegerTerm(low, high); if ( ! valid ) { double l(0), h(0); - valid = getAsDoubleTerm(l, h); + valid = getAsFloatTerm(l, h); if (valid) { if ((l == h) && isRepresentableByInt64(l)) { - low = high = std::round(l); + low = high = static_cast(std::round(l)); } else { if (l > double(std::numeric_limits::min())) { if (l < double(std::numeric_limits::max())) { @@ -89,7 +127,7 @@ QueryTermSimple::getRangeInternal(int64_t & low, int64_t & high) const template QueryTermSimple::RangeResult -QueryTermSimple::getIntegerRange() const +QueryTermSimple::getIntegerRange() const noexcept { int64_t lowRaw, highRaw; bool valid = getRangeInternal(lowRaw, highRaw); @@ -122,94 +160,72 @@ QueryTermSimple::getIntegerRange() const template <> QueryTermSimple::RangeResult -QueryTermSimple::getRange() const +QueryTermSimple::getRange() const noexcept { return getFloatRange(); } template <> QueryTermSimple::RangeResult -QueryTermSimple::getRange() const +QueryTermSimple::getRange() const noexcept { return getFloatRange(); } template <> QueryTermSimple::RangeResult -QueryTermSimple::getRange() const +QueryTermSimple::getRange() const noexcept { return getIntegerRange(); } template <> QueryTermSimple::RangeResult -QueryTermSimple::getRange() const +QueryTermSimple::getRange() const noexcept { return getIntegerRange(); } template <> QueryTermSimple::RangeResult -QueryTermSimple::getRange() const +QueryTermSimple::getRange() const noexcept { return getIntegerRange(); } template <> QueryTermSimple::RangeResult -QueryTermSimple::getRange() const +QueryTermSimple::getRange() const noexcept { return getIntegerRange(); } -struct IntDecoder { - static int64_t fromstr(const char * q, const char * qend, char ** end) noexcept { - int64_t v(0); - for (;q < qend && isspace(*q); q++); - std::from_chars_result err = std::from_chars(q, qend, v, 10); - if (err.ec == std::errc::result_out_of_range) { - v = (*q == '-') ? std::numeric_limits::min() : std::numeric_limits::max(); - } - *end = const_cast(err.ptr); - return v; - } - static int64_t nearestDownwd(int64_t n, int64_t min) noexcept { return (n > min ? n - 1 : n); } - static int64_t nearestUpward(int64_t n, int64_t max) noexcept { return (n < max ? n + 1 : n); } -}; - -struct DoubleDecoder { - static double fromstr(const char * q, const char * qend, char ** end) { - (void) qend; - return vespalib::locale::c::strtod(q, end); - } - static double nearestDownwd(double n, double min) noexcept { return std::nextafterf(n, min); } - static double nearestUpward(double n, double max) noexcept { return std::nextafterf(n, max); } -}; - -bool QueryTermSimple::getAsIntegerTerm(int64_t & lower, int64_t & upper) const +bool QueryTermSimple::getAsIntegerTerm(int64_t & lower, int64_t & upper) const noexcept { lower = std::numeric_limits::min(); upper = std::numeric_limits::max(); return getAsNumericTerm(lower, upper, IntDecoder()); } -bool QueryTermSimple::getAsDoubleTerm(double & lower, double & upper) const +bool QueryTermSimple::getAsFloatTerm(double & lower, double & upper) const noexcept { lower = - std::numeric_limits::max(); upper = std::numeric_limits::max(); - return getAsNumericTerm(lower, upper, DoubleDecoder()); + return getAsNumericTerm(lower, upper, FloatDecoder()); +} + +bool QueryTermSimple::getAsFloatTerm(float & lower, float & upper) const noexcept +{ + lower = - std::numeric_limits::max(); + upper = std::numeric_limits::max(); + return getAsNumericTerm(lower, upper, FloatDecoder()); } QueryTermSimple::~QueryTermSimple() = default; namespace { -bool isFullRange(vespalib::stringref s) { - const size_t sz(s.size()); - return (sz >= 3u) && - (s[0] == '<' || s[0] == '[') && - (s[sz-1] == '>' || s[sz-1] == ']'); -} + } @@ -244,7 +260,7 @@ QueryTermSimple::QueryTermSimple(const string & term_, Type type) } _valid = (numParts >= 2) && (numParts < NELEMS(parts)); if (_valid && numParts > 2) { - _rangeLimit = strtol(parts[2].data(), nullptr, 0); + _rangeLimit = static_cast(strtol(parts[2].data(), nullptr, 0)); if (numParts > 3) { _valid = (numParts >= 5); if (_valid) { @@ -269,12 +285,12 @@ QueryTermSimple::QueryTermSimple(const string & term_, Type type) template bool -QueryTermSimple::getAsNumericTerm(T & lower, T & upper, D d) const +QueryTermSimple::getAsNumericTerm(T & lower, T & upper, D d) const noexcept { if (empty()) return false; size_t sz(_term.size()); - char *err(nullptr); + const char *err(nullptr); T low(lower); T high(upper); const char * q = _term.c_str(); diff --git a/searchlib/src/vespa/searchlib/query/query_term_simple.h b/searchlib/src/vespa/searchlib/query/query_term_simple.h index 2b64e3812ab..87bf7c26b80 100644 --- a/searchlib/src/vespa/searchlib/query/query_term_simple.h +++ b/searchlib/src/vespa/searchlib/query/query_term_simple.h @@ -33,8 +33,8 @@ public: N high; bool valid; // Whether parsing of the range was successful bool adjusted; // Whether the low and high was adjusted according to min and max limits of the given type. - RangeResult() : low(), high(), valid(true), adjusted(false) {} - bool isEqual() const { return low == high; } + RangeResult() noexcept : low(), high(), valid(true), adjusted(false) {} + bool isEqual() const noexcept { return low == high; } }; QueryTermSimple(const QueryTermSimple &) = delete; @@ -47,39 +47,40 @@ public: * Extracts the content of this query term as a range with low and high values. */ template - RangeResult getRange() const; - int getRangeLimit() const { return _rangeLimit; } - size_t getMaxPerGroup() const { return _maxPerGroup; } - size_t getDiversityCutoffGroups() const { return _diversityCutoffGroups; } - bool getDiversityCutoffStrict() const { return _diversityCutoffStrict; } - vespalib::stringref getDiversityAttribute() const { return _diversityAttribute; } - size_t getFuzzyMaxEditDistance() const { return _fuzzyMaxEditDistance; } - size_t getFuzzyPrefixLength() const { return _fuzzyPrefixLength; } - bool getAsIntegerTerm(int64_t & lower, int64_t & upper) const; - bool getAsDoubleTerm(double & lower, double & upper) const; - const char * getTerm() const { return _term.c_str(); } - bool isPrefix() const { return (_type == Type::PREFIXTERM); } - bool isSubstring() const { return (_type == Type::SUBSTRINGTERM); } - bool isExactstring() const { return (_type == Type::EXACTSTRINGTERM); } - bool isSuffix() const { return (_type == Type::SUFFIXTERM); } - bool isWord() const { return (_type == Type::WORD); } - bool isRegex() const { return (_type == Type::REGEXP); } - bool isGeoLoc() const { return (_type == Type::GEO_LOCATION); } - bool isFuzzy() const { return (_type == Type::FUZZYTERM); } + RangeResult getRange() const noexcept; + int getRangeLimit() const noexcept { return _rangeLimit; } + size_t getMaxPerGroup() const noexcept { return _maxPerGroup; } + size_t getDiversityCutoffGroups() const noexcept { return _diversityCutoffGroups; } + bool getDiversityCutoffStrict() const noexcept { return _diversityCutoffStrict; } + vespalib::stringref getDiversityAttribute() const noexcept { return _diversityAttribute; } + size_t getFuzzyMaxEditDistance() const noexcept { return _fuzzyMaxEditDistance; } + size_t getFuzzyPrefixLength() const noexcept { return _fuzzyPrefixLength; } + bool getAsIntegerTerm(int64_t & lower, int64_t & upper) const noexcept; + bool getAsFloatTerm(double & lower, double & upper) const noexcept; + bool getAsFloatTerm(float & lower, float & upper) const noexcept; + const char * getTerm() const noexcept { return _term.c_str(); } + bool isPrefix() const noexcept { return (_type == Type::PREFIXTERM); } + bool isSubstring() const noexcept { return (_type == Type::SUBSTRINGTERM); } + bool isExactstring() const noexcept { return (_type == Type::EXACTSTRINGTERM); } + bool isSuffix() const noexcept { return (_type == Type::SUFFIXTERM); } + bool isWord() const noexcept { return (_type == Type::WORD); } + bool isRegex() const noexcept { return (_type == Type::REGEXP); } + bool isGeoLoc() const noexcept { return (_type == Type::GEO_LOCATION); } + bool isFuzzy() const noexcept { return (_type == Type::FUZZYTERM); } bool is_nearest_neighbor() const noexcept { return (_type == Type::NEAREST_NEIGHBOR); } - bool empty() const { return _term.empty(); } + bool empty() const noexcept { return _term.empty(); } virtual void visitMembers(vespalib::ObjectVisitor &visitor) const; vespalib::string getClassName() const; - bool isValid() const { return _valid; } - const string & getTermString() const { return _term; } + bool isValid() const noexcept { return _valid; } + const string & getTermString() const noexcept { return _term; } private: - bool getRangeInternal(int64_t & low, int64_t & high) const; + bool getRangeInternal(int64_t & low, int64_t & high) const noexcept; template - RangeResult getIntegerRange() const; + RangeResult getIntegerRange() const noexcept; template - RangeResult getFloatRange() const; - int _rangeLimit; + RangeResult getFloatRange() const noexcept; + int32_t _rangeLimit; uint32_t _maxPerGroup; uint32_t _diversityCutoffGroups; Type _type; @@ -88,7 +89,7 @@ private: string _term; stringref _diversityAttribute; template - bool getAsNumericTerm(T & lower, T & upper, D d) const; + bool getAsNumericTerm(T & lower, T & upper, D d) const noexcept; protected: uint32_t _fuzzyMaxEditDistance; // set in QueryTerm -- cgit v1.2.3 From c13fd050cf3131595459a6477adf2f92b3cdae5a Mon Sep 17 00:00:00 2001 From: Henning Baldersheim Date: Wed, 3 Jan 2024 16:10:12 +0000 Subject: Unify on +/- infinity for floating point numbers. --- searchlib/src/tests/query/streaming_query_test.cpp | 28 +++++++++++----------- .../vespa/searchlib/query/query_term_simple.cpp | 14 +++++------ 2 files changed, 21 insertions(+), 21 deletions(-) (limited to 'searchlib/src') diff --git a/searchlib/src/tests/query/streaming_query_test.cpp b/searchlib/src/tests/query/streaming_query_test.cpp index e1acb3b467f..a4e84a4d384 100644 --- a/searchlib/src/tests/query/streaming_query_test.cpp +++ b/searchlib/src/tests/query/streaming_query_test.cpp @@ -75,7 +75,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_EQ(ia, std::numeric_limits::min()); EXPECT_EQ(ib, 6); EXPECT_TRUE(q.getAsFloatTerm(da, db)); - EXPECT_EQ(da, -std::numeric_limits::max()); + EXPECT_EQ(da, -std::numeric_limits::infinity()); EXPECT_LT(db, 7); EXPECT_GT(db, 6.99); } @@ -86,7 +86,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_EQ(ia, std::numeric_limits::min()); EXPECT_EQ(ib, 7); EXPECT_TRUE(q.getAsFloatTerm(da, db)); - EXPECT_EQ(da, -std::numeric_limits::max()); + EXPECT_EQ(da, -std::numeric_limits::infinity()); EXPECT_EQ(db, 7); } @@ -98,7 +98,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_GT(da, 7); EXPECT_LT(da, 7.01); - EXPECT_EQ(db, std::numeric_limits::max()); + EXPECT_EQ(db, std::numeric_limits::infinity()); } { @@ -108,7 +108,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_EQ(ib, std::numeric_limits::max()); EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, 7); - EXPECT_EQ(db, std::numeric_limits::max()); + EXPECT_EQ(db, std::numeric_limits::infinity()); } { @@ -185,7 +185,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_EQ(ia, std::numeric_limits::min()); EXPECT_EQ(ib, -8); EXPECT_TRUE(q.getAsFloatTerm(da, db)); - EXPECT_EQ(da, -std::numeric_limits::max()); + EXPECT_EQ(da, -std::numeric_limits::infinity()); EXPECT_LT(db, -7); EXPECT_GT(db, -7.01); } @@ -196,7 +196,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_EQ(ia, std::numeric_limits::min()); EXPECT_EQ(ib, -7); EXPECT_TRUE(q.getAsFloatTerm(da, db)); - EXPECT_EQ(da, -std::numeric_limits::max()); + EXPECT_EQ(da, -std::numeric_limits::infinity()); EXPECT_EQ(db, -7); } @@ -206,7 +206,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_EQ(ia, std::numeric_limits::min()); EXPECT_EQ(ib, -7); EXPECT_TRUE(q.getAsFloatTerm(da, db)); - EXPECT_EQ(da, -std::numeric_limits::max()); + EXPECT_EQ(da, -std::numeric_limits::infinity()); EXPECT_EQ(db, -7); } @@ -218,7 +218,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_GT(da, -7); EXPECT_LT(da, -6.99); - EXPECT_EQ(db, std::numeric_limits::max()); + EXPECT_EQ(db, std::numeric_limits::infinity()); } { @@ -228,7 +228,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_EQ(ib, std::numeric_limits::max()); EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, -7); - EXPECT_EQ(db, std::numeric_limits::max()); + EXPECT_EQ(db, std::numeric_limits::infinity()); } { @@ -238,7 +238,7 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_EQ(ib, std::numeric_limits::max()); EXPECT_TRUE(q.getAsFloatTerm(da, db)); EXPECT_EQ(da, -7); - EXPECT_EQ(db, std::numeric_limits::max()); + EXPECT_EQ(db, std::numeric_limits::infinity()); } { @@ -648,8 +648,8 @@ TEST(StreamingQueryTest, require_that_ascending_range_can_be_specified_with_limi EXPECT_TRUE(ascending_query.getAsFloatTerm(low_double, high_double)); EXPECT_EQ(std::numeric_limits::min(), low_integer); EXPECT_EQ(std::numeric_limits::max(), high_integer); - EXPECT_EQ(-std::numeric_limits::max(), low_double); - EXPECT_EQ(std::numeric_limits::max(), high_double); + EXPECT_EQ(-std::numeric_limits::infinity(), low_double); + EXPECT_EQ(std::numeric_limits::infinity(), high_double); EXPECT_EQ(500, ascending_query.getRangeLimit()); } @@ -667,8 +667,8 @@ TEST(StreamingQueryTest, require_that_descending_range_can_be_specified_with_lim EXPECT_TRUE(descending_query.getAsFloatTerm(low_double, high_double)); EXPECT_EQ(std::numeric_limits::min(), low_integer); EXPECT_EQ(std::numeric_limits::max(), high_integer); - EXPECT_EQ(-std::numeric_limits::max(), low_double); - EXPECT_EQ(std::numeric_limits::max(), high_double); + EXPECT_EQ(-std::numeric_limits::infinity(), low_double); + EXPECT_EQ(std::numeric_limits::infinity(), high_double); EXPECT_EQ(-500, descending_query.getRangeLimit()); } diff --git a/searchlib/src/vespa/searchlib/query/query_term_simple.cpp b/searchlib/src/vespa/searchlib/query/query_term_simple.cpp index 77e245c3b7d..0550ba5f684 100644 --- a/searchlib/src/vespa/searchlib/query/query_term_simple.cpp +++ b/searchlib/src/vespa/searchlib/query/query_term_simple.cpp @@ -51,7 +51,7 @@ struct FloatDecoder { for (;q < qend && isspace(*q); q++); std::from_chars_result err = std::from_chars(q, qend, v); if (err.ec == std::errc::result_out_of_range) { - v = (*q == '-') ? std::numeric_limits::min() : std::numeric_limits::max(); + v = (*q == '-') ? -std::numeric_limits::infinity() : std::numeric_limits::infinity(); } *end = err.ptr; return v; @@ -84,8 +84,8 @@ QueryTermSimple::getFloatRange() const noexcept RangeResult res; res.valid = valid; if (!valid) { - res.low = std::numeric_limits::max(); - res.high = - std::numeric_limits::max(); + res.low = std::numeric_limits::infinity(); + res.high = -std::numeric_limits::infinity(); res.adjusted = true; } else { res.low = lowRaw; @@ -209,15 +209,15 @@ bool QueryTermSimple::getAsIntegerTerm(int64_t & lower, int64_t & upper) const n bool QueryTermSimple::getAsFloatTerm(double & lower, double & upper) const noexcept { - lower = - std::numeric_limits::max(); - upper = std::numeric_limits::max(); + lower = -std::numeric_limits::infinity(); + upper = std::numeric_limits::infinity(); return getAsNumericTerm(lower, upper, FloatDecoder()); } bool QueryTermSimple::getAsFloatTerm(float & lower, float & upper) const noexcept { - lower = - std::numeric_limits::max(); - upper = std::numeric_limits::max(); + lower = -std::numeric_limits::infinity(); + upper = std::numeric_limits::infinity(); return getAsNumericTerm(lower, upper, FloatDecoder()); } -- cgit v1.2.3 From 9da9d445a93a008f1623ce0719e99be813bd1a71 Mon Sep 17 00:00:00 2001 From: Henning Baldersheim Date: Wed, 3 Jan 2024 16:32:07 +0000 Subject: Handle + as number prefix. --- searchlib/src/tests/query/streaming_query_test.cpp | 9 +++++++++ searchlib/src/vespa/searchlib/query/query_term_simple.cpp | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'searchlib/src') diff --git a/searchlib/src/tests/query/streaming_query_test.cpp b/searchlib/src/tests/query/streaming_query_test.cpp index a4e84a4d384..f5370785167 100644 --- a/searchlib/src/tests/query/streaming_query_test.cpp +++ b/searchlib/src/tests/query/streaming_query_test.cpp @@ -52,6 +52,15 @@ TEST(StreamingQueryTest, test_query_language) EXPECT_EQ(da, -7); EXPECT_EQ(db, -7); } + { + QueryTerm q(factory.create(), "+7", "index", TermType::WORD); + EXPECT_TRUE(q.getAsIntegerTerm(ia, ib)); + EXPECT_EQ(ia, 7); + EXPECT_EQ(ib, 7); + EXPECT_TRUE(q.getAsFloatTerm(da, db)); + EXPECT_EQ(da, 7); + EXPECT_EQ(db, 7); + } { QueryTerm q(factory.create(), "7.5", "index", TermType::WORD); diff --git a/searchlib/src/vespa/searchlib/query/query_term_simple.cpp b/searchlib/src/vespa/searchlib/query/query_term_simple.cpp index 0550ba5f684..e6cea9c752b 100644 --- a/searchlib/src/vespa/searchlib/query/query_term_simple.cpp +++ b/searchlib/src/vespa/searchlib/query/query_term_simple.cpp @@ -32,7 +32,7 @@ bool isFullRange(vespalib::stringref s) noexcept { struct IntDecoder { static int64_t fromstr(const char * q, const char * qend, const char ** end) noexcept { int64_t v(0); - for (;q < qend && isspace(*q); q++); + for (;q < qend && (isspace(*q) || (*q == '+')); q++); std::from_chars_result err = std::from_chars(q, qend, v, 10); if (err.ec == std::errc::result_out_of_range) { v = (*q == '-') ? std::numeric_limits::min() : std::numeric_limits::max(); @@ -48,7 +48,7 @@ template struct FloatDecoder { static T fromstr(const char * q, const char * qend, const char ** end) noexcept { T v(0); - for (;q < qend && isspace(*q); q++); + for (;q < qend && (isspace(*q) || (*q == '+')); q++); std::from_chars_result err = std::from_chars(q, qend, v); if (err.ec == std::errc::result_out_of_range) { v = (*q == '-') ? -std::numeric_limits::infinity() : std::numeric_limits::infinity(); -- cgit v1.2.3