HDRS
FEnvImpl.h
DEPENDS
+ libc.include.errno
libc.include.fenv
+ libc.include.math
libc.src.__support.macros.attributes
libc.src.__support.macros.properties.architectures
libc.src.__support.macros.sanitizer
+ libc.src.errno.errno
)
add_header_library(
#include "src/__support/macros/attributes.h" // LIBC_INLINE
#include "src/__support/macros/properties/architectures.h"
+#include <errno.h>
+#include <fenv.h>
+#include <math.h>
+
#if defined(LIBC_TARGET_ARCH_IS_AARCH64)
#if defined(__APPLE__)
#include "aarch64/fenv_darwin_impl.h"
#elif defined(LIBC_TARGET_ARCH_IS_X86)
#include "x86_64/FEnvImpl.h"
#else
-#include <fenv.h>
-namespace __llvm_libc {
-namespace fputil {
+namespace __llvm_libc::fputil {
// All dummy functions silently succeed.
LIBC_INLINE int set_env(const fenv_t *) { return 0; }
-} // namespace fputil
-} // namespace __llvm_libc
+} // namespace __llvm_libc::fputil
#endif
+namespace __llvm_libc::fputil {
+
+LIBC_INLINE int set_except_if_required(int excepts) {
+ if (math_errhandling & MATH_ERREXCEPT)
+ return set_except(excepts);
+ return 0;
+}
+
+LIBC_INLINE int raise_except_if_required(int excepts) {
+ if (math_errhandling & MATH_ERREXCEPT)
+ return raise_except(excepts);
+ return 0;
+}
+
+LIBC_INLINE void set_errno_if_required(int err) {
+ if (math_errhandling & MATH_ERRNO)
+ errno = err;
+}
+
+} // namespace __llvm_libc::fputil
+
#endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_FENVIMPL_H
// |x| > 1, return NaNs.
if (LIBC_UNLIKELY(x_abs > 0x3f80'0000U)) {
if (x_abs <= 0x7f80'0000U) {
- errno = EDOM;
- fputil::set_except(FE_INVALID);
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
}
return x +
FPBits::build_nan(1 << (fputil::MantissaWidth<float>::VALUE - 1));
// |x| > 1, return NaNs.
if (LIBC_UNLIKELY(x_abs > 0x3f80'0000U)) {
if (x_abs <= 0x7f80'0000U) {
- errno = EDOM;
- fputil::set_except(FE_INVALID);
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
}
return x +
FPBits::build_nan(1 << (fputil::MantissaWidth<float>::VALUE - 1));
// x is inf or nan.
if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) {
if (x_abs == 0x7f80'0000U) {
- errno = EDOM;
- fputil::set_except(FE_INVALID);
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
}
return x +
FPBits::build_nan(1 << (fputil::MantissaWidth<float>::VALUE - 1));
if (LIBC_UNLIKELY(rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO))
return FPBits(FPBits::MAX_NORMAL).get_val();
- errno = ERANGE;
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_OVERFLOW);
return x + FPBits::inf().get_val();
}
return x;
if (fputil::get_round() == FE_UPWARD)
return static_cast<float>(FPBits(FPBits::MIN_SUBNORMAL));
- errno = ERANGE;
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_UNDERFLOW);
return 0.0f;
}
// x >= log10(2^128) or nan
if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
return static_cast<float>(FPBits(FPBits::MAX_NORMAL));
- errno = ERANGE;
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_OVERFLOW);
}
// x is +inf or nan
return x + static_cast<float>(FPBits::inf());
if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
return static_cast<float>(FPBits(FPBits::MAX_NORMAL));
- errno = ERANGE;
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_OVERFLOW);
}
// x is +inf or nan
return x + FPBits::inf().get_val();
return x;
if (fputil::get_round() == FE_UPWARD)
return FPBits(FPBits::MIN_SUBNORMAL).get_val();
- if (x != 0.0f)
- errno = ERANGE;
+ if (x != 0.0f) {
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_UNDERFLOW);
+ }
return 0.0f;
}
}
return x;
if (fputil::get_round() == FE_UPWARD)
return static_cast<float>(FPBits(FPBits::MIN_SUBNORMAL));
- errno = ERANGE;
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_UNDERFLOW);
return 0.0f;
}
// x >= 89 or nan
if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
return static_cast<float>(FPBits(FPBits::MAX_NORMAL));
- errno = ERANGE;
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_OVERFLOW);
}
// x is +inf or nan
return x + static_cast<float>(FPBits::inf());
if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
return static_cast<float>(FPBits(FPBits::MAX_NORMAL));
- errno = ERANGE;
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_OVERFLOW);
}
return x + static_cast<float>(FPBits::inf());
}
// x is inf or nan.
if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) {
if (x_abs == 0x7f80'0000U) {
- errno = EDOM;
- fputil::set_except(FE_INVALID);
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
}
*sinp =
x + FPBits::build_nan(1 << (fputil::MantissaWidth<float>::VALUE - 1));
if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) {
if (x_abs == 0x7f80'0000U) {
- errno = EDOM;
- fputil::set_except(FE_INVALID);
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
}
return x +
FPBits::build_nan(1 << (fputil::MantissaWidth<float>::VALUE - 1));
return FPBits(FPBits::MAX_NORMAL).get_val();
}
- errno = ERANGE;
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_OVERFLOW);
return x + FPBits::inf(sign).get_val();
}
// Inf or NaN
if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) {
if (x_abs == 0x7f80'0000U) {
- errno = EDOM;
- fputil::set_except(FE_INVALID);
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
}
return x +
FPBits::build_nan(1 << (fputil::MantissaWidth<float>::VALUE - 1));
TEST(LlvmLibcCoshfTest, Overflow) {
errno = 0;
- EXPECT_FP_EQ(inf, __llvm_libc::coshf(float(FPBits(0x7f7fffffU))));
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ inf, __llvm_libc::coshf(float(FPBits(0x7f7fffffU))), FE_OVERFLOW);
EXPECT_MATH_ERRNO(ERANGE);
- EXPECT_FP_EQ(inf, __llvm_libc::coshf(float(FPBits(0x42cffff8U))));
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ inf, __llvm_libc::coshf(float(FPBits(0x42cffff8U))), FE_OVERFLOW);
EXPECT_MATH_ERRNO(ERANGE);
- EXPECT_FP_EQ(inf, __llvm_libc::coshf(float(FPBits(0x42d00008U))));
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ inf, __llvm_libc::coshf(float(FPBits(0x42d00008U))), FE_OVERFLOW);
EXPECT_MATH_ERRNO(ERANGE);
}
TEST(LlvmLibcExp10fTest, Overflow) {
errno = 0;
- EXPECT_FP_EQ(inf, __llvm_libc::exp10f(float(FPBits(0x7f7fffffU))));
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ inf, __llvm_libc::exp10f(float(FPBits(0x7f7fffffU))), FE_OVERFLOW);
EXPECT_MATH_ERRNO(ERANGE);
- EXPECT_FP_EQ(inf, __llvm_libc::exp10f(float(FPBits(0x43000000U))));
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ inf, __llvm_libc::exp10f(float(FPBits(0x43000000U))), FE_OVERFLOW);
EXPECT_MATH_ERRNO(ERANGE);
- EXPECT_FP_EQ(inf, __llvm_libc::exp10f(float(FPBits(0x43000001U))));
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ inf, __llvm_libc::exp10f(float(FPBits(0x43000001U))), FE_OVERFLOW);
+ EXPECT_MATH_ERRNO(ERANGE);
+}
+
+TEST(LlvmLibcExp10fTest, Underflow) {
+ errno = 0;
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ 0.0f, __llvm_libc::exp10f(float(FPBits(0xff7fffffU))), FE_UNDERFLOW);
+ EXPECT_MATH_ERRNO(ERANGE);
+
+ float x = float(FPBits(0xc2cffff8U));
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp10, x,
+ __llvm_libc::exp10f(x), 0.5);
+ EXPECT_MATH_ERRNO(ERANGE);
+
+ x = float(FPBits(0xc2d00008U));
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp10, x,
+ __llvm_libc::exp10f(x), 0.5);
EXPECT_MATH_ERRNO(ERANGE);
}
TEST(LlvmLibcExp2fTest, Overflow) {
errno = 0;
- EXPECT_FP_EQ(inf, __llvm_libc::exp2f(float(FPBits(0x7f7fffffU))));
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ inf, __llvm_libc::exp2f(float(FPBits(0x7f7fffffU))), FE_OVERFLOW);
EXPECT_MATH_ERRNO(ERANGE);
- EXPECT_FP_EQ(inf, __llvm_libc::exp2f(float(FPBits(0x43000000U))));
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ inf, __llvm_libc::exp2f(float(FPBits(0x43000000U))), FE_OVERFLOW);
EXPECT_MATH_ERRNO(ERANGE);
- EXPECT_FP_EQ(inf, __llvm_libc::exp2f(float(FPBits(0x43000001U))));
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ inf, __llvm_libc::exp2f(float(FPBits(0x43000001U))), FE_OVERFLOW);
EXPECT_MATH_ERRNO(ERANGE);
}
TEST(LlvmLibcExp2fTest, Underflow) {
errno = 0;
- EXPECT_FP_EQ(0.0f, __llvm_libc::exp2f(float(FPBits(0xff7fffffU))));
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ 0.0f, __llvm_libc::exp2f(float(FPBits(0xff7fffffU))), FE_UNDERFLOW);
EXPECT_MATH_ERRNO(ERANGE);
float x = float(FPBits(0xc3158000U));
TEST(LlvmLibcExpfTest, Overflow) {
errno = 0;
- EXPECT_FP_EQ(inf, __llvm_libc::expf(float(FPBits(0x7f7fffffU))));
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ inf, __llvm_libc::expf(float(FPBits(0x7f7fffffU))), FE_OVERFLOW);
EXPECT_MATH_ERRNO(ERANGE);
- EXPECT_FP_EQ(inf, __llvm_libc::expf(float(FPBits(0x42cffff8U))));
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ inf, __llvm_libc::expf(float(FPBits(0x42cffff8U))), FE_OVERFLOW);
EXPECT_MATH_ERRNO(ERANGE);
- EXPECT_FP_EQ(inf, __llvm_libc::expf(float(FPBits(0x42d00008U))));
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ inf, __llvm_libc::expf(float(FPBits(0x42d00008U))), FE_OVERFLOW);
EXPECT_MATH_ERRNO(ERANGE);
}
TEST(LlvmLibcExpfTest, Underflow) {
errno = 0;
- EXPECT_FP_EQ(0.0f, __llvm_libc::expf(float(FPBits(0xff7fffffU))));
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ 0.0f, __llvm_libc::expf(float(FPBits(0xff7fffffU))), FE_UNDERFLOW);
EXPECT_MATH_ERRNO(ERANGE);
float x = float(FPBits(0xc2cffff8U));
TEST(LlvmLibcExpm1fTest, Overflow) {
errno = 0;
- EXPECT_FP_EQ(inf, __llvm_libc::expm1f(float(FPBits(0x7f7fffffU))));
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ inf, __llvm_libc::expm1f(float(FPBits(0x7f7fffffU))), FE_OVERFLOW);
EXPECT_MATH_ERRNO(ERANGE);
- EXPECT_FP_EQ(inf, __llvm_libc::expm1f(float(FPBits(0x42cffff8U))));
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ inf, __llvm_libc::expm1f(float(FPBits(0x42cffff8U))), FE_OVERFLOW);
EXPECT_MATH_ERRNO(ERANGE);
- EXPECT_FP_EQ(inf, __llvm_libc::expm1f(float(FPBits(0x42d00008U))));
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ inf, __llvm_libc::expm1f(float(FPBits(0x42d00008U))), FE_OVERFLOW);
EXPECT_MATH_ERRNO(ERANGE);
}
TEST(LlvmLibcSinhfTest, Overflow) {
errno = 0;
- EXPECT_FP_EQ(inf, __llvm_libc::sinhf(float(FPBits(0x7f7fffffU))));
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ inf, __llvm_libc::sinhf(float(FPBits(0x7f7fffffU))), FE_OVERFLOW);
EXPECT_MATH_ERRNO(ERANGE);
- EXPECT_FP_EQ(inf, __llvm_libc::sinhf(float(FPBits(0x42cffff8U))));
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ inf, __llvm_libc::sinhf(float(FPBits(0x42cffff8U))), FE_OVERFLOW);
EXPECT_MATH_ERRNO(ERANGE);
- EXPECT_FP_EQ(inf, __llvm_libc::sinhf(float(FPBits(0x42d00008U))));
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ inf, __llvm_libc::sinhf(float(FPBits(0x42d00008U))), FE_OVERFLOW);
EXPECT_MATH_ERRNO(ERANGE);
}