Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libc][math][c23] Add logf16 C23 math function #106072

Merged
merged 5 commits into from
Oct 18, 2024

Conversation

overmighty
Copy link
Member

Part of #95250.

@llvmbot
Copy link
Member

llvmbot commented Aug 26, 2024

@llvm/pr-subscribers-libc

Author: OverMighty (overmighty)

Changes

Part of #95250.


Full diff: https://github.com/llvm/llvm-project/pull/106072.diff

14 Files Affected:

  • (modified) libc/config/gpu/entrypoints.txt (+1)
  • (modified) libc/config/linux/x86_64/entrypoints.txt (+1)
  • (modified) libc/docs/math/index.rst (+1-1)
  • (modified) libc/spec/stdc.td (+1)
  • (modified) libc/src/math/CMakeLists.txt (+1)
  • (modified) libc/src/math/generic/CMakeLists.txt (+22)
  • (modified) libc/src/math/generic/expxf16.h (+26)
  • (added) libc/src/math/generic/logf16.cpp (+158)
  • (added) libc/src/math/logf16.h (+21)
  • (modified) libc/test/UnitTest/FPMatcher.h (+13)
  • (modified) libc/test/src/math/CMakeLists.txt (+11)
  • (added) libc/test/src/math/logf16_test.cpp (+40)
  • (modified) libc/test/src/math/smoke/CMakeLists.txt (+12)
  • (added) libc/test/src/math/smoke/logf16_test.cpp (+47)
diff --git a/libc/config/gpu/entrypoints.txt b/libc/config/gpu/entrypoints.txt
index b206bb7c936f39..e6a8e381a9212a 100644
--- a/libc/config/gpu/entrypoints.txt
+++ b/libc/config/gpu/entrypoints.txt
@@ -532,6 +532,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.llrintf16
     libc.src.math.llroundf16
     libc.src.math.logbf16
+    libc.src.math.logf16
     libc.src.math.lrintf16
     libc.src.math.lroundf16
     libc.src.math.modff16
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index b702a7ff482a5c..69944ce3904562 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -643,6 +643,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.llrintf16
     libc.src.math.llroundf16
     libc.src.math.logbf16
+    libc.src.math.logf16
     libc.src.math.lrintf16
     libc.src.math.lroundf16
     libc.src.math.modff16
diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst
index de88f14426799f..e958312b313589 100644
--- a/libc/docs/math/index.rst
+++ b/libc/docs/math/index.rst
@@ -306,7 +306,7 @@ Higher Math Functions
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
 | lgamma    |                  |                 |                        |                      |                        | 7.12.8.3               | F.10.5.3                   |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
-| log       | |check|          | |check|         |                        |                      |                        | 7.12.6.11              | F.10.3.11                  |
+| log       | |check|          | |check|         |                        | |check|              |                        | 7.12.6.11              | F.10.3.11                  |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
 | log10     | |check|          | |check|         |                        |                      |                        | 7.12.6.12              | F.10.3.12                  |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 043762bb227456..c3115b19349ff4 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -565,6 +565,7 @@ def StdC : StandardSpec<"stdc"> {
 
           FunctionSpec<"log", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
           FunctionSpec<"logf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+          GuardedFunctionSpec<"logf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
 
           FunctionSpec<"logb", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
           FunctionSpec<"logbf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index be05903d4a1c6e..47c4ad188ef6df 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -331,6 +331,7 @@ add_math_entrypoint_object(log2f)
 
 add_math_entrypoint_object(log)
 add_math_entrypoint_object(logf)
+add_math_entrypoint_object(logf16)
 
 add_math_entrypoint_object(logb)
 add_math_entrypoint_object(logbf)
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 9534d17426486b..6a9d9f02f190f0 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -2210,6 +2210,28 @@ add_entrypoint_object(
     -O3
 )
 
+add_entrypoint_object(
+  logf16
+  SRCS
+    logf16.cpp
+  HDRS
+    ../logf16.h
+  DEPENDS
+    .expxf16
+    libc.hdr.errno_macros
+    libc.hdr.fenv_macros
+    libc.src.__support.CPP.array
+    libc.src.__support.FPUtil.except_value_utils
+    libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.multiply_add
+    libc.src.__support.FPUtil.polyeval
+    libc.src.__support.macros.optimization
+    libc.src.__support.macros.properties.cpu_features
+  COMPILE_OPTIONS
+    -O3
+)
+
 add_entrypoint_object(
   logb
   SRCS
diff --git a/libc/src/math/generic/expxf16.h b/libc/src/math/generic/expxf16.h
index 3893305d5bfa18..d64bb432811067 100644
--- a/libc/src/math/generic/expxf16.h
+++ b/libc/src/math/generic/expxf16.h
@@ -287,6 +287,32 @@ template <bool IsSinh> LIBC_INLINE float16 eval_sinh_or_cosh(float16 x) {
       lo, half_p_odd * exp2_hi_mid_diff, half_p_even * exp2_hi_mid_sum));
 }
 
