44 changes: 38 additions & 6 deletions libc/test/src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1259,9 +1259,10 @@ add_fp_unittest(
libc-math-unittests
SRCS
sqrtf_test.cpp
HDRS
SqrtTest.h
DEPENDS
libc.src.math.sqrtf
libc.src.__support.FPUtil.fp_bits
)

add_fp_unittest(
Expand All @@ -1271,9 +1272,10 @@ add_fp_unittest(
libc-math-unittests
SRCS
sqrt_test.cpp
HDRS
SqrtTest.h
DEPENDS
libc.src.math.sqrt
libc.src.__support.FPUtil.fp_bits
)

add_fp_unittest(
Expand All @@ -1283,9 +1285,10 @@ add_fp_unittest(
libc-math-unittests
SRCS
sqrtl_test.cpp
HDRS
SqrtTest.h
DEPENDS
libc.src.math.sqrtl
libc.src.__support.FPUtil.fp_bits
)

add_fp_unittest(
Expand All @@ -1295,9 +1298,10 @@ add_fp_unittest(
libc-math-unittests
SRCS
generic_sqrtf_test.cpp
HDRS
SqrtTest.h
DEPENDS
libc.src.math.sqrtf
libc.src.__support.FPUtil.fp_bits
libc.src.__support.FPUtil.generic.sqrt
COMPILE_OPTIONS
-O3
Expand All @@ -1310,9 +1314,10 @@ add_fp_unittest(
libc-math-unittests
SRCS
generic_sqrt_test.cpp
HDRS
SqrtTest.h
DEPENDS
libc.src.math.sqrt
libc.src.__support.FPUtil.fp_bits
libc.src.__support.FPUtil.generic.sqrt
COMPILE_OPTIONS
-O3
Expand All @@ -1325,9 +1330,10 @@ add_fp_unittest(
libc-math-unittests
SRCS
generic_sqrtl_test.cpp
HDRS
SqrtTest.h
DEPENDS
libc.src.math.sqrtl
libc.src.__support.FPUtil.fp_bits
libc.src.__support.FPUtil.generic.sqrt
COMPILE_OPTIONS
-O3
Expand Down Expand Up @@ -1986,6 +1992,32 @@ add_fp_unittest(
libc.src.stdlib.srand
)

add_fp_unittest(
f16sqrt_test
NEED_MPFR
SUITE
libc-math-unittests
SRCS
f16sqrt_test.cpp
HDRS
SqrtTest.h
DEPENDS
libc.src.math.f16sqrt
)

add_fp_unittest(
f16sqrtl_test
NEED_MPFR
SUITE
libc-math-unittests
SRCS
f16sqrtl_test.cpp
HDRS
SqrtTest.h
DEPENDS
libc.src.math.f16sqrtl
)

add_subdirectory(generic)
add_subdirectory(smoke)

Expand Down
43 changes: 16 additions & 27 deletions libc/test/src/math/SqrtTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,51 +6,36 @@
//
//===----------------------------------------------------------------------===//

#include "src/__support/CPP/bit.h"
#include "test/UnitTest/FEnvSafeTest.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
#include "utils/MPFRWrapper/MPFRUtils.h"

#include "hdr/math_macros.h"

namespace mpfr = LIBC_NAMESPACE::testing::mpfr;

template <typename T>
template <typename OutType, typename InType>
class SqrtTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {

DECLARE_SPECIAL_CONSTANTS(T)
DECLARE_SPECIAL_CONSTANTS(InType)

static constexpr StorageType HIDDEN_BIT =
StorageType(1) << LIBC_NAMESPACE::fputil::FPBits<T>::FRACTION_LEN;
StorageType(1) << LIBC_NAMESPACE::fputil::FPBits<InType>::FRACTION_LEN;

public:
typedef T (*SqrtFunc)(T);

void test_special_numbers(SqrtFunc func) {
ASSERT_FP_EQ(aNaN, func(aNaN));
ASSERT_FP_EQ(inf, func(inf));
ASSERT_FP_EQ(aNaN, func(neg_inf));
ASSERT_FP_EQ(0.0, func(0.0));
ASSERT_FP_EQ(-0.0, func(-0.0));
ASSERT_FP_EQ(aNaN, func(T(-1.0)));
ASSERT_FP_EQ(T(1.0), func(T(1.0)));
ASSERT_FP_EQ(T(2.0), func(T(4.0)));
ASSERT_FP_EQ(T(3.0), func(T(9.0)));
}
using SqrtFunc = OutType (*)(InType);

void test_denormal_values(SqrtFunc func) {
for (StorageType mant = 1; mant < HIDDEN_BIT; mant <<= 1) {
FPBits denormal(T(0.0));
FPBits denormal(zero);
denormal.set_mantissa(mant);
T x = denormal.get_val();
InType x = denormal.get_val();
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Sqrt, x, func(x), 0.5);
}

constexpr StorageType COUNT = 200'001;
constexpr StorageType STEP = HIDDEN_BIT / COUNT;
for (StorageType i = 0, v = 0; i <= COUNT; ++i, v += STEP) {
T x = LIBC_NAMESPACE::cpp::bit_cast<T>(v);
InType x = FPBits(i).get_val();
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Sqrt, x, func(x), 0.5);
}
}
Expand All @@ -59,17 +44,21 @@ class SqrtTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
constexpr StorageType COUNT = 200'001;
constexpr StorageType STEP = STORAGE_MAX / COUNT;
for (StorageType i = 0, v = 0; i <= COUNT; ++i, v += STEP) {
T x = LIBC_NAMESPACE::cpp::bit_cast<T>(v);
if (isnan(x) || (x < 0)) {
FPBits x_bits(v);
InType x = x_bits.get_val();
if (x_bits.is_nan() || (x < 0))
continue;
}
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Sqrt, x, func(x), 0.5);
}
}
};

#define LIST_SQRT_TESTS(T, func) \
using LlvmLibcSqrtTest = SqrtTest<T>; \
TEST_F(LlvmLibcSqrtTest, SpecialNumbers) { test_special_numbers(&func); } \
using LlvmLibcSqrtTest = SqrtTest<T, T>; \
TEST_F(LlvmLibcSqrtTest, DenormalValues) { test_denormal_values(&func); } \
TEST_F(LlvmLibcSqrtTest, NormalRange) { test_normal_range(&func); }

#define LIST_NARROWING_SQRT_TESTS(OutType, InType, func) \
using LlvmLibcSqrtTest = SqrtTest<OutType, InType>; \
TEST_F(LlvmLibcSqrtTest, DenormalValues) { test_denormal_values(&func); } \
TEST_F(LlvmLibcSqrtTest, NormalRange) { test_normal_range(&func); }
13 changes: 13 additions & 0 deletions libc/test/src/math/f16sqrt_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for f16sqrt ---------------------------------------------===//
//
// 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 "SqrtTest.h"

#include "src/math/f16sqrt.h"

LIST_NARROWING_SQRT_TESTS(float16, double, LIBC_NAMESPACE::f16sqrt)
13 changes: 13 additions & 0 deletions libc/test/src/math/f16sqrtl_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for f16sqrtl --------------------------------------------===//
//
// 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 "SqrtTest.h"

#include "src/math/f16sqrtl.h"

LIST_NARROWING_SQRT_TESTS(float16, long double, LIBC_NAMESPACE::f16sqrtl)
36 changes: 36 additions & 0 deletions libc/test/src/math/smoke/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3734,6 +3734,18 @@ add_fp_unittest(
libc.src.math.f16fmaf128
)

add_fp_unittest(
f16sqrt_test
SUITE
libc-math-smoke-tests
SRCS
f16sqrt_test.cpp
HDRS
SqrtTest.h
DEPENDS
libc.src.math.f16sqrt
)

add_fp_unittest(
f16sqrtf_test
SUITE
Expand All @@ -3746,6 +3758,30 @@ add_fp_unittest(
libc.src.math.f16sqrtf
)

add_fp_unittest(
f16sqrtl_test
SUITE
libc-math-smoke-tests
SRCS
f16sqrtl_test.cpp
HDRS
SqrtTest.h
DEPENDS
libc.src.math.f16sqrtl
)

add_fp_unittest(
f16sqrtf128_test
SUITE
libc-math-smoke-tests
SRCS
f16sqrtf128_test.cpp
HDRS
SqrtTest.h
DEPENDS
libc.src.math.f16sqrtf128
)

add_fp_unittest(
sin_test
SUITE
Expand Down
13 changes: 13 additions & 0 deletions libc/test/src/math/smoke/f16sqrt_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for f16sqrt ---------------------------------------------===//
//
// 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 "SqrtTest.h"

#include "src/math/f16sqrt.h"

LIST_NARROWING_SQRT_TESTS(float16, double, LIBC_NAMESPACE::f16sqrt)
13 changes: 13 additions & 0 deletions libc/test/src/math/smoke/f16sqrtf128_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for f16sqrtf128 -----------------------------------------===//
//
// 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 "SqrtTest.h"

#include "src/math/f16sqrtf128.h"

LIST_NARROWING_SQRT_TESTS(float16, float128, LIBC_NAMESPACE::f16sqrtf128)
13 changes: 13 additions & 0 deletions libc/test/src/math/smoke/f16sqrtl_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for f16sqrtl --------------------------------------------===//
//
// 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 "SqrtTest.h"

#include "src/math/f16sqrtl.h"

LIST_NARROWING_SQRT_TESTS(float16, long double, LIBC_NAMESPACE::f16sqrtl)
11 changes: 11 additions & 0 deletions libc/utils/MPFRWrapper/MPFRUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,12 @@ template void explain_unary_operation_single_output_error(Operation op, float16,
template void explain_unary_operation_single_output_error(Operation op, float,
float16, double,
RoundingMode);
template void explain_unary_operation_single_output_error(Operation op, double,
float16, double,
RoundingMode);
template void explain_unary_operation_single_output_error(Operation op,
long double, float16,
double, RoundingMode);
#endif

template <typename T>
Expand Down Expand Up @@ -1015,6 +1021,11 @@ template bool compare_unary_operation_single_output(Operation, float16, float16,
double, RoundingMode);
template bool compare_unary_operation_single_output(Operation, float, float16,
double, RoundingMode);
template bool compare_unary_operation_single_output(Operation, double, float16,
double, RoundingMode);
template bool compare_unary_operation_single_output(Operation, long double,
float16, double,
RoundingMode);
#endif

template <typename T>
Expand Down