20 changes: 20 additions & 0 deletions libc/src/math/ldexpf128.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation header for ldexpf128 ---------------------*- 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_LDEXPF128_H
#define LLVM_LIBC_SRC_MATH_LDEXPF128_H

#include "src/__support/macros/properties/float.h"

namespace LIBC_NAMESPACE {

float128 ldexpf128(float128 x, int exp);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_MATH_LDEXPF128_H
34 changes: 34 additions & 0 deletions libc/test/src/__support/FPUtil/dyadic_float_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,37 @@ TEST(LlvmLibcDyadicFloatTest, QuickMul) {
Float256 z = quick_mul(x, y);
EXPECT_FP_EQ_ALL_ROUNDING(double(x) * double(y), double(z));
}

#define TEST_EDGE_RANGES(Name, Type) \
TEST(LlvmLibcDyadicFloatTest, EdgeRanges##Name) { \
using Bits = LIBC_NAMESPACE::fputil::FPBits<Type>; \
using DFType = LIBC_NAMESPACE::fputil::DyadicFloat<Bits::STORAGE_LEN>; \
Type max_normal = Bits::max_normal().get_val(); \
Type min_normal = Bits::min_normal().get_val(); \
Type min_subnormal = Bits::min_subnormal().get_val(); \
Type two(2); \
\
DFType x(min_normal); \
EXPECT_FP_EQ_ALL_ROUNDING(min_normal, static_cast<Type>(x)); \
--x.exponent; \
EXPECT_FP_EQ(min_normal / two, static_cast<Type>(x)); \
\
DFType y(two *min_normal - min_subnormal); \
--y.exponent; \
EXPECT_FP_EQ(min_normal, static_cast<Type>(y)); \
\
DFType z(min_subnormal); \
EXPECT_FP_EQ_ALL_ROUNDING(min_subnormal, static_cast<Type>(z)); \
--z.exponent; \
EXPECT_FP_EQ(Bits::zero().get_val(), static_cast<Type>(z)); \
\
DFType t(max_normal); \
EXPECT_FP_EQ_ALL_ROUNDING(max_normal, static_cast<Type>(t)); \
++t.exponent; \
EXPECT_FP_EQ(Bits::inf().get_val(), static_cast<Type>(t)); \
} \
static_assert(true, "Require semicolon.")

TEST_EDGE_RANGES(Float, float);
TEST_EDGE_RANGES(Double, double);
TEST_EDGE_RANGES(LongDouble, long double);
18 changes: 15 additions & 3 deletions libc/test/src/math/smoke/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -878,7 +878,6 @@ add_fp_unittest(
HDRS
LdExpTest.h
DEPENDS
libc.include.math
libc.src.math.ldexp
libc.src.__support.CPP.limits
libc.src.__support.FPUtil.fp_bits
Expand All @@ -894,7 +893,6 @@ add_fp_unittest(
HDRS
LdExpTest.h
DEPENDS
libc.include.math
libc.src.math.ldexpf
libc.src.__support.CPP.limits
libc.src.__support.FPUtil.fp_bits
Expand All @@ -910,13 +908,27 @@ add_fp_unittest(
HDRS
LdExpTest.h
DEPENDS
libc.include.math
libc.src.math.ldexpl
libc.src.__support.CPP.limits
libc.src.__support.FPUtil.fp_bits
libc.src.__support.FPUtil.normal_float
)

add_fp_unittest(
ldexpf128_test
SUITE
libc-math-smoke-tests
SRCS
ldexpf128_test.cpp
HDRS
LdExpTest.h
DEPENDS
libc.src.math.ldexpf128
libc.src.__support.CPP.limits
libc.src.__support.FPUtil.fp_bits
libc.src.__support.FPUtil.normal_float
)

add_fp_unittest(
logb_test
SUITE
Expand Down
4 changes: 2 additions & 2 deletions libc/test/src/math/smoke/LdExpTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"

#include <math.h>
#include <stdint.h>

template <typename T>
Expand Down Expand Up @@ -163,6 +162,7 @@ class LdExpTestTemplate : public LIBC_NAMESPACE::testing::Test {
TEST_F(LlvmLibcLdExpTest, UnderflowToZeroOnSubnormal) { \
testUnderflowToZeroOnSubnormal(&func); \
} \
TEST_F(LlvmLibcLdExpTest, NormalOperation) { testNormalOperation(&func); }
TEST_F(LlvmLibcLdExpTest, NormalOperation) { testNormalOperation(&func); } \
static_assert(true)

#endif // LLVM_LIBC_TEST_SRC_MATH_LDEXPTEST_H
2 changes: 1 addition & 1 deletion libc/test/src/math/smoke/ldexp_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@

#include "src/math/ldexp.h"

LIST_LDEXP_TESTS(double, LIBC_NAMESPACE::ldexp)
LIST_LDEXP_TESTS(double, LIBC_NAMESPACE::ldexp);
13 changes: 13 additions & 0 deletions libc/test/src/math/smoke/ldexpf128_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for ldexpf128 -------------------------------------------===//
//
// 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 "LdExpTest.h"

#include "src/math/ldexpf128.h"

LIST_LDEXP_TESTS(float128, LIBC_NAMESPACE::ldexpf128);
2 changes: 1 addition & 1 deletion libc/test/src/math/smoke/ldexpf_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@

#include "src/math/ldexpf.h"

LIST_LDEXP_TESTS(float, LIBC_NAMESPACE::ldexpf)
LIST_LDEXP_TESTS(float, LIBC_NAMESPACE::ldexpf);
2 changes: 1 addition & 1 deletion libc/test/src/math/smoke/ldexpl_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@

#include "src/math/ldexpl.h"

LIST_LDEXP_TESTS(long double, LIBC_NAMESPACE::ldexpl)
LIST_LDEXP_TESTS(long double, LIBC_NAMESPACE::ldexpl);