Fix a bunch of warnings

This commit is contained in:
2025-07-06 14:34:21 +02:00
parent bcdad5b876
commit 00ea14788f
13 changed files with 118 additions and 39 deletions

View File

@ -12,9 +12,36 @@ using float64_t = double;
namespace asl
{
template<is_floating_point T> constexpr T infinity() { return __builtin_inf(); }
template<typename T> struct float_traits {};
template<is_floating_point T> constexpr T nan() { return static_cast<T>(__builtin_nanf("")); }
#define ASL_FLOAT_TRAITS(T, INF, NAN, EPS, SMALLEST) \
template<> struct float_traits<T> \
{ \
static constexpr T kInfinity{__builtin_bit_cast(T, INF)}; \
static constexpr T kNaN{__builtin_bit_cast(T, NAN)}; \
static constexpr T kEpsilon{EPS}; \
static constexpr T kSmallest{__builtin_bit_cast(T, SMALLEST)}; \
};
ASL_FLOAT_TRAITS(
float32_t,
0x7F800000,
0x7FC00000,
__builtin_bit_cast(float32_t, 0x3F800001) - float32_t{1},
0x00800000
);
ASL_FLOAT_TRAITS(
float64_t,
0x7FF0000000000000,
0x7FF8000000000000,
__builtin_bit_cast(float64_t, 0x3FF0000000000001) - float64_t{1},
0x0010000000000000
);
template<is_floating_point T> constexpr T infinity() { return float_traits<T>::kInfinity; }
template<is_floating_point T> constexpr T nan() { return float_traits<T>::kNaN; }
template<is_floating_point T> constexpr bool is_infinity(T f) { return __builtin_isinf(f); }

View File

@ -42,11 +42,11 @@ enum class byte : uint8_t {};
template<typename T> struct integer_traits {};
#define ASL_INTEGER_TRAITS(T, MIN, MAX) \
template<> struct integer_traits<T> \
{ \
static constexpr T kMin = MIN; \
static constexpr T kMax = MAX; \
#define ASL_INTEGER_TRAITS(T, MIN, MAX) \
template<> struct integer_traits<T> \
{ \
static constexpr T kMin{static_cast<T>(MIN)}; \
static constexpr T kMax{static_cast<T>(MAX)}; \
}
ASL_INTEGER_TRAITS(uint8_t, 0, 0xff);

View File

@ -5,6 +5,7 @@
#pragma once
#include "asl/base/integers.hpp"
#include "asl/base/float.hpp"
#include "asl/base/bit.hpp"
#include "asl/base/meta.hpp"
#include "asl/base/assert.hpp"
@ -54,5 +55,47 @@ constexpr T clamp(T x, T a, T b)
return min(max(x, a), b);
}
constexpr float32_t abs(float32_t x) { return __builtin_fabsf(x); }
constexpr float64_t abs(float64_t x) { return __builtin_fabs(x); }
template<is_floating_point T>
bool are_nearly_equal(T a, T b)
{
// This is a fast path for identical values and correctly handles
// the case where +0.0 == -0.0.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wfloat-equal"
if (a == b) { return true; }
#pragma clang diagnostic pop
// NaNs are never equal to anything, including themselves.
if (is_nan(a) || is_nan(b)) { return false; }
// Infinities are only equal if they are identical (which is handled by the
// `a == b` check above). If one is infinity and the other is not, they
// are not equal. The relative comparison below would fail with infinities.
if (is_infinity(a) || is_infinity(b)) { return false; }
static constexpr T kMin = float_traits<T>::kSmallest;
static constexpr T kEps = float_traits<T>::kEpsilon;
const T abs_a = abs(a);
const T abs_b = abs(b);
const T abs_diff = abs(a - b);
// The relative error comparison (`|a-b| <= ε * max(|a|, |b|)`) breaks
// down when `a` and `b` are near zero. In this case, we switch to an
// absolute error comparison. `DBL_MIN` is the smallest positive
// normalized double, so it's a good threshold for this check.
if (abs_a < kMin || abs_b < kMin)
{
return abs_diff < kEps;
}
// For all other cases, we use the standard relative error formula.
// The error is scaled by the magnitude of the numbers.
return abs_diff <= kEps * max(abs_a, abs_b);
}
} // namespace asl

View File

