[libc-commits] [libc] 4a39a33 - [libc] Add implementation of fabs and fabsf.
Siva Chandra Reddy via libc-commits
libc-commits at lists.llvm.org
Fri May 15 11:20:03 PDT 2020
Author: Siva Chandra Reddy
Date: 2020-05-15T11:10:43-07:00
New Revision: 4a39a33d44f2f95dd95af9d8c1d95f21a65394f6
URL: https://github.com/llvm/llvm-project/commit/4a39a33d44f2f95dd95af9d8c1d95f21a65394f6
DIFF: https://github.com/llvm/llvm-project/commit/4a39a33d44f2f95dd95af9d8c1d95f21a65394f6.diff
LOG: [libc] Add implementation of fabs and fabsf.
Reviewers: phosek
Differential Revision: https://reviews.llvm.org/D79725
Added:
libc/src/math/fabs.cpp
libc/src/math/fabs.h
libc/src/math/fabsf.cpp
libc/src/math/fabsf.h
libc/test/src/math/fabs_test.cpp
libc/test/src/math/fabsf_test.cpp
Modified:
libc/config/linux/api.td
libc/lib/CMakeLists.txt
libc/spec/stdc.td
libc/src/math/CMakeLists.txt
libc/test/src/math/CMakeLists.txt
libc/utils/FPUtil/FloatOperations.h
libc/utils/MPFRWrapper/MPFRUtils.cpp
libc/utils/MPFRWrapper/MPFRUtils.h
Removed:
################################################################################
diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td
index 7d81c0d7e95b..3eb7ead48365 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -150,6 +150,8 @@ def MathAPI : PublicAPI<"math.h"> {
];
let Functions = [
"cosf",
+ "fabs",
+ "fabsf",
"round",
"sincosf",
"sinf",
diff --git a/libc/lib/CMakeLists.txt b/libc/lib/CMakeLists.txt
index 561ab38bc94d..2e103ee3ecf4 100644
--- a/libc/lib/CMakeLists.txt
+++ b/libc/lib/CMakeLists.txt
@@ -48,6 +48,8 @@ add_entrypoint_library(
DEPENDS
# math.h entrypoints
libc.src.math.cosf
+ libc.src.math.fabs
+ libc.src.math.fabsf
libc.src.math.round
libc.src.math.sincosf
libc.src.math.sinf
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 46296456df24..102f878d2fe0 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -182,6 +182,9 @@ def StdC : StandardSpec<"stdc"> {
],
[], // Enumerations
[
+ FunctionSpec<"fabs", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
+ FunctionSpec<"fabsf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+
FunctionSpec<"cosf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
FunctionSpec<"sinf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 5ec98ddd18dd..f74577ba85a1 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -68,3 +68,23 @@ add_entrypoint_object(
libc.include.math
libc.src.errno.__errno_location
)
+
+add_entrypoint_object(
+ fabs
+ SRCS
+ fabs.cpp
+ HDRS
+ fabs.h
+ DEPENDS
+ libc.utils.FPUtil.fputil
+)
+
+add_entrypoint_object(
+ fabsf
+ SRCS
+ fabsf.cpp
+ HDRS
+ fabsf.h
+ DEPENDS
+ libc.utils.FPUtil.fputil
+)
diff --git a/libc/src/math/fabs.cpp b/libc/src/math/fabs.cpp
new file mode 100644
index 000000000000..15c60e88eb72
--- /dev/null
+++ b/libc/src/math/fabs.cpp
@@ -0,0 +1,16 @@
+//===-- Implementation of fabs 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/__support/common.h"
+#include "utils/FPUtil/FloatOperations.h"
+
+namespace __llvm_libc {
+
+double LLVM_LIBC_ENTRYPOINT(fabs)(double x) { return fputil::abs(x); }
+
+} // namespace __llvm_libc
diff --git a/libc/src/math/fabs.h b/libc/src/math/fabs.h
new file mode 100644
index 000000000000..424d2e01646b
--- /dev/null
+++ b/libc/src/math/fabs.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for fabs --------------------------*- 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_FABS_H
+#define LLVM_LIBC_SRC_MATH_FABS_H
+
+namespace __llvm_libc {
+
+double fabs(double x);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_MATH_FABS_H
diff --git a/libc/src/math/fabsf.cpp b/libc/src/math/fabsf.cpp
new file mode 100644
index 000000000000..dd2b055ed0dd
--- /dev/null
+++ b/libc/src/math/fabsf.cpp
@@ -0,0 +1,16 @@
+//===-- Implementation of fabsf 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/__support/common.h"
+#include "utils/FPUtil/FloatOperations.h"
+
+namespace __llvm_libc {
+
+float LLVM_LIBC_ENTRYPOINT(fabsf)(float x) { return fputil::abs(x); }
+
+} // namespace __llvm_libc
diff --git a/libc/src/math/fabsf.h b/libc/src/math/fabsf.h
new file mode 100644
index 000000000000..0ad97a027c6c
--- /dev/null
+++ b/libc/src/math/fabsf.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for fabsf -------------------------*- 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_FABSF_H
+#define LLVM_LIBC_SRC_MATH_FABSF_H
+
+namespace __llvm_libc {
+
+float fabsf(float x);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_MATH_FABSF_H
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index 3790a476369e..3ea485c34301 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -70,3 +70,29 @@ add_math_unittest(
libc.utils.CPP.standalone_cpp
libc.utils.FPUtil.fputil
)
+
+add_math_unittest(
+ fabs_test
+ NEED_MPFR
+ SUITE
+ libc_math_unittests
+ SRCS
+ fabs_test.cpp
+ DEPENDS
+ libc.include.math
+ libc.src.math.fabs
+ libc.utils.FPUtil.fputil
+)
+
+add_math_unittest(
+ fabsf_test
+ NEED_MPFR
+ SUITE
+ libc_math_unittests
+ SRCS
+ fabsf_test.cpp
+ DEPENDS
+ libc.include.math
+ libc.src.math.fabsf
+ libc.utils.FPUtil.fputil
+)
diff --git a/libc/test/src/math/fabs_test.cpp b/libc/test/src/math/fabs_test.cpp
new file mode 100644
index 000000000000..a4c934b07f5a
--- /dev/null
+++ b/libc/test/src/math/fabs_test.cpp
@@ -0,0 +1,64 @@
+//===-- Unittests for fabs ------------------------------------------------===//
+//
+// 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 "include/math.h"
+#include "src/math/fabs.h"
+#include "utils/FPUtil/BitPatterns.h"
+#include "utils/FPUtil/FloatOperations.h"
+#include "utils/FPUtil/FloatProperties.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+#include "utils/UnitTest/Test.h"
+
+using __llvm_libc::fputil::valueAsBits;
+using __llvm_libc::fputil::valueFromBits;
+
+using BitPatterns = __llvm_libc::fputil::BitPatterns<double>;
+using Properties = __llvm_libc::fputil::FloatProperties<double>;
+
+namespace mpfr = __llvm_libc::testing::mpfr;
+
+// Zero tolerance; As in, exact match with MPFR result.
+static constexpr mpfr::Tolerance tolerance{mpfr::Tolerance::doublePrecision, 0,
+ 0};
+
+TEST(FabsTest, SpecialNumbers) {
+ EXPECT_EQ(
+ BitPatterns::aQuietNaN,
+ valueAsBits(__llvm_libc::fabs(valueFromBits(BitPatterns::aQuietNaN))));
+ EXPECT_EQ(BitPatterns::aQuietNaN, valueAsBits(__llvm_libc::fabs(valueFromBits(
+ BitPatterns::aNegativeQuietNaN))));
+
+ EXPECT_EQ(BitPatterns::aSignallingNaN,
+ valueAsBits(
+ __llvm_libc::fabs(valueFromBits(BitPatterns::aSignallingNaN))));
+ EXPECT_EQ(BitPatterns::aSignallingNaN,
+ valueAsBits(__llvm_libc::fabs(
+ valueFromBits(BitPatterns::aNegativeSignallingNaN))));
+
+ EXPECT_EQ(BitPatterns::inf,
+ valueAsBits(__llvm_libc::fabs(valueFromBits(BitPatterns::inf))));
+ EXPECT_EQ(BitPatterns::inf,
+ valueAsBits(__llvm_libc::fabs(valueFromBits(BitPatterns::negInf))));
+
+ EXPECT_EQ(BitPatterns::zero,
+ valueAsBits(__llvm_libc::fabs(valueFromBits(BitPatterns::zero))));
+ EXPECT_EQ(BitPatterns::zero, valueAsBits(__llvm_libc::fabs(
+ valueFromBits(BitPatterns::negZero))));
+}
+
+TEST(FabsTest, InDoubleRange) {
+ using BitsType = Properties::BitsType;
+ constexpr BitsType count = 1000000;
+ constexpr BitsType step = UINT64_MAX / count;
+ for (BitsType i = 0, v = 0; i <= count; ++i, v += step) {
+ double x = valueFromBits(v);
+ if (isnan(x) || isinf(x))
+ continue;
+ ASSERT_MPFR_MATCH(mpfr::OP_Abs, x, __llvm_libc::fabs(x), tolerance);
+ }
+}
diff --git a/libc/test/src/math/fabsf_test.cpp b/libc/test/src/math/fabsf_test.cpp
new file mode 100644
index 000000000000..40e61e6091b6
--- /dev/null
+++ b/libc/test/src/math/fabsf_test.cpp
@@ -0,0 +1,66 @@
+//===-- Unittests for fabsf -----------------------------------------------===//
+//
+// 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 "include/math.h"
+#include "src/math/fabsf.h"
+#include "utils/FPUtil/BitPatterns.h"
+#include "utils/FPUtil/FloatOperations.h"
+#include "utils/FPUtil/FloatProperties.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+#include "utils/UnitTest/Test.h"
+
+using __llvm_libc::fputil::valueAsBits;
+using __llvm_libc::fputil::valueFromBits;
+
+using BitPatterns = __llvm_libc::fputil::BitPatterns<float>;
+using Properties = __llvm_libc::fputil::FloatProperties<float>;
+
+namespace mpfr = __llvm_libc::testing::mpfr;
+
+// Zero tolerance; As in, exact match with MPFR result.
+static constexpr mpfr::Tolerance tolerance{mpfr::Tolerance::floatPrecision, 0,
+ 0};
+
+namespace mpfr = __llvm_libc::testing::mpfr;
+TEST(FabsfTest, SpecialNumbers) {
+ EXPECT_EQ(
+ BitPatterns::aQuietNaN,
+ valueAsBits(__llvm_libc::fabsf(valueFromBits(BitPatterns::aQuietNaN))));
+ EXPECT_EQ(BitPatterns::aQuietNaN,
+ valueAsBits(__llvm_libc::fabsf(
+ valueFromBits(BitPatterns::aNegativeQuietNaN))));
+
+ EXPECT_EQ(BitPatterns::aSignallingNaN,
+ valueAsBits(__llvm_libc::fabsf(
+ valueFromBits(BitPatterns::aSignallingNaN))));
+ EXPECT_EQ(BitPatterns::aSignallingNaN,
+ valueAsBits(__llvm_libc::fabsf(
+ valueFromBits(BitPatterns::aNegativeSignallingNaN))));
+
+ EXPECT_EQ(BitPatterns::inf,
+ valueAsBits(__llvm_libc::fabsf(valueFromBits(BitPatterns::inf))));
+ EXPECT_EQ(BitPatterns::inf, valueAsBits(__llvm_libc::fabsf(
+ valueFromBits(BitPatterns::negInf))));
+
+ EXPECT_EQ(BitPatterns::zero,
+ valueAsBits(__llvm_libc::fabsf(valueFromBits(BitPatterns::zero))));
+ EXPECT_EQ(BitPatterns::zero, valueAsBits(__llvm_libc::fabsf(
+ valueFromBits(BitPatterns::negZero))));
+}
+
+TEST(FabsfTest, InFloatRange) {
+ using BitsType = Properties::BitsType;
+ constexpr BitsType count = 1000000;
+ constexpr BitsType step = UINT32_MAX / count;
+ for (BitsType i = 0, v = 0; i <= count; ++i, v += step) {
+ double x = valueFromBits(v);
+ if (isnan(x) || isinf(x))
+ continue;
+ ASSERT_MPFR_MATCH(mpfr::OP_Abs, x, __llvm_libc::fabsf(x), tolerance);
+ }
+}
diff --git a/libc/utils/FPUtil/FloatOperations.h b/libc/utils/FPUtil/FloatOperations.h
index 902929eb8d47..ff7604bc8102 100644
--- a/libc/utils/FPUtil/FloatOperations.h
+++ b/libc/utils/FPUtil/FloatOperations.h
@@ -96,6 +96,13 @@ static inline bool isNegativeQuietNaN(T x) {
((bits & Properties::quietNaNMask) != 0);
}
+// Return the absolute value of x.
+template <typename T,
+ cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
+static inline T abs(T x) {
+ return valueFromBits(absBits(x));
+}
+
} // namespace fputil
} // namespace __llvm_libc
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp
index 74bb07a94bf6..fe84c381114e 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.cpp
+++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp
@@ -86,6 +86,9 @@ class MPFRNumber {
mpfr_init2(value, mpfrPrecision);
MPFRNumber mpfrInput(rawValue);
switch (op) {
+ case OP_Abs:
+ mpfr_abs(value, mpfrInput.value, MPFR_RNDN);
+ break;
case OP_Cos:
mpfr_cos(value, mpfrInput.value, MPFR_RNDN);
break;
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.h b/libc/utils/MPFRWrapper/MPFRUtils.h
index 6cdba34882d5..f94a146a35f2 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.h
+++ b/libc/utils/MPFRWrapper/MPFRUtils.h
@@ -40,6 +40,7 @@ struct Tolerance {
};
enum Operation {
+ OP_Abs,
OP_Cos,
OP_Sin,
};
More information about the libc-commits
mailing list