Fix a bunch of warnings
This commit is contained in:
@ -12,9 +12,36 @@ using float64_t = double;
|
|||||||
namespace asl
|
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); }
|
template<is_floating_point T> constexpr bool is_infinity(T f) { return __builtin_isinf(f); }
|
||||||
|
|
||||||
|
@ -42,11 +42,11 @@ enum class byte : uint8_t {};
|
|||||||
|
|
||||||
template<typename T> struct integer_traits {};
|
template<typename T> struct integer_traits {};
|
||||||
|
|
||||||
#define ASL_INTEGER_TRAITS(T, MIN, MAX) \
|
#define ASL_INTEGER_TRAITS(T, MIN, MAX) \
|
||||||
template<> struct integer_traits<T> \
|
template<> struct integer_traits<T> \
|
||||||
{ \
|
{ \
|
||||||
static constexpr T kMin = MIN; \
|
static constexpr T kMin{static_cast<T>(MIN)}; \
|
||||||
static constexpr T kMax = MAX; \
|
static constexpr T kMax{static_cast<T>(MAX)}; \
|
||||||
}
|
}
|
||||||
|
|
||||||
ASL_INTEGER_TRAITS(uint8_t, 0, 0xff);
|
ASL_INTEGER_TRAITS(uint8_t, 0, 0xff);
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "asl/base/integers.hpp"
|
#include "asl/base/integers.hpp"
|
||||||
|
#include "asl/base/float.hpp"
|
||||||
#include "asl/base/bit.hpp"
|
#include "asl/base/bit.hpp"
|
||||||
#include "asl/base/meta.hpp"
|
#include "asl/base/meta.hpp"
|
||||||
#include "asl/base/assert.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);
|
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
|
} // namespace asl
|
||||||
|
|
||||||
|
@ -155,8 +155,8 @@ ASL_TEST(pop)
|
|||||||
|
|
||||||
ASL_TEST(pop_destruct)
|
ASL_TEST(pop_destruct)
|
||||||
{
|
{
|
||||||
|
bool d[3]{};
|
||||||
asl::chunked_buffer<DestructorObserver, 16> b;
|
asl::chunked_buffer<DestructorObserver, 16> b;
|
||||||
bool d[3];
|
|
||||||
|
|
||||||
b.push(&d[0]);
|
b.push(&d[0]);
|
||||||
b.push(&d[1]);
|
b.push(&d[1]);
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "asl/base/integers.hpp"
|
#include "asl/base/integers.hpp"
|
||||||
|
#include "asl/base/float.hpp"
|
||||||
#include "asl/base/meta.hpp"
|
#include "asl/base/meta.hpp"
|
||||||
#include "asl/io/writer.hpp"
|
#include "asl/io/writer.hpp"
|
||||||
#include "asl/types/span.hpp"
|
#include "asl/types/span.hpp"
|
||||||
@ -93,8 +94,8 @@ inline void AslFormat(Formatter& f, string_view sv)
|
|||||||
f.write(sv);
|
f.write(sv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AslFormat(Formatter& f, float);
|
void AslFormat(Formatter& f, float32_t);
|
||||||
void AslFormat(Formatter& f, double);
|
void AslFormat(Formatter& f, float64_t);
|
||||||
|
|
||||||
void AslFormat(Formatter& f, bool);
|
void AslFormat(Formatter& f, bool);
|
||||||
|
|
||||||
|
@ -6,9 +6,12 @@
|
|||||||
#include "asl/base/float.hpp"
|
#include "asl/base/float.hpp"
|
||||||
#include "asl/base/numeric.hpp"
|
#include "asl/base/numeric.hpp"
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Weverything"
|
||||||
#define JKJ_STD_REPLACEMENT_NAMESPACE_DEFINED 0
|
#define JKJ_STD_REPLACEMENT_NAMESPACE_DEFINED 0
|
||||||
#define JKJ_STATIC_DATA_SECTION_DEFINED 0
|
#define JKJ_STATIC_DATA_SECTION_DEFINED 0
|
||||||
#include <dragonbox.h>
|
#include <dragonbox.h>
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
static constexpr isize_t kZeroCount = 100;
|
static constexpr isize_t kZeroCount = 100;
|
||||||
static constexpr char kZeros[kZeroCount] = {
|
static constexpr char kZeros[kZeroCount] = {
|
||||||
@ -24,12 +27,12 @@ static constexpr char kZeros[kZeroCount] = {
|
|||||||
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
|
'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;
|
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;
|
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);
|
format_float(f, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void asl::AslFormat(Formatter& f, double value)
|
void asl::AslFormat(Formatter& f, float64_t value)
|
||||||
{
|
{
|
||||||
format_float(f, value);
|
format_float(f, value);
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ ASL_TEST(format_floats)
|
|||||||
s = asl::format_to_string("{}", 123e-8);
|
s = asl::format_to_string("{}", 123e-8);
|
||||||
ASL_TEST_EXPECT(s == "0.00000123"_sv);
|
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);
|
ASL_TEST_EXPECT(s == "Infinity -Infinity"_sv);
|
||||||
|
|
||||||
s = asl::format_to_string("{}", asl::nan<float>());
|
s = asl::format_to_string("{}", asl::nan<float>());
|
||||||
|
@ -35,8 +35,8 @@ class DenseHandlePool
|
|||||||
T obj;
|
T obj;
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
explicit Slot(ThisIndexPool::handle h, Args&&... args)
|
explicit Slot(ThisIndexPool::handle h_, Args&&... args)
|
||||||
: h{h}
|
: h{h_}
|
||||||
, obj(std::forward<Args>(args)...)
|
, obj(std::forward<Args>(args)...)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
@ -252,7 +252,8 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] bool is_full() const
|
[[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()
|
option<handle> acquire()
|
||||||
|
@ -12,14 +12,14 @@ bool parse_double_impl(const char** begin, const char* end, double*);
|
|||||||
|
|
||||||
} // namespace asl
|
} // 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();
|
const auto* begin = sv.data();
|
||||||
// NOLINTNEXTLINE(*-pointer-arithmetic)
|
// NOLINTNEXTLINE(*-pointer-arithmetic)
|
||||||
const auto* end = begin + sv.size();
|
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,
|
.value = value,
|
||||||
.remaining = string_view{begin, end},
|
.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();
|
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();
|
const auto* begin = sv.data();
|
||||||
// NOLINTNEXTLINE(*-pointer-arithmetic)
|
// NOLINTNEXTLINE(*-pointer-arithmetic)
|
||||||
const auto* end = begin + sv.size();
|
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,
|
.value = value,
|
||||||
.remaining = string_view{begin, end},
|
.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)
|
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))
|
if (__builtin_add_overflow(value, static_cast<T>(digit), &value))
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "asl/types/status_or.hpp"
|
#include "asl/types/status_or.hpp"
|
||||||
#include "asl/strings/string_view.hpp"
|
#include "asl/strings/string_view.hpp"
|
||||||
|
#include "asl/base/float.hpp"
|
||||||
|
|
||||||
namespace asl
|
namespace asl
|
||||||
{
|
{
|
||||||
@ -17,8 +18,8 @@ struct parse_number_result
|
|||||||
string_view remaining;
|
string_view remaining;
|
||||||
};
|
};
|
||||||
|
|
||||||
status_or<parse_number_result<float>> parse_float(string_view);
|
status_or<parse_number_result<float32_t>> parse_float32(string_view);
|
||||||
status_or<parse_number_result<double>> parse_double(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<uint8_t>> parse_uint8(string_view, int base = 10);
|
||||||
status_or<parse_number_result<uint16_t>> parse_uint16(string_view, int base = 10);
|
status_or<parse_number_result<uint16_t>> parse_uint16(string_view, int base = 10);
|
||||||
|
@ -2,13 +2,18 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Weverything"
|
||||||
#include <fast_float.h>
|
#include <fast_float.h>
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
// We need to isolate fast_float.h completely from asl
|
// We need to isolate fast_float.h completely from asl
|
||||||
// because it conflicts with our redefinitions of things
|
// because it conflicts with our redefinitions of things
|
||||||
// from the STL. In this case it's operator new, but there
|
// from the STL. In this case it's operator new, but there
|
||||||
// might be other conflicts.
|
// might be other conflicts.
|
||||||
|
|
||||||
|
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||||
|
|
||||||
namespace asl
|
namespace asl
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -3,38 +3,36 @@
|
|||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
#include "asl/strings/parse_number.hpp"
|
#include "asl/strings/parse_number.hpp"
|
||||||
|
#include "asl/base/numeric.hpp"
|
||||||
#include "asl/testing/testing.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)
|
ASL_TEST(parse_float_error)
|
||||||
{
|
{
|
||||||
const asl::string_view sv = "this is not a number lmao";
|
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_EXPECT(!res.ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
ASL_TEST(parse_float_empty)
|
ASL_TEST(parse_float_empty)
|
||||||
{
|
{
|
||||||
const asl::string_view sv = "";
|
const asl::string_view sv = "";
|
||||||
auto res = asl::parse_float(sv);
|
auto res = asl::parse_float32(sv);
|
||||||
ASL_TEST_EXPECT(!res.ok());
|
ASL_TEST_EXPECT(!res.ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
ASL_TEST(parse_float_simple)
|
ASL_TEST(parse_float_simple)
|
||||||
{
|
{
|
||||||
const asl::string_view sv = "3.1415";
|
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.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_EXPECT(res.value().remaining.size() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASL_TEST(parse_float_integer)
|
ASL_TEST(parse_float_integer)
|
||||||
{
|
{
|
||||||
const asl::string_view sv = "31415";
|
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.ok());
|
||||||
ASL_TEST_EXPECT(res.value().value == 31415.0F);
|
ASL_TEST_EXPECT(res.value().value == 31415.0F);
|
||||||
ASL_TEST_EXPECT(res.value().remaining.size() == 0);
|
ASL_TEST_EXPECT(res.value().remaining.size() == 0);
|
||||||
@ -43,18 +41,18 @@ ASL_TEST(parse_float_integer)
|
|||||||
ASL_TEST(parse_float_scientific)
|
ASL_TEST(parse_float_scientific)
|
||||||
{
|
{
|
||||||
const asl::string_view sv = "314.15e-2";
|
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.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_EXPECT(res.value().remaining.size() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASL_TEST(parse_float_suffix)
|
ASL_TEST(parse_float_suffix)
|
||||||
{
|
{
|
||||||
const asl::string_view sv = "3.1415 yoyoyo";
|
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.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");
|
ASL_TEST_EXPECT(res.value().remaining == " yoyoyo");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user