Skip to content

Commit

Permalink
[libc] Add implementations of ilogb[f|l].
Browse files Browse the repository at this point in the history
Depends on D90805.

Reviewed By: lntue

Differential Revision: https://reviews.llvm.org/D90806
  • Loading branch information
Siva Chandra Reddy committed Nov 6, 2020
1 parent e9e2e31 commit 930cf1c
Show file tree
Hide file tree
Showing 18 changed files with 460 additions and 0 deletions.
3 changes: 3 additions & 0 deletions libc/config/linux/aarch64/entrypoints.txt
Expand Up @@ -65,6 +65,9 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.frexpf
libc.src.math.frexpl
libc.src.math.hypotf
libc.src.math.ilogb
libc.src.math.ilogbf
libc.src.math.ilogbl
libc.src.math.logb
libc.src.math.logbf
libc.src.math.logbl
Expand Down
3 changes: 3 additions & 0 deletions libc/config/linux/api.td
Expand Up @@ -144,6 +144,9 @@ def MathAPI : PublicAPI<"math.h"> {
SimpleMacroDef<"INFINITY", "__builtin_inff()">,
SimpleMacroDef<"NAN", "__builtin_nanf(\"\")">,

SimpleMacroDef<"FP_ILOGB0", "(-__INT_MAX__ - 1)">, // INT_MIN
SimpleMacroDef<"FP_ILOGBNAN", "__INT_MAX__">,

IsFiniteMacro,
IsInfMacro,
IsNanMacro,
Expand Down
3 changes: 3 additions & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Expand Up @@ -98,6 +98,9 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.frexpf
libc.src.math.frexpl
libc.src.math.hypotf
libc.src.math.ilogb
libc.src.math.ilogbf
libc.src.math.ilogbl
libc.src.math.logb
libc.src.math.logbf
libc.src.math.logbl
Expand Down
7 changes: 7 additions & 0 deletions libc/spec/stdc.td
Expand Up @@ -233,6 +233,9 @@ def StdC : StandardSpec<"stdc"> {
Macro<"INFINITY">,
Macro<"NAN">,

Macro<"FP_ILOGB0">,
Macro<"FP_ILOGBNAN">,

Macro<"isfinite">,
Macro<"isinf">,
Macro<"isnan">,
Expand Down Expand Up @@ -273,6 +276,10 @@ def StdC : StandardSpec<"stdc"> {

FunctionSpec<"hypotf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,

FunctionSpec<"ilogb", RetValSpec<IntType>, [ArgSpec<DoubleType>]>,
FunctionSpec<"ilogbf", RetValSpec<IntType>, [ArgSpec<FloatType>]>,
FunctionSpec<"ilogbl", RetValSpec<IntType>, [ArgSpec<LongDoubleType>]>,

FunctionSpec<"logb", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
FunctionSpec<"logbf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
FunctionSpec<"logbl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>,
Expand Down
36 changes: 36 additions & 0 deletions libc/src/math/CMakeLists.txt
Expand Up @@ -342,6 +342,42 @@ add_entrypoint_object(
-O2
)

add_entrypoint_object(
ilogb
SRCS
ilogb.cpp
HDRS
ilogb.h
DEPENDS
libc.utils.FPUtil.fputil
COMPILE_OPTIONS
-O2
)

add_entrypoint_object(
ilogbf
SRCS
ilogbf.cpp
HDRS
ilogbf.h
DEPENDS
libc.utils.FPUtil.fputil
COMPILE_OPTIONS
-O2
)

add_entrypoint_object(
ilogbl
SRCS
ilogbl.cpp
HDRS
ilogbl.h
DEPENDS
libc.utils.FPUtil.fputil
COMPILE_OPTIONS
-O2
)

add_entrypoint_object(
logb
SRCS
Expand Down
16 changes: 16 additions & 0 deletions libc/src/math/ilogb.cpp
@@ -0,0 +1,16 @@
//===-- Implementation of ilogb 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/ManipulationFunctions.h"

namespace __llvm_libc {

int LLVM_LIBC_ENTRYPOINT(ilogb)(double x) { return fputil::ilogb(x); }

} // namespace __llvm_libc
18 changes: 18 additions & 0 deletions libc/src/math/ilogb.h
@@ -0,0 +1,18 @@
//===-- Implementation header for ilogb -------------------------*- 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_ILOGB_H
#define LLVM_LIBC_SRC_MATH_ILOGB_H

namespace __llvm_libc {

int ilogb(double x);

} // namespace __llvm_libc

#endif // LLVM_LIBC_SRC_MATH_ILOGB_H
16 changes: 16 additions & 0 deletions libc/src/math/ilogbf.cpp
@@ -0,0 +1,16 @@
//===-- Implementation of ilogbf 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/ManipulationFunctions.h"

namespace __llvm_libc {

int LLVM_LIBC_ENTRYPOINT(ilogbf)(float x) { return fputil::ilogb(x); }

} // namespace __llvm_libc
18 changes: 18 additions & 0 deletions libc/src/math/ilogbf.h
@@ -0,0 +1,18 @@
//===-- Implementation header for ilogbf ------------------------*- 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_ILOGBF_H
#define LLVM_LIBC_SRC_MATH_ILOGBF_H

namespace __llvm_libc {

int ilogbf(float x);

} // namespace __llvm_libc

#endif // LLVM_LIBC_SRC_MATH_ILOGBF_H
16 changes: 16 additions & 0 deletions libc/src/math/ilogbl.cpp
@@ -0,0 +1,16 @@
//===-- Implementation of ilogbl 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/ManipulationFunctions.h"

namespace __llvm_libc {

int LLVM_LIBC_ENTRYPOINT(ilogbl)(long double x) { return fputil::ilogb(x); }

} // namespace __llvm_libc
18 changes: 18 additions & 0 deletions libc/src/math/ilogbl.h
@@ -0,0 +1,18 @@
//===-- Implementation header for ilogbl ------------------------*- 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_ILOGBL_H
#define LLVM_LIBC_SRC_MATH_ILOGBL_H

namespace __llvm_libc {

int ilogbl(long double x);

} // namespace __llvm_libc

#endif // LLVM_LIBC_SRC_MATH_ILOGBL_H
42 changes: 42 additions & 0 deletions libc/test/src/math/CMakeLists.txt
Expand Up @@ -370,6 +370,48 @@ add_fp_unittest(
libc.utils.FPUtil.fputil
)

add_fp_unittest(
ilogb_test
SUITE
libc_math_unittests
SRCS
ilogb_test.cpp
HDRS
ILogbTest.h
DEPENDS
libc.include.math
libc.src.math.ilogb
libc.utils.FPUtil.fputil
)

add_fp_unittest(
ilogbf_test
SUITE
libc_math_unittests
SRCS
ilogbf_test.cpp
HDRS
ILogbTest.h
DEPENDS
libc.include.math
libc.src.math.ilogbf
libc.utils.FPUtil.fputil
)

add_fp_unittest(
ilogbl_test
SUITE
libc_math_unittests
SRCS
ilogbl_test.cpp
HDRS
ILogbTest.h
DEPENDS
libc.include.math
libc.src.math.ilogbl
libc.utils.FPUtil.fputil
)

add_fp_unittest(
logb_test
SUITE
Expand Down
108 changes: 108 additions & 0 deletions libc/test/src/math/ILogbTest.h
@@ -0,0 +1,108 @@
//===-- Utility class to test different flavors of ilogb --------*- 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_TEST_SRC_MATH_ILOGBTEST_H
#define LLVM_LIBC_TEST_SRC_MATH_ILOGBTEST_H

#include "include/math.h"
#include "utils/FPUtil/FPBits.h"
#include "utils/FPUtil/ManipulationFunctions.h"
#include "utils/UnitTest/Test.h"

#include <limits.h>

class ILogbTest : public __llvm_libc::testing::Test {
public:
template <typename T> struct ILogbFunc { typedef int (*Func)(T); };

template <typename T>
void testSpecialNumbers(typename ILogbFunc<T>::Func func) {
EXPECT_EQ(FP_ILOGB0, func(__llvm_libc::fputil::FPBits<T>::zero()));
EXPECT_EQ(FP_ILOGB0, func(__llvm_libc::fputil::FPBits<T>::negZero()));

EXPECT_EQ(FP_ILOGBNAN, func(__llvm_libc::fputil::FPBits<T>::buildNaN(1)));

EXPECT_EQ(INT_MAX, func(__llvm_libc::fputil::FPBits<T>::inf()));
EXPECT_EQ(INT_MAX, func(__llvm_libc::fputil::FPBits<T>::negInf()));
}

template <typename T> void testPowersOfTwo(typename ILogbFunc<T>::Func func) {
EXPECT_EQ(0, func(T(1.0)));
EXPECT_EQ(0, func(T(-1.0)));

EXPECT_EQ(1, func(T(2.0)));
EXPECT_EQ(1, func(T(-2.0)));

EXPECT_EQ(2, func(T(4.0)));
EXPECT_EQ(2, func(T(-4.0)));

EXPECT_EQ(3, func(T(8.0)));
EXPECT_EQ(3, func(-8.0));

EXPECT_EQ(4, func(16.0));
EXPECT_EQ(4, func(-16.0));

EXPECT_EQ(5, func(32.0));
EXPECT_EQ(5, func(-32.0));
}

template <typename T>
void testSomeIntegers(typename ILogbFunc<T>::Func func) {
EXPECT_EQ(1, func(T(3.0)));
EXPECT_EQ(1, func(T(-3.0)));

EXPECT_EQ(2, func(T(7.0)));
EXPECT_EQ(2, func(T(-7.0)));

EXPECT_EQ(3, func(T(10.0)));
EXPECT_EQ(3, func(T(-10.0)));

EXPECT_EQ(4, func(T(31.0)));
EXPECT_EQ(4, func(-31.0));

EXPECT_EQ(5, func(55.0));
EXPECT_EQ(5, func(-55.0));
}

template <typename T>
void testSubnormalRange(typename ILogbFunc<T>::Func func) {
using FPBits = __llvm_libc::fputil::FPBits<T>;
using UIntType = typename FPBits::UIntType;
constexpr UIntType count = 1000001;
constexpr UIntType step =
(FPBits::maxSubnormal - FPBits::minSubnormal) / count;
for (UIntType v = FPBits::minSubnormal; v <= FPBits::maxSubnormal;
v += step) {
T x = FPBits(v);
if (isnan(x) || isinf(x) || x == 0.0)
continue;

int exponent;
__llvm_libc::fputil::frexp(x, exponent);
ASSERT_EQ(exponent, func(x) + 1);
}
}

template <typename T> void testNormalRange(typename ILogbFunc<T>::Func func) {
using FPBits = __llvm_libc::fputil::FPBits<T>;
using UIntType = typename FPBits::UIntType;
constexpr UIntType count = 1000001;
constexpr UIntType step = (FPBits::maxNormal - FPBits::minNormal) / count;
for (UIntType v = FPBits::minNormal; v <= FPBits::maxNormal; v += step) {
T x = FPBits(v);
if (isnan(x) || isinf(x) || x == 0.0)
continue;

int exponent;
__llvm_libc::fputil::frexp(x, exponent);
ASSERT_EQ(exponent, func(x) + 1);
}
}
};

#endif // LLVM_LIBC_TEST_SRC_MATH_ILOGBTEST_H

0 comments on commit 930cf1c

Please sign in to comment.