Skip to content

Commit 6439428

Browse files
committed
fixup! [libc][math][c23] Add f16divf C23 math function
Fix and optimize exception signaling, and fix missing include.
1 parent 771a449 commit 6439428

File tree

4 files changed

+24
-14
lines changed

4 files changed

+24
-14
lines changed

libc/src/__support/FPUtil/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ add_header_library(
199199
HDRS
200200
dyadic_float.h
201201
DEPENDS
202+
.fenv_impl
202203
.fp_bits
203204
.multiply_add
204205
libc.src.__support.CPP.type_traits

libc/src/__support/FPUtil/dyadic_float.h

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_DYADIC_FLOAT_H
1010
#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_DYADIC_FLOAT_H
1111

12+
#include "FEnvImpl.h"
1213
#include "FPBits.h"
1314
#include "multiply_add.h"
1415
#include "src/__support/CPP/type_traits.h"
@@ -86,11 +87,11 @@ template <size_t Bits> struct DyadicFloat {
8687

8788
// Assume that it is already normalized.
8889
// Output is rounded correctly with respect to the current rounding mode.
89-
template <typename T,
90+
template <typename T, bool ShouldSignalExceptions,
9091
typename = cpp::enable_if_t<cpp::is_floating_point_v<T> &&
9192
(FPBits<T>::FRACTION_LEN < Bits),
9293
void>>
93-
LIBC_INLINE explicit constexpr operator T() const {
94+
LIBC_INLINE constexpr T as() const {
9495
if (LIBC_UNLIKELY(mantissa.is_zero()))
9596
return FPBits<T>::zero(sign).get_val();
9697

@@ -110,7 +111,14 @@ template <size_t Bits> struct DyadicFloat {
110111
// volatile prevents constant propagation that would result in infinity
111112
// always being returned no matter the current rounding mode.
112113
volatile T two(2.0);
113-
return two * d_hi;
114+
T r = two * d_hi;
115+
116+
// TODO: Whether rounding down the absolute value to max_normal should
117+
// also raise FE_OVERFLOW and set ERANGE is debatable.
118+
if (ShouldSignalExceptions && FPBits<T>(r).is_inf())
119+
set_errno_if_required(ERANGE);
120+
121+
return r;
114122
}
115123

116124
bool denorm = false;
@@ -192,8 +200,10 @@ template <size_t Bits> struct DyadicFloat {
192200
// "tininess" before or after rounding for base-2 formats, as long as
193201
// the same choice is made for all operations. Our choice to check after
194202
// rounding might not be the same as the hardware's.
195-
if (round_and_sticky)
203+
if (ShouldSignalExceptions && round_and_sticky) {
204+
set_errno_if_required(ERANGE);
196205
raise_except_if_required(FE_UNDERFLOW);
206+
}
197207
}
198208

199209
return FPBits<T>(r_bits).get_val();
@@ -202,6 +212,14 @@ template <size_t Bits> struct DyadicFloat {
202212
return r;
203213
}
204214

215+
template <typename T,
216+
typename = cpp::enable_if_t<cpp::is_floating_point_v<T> &&
217+
(FPBits<T>::FRACTION_LEN < Bits),
218+
void>>
219+
LIBC_INLINE explicit constexpr operator T() const {
220+
return as<T, /*ShouldSignalExceptions=*/false>();
221+
}
222+
205223
LIBC_INLINE explicit constexpr operator MantissaType() const {
206224
if (mantissa.is_zero())
207225
return 0;

libc/src/__support/FPUtil/generic/div.h

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -116,12 +116,7 @@ div(InType x, InType y) {
116116
DyadicFloat result(result_sign, result_exp, q);
117117
result.mantissa += r != 0;
118118

119-
OutType output = static_cast<OutType>(result);
120-
121-
if (test_except(FE_OVERFLOW | FE_UNDERFLOW) != 0)
122-
set_errno_if_required(ERANGE);
123-
124-
return output;
119+
return result.template as<OutType, /*ShouldSignalExceptions=*/true>();
125120
}
126121

127122
} // namespace LIBC_NAMESPACE::fputil::generic

libc/test/src/math/smoke/DivTest.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,9 @@ class DivTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
107107
if (ForceRoundingMode r(RoundingMode::TowardZero); r.success) {
108108
EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, func(max_normal, min_normal),
109109
FE_OVERFLOW | FE_INEXACT);
110-
EXPECT_MATH_ERRNO(ERANGE);
111110
EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal,
112111
func(neg_max_normal, min_denormal),
113112
FE_OVERFLOW | FE_INEXACT);
114-
EXPECT_MATH_ERRNO(ERANGE);
115113

116114
EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(min_denormal, max_normal),
117115
FE_UNDERFLOW | FE_INEXACT);
@@ -124,7 +122,6 @@ class DivTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
124122
if (ForceRoundingMode r(RoundingMode::Downward); r.success) {
125123
EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, func(max_normal, min_normal),
126124
FE_OVERFLOW | FE_INEXACT);
127-
EXPECT_MATH_ERRNO(ERANGE);
128125
EXPECT_FP_EQ_WITH_EXCEPTION(-inf, func(neg_max_normal, min_denormal),
129126
FE_OVERFLOW | FE_INEXACT);
130127
EXPECT_MATH_ERRNO(ERANGE);
@@ -145,7 +142,6 @@ class DivTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
145142
EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal,
146143
func(neg_max_normal, min_denormal),
147144
FE_OVERFLOW | FE_INEXACT);
148-
EXPECT_MATH_ERRNO(ERANGE);
149145

150146
EXPECT_FP_EQ_WITH_EXCEPTION(min_denormal, func(min_denormal, max_normal),
151147
FE_UNDERFLOW | FE_INEXACT);

0 commit comments

Comments
 (0)