@ -155,8 +155,8 @@ ASL_TEST(pop)
ASL_TEST(pop_destruct)
{
bool d[3]{};
asl::chunked_buffer<DestructorObserver, 16> b;
bool d[3];
b.push(&d[0]);
b.push(&d[1]);

View File

@ -5,6 +5,7 @@
#pragma once
#include "asl/base/integers.hpp"
#include "asl/base/float.hpp"
#include "asl/base/meta.hpp"
#include "asl/io/writer.hpp"
#include "asl/types/span.hpp"
@ -93,8 +94,8 @@ inline void AslFormat(Formatter& f, string_view sv)
f.write(sv);
}
void AslFormat(Formatter& f, float);
void AslFormat(Formatter& f, double);
void AslFormat(Formatter& f, float32_t);
void AslFormat(Formatter& f, float64_t);
void AslFormat(Formatter& f, bool);

View File

@ -6,9 +6,12 @@
#include "asl/base/float.hpp"
#include "asl/base/numeric.hpp"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Weverything"
#define JKJ_STD_REPLACEMENT_NAMESPACE_DEFINED 0
#define JKJ_STATIC_DATA_SECTION_DEFINED 0
#include <dragonbox.h>
#pragma clang diagnostic pop
static constexpr isize_t kZeroCount = 100;
static constexpr char kZeros[kZeroCount] = {
@ -24,12 +27,12 @@ static constexpr char kZeros[kZeroCount] = {
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
};
static constexpr bool is_zero(float x)
static constexpr bool is_zero(float32_t x)
{
return (asl::bit_cast<uint32_t>(x) & 0x7fff'ffffU) == 0;
}
static constexpr bool is_zero(double x)
static constexpr bool is_zero(float64_t x)
{
return (asl::bit_cast<uint64_t>(x) & 0x7fff'ffff'ffff'ffffULL) == 0;
}
@ -102,12 +105,12 @@ static void format_float(asl::Formatter& f, T value)
}
}
void asl::AslFormat(Formatter& f, float value)
void asl::AslFormat(Formatter& f, float32_t value)
{
format_float(f, value);
}
void asl::AslFormat(Formatter& f, double value)
void asl::AslFormat(Formatter& f, float64_t value)
{
format_float(f, value);
}

View File

@ -79,7 +79,7 @@ ASL_TEST(format_floats)
s = asl::format_to_string("{}", 123e-8);
ASL_TEST_EXPECT(s == "0.00000123"_sv);
s = asl::format_to_string("{} {}", asl::infinity<float>(), -asl::infinity<double>());
s = asl::format_to_string("{} {}", asl::infinity<float32_t>(), -asl::infinity<float64_t>());
ASL_TEST_EXPECT(s == "Infinity -Infinity"_sv);
s = asl::format_to_string("{}", asl::nan<float>());

View File

@ -35,8 +35,8 @@ class DenseHandlePool
T obj;
template<typename... Args>
explicit Slot(ThisIndexPool::handle h, Args&&... args)
: h{h}
explicit Slot(ThisIndexPool::handle h_, Args&&... args)
: h{h_}
, obj(std::forward<Args>(args)...)
{}
};

View File

@ -252,7 +252,8 @@ public:
[[nodiscard]] bool is_full() const
{
return m_first_available.is_null() && m_slots.size() > config::kMaxIndex;
return m_first_available.is_null()
&& static_cast<uint64_t>(m_slots.size()) > config::kMaxIndex;
}
option<handle> acquire()

View File

