[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