Skip to content

Commit a905cc8

Browse files
committed
Add tests for all the floating point functions
1 parent cea8b18 commit a905cc8

File tree

4 files changed

+744
-50
lines changed

4 files changed

+744
-50
lines changed

num/__private/float_macros.h

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -303,9 +303,6 @@
303303
* Returns NaN if both `self` and `other` are 0. \
304304
*/ \
305305
inline T atan2(const T& other) const& noexcept { \
306-
if (primitive_value == PrimitiveT{0} && \
307-
other.primitive_value == PrimitiveT{0}) [[unlikely]] \
308-
return TODO_NAN(); \
309306
/* MSVC atan2(float) is returning a double for some reason. */ \
310307
return static_cast<PrimitiveT>( \
311308
::atan2(primitive_value, other.primitive_value)); \
@@ -465,8 +462,7 @@
465462
* `0.0`. \
466463
*/ \
467464
inline T round() const& noexcept { \
468-
/* MSVC round(float) is returning a double for some reason. */ \
469-
return static_cast<PrimitiveT>(::round(primitive_value)); \
465+
return __private::float_round(primitive_value); \
470466
} \
471467
/** Returns a number that represents the sign of self. \
472468
* \
@@ -522,7 +518,7 @@
522518
/** Returns the integer part of self. This means that non-integer numbers \
523519
* are always truncated towards zero. \
524520
*/ \
525-
inline T truc() const& noexcept { \
521+
inline T trunc() const& noexcept { \
526522
return __private::truncate_float(primitive_value); \
527523
} \
528524
static_assert(true)
@@ -532,7 +528,8 @@
532528
*/ \
533529
inline T to_degrees() const& noexcept { \
534530
/* Use a constant for better precision. */ \
535-
constexpr float PIS_IN_180 = 57.2957795130823208767981548141051703f; \
531+
constexpr auto PIS_IN_180 = \
532+
PrimitiveT{57.2957795130823208767981548141051703}; \
536533
return primitive_value * PIS_IN_180; \
537534
} \
538535
/** Converts degrees to radians. \
@@ -549,30 +546,33 @@
549546
} \
550547
static_assert(true)
551548

552-
#define _sus__float_bytes(T, UnsignedIntT) \
553-
/** Raw transmutation from `##UnsignedIntT##`. \
554-
* \
555-
* Note that this function is distinct from Into<##T##>, which attempts to \
556-
* preserve the numeric value, and not the bitwise value. \
557-
* \
558-
* # Examples \
559-
* ``` \
560-
* auto v = f32::from_bits(0x41480000); \
561-
* sus::check!(v, 12.5); \
562-
* ``` \
563-
*/ \
564-
static T from_bits(const UnsignedIntT& v) noexcept { \
565-
return std::bit_cast<T>(v); \
566-
} \
567-
/** Raw transmutation to ##UnsignedT##. \
568-
* \
569-
* Note that this function is distinct from Into<##UnsignedIntT##>, which \
570-
* attempts to preserve the numeric value, and not the bitwise value. \
571-
*/ \
572-
constexpr inline UnsignedIntT to_bits() const& noexcept { \
573-
return std::bit_cast<decltype(UnsignedIntT::primitive_value)>( \
574-
primitive_value); \
575-
} \
549+
#define _sus__float_bytes(T, UnsignedIntT) \
550+
/** Raw transmutation from `##UnsignedIntT##`. \
551+
* \
552+
* Note that this function is distinct from Into<##T##>, which attempts to \
553+
* preserve the numeric value, and not the bitwise value. \
554+
* \
555+
* # Examples \
556+
* ``` \
557+
* auto v = f32::from_bits(0x41480000); \
558+
* sus::check!(v, 12.5); \
559+
* ``` \
560+
* \
561+
* This function is not constexpr, as converting to a float does not always \
562+
* preserve the exact bits in a NaN in a constexpr context. \
563+
*/ \
564+
static T from_bits(const UnsignedIntT& v) noexcept { \
565+
return std::bit_cast<T>(v); \
566+
} \
567+
/** Raw transmutation to ##UnsignedT##. \
568+
* \
569+
* Note that this function is distinct from Into<##UnsignedIntT##>, which \
570+
* attempts to preserve the numeric value, and not the bitwise value. \
571+
*/ \
572+
constexpr inline UnsignedIntT to_bits() const& noexcept { \
573+
return std::bit_cast<decltype(UnsignedIntT::primitive_value)>( \
574+
primitive_value); \
575+
} \
576576
static_assert(true)
577577

578578
// clamp

num/__private/intrinsics.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1233,11 +1233,23 @@ constexpr T truncate_float(T x) noexcept {
12331233
template <class T>
12341234
requires(std::is_floating_point_v<T> && sizeof(T) <= 8)
12351235
constexpr T float_signum(T x) noexcept {
1236-
// TODO: Can this be done without a branch?
1236+
// TODO: Can this be done without a branch? Beware nan values in constexpr
1237+
// context are rewritten.
12371238
if (float_is_nan(x)) [[unlikely]]
12381239
return x;
12391240
const auto signbit = unchecked_and(into_unsigned_integer(x), high_bit<T>());
12401241
return into_float(unchecked_add(into_unsigned_integer(T{1}), signbit));
12411242
}
12421243

1244+
template <class T>
1245+
requires(std::is_floating_point_v<T> && sizeof(T) <= 8)
1246+
inline T float_round(T x) noexcept {
1247+
/* MSVC round(float) is returning a double for some reason. */
1248+
const auto out = into_unsigned_integer(static_cast<T>(::round(x)));
1249+
// `round()` doesn't preserve the sign bit, so we need to restore it, for
1250+
// (-0.5, -0.0].
1251+
return into_float((out & ~high_bit<T>()) |
1252+
(into_unsigned_integer(x) & high_bit<T>()));
1253+
}
1254+
12431255
} // namespace sus::num::__private

0 commit comments

Comments
 (0)