+// Generated by Sollya with the following commands:
+//   > display = hexadecimal;
+//   > for i from 0 to 31 do print(round(log(1 + i * 2^-5), SG, RN));
+constexpr cpp::array<float, 32> LOGF_F = {
+    0x0p+0,        0x1.f829bp-6,  0x1.f0a30cp-5, 0x1.6f0d28p-4, 0x1.e27076p-4,
+    0x1.29553p-3,  0x1.5ff308p-3, 0x1.9525aap-3, 0x1.c8ff7cp-3, 0x1.fb9186p-3,
+    0x1.1675cap-2, 0x1.2e8e2cp-2, 0x1.4618bcp-2, 0x1.5d1bdcp-2, 0x1.739d8p-2,
+    0x1.89a338p-2, 0x1.9f323ep-2, 0x1.b44f78p-2, 0x1.c8ff7cp-2, 0x1.dd46ap-2,
+    0x1.f128f6p-2, 0x1.02552ap-1, 0x1.0be72ep-1, 0x1.154c3ep-1, 0x1.1e85f6p-1,
+    0x1.2795e2p-1, 0x1.307d74p-1, 0x1.393e0ep-1, 0x1.41d8fep-1, 0x1.4a4f86p-1,
+    0x1.52a2d2p-1, 0x1.5ad404p-1,
+};
+
+// Generated by Sollya with the following commands:
+//   > display = hexadecimal;
+//   > for i from 0 to 31 do print(round(1 / (1 + i * 2^-5), SG, RN));
+constexpr cpp::array<float, 32> ONE_OVER_F = {
+    0x1p+0,        0x1.f07c2p-1,  0x1.e1e1e2p-1, 0x1.d41d42p-1, 0x1.c71c72p-1,
+    0x1.bacf92p-1, 0x1.af286cp-1, 0x1.a41a42p-1, 0x1.99999ap-1, 0x1.8f9c18p-1,
+    0x1.861862p-1, 0x1.7d05f4p-1, 0x1.745d18p-1, 0x1.6c16c2p-1, 0x1.642c86p-1,
+    0x1.5c9882p-1, 0x1.555556p-1, 0x1.4e5e0ap-1, 0x1.47ae14p-1, 0x1.414142p-1,
+    0x1.3b13b2p-1, 0x1.3521dp-1,  0x1.2f684cp-1, 0x1.29e412p-1, 0x1.24924ap-1,
+    0x1.1f7048p-1, 0x1.1a7b96p-1, 0x1.15b1e6p-1, 0x1.111112p-1, 0x1.0c9714p-1,
+    0x1.08421p-1,  0x1.041042p-1,
+};
+
 } // namespace LIBC_NAMESPACE_DECL
 
 #endif // LLVM_LIBC_SRC_MATH_GENERIC_EXPXF16_H
