[libc-commits] [libc] [libc][math] Improve fmul performance by using double-double arithmetic. (PR #107517)
Job Henandez Lara via libc-commits
libc-commits at lists.llvm.org
Sat Sep 14 12:38:01 PDT 2024
https://github.com/Jobhdez updated https://github.com/llvm/llvm-project/pull/107517
>From 51364fbfe327624bcb6e09d69a6f6d77d6a3447f Mon Sep 17 00:00:00 2001
From: Job Hernandez <hj93 at protonmail.com>
Date: Thu, 5 Sep 2024 21:26:49 -0700
Subject: [PATCH 01/22] add draft, one more test to go
---
libc/src/math/generic/CMakeLists.txt | 4 +++-
libc/src/math/generic/fmul.cpp | 18 ++++++++++++++++--
2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 350072f4b9649d..5a1ee3b8b83c77 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -2958,7 +2958,9 @@ add_entrypoint_object(
HDRS
../fmul.h
DEPENDS
- libc.src.__support.FPUtil.generic.mul
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+ libc.src.__support.FPUtil.double_double
COMPILE_OPTIONS
-O3
)
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
index 64c27d6e2f9564..fe8f5b0bb7c45b 100644
--- a/libc/src/math/generic/fmul.cpp
+++ b/libc/src/math/generic/fmul.cpp
@@ -5,16 +5,30 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
-
+#include "hdr/errno_macros.h"
+#include "hdr/fenv_macros.h"
#include "src/math/fmul.h"
#include "src/__support/FPUtil/generic/mul.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
+#include "src/__support/FPUtil/double_double.h"
namespace LIBC_NAMESPACE_DECL {
-
+ /*
LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
return fputil::generic::mul<float>(x, y);
}
+ */
+LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
+ fputil::DoubleDouble prod = fputil::exact_mult(x, y);
+ if (LIBC_UNLIKELY(fputil::FPBits<double>(prod.hi).is_inf_or_nan() || fputil::FPBits<double>(prod.hi).is_zero()))
+ return static_cast<float>(prod.hi);
+ if (LIBC_UNLIKELY(fputil::FPBits<double>(prod.hi).is_inf() || fputil::FPBits<double>(prod.hi).is_zero())) {
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
+ return fputil::FPBits<double>::quiet_nan().get_val();
+ }
+ return static_cast<float>(prod.hi + prod.lo);
+}
} // namespace LIBC_NAMESPACE_DECL
>From 693746c38eeac04a6e908cec51e98b2df54dd3db Mon Sep 17 00:00:00 2001
From: Job Hernandez Lara <hj93 at protonmail.com>
Date: Fri, 6 Sep 2024 16:35:42 -0700
Subject: [PATCH 02/22] format code
---
libc/src/math/generic/fmul.cpp | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
index fe8f5b0bb7c45b..c2536645b593bd 100644
--- a/libc/src/math/generic/fmul.cpp
+++ b/libc/src/math/generic/fmul.cpp
@@ -5,25 +5,27 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
+#include "src/math/fmul.h"
#include "hdr/errno_macros.h"
#include "hdr/fenv_macros.h"
-#include "src/math/fmul.h"
+#include "src/__support/FPUtil/double_double.h"
#include "src/__support/FPUtil/generic/mul.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
-#include "src/__support/FPUtil/double_double.h"
namespace LIBC_NAMESPACE_DECL {
- /*
+/*
LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
- return fputil::generic::mul<float>(x, y);
+return fputil::generic::mul<float>(x, y);
}
- */
+*/
LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
fputil::DoubleDouble prod = fputil::exact_mult(x, y);
- if (LIBC_UNLIKELY(fputil::FPBits<double>(prod.hi).is_inf_or_nan() || fputil::FPBits<double>(prod.hi).is_zero()))
+ if (LIBC_UNLIKELY(fputil::FPBits<double>(prod.hi).is_inf_or_nan() ||
+ fputil::FPBits<double>(prod.hi).is_zero()))
return static_cast<float>(prod.hi);
- if (LIBC_UNLIKELY(fputil::FPBits<double>(prod.hi).is_inf() || fputil::FPBits<double>(prod.hi).is_zero())) {
+ if (LIBC_UNLIKELY(fputil::FPBits<double>(prod.hi).is_inf() ||
+ fputil::FPBits<double>(prod.hi).is_zero())) {
fputil::set_errno_if_required(EDOM);
fputil::raise_except_if_required(FE_INVALID);
return fputil::FPBits<double>::quiet_nan().get_val();
>From f4981c1852b86ee47c099214eeaed91428728029 Mon Sep 17 00:00:00 2001
From: Job Hernandez Lara <hj93 at protonmail.com>
Date: Sat, 7 Sep 2024 20:14:50 -0700
Subject: [PATCH 03/22] add new case
---
libc/src/math/generic/fmul.cpp | 17 +++++++++++++++--
libc/test/src/math/smoke/fmul_test.cpp | 17 +++++++++++++++++
2 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
index c2536645b593bd..28d96448cbb2df 100644
--- a/libc/src/math/generic/fmul.cpp
+++ b/libc/src/math/generic/fmul.cpp
@@ -21,8 +21,9 @@ return fputil::generic::mul<float>(x, y);
*/
LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
fputil::DoubleDouble prod = fputil::exact_mult(x, y);
- if (LIBC_UNLIKELY(fputil::FPBits<double>(prod.hi).is_inf_or_nan() ||
- fputil::FPBits<double>(prod.hi).is_zero()))
+ fputil::FPBits<double> hi_bits(prod.hi), lo_bits(prod.lo);
+
+ if (LIBC_UNLIKELY(hi_bits.is_inf_or_nan() || hi_bits.is_zero()))
return static_cast<float>(prod.hi);
if (LIBC_UNLIKELY(fputil::FPBits<double>(prod.hi).is_inf() ||
fputil::FPBits<double>(prod.hi).is_zero())) {
@@ -30,7 +31,19 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
fputil::raise_except_if_required(FE_INVALID);
return fputil::FPBits<double>::quiet_nan().get_val();
}
+ if (prod.lo == 0.0)
+ return static_cast<float>(prod.hi);
+
+ if (lo_bits.sign() != hi_bits.sign()) {
+ // Check if sticky bit of hi are all 0
+ constexpr uint64_t STICKY_MASK = 0xFFF'FFFF; // Lower (52 - 23 - 1 = 28 bits)
+ uint64_t sticky_bits = (hi_bits.uintval() & STICKY_MASK);
+ uint64_t result_bits = (sticky_bits == 0) ? (hi_bits.uintval() - 1) : hi_bits.uintval();
+ double result = fputil::FPBits<double>(result_bits).get_val();
+ return static_cast<float>(result);
+}
return static_cast<float>(prod.hi + prod.lo);
+
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/src/math/smoke/fmul_test.cpp b/libc/test/src/math/smoke/fmul_test.cpp
index 3f6df66456bac5..e4165b23da1389 100644
--- a/libc/test/src/math/smoke/fmul_test.cpp
+++ b/libc/test/src/math/smoke/fmul_test.cpp
@@ -11,3 +11,20 @@
#include "src/math/fmul.h"
LIST_MUL_TESTS(float, double, LIBC_NAMESPACE::fmul)
+
+TEST_F(LlvmLibcMulTest, SpecialInputs) {
+ constexpr double INPUTS[][2] = {
+ {0x1.0100010002p8, 0x1.fffcp14},
+ };
+
+ constexpr float RESULTS[] = {
+ 0x1.00fdfep+23f,
+ };
+
+ constexpr size_t N = sizeof(RESULTS) / sizeof(RESULTS[0]);
+
+ for (size_t i = 0; i < N; ++i) {
+ float result = LIBC_NAMESPACE::fmul(INPUTS[i][0], INPUTS[i][1]);
+ EXPECT_FP_EQ(RESULTS[i], result);
+ }
+}
>From be366e7333f638f2c2e1a9fa9a86740f37da03ea Mon Sep 17 00:00:00 2001
From: Job Hernandez Lara <hj93 at protonmail.com>
Date: Sat, 7 Sep 2024 20:15:16 -0700
Subject: [PATCH 04/22] format code
---
libc/src/math/generic/fmul.cpp | 15 ++++++++-------
libc/test/src/math/smoke/fmul_test.cpp | 4 ++--
2 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
index 28d96448cbb2df..a9de90edd2a7ab 100644
--- a/libc/src/math/generic/fmul.cpp
+++ b/libc/src/math/generic/fmul.cpp
@@ -22,7 +22,7 @@ return fputil::generic::mul<float>(x, y);
LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
fputil::DoubleDouble prod = fputil::exact_mult(x, y);
fputil::FPBits<double> hi_bits(prod.hi), lo_bits(prod.lo);
-
+
if (LIBC_UNLIKELY(hi_bits.is_inf_or_nan() || hi_bits.is_zero()))
return static_cast<float>(prod.hi);
if (LIBC_UNLIKELY(fputil::FPBits<double>(prod.hi).is_inf() ||
@@ -33,17 +33,18 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
}
if (prod.lo == 0.0)
return static_cast<float>(prod.hi);
-
+
if (lo_bits.sign() != hi_bits.sign()) {
- // Check if sticky bit of hi are all 0
- constexpr uint64_t STICKY_MASK = 0xFFF'FFFF; // Lower (52 - 23 - 1 = 28 bits)
+ // Check if sticky bit of hi are all 0
+ constexpr uint64_t STICKY_MASK =
+ 0xFFF'FFFF; // Lower (52 - 23 - 1 = 28 bits)
uint64_t sticky_bits = (hi_bits.uintval() & STICKY_MASK);
- uint64_t result_bits = (sticky_bits == 0) ? (hi_bits.uintval() - 1) : hi_bits.uintval();
+ uint64_t result_bits =
+ (sticky_bits == 0) ? (hi_bits.uintval() - 1) : hi_bits.uintval();
double result = fputil::FPBits<double>(result_bits).get_val();
return static_cast<float>(result);
-}
+ }
return static_cast<float>(prod.hi + prod.lo);
-
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/src/math/smoke/fmul_test.cpp b/libc/test/src/math/smoke/fmul_test.cpp
index e4165b23da1389..48a5afd247bcfb 100644
--- a/libc/test/src/math/smoke/fmul_test.cpp
+++ b/libc/test/src/math/smoke/fmul_test.cpp
@@ -14,11 +14,11 @@ LIST_MUL_TESTS(float, double, LIBC_NAMESPACE::fmul)
TEST_F(LlvmLibcMulTest, SpecialInputs) {
constexpr double INPUTS[][2] = {
- {0x1.0100010002p8, 0x1.fffcp14},
+ {0x1.0100010002p8, 0x1.fffcp14},
};
constexpr float RESULTS[] = {
- 0x1.00fdfep+23f,
+ 0x1.00fdfep+23f,
};
constexpr size_t N = sizeof(RESULTS) / sizeof(RESULTS[0]);
>From 07331c1086c95ff2e15c14d6e4ff2d2025118fff Mon Sep 17 00:00:00 2001
From: Job Hernandez Lara <hj93 at protonmail.com>
Date: Mon, 9 Sep 2024 19:30:08 -0700
Subject: [PATCH 05/22] run mpfr tests
---
libc/test/src/math/fmul_test.cpp | 27 +++++++++++++++++++
.../math/performance_testing/CMakeLists.txt | 2 ++
.../math/performance_testing/fmul_perf.cpp | 4 ++-
3 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/libc/test/src/math/fmul_test.cpp b/libc/test/src/math/fmul_test.cpp
index 3f6df66456bac5..c134c3fa299d85 100644
--- a/libc/test/src/math/fmul_test.cpp
+++ b/libc/test/src/math/fmul_test.cpp
@@ -10,4 +10,31 @@
#include "src/math/fmul.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
LIST_MUL_TESTS(float, double, LIBC_NAMESPACE::fmul)
+
+TEST_F(LlvmLibcMulTest, SpecialInputs) {
+ namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+ double INPUTS[][2] = {
+ {0x1.0100010002p8, 0x1.fffcp14},
+ };
+
+ constexpr float RESULTS[] = {
+ 0x1.00fdfep+23f,
+ };
+
+
+ constexpr size_t N = sizeof(RESULTS) / sizeof(RESULTS[0]);
+
+ for (size_t i = 0; i < N; ++i) {
+ double a = INPUTS[i][0];
+
+ for (int j = 0; j < 180; ++j) {
+ a *= 0.5;
+ mpfr::BinaryInput<double> input{INPUTS[i][0], INPUTS[i][1]};
+ ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Mul, input, LIBC_NAMESPACE::fmul(INPUTS[i][0], INPUTS[i][1]), 0.5);
+ }
+ }
+}
diff --git a/libc/test/src/math/performance_testing/CMakeLists.txt b/libc/test/src/math/performance_testing/CMakeLists.txt
index ed1b03f3493c7d..60c074a248f72a 100644
--- a/libc/test/src/math/performance_testing/CMakeLists.txt
+++ b/libc/test/src/math/performance_testing/CMakeLists.txt
@@ -484,6 +484,8 @@ add_perf_binary(
DEPENDS
.binary_op_single_output_diff
libc.src.math.fmul
+ libc.src.__support.FPUtil.generic.mul
+ libc.src.__support.FPUtil.fp_bits
COMPILE_OPTIONS
-fno-builtin
)
diff --git a/libc/test/src/math/performance_testing/fmul_perf.cpp b/libc/test/src/math/performance_testing/fmul_perf.cpp
index a215405eb6aa5d..d6156f1519c507 100644
--- a/libc/test/src/math/performance_testing/fmul_perf.cpp
+++ b/libc/test/src/math/performance_testing/fmul_perf.cpp
@@ -7,12 +7,14 @@
//===----------------------------------------------------------------------===//
#include "BinaryOpSingleOutputPerf.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/generic/mul.h"
#include "src/math/fmul.h"
static constexpr size_t DOUBLE_ROUNDS = 40;
float fmul_placeholder_binary(double x, double y) {
- return static_cast<float>(x * y);
+ return LIBC_NAMESPACE::fputil::generic::mul<float>(x, y);
}
int main() {
>From 8ce2aea18760c7aa69a06776af23784873c2b21e Mon Sep 17 00:00:00 2001
From: Job Hernandez Lara <hj93 at protonmail.com>
Date: Mon, 9 Sep 2024 19:30:34 -0700
Subject: [PATCH 06/22] format code
---
libc/test/src/math/fmul_test.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/libc/test/src/math/fmul_test.cpp b/libc/test/src/math/fmul_test.cpp
index c134c3fa299d85..d1caca0c38de20 100644
--- a/libc/test/src/math/fmul_test.cpp
+++ b/libc/test/src/math/fmul_test.cpp
@@ -25,7 +25,6 @@ TEST_F(LlvmLibcMulTest, SpecialInputs) {
0x1.00fdfep+23f,
};
-
constexpr size_t N = sizeof(RESULTS) / sizeof(RESULTS[0]);
for (size_t i = 0; i < N; ++i) {
@@ -34,7 +33,9 @@ TEST_F(LlvmLibcMulTest, SpecialInputs) {
for (int j = 0; j < 180; ++j) {
a *= 0.5;
mpfr::BinaryInput<double> input{INPUTS[i][0], INPUTS[i][1]};
- ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Mul, input, LIBC_NAMESPACE::fmul(INPUTS[i][0], INPUTS[i][1]), 0.5);
+ ASSERT_MPFR_MATCH_ALL_ROUNDING(
+ mpfr::Operation::Mul, input,
+ LIBC_NAMESPACE::fmul(INPUTS[i][0], INPUTS[i][1]), 0.5);
}
}
}
>From 2d928d30e606db9caf767978434c036346da35e5 Mon Sep 17 00:00:00 2001
From: Job Hernandez Lara <hj93 at protonmail.com>
Date: Tue, 10 Sep 2024 09:08:23 -0700
Subject: [PATCH 07/22] handle all cases
Co-authored-by: Tue Ly <lntue at google.com>
---
libc/src/math/generic/fmul.cpp | 4 +++-
libc/test/src/math/smoke/fmul_test.cpp | 3 +++
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
index a9de90edd2a7ab..6d3b4c3016ff2b 100644
--- a/libc/src/math/generic/fmul.cpp
+++ b/libc/src/math/generic/fmul.cpp
@@ -44,7 +44,9 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
double result = fputil::FPBits<double>(result_bits).get_val();
return static_cast<float>(result);
}
- return static_cast<float>(prod.hi + prod.lo);
+
+ double result = fputil::FPBits<double>(hi_bits.uintval() | 1).get_val();
+ return static_cast<float>(result);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/src/math/smoke/fmul_test.cpp b/libc/test/src/math/smoke/fmul_test.cpp
index 48a5afd247bcfb..dd0d89143f623d 100644
--- a/libc/test/src/math/smoke/fmul_test.cpp
+++ b/libc/test/src/math/smoke/fmul_test.cpp
@@ -15,10 +15,12 @@ LIST_MUL_TESTS(float, double, LIBC_NAMESPACE::fmul)
TEST_F(LlvmLibcMulTest, SpecialInputs) {
constexpr double INPUTS[][2] = {
{0x1.0100010002p8, 0x1.fffcp14},
+ {0x1.000000b92144p-7, 0x1.62p7},
};
constexpr float RESULTS[] = {
0x1.00fdfep+23f,
+ 0x1.620002p0f,
};
constexpr size_t N = sizeof(RESULTS) / sizeof(RESULTS[0]);
@@ -28,3 +30,4 @@ TEST_F(LlvmLibcMulTest, SpecialInputs) {
EXPECT_FP_EQ(RESULTS[i], result);
}
}
+
>From be463f29dc0fa764b543ec02e4eb7d548ebf9f2b Mon Sep 17 00:00:00 2001
From: Job Hernandez Lara <hj93 at protonmail.com>
Date: Tue, 10 Sep 2024 18:03:01 -0700
Subject: [PATCH 08/22] handle exceptions
---
libc/src/math/generic/fmul.cpp | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
index 6d3b4c3016ff2b..836779d0cad8ae 100644
--- a/libc/src/math/generic/fmul.cpp
+++ b/libc/src/math/generic/fmul.cpp
@@ -24,13 +24,9 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
fputil::FPBits<double> hi_bits(prod.hi), lo_bits(prod.lo);
if (LIBC_UNLIKELY(hi_bits.is_inf_or_nan() || hi_bits.is_zero()))
- return static_cast<float>(prod.hi);
- if (LIBC_UNLIKELY(fputil::FPBits<double>(prod.hi).is_inf() ||
- fputil::FPBits<double>(prod.hi).is_zero())) {
fputil::set_errno_if_required(EDOM);
fputil::raise_except_if_required(FE_INVALID);
- return fputil::FPBits<double>::quiet_nan().get_val();
- }
+ return static_cast<float>(prod.hi);
if (prod.lo == 0.0)
return static_cast<float>(prod.hi);
>From e6c377890e7a466068db99450e498557a59afd6b Mon Sep 17 00:00:00 2001
From: Job Hernandez Lara <hj93 at protonmail.com>
Date: Tue, 10 Sep 2024 18:03:27 -0700
Subject: [PATCH 09/22] format code
---
libc/src/math/generic/fmul.cpp | 22 +++++++++++-----------
libc/test/src/math/smoke/fmul_test.cpp | 1 -
2 files changed, 11 insertions(+), 12 deletions(-)
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
index 836779d0cad8ae..a1e1c65e768fc5 100644
--- a/libc/src/math/generic/fmul.cpp
+++ b/libc/src/math/generic/fmul.cpp
@@ -27,18 +27,18 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
fputil::set_errno_if_required(EDOM);
fputil::raise_except_if_required(FE_INVALID);
return static_cast<float>(prod.hi);
- if (prod.lo == 0.0)
- return static_cast<float>(prod.hi);
+ if (prod.lo == 0.0)
+ return static_cast<float>(prod.hi);
- if (lo_bits.sign() != hi_bits.sign()) {
- // Check if sticky bit of hi are all 0
- constexpr uint64_t STICKY_MASK =
- 0xFFF'FFFF; // Lower (52 - 23 - 1 = 28 bits)
- uint64_t sticky_bits = (hi_bits.uintval() & STICKY_MASK);
- uint64_t result_bits =
- (sticky_bits == 0) ? (hi_bits.uintval() - 1) : hi_bits.uintval();
- double result = fputil::FPBits<double>(result_bits).get_val();
- return static_cast<float>(result);
+ if (lo_bits.sign() != hi_bits.sign()) {
+ // Check if sticky bit of hi are all 0
+ constexpr uint64_t STICKY_MASK =
+ 0xFFF'FFFF; // Lower (52 - 23 - 1 = 28 bits)
+ uint64_t sticky_bits = (hi_bits.uintval() & STICKY_MASK);
+ uint64_t result_bits =
+ (sticky_bits == 0) ? (hi_bits.uintval() - 1) : hi_bits.uintval();
+ double result = fputil::FPBits<double>(result_bits).get_val();
+ return static_cast<float>(result);
}
double result = fputil::FPBits<double>(hi_bits.uintval() | 1).get_val();
diff --git a/libc/test/src/math/smoke/fmul_test.cpp b/libc/test/src/math/smoke/fmul_test.cpp
index dd0d89143f623d..3fcf514bcd9f05 100644
--- a/libc/test/src/math/smoke/fmul_test.cpp
+++ b/libc/test/src/math/smoke/fmul_test.cpp
@@ -30,4 +30,3 @@ TEST_F(LlvmLibcMulTest, SpecialInputs) {
EXPECT_FP_EQ(RESULTS[i], result);
}
}
-
>From b69581b55c3cfc8aef5d44b1b9323ecfb52d7967 Mon Sep 17 00:00:00 2001
From: Job Hernandez <hj93 at protonmail.com>
Date: Tue, 10 Sep 2024 18:28:17 -0700
Subject: [PATCH 10/22] fix typo
---
libc/src/math/generic/fmul.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
index a1e1c65e768fc5..8b2315792a74c1 100644
--- a/libc/src/math/generic/fmul.cpp
+++ b/libc/src/math/generic/fmul.cpp
@@ -23,10 +23,11 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
fputil::DoubleDouble prod = fputil::exact_mult(x, y);
fputil::FPBits<double> hi_bits(prod.hi), lo_bits(prod.lo);
- if (LIBC_UNLIKELY(hi_bits.is_inf_or_nan() || hi_bits.is_zero()))
+ if (LIBC_UNLIKELY(hi_bits.is_inf_or_nan() || hi_bits.is_zero())) {
fputil::set_errno_if_required(EDOM);
fputil::raise_except_if_required(FE_INVALID);
return static_cast<float>(prod.hi);
+ }
if (prod.lo == 0.0)
return static_cast<float>(prod.hi);
>From 9507d99799925a08d9d1509a0d04555119f54005 Mon Sep 17 00:00:00 2001
From: Job Hernandez Lara <hj93 at protonmail.com>
Date: Wed, 11 Sep 2024 15:29:02 -0700
Subject: [PATCH 11/22] handle exceptions
---
libc/src/math/generic/fmul.cpp | 89 ++++++++++++++++++++++++++++------
1 file changed, 73 insertions(+), 16 deletions(-)
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
index 8b2315792a74c1..c0974c6413d552 100644
--- a/libc/src/math/generic/fmul.cpp
+++ b/libc/src/math/generic/fmul.cpp
@@ -23,23 +23,80 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
fputil::DoubleDouble prod = fputil::exact_mult(x, y);
fputil::FPBits<double> hi_bits(prod.hi), lo_bits(prod.lo);
- if (LIBC_UNLIKELY(hi_bits.is_inf_or_nan() || hi_bits.is_zero())) {
- fputil::set_errno_if_required(EDOM);
- fputil::raise_except_if_required(FE_INVALID);
- return static_cast<float>(prod.hi);
+ float prod_hif = static_cast<float>(prod.hi);
+ fputil::FPBits<float> hif_bits(prod_hif);
+ using OutFPBits = fputil::FPBits<float>;
+ using OutStorageType = typename OutFPBits::StorageType;
+ using InFPBits = FPBits<double>;
+ using InStorageType = typename InFPBits::StorageType;
+
+ InFPBits x_bits(x);
+ InFPBits y_bits(y);
+
+
+ Sign result_sign = x_bits.sign() == y_bits.sign() ? Sign::POS : Sign::NEG;
+
+ if (LIBC_UNLIKELY(x_bits.is_inf_or_nan() || y_bits.is_inf_or_nan() ||
+ x_bits.is_zero() || y_bits.is_zero())) {
+ if (x_bits.is_nan() || y_bits.is_nan()) {
+ if (x_bits.is_signaling_nan() || y_bits.is_signaling_nan())
+ raise_except_if_required(FE_INVALID);
+
+ if (x_bits.is_quiet_nan()) {
+ InStorageType x_payload = x_bits.get_mantissa();
+ x_payload >>= InFPBits::FRACTION_LEN - OutFPBits::FRACTION_LEN;
+ return OutFPBits::quiet_nan(x_bits.sign(),
+ static_cast<OutStorageType>(x_payload))
+ .get_val();
+ }
+
+ if (y_bits.is_quiet_nan()) {
+ InStorageType y_payload = y_bits.get_mantissa();
+ y_payload >>= InFPBits::FRACTION_LEN - OutFPBits::FRACTION_LEN;
+ return OutFPBits::quiet_nan(y_bits.sign(),
+ static_cast<OutStorageType>(y_payload))
+ .get_val();
+ }
+
+ return OutFPBits::quiet_nan().get_val();
+ }
+
+ if (x_bits.is_inf()) {
+ if (y_bits.is_zero()) {
+ set_errno_if_required(EDOM);
+ raise_except_if_required(FE_INVALID);
+ return OutFPBits::quiet_nan().get_val();
+ }
+
+ return OutFPBits::inf(result_sign).get_val();
+ }
+
+ if (y_bits.is_inf()) {
+ if (x_bits.is_zero()) {
+ set_errno_if_required(EDOM);
+ raise_except_if_required(FE_INVALID);
+ return OutFPBits::quiet_nan().get_val();
+ }
+
+ return OutFPBits::inf(result_sign).get_val();
+ }
+
+ // Now either x or y is zero, and the other one is finite.
+ return OutFPBits::zero(result_sign).get_val();
}
- if (prod.lo == 0.0)
- return static_cast<float>(prod.hi);
-
- if (lo_bits.sign() != hi_bits.sign()) {
- // Check if sticky bit of hi are all 0
- constexpr uint64_t STICKY_MASK =
- 0xFFF'FFFF; // Lower (52 - 23 - 1 = 28 bits)
- uint64_t sticky_bits = (hi_bits.uintval() & STICKY_MASK);
- uint64_t result_bits =
- (sticky_bits == 0) ? (hi_bits.uintval() - 1) : hi_bits.uintval();
- double result = fputil::FPBits<double>(result_bits).get_val();
- return static_cast<float>(result);
+
+ if (prod.lo == 0.0)
+ return static_cast<float>(prod.hi);
+
+ if (lo_bits.sign() != hi_bits.sign()) {
+ // Check if sticky bit of hi are all 0
+ constexpr uint64_t STICKY_MASK =
+ 0xFFF'FFFF; // Lower (52 - 23 - 1 = 28 bits)
+ uint64_t sticky_bits = (hi_bits.uintval() & STICKY_MASK);
+ uint64_t result_bits =
+ (sticky_bits == 0) ? (hi_bits.uintval() - 1) : hi_bits.uintval();
+ double result = fputil::FPBits<double>(result_bits).get_val();
+ return static_cast<float>(result);
}
double result = fputil::FPBits<double>(hi_bits.uintval() | 1).get_val();
>From 59f5656a34cc1c1804cd136d0dfa40a20711ab4e Mon Sep 17 00:00:00 2001
From: Job Hernandez Lara <hj93 at protonmail.com>
Date: Wed, 11 Sep 2024 15:29:42 -0700
Subject: [PATCH 12/22] fix format
---
libc/src/math/generic/fmul.cpp | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
index c0974c6413d552..81bf6e7b9aae08 100644
--- a/libc/src/math/generic/fmul.cpp
+++ b/libc/src/math/generic/fmul.cpp
@@ -33,7 +33,6 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
InFPBits x_bits(x);
InFPBits y_bits(y);
-
Sign result_sign = x_bits.sign() == y_bits.sign() ? Sign::POS : Sign::NEG;
if (LIBC_UNLIKELY(x_bits.is_inf_or_nan() || y_bits.is_inf_or_nan() ||
@@ -84,17 +83,17 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
// Now either x or y is zero, and the other one is finite.
return OutFPBits::zero(result_sign).get_val();
}
-
+
if (prod.lo == 0.0)
return static_cast<float>(prod.hi);
if (lo_bits.sign() != hi_bits.sign()) {
// Check if sticky bit of hi are all 0
constexpr uint64_t STICKY_MASK =
- 0xFFF'FFFF; // Lower (52 - 23 - 1 = 28 bits)
+ 0xFFF'FFFF; // Lower (52 - 23 - 1 = 28 bits)
uint64_t sticky_bits = (hi_bits.uintval() & STICKY_MASK);
uint64_t result_bits =
- (sticky_bits == 0) ? (hi_bits.uintval() - 1) : hi_bits.uintval();
+ (sticky_bits == 0) ? (hi_bits.uintval() - 1) : hi_bits.uintval();
double result = fputil::FPBits<double>(result_bits).get_val();
return static_cast<float>(result);
}
>From 5f9ec22fc0abb4667b97af3b26139f36a18aa98f Mon Sep 17 00:00:00 2001
From: Job Hernandez <hj93 at protonmail.com>
Date: Fri, 13 Sep 2024 19:12:38 -0700
Subject: [PATCH 13/22] update
---
libc/src/math/generic/fmul.cpp | 78 ++++++++++++++++++++++------------
1 file changed, 50 insertions(+), 28 deletions(-)
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
index 81bf6e7b9aae08..5f83a4dcdd0ff1 100644
--- a/libc/src/math/generic/fmul.cpp
+++ b/libc/src/math/generic/fmul.cpp
@@ -20,14 +20,15 @@ return fputil::generic::mul<float>(x, y);
}
*/
LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
- fputil::DoubleDouble prod = fputil::exact_mult(x, y);
- fputil::FPBits<double> hi_bits(prod.hi), lo_bits(prod.lo);
+ //fputil::DoubleDouble prod = fputil::exact_mult(x, y);
+ //fputil::FPBits<double> hi_bits(prod.hi), lo_bits(prod.lo);
+ fputil::DoubleDouble prod = fputil::exact_mult(x, y);
float prod_hif = static_cast<float>(prod.hi);
fputil::FPBits<float> hif_bits(prod_hif);
using OutFPBits = fputil::FPBits<float>;
using OutStorageType = typename OutFPBits::StorageType;
- using InFPBits = FPBits<double>;
+ using InFPBits = fputil::FPBits<double>;
using InStorageType = typename InFPBits::StorageType;
InFPBits x_bits(x);
@@ -35,11 +36,38 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
Sign result_sign = x_bits.sign() == y_bits.sign() ? Sign::POS : Sign::NEG;
+ using DoubleBits = fputil::FPBits<double>;
+ using FloatBits = fputil::FPBits<float>;
+ double result = prod.hi;
+ DoubleBits hi_bits(prod.hi), lo_bits(prod.lo);
+ // Check for cases where we need to propagate the sticky bits:
+ constexpr uint64_t STICKY_MASK = 0xFFF'FFF; // Lower (52 - 23 - 1 = 28 bits)
+ uint64_t sticky_bits = (hif_bits.uintval() & STICKY_MASK);
+ if (LIBC_UNLIKELY(sticky_bits == 0)) {
+ // Might need to propagate sticky bits:
+ if (!(lo_bits.is_inf_or_nan() || lo_bits.is_zero())) {
+ // Now prod.lo is nonzero and finite, we need to propagate sticky bits.
+ if (lo_bits.sign() != hi_bits.sign())
+ result = DoubleBits(hi_bits.uintval() - 1).get_val();
+ else
+ result = DoubleBits(hi_bits.uintval() | 1).get_val();
+ }
+ }
+
+ float result_f = static_cast<float>(result);
+ FloatBits rf_bits(result_f);
+ uint32_t rf_exp = rf_bits.get_biased_exponent();
+
+ if (LIBC_LIKELY(rf_exp > 0 && rf_exp < 2*FloatBits::EXP_BIAS + 1))
+ return result_f;
+
+ // Now result_f is either inf/nan/zero/denormal.
+ // Perform all exceptional checks.
if (LIBC_UNLIKELY(x_bits.is_inf_or_nan() || y_bits.is_inf_or_nan() ||
x_bits.is_zero() || y_bits.is_zero())) {
- if (x_bits.is_nan() || y_bits.is_nan()) {
+ if (x_bits.is_nan() || y_bits.is_nan()) {
if (x_bits.is_signaling_nan() || y_bits.is_signaling_nan())
- raise_except_if_required(FE_INVALID);
+ fputil::raise_except_if_required(FE_INVALID);
if (x_bits.is_quiet_nan()) {
InStorageType x_payload = x_bits.get_mantissa();
@@ -62,8 +90,8 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
if (x_bits.is_inf()) {
if (y_bits.is_zero()) {
- set_errno_if_required(EDOM);
- raise_except_if_required(FE_INVALID);
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
return OutFPBits::quiet_nan().get_val();
}
@@ -72,34 +100,28 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
if (y_bits.is_inf()) {
if (x_bits.is_zero()) {
- set_errno_if_required(EDOM);
- raise_except_if_required(FE_INVALID);
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
return OutFPBits::quiet_nan().get_val();
}
return OutFPBits::inf(result_sign).get_val();
}
+ }
// Now either x or y is zero, and the other one is finite.
- return OutFPBits::zero(result_sign).get_val();
- }
+ if (hif_bits.is_inf()) {
+ fputil::set_errno_if_required(ERANGE);
+ return OutFPBits::zero(result_sign).get_val();
+ }
- if (prod.lo == 0.0)
- return static_cast<float>(prod.hi);
-
- if (lo_bits.sign() != hi_bits.sign()) {
- // Check if sticky bit of hi are all 0
- constexpr uint64_t STICKY_MASK =
- 0xFFF'FFFF; // Lower (52 - 23 - 1 = 28 bits)
- uint64_t sticky_bits = (hi_bits.uintval() & STICKY_MASK);
- uint64_t result_bits =
- (sticky_bits == 0) ? (hi_bits.uintval() - 1) : hi_bits.uintval();
- double result = fputil::FPBits<double>(result_bits).get_val();
- return static_cast<float>(result);
- }
+ if (hif_bits.get_biased_exponent() == 0.0) {
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_UNDERFLOW);
+ return OutFPBits::zero(result_sign).get_val();
+ }
- double result = fputil::FPBits<double>(hi_bits.uintval() | 1).get_val();
- return static_cast<float>(result);
-}
+ return OutFPBits::zero(result_sign).get_val();
-} // namespace LIBC_NAMESPACE_DECL
+}
+}// namespace LIBC_NAMESPACE_DECL
>From 2027e828a61279c31df2042e34f0f337c0ec2e19 Mon Sep 17 00:00:00 2001
From: Job Hernandez <hj93 at protonmail.com>
Date: Fri, 13 Sep 2024 21:08:25 -0700
Subject: [PATCH 14/22] fix tests
---
libc/src/math/generic/fmul.cpp | 42 +++++++++++++-----------------
libc/test/src/math/smoke/MulTest.h | 14 ++++++----
2 files changed, 27 insertions(+), 29 deletions(-)
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
index 5f83a4dcdd0ff1..191124614413ec 100644
--- a/libc/src/math/generic/fmul.cpp
+++ b/libc/src/math/generic/fmul.cpp
@@ -12,17 +12,15 @@
#include "src/__support/FPUtil/generic/mul.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
+#include <iostream>
namespace LIBC_NAMESPACE_DECL {
-/*
-LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
-return fputil::generic::mul<float>(x, y);
-}
-*/
+
LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
- //fputil::DoubleDouble prod = fputil::exact_mult(x, y);
- //fputil::FPBits<double> hi_bits(prod.hi), lo_bits(prod.lo);
+ #ifndef LIBC_TARGET_CPU_HAS_FMA
+ return fputil::generic::mul<float>(x, y);
+ #else
fputil::DoubleDouble prod = fputil::exact_mult(x, y);
float prod_hif = static_cast<float>(prod.hi);
fputil::FPBits<float> hif_bits(prod_hif);
@@ -36,13 +34,13 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
Sign result_sign = x_bits.sign() == y_bits.sign() ? Sign::POS : Sign::NEG;
- using DoubleBits = fputil::FPBits<double>;
+ using DoubleBits = fputil::FPBits<double>;
using FloatBits = fputil::FPBits<float>;
double result = prod.hi;
DoubleBits hi_bits(prod.hi), lo_bits(prod.lo);
// Check for cases where we need to propagate the sticky bits:
constexpr uint64_t STICKY_MASK = 0xFFF'FFF; // Lower (52 - 23 - 1 = 28 bits)
- uint64_t sticky_bits = (hif_bits.uintval() & STICKY_MASK);
+ uint64_t sticky_bits = (hi_bits.uintval() & STICKY_MASK);
if (LIBC_UNLIKELY(sticky_bits == 0)) {
// Might need to propagate sticky bits:
if (!(lo_bits.is_inf_or_nan() || lo_bits.is_zero())) {
@@ -57,14 +55,11 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
float result_f = static_cast<float>(result);
FloatBits rf_bits(result_f);
uint32_t rf_exp = rf_bits.get_biased_exponent();
-
- if (LIBC_LIKELY(rf_exp > 0 && rf_exp < 2*FloatBits::EXP_BIAS + 1))
+ if (LIBC_LIKELY(rf_exp > 0 && rf_exp < 2*FloatBits::EXP_BIAS + 1)) {
return result_f;
+ }
// Now result_f is either inf/nan/zero/denormal.
- // Perform all exceptional checks.
- if (LIBC_UNLIKELY(x_bits.is_inf_or_nan() || y_bits.is_inf_or_nan() ||
- x_bits.is_zero() || y_bits.is_zero())) {
if (x_bits.is_nan() || y_bits.is_nan()) {
if (x_bits.is_signaling_nan() || y_bits.is_signaling_nan())
fputil::raise_except_if_required(FE_INVALID);
@@ -92,6 +87,7 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
if (y_bits.is_zero()) {
fputil::set_errno_if_required(EDOM);
fputil::raise_except_if_required(FE_INVALID);
+
return OutFPBits::quiet_nan().get_val();
}
@@ -107,21 +103,19 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
return OutFPBits::inf(result_sign).get_val();
}
- }
// Now either x or y is zero, and the other one is finite.
if (hif_bits.is_inf()) {
fputil::set_errno_if_required(ERANGE);
- return OutFPBits::zero(result_sign).get_val();
- }
-
- if (hif_bits.get_biased_exponent() == 0.0) {
- fputil::set_errno_if_required(ERANGE);
- fputil::raise_except_if_required(FE_UNDERFLOW);
- return OutFPBits::zero(result_sign).get_val();
+ return OutFPBits::inf(result_sign).get_val();
}
- return OutFPBits::zero(result_sign).get_val();
+ if (x_bits.is_zero() || y_bits.is_zero())
+ return FloatBits::zero(result_sign).get_val();
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_UNDERFLOW);
+ return result_f;
+}
}
-}// namespace LIBC_NAMESPACE_DECL
+// namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/src/math/smoke/MulTest.h b/libc/test/src/math/smoke/MulTest.h
index 0c847e39687b72..eac0ef1b60b992 100644
--- a/libc/test/src/math/smoke/MulTest.h
+++ b/libc/test/src/math/smoke/MulTest.h
@@ -66,10 +66,11 @@ class MulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
void test_range_errors(MulFunc func) {
using namespace LIBC_NAMESPACE::fputil::testing;
-
+
if (ForceRoundingMode r(RoundingMode::Nearest); r.success) {
EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(max_normal, max_normal),
FE_OVERFLOW | FE_INEXACT);
+
EXPECT_MATH_ERRNO(ERANGE);
EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, func(neg_max_normal, max_normal),
FE_OVERFLOW | FE_INEXACT);
@@ -82,8 +83,9 @@ class MulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
func(in.neg_min_denormal, in.min_denormal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
+
}
-
+
if (ForceRoundingMode r(RoundingMode::TowardZero); r.success) {
EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, func(max_normal, max_normal),
FE_OVERFLOW | FE_INEXACT);
@@ -98,9 +100,10 @@ class MulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
func(in.neg_min_denormal, in.min_denormal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
- }
+ }
if (ForceRoundingMode r(RoundingMode::Downward); r.success) {
+
EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, func(max_normal, max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, func(neg_max_normal, max_normal),
@@ -110,12 +113,13 @@ class MulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.min_denormal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
+
EXPECT_FP_EQ_WITH_EXCEPTION(neg_min_denormal,
func(in.neg_min_denormal, in.min_denormal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
}
-
+
if (ForceRoundingMode r(RoundingMode::Upward); r.success) {
EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(max_normal, max_normal),
FE_OVERFLOW | FE_INEXACT);
@@ -132,8 +136,8 @@ class MulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
func(in.neg_min_denormal, in.min_denormal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
+ }
}
- }
void test_inexact_results(MulFunc func) {
InFPBits x_bits = InFPBits::one();
>From e125d74e4cbbc9f4b6eba3e2992cd300a5950d98 Mon Sep 17 00:00:00 2001
From: Job Hernandez <hj93 at protonmail.com>
Date: Fri, 13 Sep 2024 21:08:48 -0700
Subject: [PATCH 15/22] format code
---
libc/src/math/generic/fmul.cpp | 4 ++--
libc/test/src/math/smoke/MulTest.h | 17 ++++++++---------
2 files changed, 10 insertions(+), 11 deletions(-)
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
index 191124614413ec..9330c8c92ae77b 100644
--- a/libc/src/math/generic/fmul.cpp
+++ b/libc/src/math/generic/fmul.cpp
@@ -18,9 +18,9 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
- #ifndef LIBC_TARGET_CPU_HAS_FMA
+#ifndef LIBC_TARGET_CPU_HAS_FMA
return fputil::generic::mul<float>(x, y);
- #else
+#else
fputil::DoubleDouble prod = fputil::exact_mult(x, y);
float prod_hif = static_cast<float>(prod.hi);
fputil::FPBits<float> hif_bits(prod_hif);
diff --git a/libc/test/src/math/smoke/MulTest.h b/libc/test/src/math/smoke/MulTest.h
index eac0ef1b60b992..d586423795cedd 100644
--- a/libc/test/src/math/smoke/MulTest.h
+++ b/libc/test/src/math/smoke/MulTest.h
@@ -66,11 +66,11 @@ class MulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
void test_range_errors(MulFunc func) {
using namespace LIBC_NAMESPACE::fputil::testing;
-
+
if (ForceRoundingMode r(RoundingMode::Nearest); r.success) {
EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(max_normal, max_normal),
FE_OVERFLOW | FE_INEXACT);
-
+
EXPECT_MATH_ERRNO(ERANGE);
EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, func(neg_max_normal, max_normal),
FE_OVERFLOW | FE_INEXACT);
@@ -83,9 +83,8 @@ class MulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
func(in.neg_min_denormal, in.min_denormal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
-
}
-
+
if (ForceRoundingMode r(RoundingMode::TowardZero); r.success) {
EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, func(max_normal, max_normal),
FE_OVERFLOW | FE_INEXACT);
@@ -100,10 +99,10 @@ class MulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
func(in.neg_min_denormal, in.min_denormal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
- }
+ }
if (ForceRoundingMode r(RoundingMode::Downward); r.success) {
-
+
EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, func(max_normal, max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, func(neg_max_normal, max_normal),
@@ -113,13 +112,13 @@ class MulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.min_denormal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
-
+
EXPECT_FP_EQ_WITH_EXCEPTION(neg_min_denormal,
func(in.neg_min_denormal, in.min_denormal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
}
-
+
if (ForceRoundingMode r(RoundingMode::Upward); r.success) {
EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(max_normal, max_normal),
FE_OVERFLOW | FE_INEXACT);
@@ -136,8 +135,8 @@ class MulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
func(in.neg_min_denormal, in.min_denormal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
- }
}
+ }
void test_inexact_results(MulFunc func) {
InFPBits x_bits = InFPBits::one();
>From 801eb3938894ea8615c9a0d3cc1d737f23da14a4 Mon Sep 17 00:00:00 2001
From: Job Hernandez <hj93 at protonmail.com>
Date: Fri, 13 Sep 2024 22:04:18 -0700
Subject: [PATCH 16/22] address review
---
libc/src/math/generic/fmul.cpp | 3 +++
libc/test/src/math/fmul_test.cpp | 13 ++++---------
.../performance_testing/BinaryOpSingleOutputPerf.h | 1 -
libc/test/src/math/smoke/MulTest.h | 3 ---
4 files changed, 7 insertions(+), 13 deletions(-)
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
index 9330c8c92ae77b..f48ad2bc0c1278 100644
--- a/libc/src/math/generic/fmul.cpp
+++ b/libc/src/math/generic/fmul.cpp
@@ -116,6 +116,9 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
fputil::set_errno_if_required(ERANGE);
fputil::raise_except_if_required(FE_UNDERFLOW);
return result_f;
+
+ #endif
+
}
}
// namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/src/math/fmul_test.cpp b/libc/test/src/math/fmul_test.cpp
index d1caca0c38de20..01898cd6fd50f1 100644
--- a/libc/test/src/math/fmul_test.cpp
+++ b/libc/test/src/math/fmul_test.cpp
@@ -19,23 +19,18 @@ TEST_F(LlvmLibcMulTest, SpecialInputs) {
namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
double INPUTS[][2] = {
{0x1.0100010002p8, 0x1.fffcp14},
+ {0x1.000000b92144p-7, 0x1.62p7},
};
- constexpr float RESULTS[] = {
- 0x1.00fdfep+23f,
- };
-
- constexpr size_t N = sizeof(RESULTS) / sizeof(RESULTS[0]);
-
- for (size_t i = 0; i < N; ++i) {
+ for (size_t i = 0; i < 2; ++i) {
double a = INPUTS[i][0];
for (int j = 0; j < 180; ++j) {
a *= 0.5;
- mpfr::BinaryInput<double> input{INPUTS[i][0], INPUTS[i][1]};
+ mpfr::BinaryInput<double> input{a, INPUTS[i][1]};
ASSERT_MPFR_MATCH_ALL_ROUNDING(
mpfr::Operation::Mul, input,
- LIBC_NAMESPACE::fmul(INPUTS[i][0], INPUTS[i][1]), 0.5);
+ LIBC_NAMESPACE::fmul(a, INPUTS[i][1]), 0.5);
}
}
}
diff --git a/libc/test/src/math/performance_testing/BinaryOpSingleOutputPerf.h b/libc/test/src/math/performance_testing/BinaryOpSingleOutputPerf.h
index 98a1813bd7b54a..7a0ab5e74b0277 100644
--- a/libc/test/src/math/performance_testing/BinaryOpSingleOutputPerf.h
+++ b/libc/test/src/math/performance_testing/BinaryOpSingleOutputPerf.h
@@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
#include "src/__support/CPP/algorithm.h"
-#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/macros/config.h"
#include "test/src/math/performance_testing/Timer.h"
diff --git a/libc/test/src/math/smoke/MulTest.h b/libc/test/src/math/smoke/MulTest.h
index d586423795cedd..0c847e39687b72 100644
--- a/libc/test/src/math/smoke/MulTest.h
+++ b/libc/test/src/math/smoke/MulTest.h
@@ -70,7 +70,6 @@ class MulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
if (ForceRoundingMode r(RoundingMode::Nearest); r.success) {
EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(max_normal, max_normal),
FE_OVERFLOW | FE_INEXACT);
-
EXPECT_MATH_ERRNO(ERANGE);
EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, func(neg_max_normal, max_normal),
FE_OVERFLOW | FE_INEXACT);
@@ -102,7 +101,6 @@ class MulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
}
if (ForceRoundingMode r(RoundingMode::Downward); r.success) {
-
EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, func(max_normal, max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, func(neg_max_normal, max_normal),
@@ -112,7 +110,6 @@ class MulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.min_denormal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
-
EXPECT_FP_EQ_WITH_EXCEPTION(neg_min_denormal,
func(in.neg_min_denormal, in.min_denormal),
FE_UNDERFLOW | FE_INEXACT);
>From 8c3af580e23eb193d6235c0ebf9eaeebf80f9c31 Mon Sep 17 00:00:00 2001
From: Job Hernandez <hj93 at protonmail.com>
Date: Fri, 13 Sep 2024 22:11:39 -0700
Subject: [PATCH 17/22] address review
---
.../test/src/math/performance_testing/BinaryOpSingleOutputPerf.h | 1 +
libc/test/src/math/performance_testing/fmul_perf.cpp | 1 -
2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/libc/test/src/math/performance_testing/BinaryOpSingleOutputPerf.h b/libc/test/src/math/performance_testing/BinaryOpSingleOutputPerf.h
index 7a0ab5e74b0277..8ddeaf7c5ed813 100644
--- a/libc/test/src/math/performance_testing/BinaryOpSingleOutputPerf.h
+++ b/libc/test/src/math/performance_testing/BinaryOpSingleOutputPerf.h
@@ -8,6 +8,7 @@
#include "src/__support/CPP/algorithm.h"
#include "src/__support/macros/config.h"
+#include "src/__support/FPUtil/FPBits.h"
#include "test/src/math/performance_testing/Timer.h"
#include <cstddef>
diff --git a/libc/test/src/math/performance_testing/fmul_perf.cpp b/libc/test/src/math/performance_testing/fmul_perf.cpp
index d6156f1519c507..f15cfafbf29451 100644
--- a/libc/test/src/math/performance_testing/fmul_perf.cpp
+++ b/libc/test/src/math/performance_testing/fmul_perf.cpp
@@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
#include "BinaryOpSingleOutputPerf.h"
-#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/generic/mul.h"
#include "src/math/fmul.h"
>From 0deb4a9eed45a47ce3c5633ee06896081567e17c Mon Sep 17 00:00:00 2001
From: Job Hernandez <hj93 at protonmail.com>
Date: Fri, 13 Sep 2024 22:12:22 -0700
Subject: [PATCH 18/22] format code
---
libc/src/math/generic/fmul.cpp | 95 +++++++++----------
libc/test/src/math/fmul_test.cpp | 6 +-
.../BinaryOpSingleOutputPerf.h | 2 +-
3 files changed, 51 insertions(+), 52 deletions(-)
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
index f48ad2bc0c1278..dbc6439484e52a 100644
--- a/libc/src/math/generic/fmul.cpp
+++ b/libc/src/math/generic/fmul.cpp
@@ -55,70 +55,69 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
float result_f = static_cast<float>(result);
FloatBits rf_bits(result_f);
uint32_t rf_exp = rf_bits.get_biased_exponent();
- if (LIBC_LIKELY(rf_exp > 0 && rf_exp < 2*FloatBits::EXP_BIAS + 1)) {
+ if (LIBC_LIKELY(rf_exp > 0 && rf_exp < 2 * FloatBits::EXP_BIAS + 1)) {
return result_f;
}
// Now result_f is either inf/nan/zero/denormal.
if (x_bits.is_nan() || y_bits.is_nan()) {
- if (x_bits.is_signaling_nan() || y_bits.is_signaling_nan())
- fputil::raise_except_if_required(FE_INVALID);
-
- if (x_bits.is_quiet_nan()) {
- InStorageType x_payload = x_bits.get_mantissa();
- x_payload >>= InFPBits::FRACTION_LEN - OutFPBits::FRACTION_LEN;
- return OutFPBits::quiet_nan(x_bits.sign(),
- static_cast<OutStorageType>(x_payload))
- .get_val();
- }
-
- if (y_bits.is_quiet_nan()) {
- InStorageType y_payload = y_bits.get_mantissa();
- y_payload >>= InFPBits::FRACTION_LEN - OutFPBits::FRACTION_LEN;
- return OutFPBits::quiet_nan(y_bits.sign(),
- static_cast<OutStorageType>(y_payload))
- .get_val();
- }
-
- return OutFPBits::quiet_nan().get_val();
+ if (x_bits.is_signaling_nan() || y_bits.is_signaling_nan())
+ fputil::raise_except_if_required(FE_INVALID);
+
+ if (x_bits.is_quiet_nan()) {
+ InStorageType x_payload = x_bits.get_mantissa();
+ x_payload >>= InFPBits::FRACTION_LEN - OutFPBits::FRACTION_LEN;
+ return OutFPBits::quiet_nan(x_bits.sign(),
+ static_cast<OutStorageType>(x_payload))
+ .get_val();
}
- if (x_bits.is_inf()) {
- if (y_bits.is_zero()) {
- fputil::set_errno_if_required(EDOM);
- fputil::raise_except_if_required(FE_INVALID);
-
- return OutFPBits::quiet_nan().get_val();
- }
-
- return OutFPBits::inf(result_sign).get_val();
+ if (y_bits.is_quiet_nan()) {
+ InStorageType y_payload = y_bits.get_mantissa();
+ y_payload >>= InFPBits::FRACTION_LEN - OutFPBits::FRACTION_LEN;
+ return OutFPBits::quiet_nan(y_bits.sign(),
+ static_cast<OutStorageType>(y_payload))
+ .get_val();
}
- if (y_bits.is_inf()) {
- if (x_bits.is_zero()) {
- fputil::set_errno_if_required(EDOM);
- fputil::raise_except_if_required(FE_INVALID);
- return OutFPBits::quiet_nan().get_val();
- }
+ return OutFPBits::quiet_nan().get_val();
+ }
+
+ if (x_bits.is_inf()) {
+ if (y_bits.is_zero()) {
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
- return OutFPBits::inf(result_sign).get_val();
+ return OutFPBits::quiet_nan().get_val();
}
- // Now either x or y is zero, and the other one is finite.
- if (hif_bits.is_inf()) {
- fputil::set_errno_if_required(ERANGE);
- return OutFPBits::inf(result_sign).get_val();
+ return OutFPBits::inf(result_sign).get_val();
+ }
+
+ if (y_bits.is_inf()) {
+ if (x_bits.is_zero()) {
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
+ return OutFPBits::quiet_nan().get_val();
}
- if (x_bits.is_zero() || y_bits.is_zero())
- return FloatBits::zero(result_sign).get_val();
+ return OutFPBits::inf(result_sign).get_val();
+ }
+ // Now either x or y is zero, and the other one is finite.
+ if (hif_bits.is_inf()) {
fputil::set_errno_if_required(ERANGE);
- fputil::raise_except_if_required(FE_UNDERFLOW);
- return result_f;
+ return OutFPBits::inf(result_sign).get_val();
+ }
- #endif
-
-}
+ if (x_bits.is_zero() || y_bits.is_zero())
+ return FloatBits::zero(result_sign).get_val();
+
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_UNDERFLOW);
+ return result_f;
+
+#endif
}
+} // namespace LIBC_NAMESPACE_DECL
// namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/src/math/fmul_test.cpp b/libc/test/src/math/fmul_test.cpp
index 01898cd6fd50f1..488e087a325205 100644
--- a/libc/test/src/math/fmul_test.cpp
+++ b/libc/test/src/math/fmul_test.cpp
@@ -28,9 +28,9 @@ TEST_F(LlvmLibcMulTest, SpecialInputs) {
for (int j = 0; j < 180; ++j) {
a *= 0.5;
mpfr::BinaryInput<double> input{a, INPUTS[i][1]};
- ASSERT_MPFR_MATCH_ALL_ROUNDING(
- mpfr::Operation::Mul, input,
- LIBC_NAMESPACE::fmul(a, INPUTS[i][1]), 0.5);
+ ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Mul, input,
+ LIBC_NAMESPACE::fmul(a, INPUTS[i][1]),
+ 0.5);
}
}
}
diff --git a/libc/test/src/math/performance_testing/BinaryOpSingleOutputPerf.h b/libc/test/src/math/performance_testing/BinaryOpSingleOutputPerf.h
index 8ddeaf7c5ed813..98a1813bd7b54a 100644
--- a/libc/test/src/math/performance_testing/BinaryOpSingleOutputPerf.h
+++ b/libc/test/src/math/performance_testing/BinaryOpSingleOutputPerf.h
@@ -7,8 +7,8 @@
//===----------------------------------------------------------------------===//
#include "src/__support/CPP/algorithm.h"
-#include "src/__support/macros/config.h"
#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/macros/config.h"
#include "test/src/math/performance_testing/Timer.h"
#include <cstddef>
>From 2161862d8dc0a2fda5487ea4854b7592f5c0433c Mon Sep 17 00:00:00 2001
From: Job Hernandez <hj93 at protonmail.com>
Date: Sat, 14 Sep 2024 12:13:49 -0700
Subject: [PATCH 19/22] address review
---
libc/src/math/generic/fmul.cpp | 53 ++++++++++++++++------------------
1 file changed, 25 insertions(+), 28 deletions(-)
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
index dbc6439484e52a..ea5f7d928c0a6d 100644
--- a/libc/src/math/generic/fmul.cpp
+++ b/libc/src/math/generic/fmul.cpp
@@ -18,24 +18,22 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
+ /* Without FMA instructions, fputil::exact_mult is not
+ correctly rounded for all rounding modes, so we fall
+ back to the generic `fmul` implementation
+ */
#ifndef LIBC_TARGET_CPU_HAS_FMA
return fputil::generic::mul<float>(x, y);
#else
fputil::DoubleDouble prod = fputil::exact_mult(x, y);
- float prod_hif = static_cast<float>(prod.hi);
- fputil::FPBits<float> hif_bits(prod_hif);
- using OutFPBits = fputil::FPBits<float>;
- using OutStorageType = typename OutFPBits::StorageType;
- using InFPBits = fputil::FPBits<double>;
- using InStorageType = typename InFPBits::StorageType;
-
- InFPBits x_bits(x);
- InFPBits y_bits(y);
-
- Sign result_sign = x_bits.sign() == y_bits.sign() ? Sign::POS : Sign::NEG;
-
using DoubleBits = fputil::FPBits<double>;
+ using DoubleStorageType = typename DoubleBits::StorageType;
using FloatBits = fputil::FPBits<float>;
+ using FloatStorageType = typename FloatBits::StorageType;
+ DoubleBits x_bits(x);
+ DoubleBits y_bits(y);
+
+ Sign result_sign = x_bits.sign() == y_bits.sign() ? Sign::POS : Sign::NEG;
double result = prod.hi;
DoubleBits hi_bits(prod.hi), lo_bits(prod.lo);
// Check for cases where we need to propagate the sticky bits:
@@ -65,22 +63,22 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
fputil::raise_except_if_required(FE_INVALID);
if (x_bits.is_quiet_nan()) {
- InStorageType x_payload = x_bits.get_mantissa();
- x_payload >>= InFPBits::FRACTION_LEN - OutFPBits::FRACTION_LEN;
- return OutFPBits::quiet_nan(x_bits.sign(),
- static_cast<OutStorageType>(x_payload))
+ DoubleStorageType x_payload = x_bits.get_mantissa();
+ x_payload >>= DoubleBits::FRACTION_LEN - FloatBits::FRACTION_LEN;
+ return FloatBits::quiet_nan(x_bits.sign(),
+ static_cast<FloatStorageType>(x_payload))
.get_val();
}
if (y_bits.is_quiet_nan()) {
- InStorageType y_payload = y_bits.get_mantissa();
- y_payload >>= InFPBits::FRACTION_LEN - OutFPBits::FRACTION_LEN;
- return OutFPBits::quiet_nan(y_bits.sign(),
- static_cast<OutStorageType>(y_payload))
+ DoubleStorageType y_payload = y_bits.get_mantissa();
+ y_payload >>= DoubleBits::FRACTION_LEN - FloatBits::FRACTION_LEN;
+ return FloatBits::quiet_nan(y_bits.sign(),
+ static_cast<FloatStorageType>(y_payload))
.get_val();
}
- return OutFPBits::quiet_nan().get_val();
+ return FloatBits::quiet_nan().get_val();
}
if (x_bits.is_inf()) {
@@ -88,26 +86,26 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
fputil::set_errno_if_required(EDOM);
fputil::raise_except_if_required(FE_INVALID);
- return OutFPBits::quiet_nan().get_val();
+ return FloatBits::quiet_nan().get_val();
}
- return OutFPBits::inf(result_sign).get_val();
+ return FloatBits::inf(result_sign).get_val();
}
if (y_bits.is_inf()) {
if (x_bits.is_zero()) {
fputil::set_errno_if_required(EDOM);
fputil::raise_except_if_required(FE_INVALID);
- return OutFPBits::quiet_nan().get_val();
+ return FloatBits::quiet_nan().get_val();
}
- return OutFPBits::inf(result_sign).get_val();
+ return FloatBits::inf(result_sign).get_val();
}
// Now either x or y is zero, and the other one is finite.
- if (hif_bits.is_inf()) {
+ if (rf_bits.is_inf()) {
fputil::set_errno_if_required(ERANGE);
- return OutFPBits::inf(result_sign).get_val();
+ return FloatBits::inf(result_sign).get_val();
}
if (x_bits.is_zero() || y_bits.is_zero())
@@ -120,4 +118,3 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
#endif
}
} // namespace LIBC_NAMESPACE_DECL
-// namespace LIBC_NAMESPACE_DECL
>From fa5a8af5e0e022301ab4cbd0f790081ee66034a2 Mon Sep 17 00:00:00 2001
From: Job Hernandez <hj93 at protonmail.com>
Date: Sat, 14 Sep 2024 12:14:10 -0700
Subject: [PATCH 20/22] format code
---
libc/src/math/generic/fmul.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
index ea5f7d928c0a6d..a8d82ee0bd07eb 100644
--- a/libc/src/math/generic/fmul.cpp
+++ b/libc/src/math/generic/fmul.cpp
@@ -21,7 +21,7 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
/* Without FMA instructions, fputil::exact_mult is not
correctly rounded for all rounding modes, so we fall
back to the generic `fmul` implementation
- */
+ */
#ifndef LIBC_TARGET_CPU_HAS_FMA
return fputil::generic::mul<float>(x, y);
#else
>From 78d388c74f1b29888451936f8af23ac76dd4ae14 Mon Sep 17 00:00:00 2001
From: Job Hernandez <hj93 at protonmail.com>
Date: Sat, 14 Sep 2024 12:37:12 -0700
Subject: [PATCH 21/22] address review
---
libc/src/math/generic/fmul.cpp | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
index a8d82ee0bd07eb..2454359e717481 100644
--- a/libc/src/math/generic/fmul.cpp
+++ b/libc/src/math/generic/fmul.cpp
@@ -12,16 +12,15 @@
#include "src/__support/FPUtil/generic/mul.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
-#include <iostream>
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
- /* Without FMA instructions, fputil::exact_mult is not
- correctly rounded for all rounding modes, so we fall
- back to the generic `fmul` implementation
- */
+ // Without FMA instructions, fputil::exact_mult is not
+ // correctly rounded for all rounding modes, so we fall
+ // back to the generic `fmul` implementation
+
#ifndef LIBC_TARGET_CPU_HAS_FMA
return fputil::generic::mul<float>(x, y);
#else
>From f19954caffe70f6406918f5fe948eb13312feba9 Mon Sep 17 00:00:00 2001
From: Job Hernandez <hj93 at protonmail.com>
Date: Sat, 14 Sep 2024 12:37:34 -0700
Subject: [PATCH 22/22] format code
---
libc/src/math/generic/fmul.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
index 2454359e717481..e759e48cd6989a 100644
--- a/libc/src/math/generic/fmul.cpp
+++ b/libc/src/math/generic/fmul.cpp
@@ -20,7 +20,7 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
// Without FMA instructions, fputil::exact_mult is not
// correctly rounded for all rounding modes, so we fall
// back to the generic `fmul` implementation
-
+
#ifndef LIBC_TARGET_CPU_HAS_FMA
return fputil::generic::mul<float>(x, y);
#else
More information about the libc-commits
mailing list