@ -12,14 +12,14 @@ bool parse_double_impl(const char** begin, const char* end, double*);
} // namespace asl
asl::status_or<asl::parse_number_result<float>> asl::parse_float(asl::string_view sv)
asl::status_or<asl::parse_number_result<float32_t>> asl::parse_float32(asl::string_view sv)
{
const auto* begin = sv.data();
// NOLINTNEXTLINE(*-pointer-arithmetic)
const auto* end = begin + sv.size();
if (float value{}; parse_float_impl(&begin, end, &value))
if (float32_t value{}; parse_float_impl(&begin, end, &value))
{
return parse_number_result<float>{
return parse_number_result<float32_t>{
.value = value,
.remaining = string_view{begin, end},
};
@ -27,14 +27,14 @@ asl::status_or<asl::parse_number_result<float>> asl::parse_float(asl::string_vie
return invalid_argument_error();
}
asl::status_or<asl::parse_number_result<double>> asl::parse_double(asl::string_view sv)
asl::status_or<asl::parse_number_result<float64_t>> asl::parse_float64(asl::string_view sv)
{
const auto* begin = sv.data();
// NOLINTNEXTLINE(*-pointer-arithmetic)
const auto* end = begin + sv.size();
if (float value{}; parse_float_impl(&begin, end, &value))
if (float64_t value{}; parse_double_impl(&begin, end, &value))
{
return parse_number_result<double>{
return parse_number_result<float64_t>{
.value = value,
.remaining = string_view{begin, end},
};
@ -96,7 +96,7 @@ asl::status_or<asl::parse_number_result<T>> parse_integer(asl::string_view sv, i
if (asl::is_signed_integer<T> && is_negative)
{
digit = static_cast<T>(-digit);
digit = static_cast<int8_t>(-digit);
}
if (__builtin_add_overflow(value, static_cast<T>(digit), &value))

View File

@ -6,6 +6,7 @@
#include "asl/types/status_or.hpp"
#include "asl/strings/string_view.hpp"
#include "asl/base/float.hpp"
namespace asl
{
@ -17,8 +18,8 @@ struct parse_number_result
string_view remaining;
};
status_or<parse_number_result<float>> parse_float(string_view);
status_or<parse_number_result<double>> parse_double(string_view);
status_or<parse_number_result<float32_t>> parse_float32(string_view);
status_or<parse_number_result<float64_t>> parse_float64(string_view);
status_or<parse_number_result<uint8_t>> parse_uint8(string_view, int base = 10);
status_or<parse_number_result<uint16_t>> parse_uint16(string_view, int base = 10);

View File

@ -2,13 +2,18 @@
//
// SPDX-License-Identifier: BSD-3-Clause
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Weverything"
#include <fast_float.h>
#pragma clang diagnostic pop
// We need to isolate fast_float.h completely from asl
// because it conflicts with our redefinitions of things
// from the STL. In this case it's operator new, but there
// might be other conflicts.
#pragma clang diagnostic ignored "-Wmissing-prototypes"
namespace asl
{

View File

@ -3,38 +3,36 @@
// SPDX-License-Identifier: BSD-3-Clause
#include "asl/strings/parse_number.hpp"
#include "asl/base/numeric.hpp"
#include "asl/testing/testing.hpp"
// @Todo Once we have an equivalent of std::numeric_limits,
// properly compare floating point values in these tests.
ASL_TEST(parse_float_error)
{
const asl::string_view sv = "this is not a number lmao";
auto res = asl::parse_float(sv);
auto res = asl::parse_float32(sv);
ASL_TEST_EXPECT(!res.ok());
}
ASL_TEST(parse_float_empty)
{
const asl::string_view sv = "";
auto res = asl::parse_float(sv);
auto res = asl::parse_float32(sv);
ASL_TEST_EXPECT(!res.ok());
}
ASL_TEST(parse_float_simple)
{
const asl::string_view sv = "3.1415";
auto res = asl::parse_float(sv);
auto res = asl::parse_float32(sv);
ASL_TEST_EXPECT(res.ok());
ASL_TEST_EXPECT(res.value().value == 3.1415F);
ASL_TEST_EXPECT(asl::are_nearly_equal(res.value().value, 3.1415F));
ASL_TEST_EXPECT(res.value().remaining.size() == 0);
}
ASL_TEST(parse_float_integer)
{
const asl::string_view sv = "31415";
auto res = asl::parse_float(sv);
auto res = asl::parse_float32(sv);
ASL_TEST_EXPECT(res.ok());
ASL_TEST_EXPECT(res.value().value == 31415.0F);
ASL_TEST_EXPECT(res.value().remaining.size() == 0);
@ -43,18 +41,18 @@ ASL_TEST(parse_float_integer)
ASL_TEST(parse_float_scientific)
{
const asl::string_view sv = "314.15e-2";
auto res = asl::parse_float(sv);
auto res = asl::parse_float32(sv);
ASL_TEST_EXPECT(res.ok());
ASL_TEST_EXPECT(res.value().value == 3.1415F);
ASL_TEST_EXPECT(asl::are_nearly_equal(res.value().value, 3.1415F));
ASL_TEST_EXPECT(res.value().remaining.size() == 0);
}
ASL_TEST(parse_float_suffix)
{
const asl::string_view sv = "3.1415 yoyoyo";
auto res = asl::parse_float(sv);
auto res = asl::parse_float32(sv);
ASL_TEST_EXPECT(res.ok());
ASL_TEST_EXPECT(res.value().value == 3.1415F);
ASL_TEST_EXPECT(asl::are_nearly_equal(res.value().value, 3.1415F));
ASL_TEST_EXPECT(res.value().remaining == " yoyoyo");
}