diff --git a/libc/src/math/generic/logf16.cpp b/libc/src/math/generic/logf16.cpp
new file mode 100644
index 00000000000000..adb24306a0f466
--- /dev/null
+++ b/libc/src/math/generic/logf16.cpp
@@ -0,0 +1,158 @@
+//===-- Half-precision log(x) function ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/math/logf16.h"
+#include "expxf16.h"
+#include "hdr/errno_macros.h"
+#include "hdr/fenv_macros.h"
+#include "src/__support/CPP/array.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/except_value_utils.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h"
+#include "src/__support/macros/properties/cpu_features.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+#ifdef LIBC_TARGET_CPU_HAS_FMA
+static constexpr size_t N_LOGF16_EXCEPTS = 5;
+#else
+static constexpr size_t N_LOGF16_EXCEPTS = 11;
+#endif
+
+static constexpr fputil::ExceptValues<float16, N_LOGF16_EXCEPTS>
+    LOGF16_EXCEPTS = {{
+// (input, RZ output, RU offset, RD offset, RN offset)
+#ifndef LIBC_TARGET_CPU_HAS_FMA
+        // x = 0x1.61cp-13, logf16(x) = -0x1.16p+3 (RZ)
+        {0x0987U, 0xc858U, 0U, 1U, 0U},
+        // x = 0x1.f2p-12, logf16(x) = -0x1.e98p+2 (RZ)
+        {0x0fc8U, 0xc7a6U, 0U, 1U, 1U},
+// x = 0x1.4d4p-9, logf16(x) = -0x1.7e4p+2 (RZ)
+#endif
+        // x = 0x1.4d4p-9, logf16(x) = -0x1.7e4p+2 (RZ)
+        {0x1935U, 0xc5f9U, 0U, 1U, 0U},
+        // x = 0x1.5ep-8, logf16(x) = -0x1.4ecp+2 (RZ)
+        {0x1d78U, 0xc53bU, 0U, 1U, 0U},
+#ifndef LIBC_TARGET_CPU_HAS_FMA
+        // x = 0x1.fdp-1, logf16(x) = -0x1.81p-8 (RZ)
+        {0x3bf4U, 0x9e04U, 0U, 1U, 1U},
+        // x = 0x1.fep-1, logf16(x) = -0x1.008p-8 (RZ)
+        {0x3bf8U, 0x9c02U, 0U, 1U, 0U},
+#endif
+        // x = 0x1.ffp-1, logf16(x) = -0x1.004p-9 (RZ)
+        {0x3bfcU, 0x9801U, 0U, 1U, 0U},
+        // x = 0x1.ff8p-1, logf16(x) = -0x1p-10 (RZ)
+        {0x3bfeU, 0x9400U, 0U, 1U, 1U},
+#ifdef LIBC_TARGET_CPU_HAS_FMA
+        // x = 0x1.4c4p+1, logf16(x) = 0x1.e84p-1 (RZ)
+        {0x4131U, 0x3ba1U, 1U, 0U, 1U},
+#else
+        // x = 0x1.75p+2, logf16(x) = 0x1.c34p+0 (RZ)
+        {0x45d4U, 0x3f0dU, 1U, 0U, 0U},
+        // x = 0x1.75p+2, logf16(x) = 0x1.c34p+0 (RZ)
+        {0x45d4U, 0x3f0dU, 1U, 0U, 0U},
+        // x = 0x1.d5p+9, logf16(x) = 0x1.b5cp+2 (RZ)
+        {0x6354U, 0x46d7U, 1U, 0U, 1U},
+#endif
+    }};
+
+LLVM_LIBC_FUNCTION(float16, logf16, (float16 x)) {
+  using FPBits = fputil::FPBits<float16>;
+  FPBits x_bits(x);
+
+  uint16_t x_u = x_bits.uintval();
+
+  // If x <= 0, or x is 1, or x is +inf, or x is NaN.
+  if (LIBC_UNLIKELY(x_u == 0U || x_u == 0x3c00U || x_u >= 0x7c00U)) {
+    // log(NaN) = NaN
+    if (x_bits.is_nan()) {
+      if (x_bits.is_signaling_nan()) {
+        fputil::raise_except_if_required(FE_INVALID);
+        return FPBits::quiet_nan().get_val();
+      }
+
+      return x;
+    }
+
+    // log(+/-0) = −inf
+    if ((x_u & 0x7fffU) == 0U) {
+      fputil::raise_except_if_required(FE_DIVBYZERO);
+      return FPBits::inf(Sign::NEG).get_val();
+    }
+
+    if (x_u == 0x3c00U)
+      return FPBits::zero().get_val();
+
+    // When x < 0.
+    if (x_u > 0x8000) {
+      fputil::set_errno_if_required(EDOM);
+      fputil::raise_except_if_required(FE_INVALID);
+      return FPBits::quiet_nan().get_val();
+    }
+
+    // log(+inf) = +inf
+    return FPBits::inf().get_val();
+  }
+
+  if (auto r = LOGF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
+    return r.value();
+
+  // To compute log(x), we perform the following range reduction:
+  //   x = 2^m * 1.mant,
+  //   log(x) = m * log(2) + log(1.mant).
+  // To compute log(1.mant), let f be the highest 6 bits including the hidden
+  // bit, and d be the difference (1.mant - f), i.e., the remaining 5 bits of
+  // the mantissa, then:
+  //   log(1.mant) = log(f) + log(1.mant / f)
+  //               = log(f) + log(1 + d/f)
+  // since d/f is sufficiently small.
+  // We store log(f) and 1/f in the lookup tables LOGF_F and ONE_OVER_F
+  // respectively.
+
+  int m = -FPBits::EXP_BIAS;
+
+  // When x is subnormal.
+  if ((x_u & FPBits::EXP_MASK) == 0U) {
+    // Normalize x.
+    x_bits = FPBits(x_bits.get_val() *
+                    static_cast<float16>((1U << FPBits::FRACTION_LEN)));
+    x_u = x_bits.uintval();
+    m -= FPBits::FRACTION_LEN;
+  }
+
+  uint16_t mant = x_bits.get_mantissa();
+  // Leading 10 - 5 = 5 bits of the mantissa.
+  int f = mant >> 5;
+  // Unbiased exponent.
+  m += x_u >> FPBits::FRACTION_LEN;
+
+  // Set bits to 1.mant instead of 2^m * 1.mant.
+  x_bits.set_biased_exponent(FPBits::EXP_BIAS);
+  float mant_f = x_bits.get_val();
+  // v = 1.mant * 1/f - 1 = d/f
+  float v = fputil::multiply_add(mant_f, ONE_OVER_F[f], -1.0f);
+
+  // Degree-3 minimax polynomial generated by Sollya with the following
+  // commands:
+  //   > display = hexadecimal;
+  //   > P = fpminimax(log(1 + x)/x, 2, [|SG...|], [-2^-5, 2^-5]);
+  //   > x * P;
+  float log1p_d_over_f =
+      v * fputil::polyeval(v, 0x1p+0f, -0x1.001804p-1f, 0x1.557ef6p-2f);
+  // log(1.mant) = log(f) + log(1 + d/f)
+  float log_1_mant = LOGF_F[f] + log1p_d_over_f;
+  return static_cast<float16>(
+      fputil::multiply_add(static_cast<float>(m), LOGF_2, log_1_mant));
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/logf16.h b/libc/src/math/logf16.h
new file mode 100644
index 00000000000000..e2d296b1d90881
--- /dev/null
+++ b/libc/src/math/logf16.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for logf16 ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_MATH_LOGF16_H
+#define LLVM_LIBC_SRC_MATH_LOGF16_H
+
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+float16 logf16(float16 x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_LOGF16_H
diff --git a/libc/test/UnitTest/FPMatcher.h b/libc/test/UnitTest/FPMatcher.h
index 43752a4942ad56..9a695885101013 100644
--- a/libc/test/UnitTest/FPMatcher.h
+++ b/libc/test/UnitTest/FPMatcher.h
@@ -266,4 +266,17 @@ template <typename T> struct FPTest : public Test {
   EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_MODE(                                   \
       (expected), (actual), (expected_except), RoundingMode::TowardZero)
 
+#define EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(expected, actual,             \
+                                                 expected_except)              \
+  do {                                                                         \
+    EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_NEAREST((expected), (actual),         \
+                                                 (expected_except));           \
+    EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_UPWARD((expected), (actual),          \
+                                                (expected_except));            \
+    EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_DOWNWARD((expected), (actual),        \
+                                                  (expected_except));          \
+    EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_TOWARD_ZERO((expected), (actual),     \
+                                                     (expected_except));       \
+  } while (0)
+
 #endif // LLVM_LIBC_TEST_UNITTEST_FPMATCHER_H
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index d2a75bd7c8e1f9..fabc1b51f5b0c8 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -1761,6 +1761,17 @@ add_fp_unittest(
     libc.src.__support.FPUtil.fp_bits
 )
 
+add_fp_unittest(
+  logf16_test
+  NEED_MPFR
+  SUITE
+    libc-math-unittests
+  SRCS
+    logf16_test.cpp
+  DEPENDS
+    libc.src.math.logf16
+)
+
 add_fp_unittest(
 log2_test
  NEED_MPFR
diff --git a/libc/test/src/math/logf16_test.cpp b/libc/test/src/math/logf16_test.cpp
new file mode 100644
index 00000000000000..67e5e172e53b8c
--- /dev/null
+++ b/libc/test/src/math/logf16_test.cpp
@@ -0,0 +1,40 @@
+//===-- Exhaustive test for logf16 ---------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/math/logf16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+using LlvmLibcLogf16Test = LIBC_NAMESPACE::testing::FPTest<float16>;
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+
+// Range: [0, Inf];
+static constexpr uint16_t POS_START = 0x0000U;
+static constexpr uint16_t POS_STOP = 0x7c00U;
+
+// Range: [-Inf, 0];
+static constexpr uint16_t NEG_START = 0x8000U;
+static constexpr uint16_t NEG_STOP = 0xfc00U;
+
+TEST_F(LlvmLibcLogf16Test, PositiveRange) {
+  for (uint16_t v = POS_START; v <= POS_STOP; ++v) {
+    float16 x = FPBits(v).get_val();
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log, x,
+                                   LIBC_NAMESPACE::logf16(x), 0.5);
+  }
+}
+
+TEST_F(LlvmLibcLogf16Test, NegativeRange) {
+  for (uint16_t v = NEG_START; v <= NEG_STOP; ++v) {
+    float16 x = FPBits(v).get_val();
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log, x,
+                                   LIBC_NAMESPACE::logf16(x), 0.5);
+  }
+}
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index db21c90acc1f3f..f3aa81506ac4ac 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -3408,6 +3408,18 @@ add_fp_unittest(
     libc.src.__support.FPUtil.fp_bits
 )
 
+add_fp_unittest(
+  logf16_test
+  SUITE
+    libc-math-smoke-tests
+  SRCS
+    logf16_test.cpp
+  DEPENDS
+    libc.hdr.fenv_macros
+    libc.src.errno.errno
+    libc.src.math.logf16
+)
+
 add_fp_unittest(
   log2_test
   SUITE
diff --git a/libc/test/src/math/smoke/logf16_test.cpp b/libc/test/src/math/smoke/logf16_test.cpp
new file mode 100644
index 00000000000000..e2f21003e8d81b
--- /dev/null
+++ b/libc/test/src/math/smoke/logf16_test.cpp
@@ -0,0 +1,47 @@
+//===-- Unittests for logf16 ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "hdr/fenv_macros.h"
+#include "src/errno/libc_errno.h"
+#include "src/math/logf16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using LlvmLibcLogf16Test = LIBC_NAMESPACE::testing::FPTest<float16>;
+
+TEST_F(LlvmLibcLogf16Test, SpecialNumbers) {
+  LIBC_NAMESPACE::libc_errno = 0;
+
+  EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::logf16(aNaN));
+  EXPECT_MATH_ERRNO(0);
+
+  EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, LIBC_NAMESPACE::logf16(sNaN), FE_INVALID);
+  EXPECT_MATH_ERRNO(0);
+
+  EXPECT_FP_EQ_ALL_ROUNDING(inf, LIBC_NAMESPACE::logf16(inf));
+  EXPECT_MATH_ERRNO(0);
+
+  EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::logf16(neg_inf));
+  EXPECT_MATH_ERRNO(EDOM);
+
+  EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
+      neg_inf, LIBC_NAMESPACE::logf16(zero), FE_DIVBYZERO);
+  EXPECT_MATH_ERRNO(0);
+
+  EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
+      neg_inf, LIBC_NAMESPACE::logf16(neg_zero), FE_DIVBYZERO);
+  EXPECT_MATH_ERRNO(0);
+
+  EXPECT_FP_EQ_ALL_ROUNDING(zero,
+                            LIBC_NAMESPACE::logf16(static_cast<float16>(1.0)));
+  EXPECT_MATH_ERRNO(0);
+
+  EXPECT_FP_EQ_ALL_ROUNDING(aNaN,
+                            LIBC_NAMESPACE::logf16(static_cast<float16>(-1.0)));
+  EXPECT_MATH_ERRNO(EDOM);
+}

