Skip to content

Commit

Permalink
Add fmt support to floats
Browse files Browse the repository at this point in the history
  • Loading branch information
danakj committed May 27, 2023
1 parent ee1fe3c commit 19efb70
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 20 deletions.
54 changes: 36 additions & 18 deletions subspace/num/__private/float_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,14 +126,14 @@
#define _sus__float_comparison(T) \
/** sus::ops::Eq<##T##> trait. \
* #[doc.overloads=float##T##.eq] */ \
[[nodiscard]] friend sus_pure constexpr inline bool operator==(const T& l, \
const T& r) noexcept { \
[[nodiscard]] friend sus_pure constexpr inline bool operator==( \
const T& l, const T& r) noexcept { \
return (l.primitive_value <=> r.primitive_value) == 0; \
} \
/** sus::ops::PartialOrd<##T##> trait. \
* #[doc.overloads=float##T##.ord] */ \
[[nodiscard]] friend sus_pure constexpr inline auto operator<=>(const T& l, \
const T& r) noexcept { \
[[nodiscard]] friend sus_pure constexpr inline auto operator<=>( \
const T& l, const T& r) noexcept { \
return l.primitive_value <=> r.primitive_value; \
} \
/** Return the ordering between self and other. \
Expand Down Expand Up @@ -178,26 +178,26 @@
#define _sus__float_binary_ops(T) \
/** sus::num::Add<##T##> trait. \
* #[doc.overloads=float##T##.+] */ \
[[nodiscard]] friend sus_pure constexpr inline T operator+(const T& l, \
const T& r) noexcept { \
[[nodiscard]] friend sus_pure constexpr inline T operator+( \
const T& l, const T& r) noexcept { \
return l.primitive_value + r.primitive_value; \
} \
/** sus::num::Sub<##T##> trait. \
* #[doc.overloads=float##T##.-] */ \
[[nodiscard]] friend sus_pure constexpr inline T operator-(const T& l, \
const T& r) noexcept { \
[[nodiscard]] friend sus_pure constexpr inline T operator-( \
const T& l, const T& r) noexcept { \
return l.primitive_value - r.primitive_value; \
} \
/** sus::num::Mul<##T##> trait. \
* #[doc.overloads=float##T##.*] */ \
[[nodiscard]] friend sus_pure constexpr inline T operator*(const T& l, \
const T& r) noexcept { \
[[nodiscard]] friend sus_pure constexpr inline T operator*( \
const T& l, const T& r) noexcept { \
return l.primitive_value * r.primitive_value; \
} \
/** sus::num::Div<##T##> trait. \
* #[doc.overloads=float##T##./] */ \
[[nodiscard]] friend sus_pure constexpr inline T operator/(const T& l, \
const T& r) noexcept { \
[[nodiscard]] friend sus_pure constexpr inline T operator/( \
const T& l, const T& r) noexcept { \
return l.primitive_value / r.primitive_value; \
} \
/** sus::num::Rem<##T##> trait. \
Expand All @@ -208,8 +208,8 @@
* `l - (l / r).trunc() * r`. \
* \
* #[doc.overloads=float##T##.%] */ \
[[nodiscard]] friend sus_pure constexpr inline T operator%(const T& l, \
const T& r) noexcept { \
[[nodiscard]] friend sus_pure constexpr inline T operator%( \
const T& l, const T& r) noexcept { \
const auto x = l.primitive_value; \
const auto y = r.primitive_value; \
return x - __private::truncate_float(x / y) * y; \
Expand Down Expand Up @@ -809,15 +809,33 @@

#define _sus__float_hash_equal_to(T) \
template <> \
struct hash<T> { \
sus_pure auto operator()(const T& u) const { \
struct hash<::sus::num::T> { \
sus_pure auto operator()(::sus::num::T u) const { \
return std::hash<decltype(u.primitive_value)>()(u.primitive_value); \
} \
}; \
template <> \
struct equal_to<T> { \
sus_pure constexpr auto operator()(const T& l, const T& r) const { \
struct equal_to<::sus::num::T> { \
sus_pure constexpr auto operator()(::sus::num::T l, \
::sus::num::T r) const { \
return l == r; \
} \
}; \
static_assert(true)

// fmt support.
#define _sus__float_fmt(T) \
template <typename Char> \
struct formatter<::sus::num::T, Char> { \
template <typename ParseContext> \
constexpr decltype(auto) parse(ParseContext& ctx) { \
return ctx.begin(); \
} \
\
template <typename FormatContext> \
constexpr auto format(::sus::num::T t, FormatContext& ctx) const { \
auto out = ctx.out(); \
out = detail::write<Char>(out, t.primitive_value); \
return out; \
} \
};
5 changes: 5 additions & 0 deletions subspace/num/f32_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1095,4 +1095,9 @@ TEST(f32, FromNeBytes) {
}
}

TEST(f32, fmt) {
EXPECT_EQ(fmt::format("{}", -123.456_f32), "-123.456");
EXPECT_EQ(fmt::format("{}", 1234.567_f32), "1234.567");
}

} // namespace
5 changes: 5 additions & 0 deletions subspace/num/f64_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1068,4 +1068,9 @@ TEST(f64, FromNeBytes) {
}
}

TEST(f64, fmt) {
EXPECT_EQ(fmt::format("{}", -123789.456_f64), "-123789.456");
EXPECT_EQ(fmt::format("{}", 1234890.567_f64), "1234890.567");
}

} // namespace
9 changes: 7 additions & 2 deletions subspace/num/float.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <concepts>
#include <functional> // TODO: remove this but we need to hash things > size_t.

#include "fmt/format.h"
#include "subspace/macros/__private/compiler_bugs.h"
#include "subspace/macros/pure.h"
#include "subspace/marker/unsafe.h"
Expand Down Expand Up @@ -59,9 +60,13 @@ struct f64 final {
} // namespace sus::num

namespace std {
_sus__float_hash_equal_to(::sus::num::f32);
_sus__float_hash_equal_to(::sus::num::f64);
_sus__float_hash_equal_to(f32);
_sus__float_hash_equal_to(f64);
} // namespace std
namespace fmt {
_sus__float_fmt(f32);
_sus__float_fmt(f64);
} // namespace fmt

_sus__float_literal(f32, ::sus::num::f32);
_sus__float_literal(f64, ::sus::num::f64);
Expand Down

0 comments on commit 19efb70

Please sign in to comment.