Fixed failing is_finite tests on the latest clang

Signed-off-by: Alexander Borsuk <me@alex.bio>
This commit is contained in:
Alexander Borsuk
2025-06-20 04:11:56 +02:00
committed by Konstantin Pastbin
parent 8fe788c98d
commit 82133c5743
11 changed files with 97 additions and 74 deletions

View File

@@ -28,6 +28,7 @@ set(SRC
dfa_helpers.hpp
exception.cpp
exception.hpp
fast_math.cpp
fifo_cache.hpp
file_name_utils.cpp
file_name_utils.hpp
@@ -105,6 +106,10 @@ set(SRC
omim_add_library(${PROJECT_NAME} ${SRC})
# Exception for some of our math to work reliably.
# Ubuntu x86_64 gcc 14.2.0 ignores -fno-finite-math-only in debug builds without -O1
set_source_files_properties(fast_math.cpp PROPERTIES COMPILE_OPTIONS "-fno-finite-math-only;$<$<CONFIG:DEBUG>:-O1>")
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(${PROJECT_NAME} INTERFACE Threads::Threads)

View File

@@ -172,3 +172,22 @@ UNIT_TEST(Sign)
TEST_EQUAL(-1, base::Sign(-11), ());
TEST_EQUAL(-1, base::Sign(-10.4), ());
}
UNIT_TEST(is_finite)
{
static_assert(std::numeric_limits<double>::has_infinity);
static_assert(std::numeric_limits<double>::has_quiet_NaN);
using math::is_finite, math::Nan, math::Infinity;
TEST(!is_finite(Nan()), ());
TEST(!is_finite(Infinity()), ());
TEST(!is_finite(DBL_MAX*2.0), ());
TEST(is_finite(0.0), ());
TEST(is_finite(1.0), ());
TEST(is_finite(-2.0), ());
TEST(is_finite(DBL_MIN), ());
TEST(is_finite(DBL_MAX), ());
TEST(is_finite(DBL_MIN/2.0), ("As in cppreference example"));
}

View File

@@ -131,22 +131,6 @@ UNIT_TEST(EqualNoCase)
TEST(strings::EqualNoCase("HaHaHa", "hahaha"), ());
}
UNIT_TEST(is_finite)
{
using namespace strings;
TEST(!is_finite(NAN), ());
TEST(!is_finite(INFINITY), ());
//TEST(!is_finite(DBL_MIN/2.0), ());
TEST(!is_finite(DBL_MAX*2.0), ());
TEST(is_finite(0.0), ());
TEST(is_finite(1.0), ());
TEST(is_finite(-2.0), ());
TEST(is_finite(DBL_MIN), ());
TEST(is_finite(DBL_MAX), ());
}
UNIT_TEST(to_double)
{
std::string s;

19
base/fast_math.cpp Normal file
View File

@@ -0,0 +1,19 @@
// Separate cpp for different compiler flags.
#include <cmath>
#include <limits>
namespace math
{
double Nan()
{
return std::numeric_limits<double>::quiet_NaN();
}
double Infinity()
{
return std::numeric_limits<double>::infinity();
}
bool is_finite(double t)
{
return std::isfinite(t);
}
} // namespace base

View File

@@ -12,6 +12,11 @@ namespace math
double constexpr pi = 3.14159265358979323846;
double constexpr pi2 = pi / 2.0;
double constexpr pi4 = pi / 4.0;
// Defined in fast_math.cpp
double Nan();
double Infinity();
bool is_finite(double d);
} // namespace math
namespace base

View File

@@ -1,6 +1,7 @@
#include "base/string_utils.hpp"
#include "base/assert.hpp"
#include "base/math.hpp"
#include "base/stl_helpers.hpp"
#include <algorithm>
@@ -10,7 +11,6 @@
#include <iterator>
#include <boost/algorithm/string/trim.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <fast_double_parser.h>
namespace strings
@@ -34,27 +34,22 @@ double RealConverter<double>(char const * start, char ** stop)
return std::strtod(start, stop);
}
template <typename T>
bool IsFinite(T t)
{
return boost::math::isfinite(t);
}
template <typename T>
bool ToReal(char const * start, T & result)
{
// Try faster implementation first.
double d;
// TODO(AB): replace with more robust dependency that doesn't use std::is_finite in the implementation.
char const * endptr = fast_double_parser::parse_number(start, &d);
if (endptr == nullptr)
{
// Fallback to our implementation, it supports numbers like "1."
char * stop;
result = RealConverter<T>(start, &stop);
if (*stop == 0 && start != stop && IsFinite(result))
if (*stop == 0 && start != stop && math::is_finite(result))
return true;
}
else if (*endptr == 0 && IsFinite(d))
else if (*endptr == 0 && math::is_finite(d))
{
result = static_cast<T>(d);
return true;
@@ -116,11 +111,6 @@ bool to_double(char const * start, double & d)
return ToReal(start, d);
}
bool is_finite(double d)
{
return IsFinite(d);
}
UniString MakeLowerCase(UniString s)
{
MakeLowerCaseInplace(s);