// Generated by Sollya with the following commands:
// > display = hexadecimal;
// > for i from 0 to 31 do print(round(1 / (1 + i * 2^-5), SG, RN));
constexpr cpp::array<float, 32> ONE_OVER_F = {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I shouldn't have used the same ONE_OVER_F name that common_constants.h uses for the double 1/f lookup table.

Copy link
Contributor

@lntue lntue Oct 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes,I think we should at least add type suffix to these tables.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't think of a better name than ONE_OVER_F_F since I usually add _F as suffix for float constants.

@overmighty overmighty force-pushed the users/overmighty/libc-math-tanhf16 branch from eadda81 to c343f44 Compare October 15, 2024 13:49
@overmighty overmighty force-pushed the users/overmighty/libc-math-logf16 branch from 37db333 to cbc95e7 Compare October 15, 2024 14:53
@overmighty overmighty force-pushed the users/overmighty/libc-math-tanhf16 branch from c343f44 to 4758caf Compare October 17, 2024 18:48
@overmighty overmighty force-pushed the users/overmighty/libc-math-logf16 branch from cbc95e7 to 0541aa4 Compare October 17, 2024 18:50
Base automatically changed from users/overmighty/libc-math-tanhf16 to main October 18, 2024 12:22
@overmighty overmighty force-pushed the users/overmighty/libc-math-logf16 branch from 0541aa4 to 9450748 Compare October 18, 2024 13:04
@overmighty overmighty merged commit 65cf7af into main Oct 18, 2024
8 checks passed
@overmighty overmighty deleted the users/overmighty/libc-math-logf16 branch October 18, 2024 20:35
EricWF pushed a commit to efcs/llvm-project that referenced this pull request Oct 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants