227 changes: 114 additions & 113 deletions libc/test/src/math/CMakeLists.txt

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions libc/test/src/math/generic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ add_fp_unittest(
ceil_test
NEED_MPFR
SUITE
libc_math_unittests
libc-math-unittests
SRCS
../ceil_test.cpp
DEPENDS
Expand All @@ -14,7 +14,7 @@ add_fp_unittest(
ceilf_test
NEED_MPFR
SUITE
libc_math_unittests
libc-math-unittests
SRCS
../ceilf_test.cpp
DEPENDS
Expand All @@ -26,7 +26,7 @@ add_fp_unittest(
ceill_test
NEED_MPFR
SUITE
libc_math_unittests
libc-math-unittests
SRCS
../ceill_test.cpp
DEPENDS
Expand Down
1,523 changes: 1,523 additions & 0 deletions libc/test/src/math/smoke/CMakeLists.txt

Large diffs are not rendered by default.

68 changes: 68 additions & 0 deletions libc/test/src/math/smoke/CeilTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//===-- Utility class to test ceil[f|l] -------------------------*- 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
//
//===----------------------------------------------------------------------===//

#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"

#include <math.h>

template <typename T> class CeilTest : public __llvm_libc::testing::Test {

DECLARE_SPECIAL_CONSTANTS(T)

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

void testSpecialNumbers(CeilFunc func) {
EXPECT_FP_EQ(zero, func(zero));
EXPECT_FP_EQ(neg_zero, func(neg_zero));

EXPECT_FP_EQ(inf, func(inf));
EXPECT_FP_EQ(neg_inf, func(neg_inf));

EXPECT_FP_EQ(aNaN, func(aNaN));
}

void testRoundedNumbers(CeilFunc func) {
EXPECT_FP_EQ(T(1.0), func(T(1.0)));
EXPECT_FP_EQ(T(-1.0), func(T(-1.0)));
EXPECT_FP_EQ(T(10.0), func(T(10.0)));
EXPECT_FP_EQ(T(-10.0), func(T(-10.0)));
EXPECT_FP_EQ(T(1234.0), func(T(1234.0)));
EXPECT_FP_EQ(T(-1234.0), func(T(-1234.0)));
}

void testFractions(CeilFunc func) {
EXPECT_FP_EQ(T(1.0), func(T(0.5)));
EXPECT_FP_EQ(T(-0.0), func(T(-0.5)));
EXPECT_FP_EQ(T(1.0), func(T(0.115)));
EXPECT_FP_EQ(T(-0.0), func(T(-0.115)));
EXPECT_FP_EQ(T(1.0), func(T(0.715)));
EXPECT_FP_EQ(T(-0.0), func(T(-0.715)));
EXPECT_FP_EQ(T(2.0), func(T(1.3)));
EXPECT_FP_EQ(T(-1.0), func(T(-1.3)));
EXPECT_FP_EQ(T(2.0), func(T(1.5)));
EXPECT_FP_EQ(T(-1.0), func(T(-1.5)));
EXPECT_FP_EQ(T(2.0), func(T(1.75)));
EXPECT_FP_EQ(T(-1.0), func(T(-1.75)));
EXPECT_FP_EQ(T(11.0), func(T(10.32)));
EXPECT_FP_EQ(T(-10.0), func(T(-10.32)));
EXPECT_FP_EQ(T(11.0), func(T(10.65)));
EXPECT_FP_EQ(T(-10.0), func(T(-10.65)));
EXPECT_FP_EQ(T(1235.0), func(T(1234.38)));
EXPECT_FP_EQ(T(-1234.0), func(T(-1234.38)));
EXPECT_FP_EQ(T(1235.0), func(T(1234.96)));
EXPECT_FP_EQ(T(-1234.0), func(T(-1234.96)));
}
};

#define LIST_CEIL_TESTS(T, func) \
using LlvmLibcCeilTest = CeilTest<T>; \
TEST_F(LlvmLibcCeilTest, SpecialNumbers) { testSpecialNumbers(&func); } \
TEST_F(LlvmLibcCeilTest, RoundedNubmers) { testRoundedNumbers(&func); } \
TEST_F(LlvmLibcCeilTest, Fractions) { testFractions(&func); }
52 changes: 52 additions & 0 deletions libc/test/src/math/smoke/CopySignTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//===-- Utility class to test copysign[f|l] ---------------------*- 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
//
//===----------------------------------------------------------------------===//

#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"

#include <math.h>

template <typename T> class CopySignTest : public __llvm_libc::testing::Test {

DECLARE_SPECIAL_CONSTANTS(T)

public:
typedef T (*CopySignFunc)(T, T);

void testSpecialNumbers(CopySignFunc func) {
EXPECT_FP_EQ(aNaN, func(aNaN, -1.0));
EXPECT_FP_EQ(aNaN, func(aNaN, 1.0));

EXPECT_FP_EQ(neg_inf, func(inf, -1.0));
EXPECT_FP_EQ(inf, func(neg_inf, 1.0));

EXPECT_FP_EQ(neg_zero, func(zero, -1.0));
EXPECT_FP_EQ(zero, func(neg_zero, 1.0));
}

void testRange(CopySignFunc func) {
constexpr UIntType COUNT = 100'000;
constexpr UIntType STEP = UIntType(-1) / COUNT;
for (UIntType i = 0, v = 0; i <= COUNT; ++i, v += STEP) {
T x = T(FPBits(v));
if (isnan(x) || isinf(x))
continue;

double res1 = func(x, -x);
ASSERT_FP_EQ(res1, -x);

double res2 = func(x, x);
ASSERT_FP_EQ(res2, x);
}
}
};

#define LIST_COPYSIGN_TESTS(T, func) \
using LlvmLibcCopySignTest = CopySignTest<T>; \
TEST_F(LlvmLibcCopySignTest, SpecialNumbers) { testSpecialNumbers(&func); } \
TEST_F(LlvmLibcCopySignTest, Range) { testRange(&func); }
37 changes: 37 additions & 0 deletions libc/test/src/math/smoke/FAbsTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//===-- Utility class to test fabs[f|l] -------------------------*- 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
//
//===----------------------------------------------------------------------===//

#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"

#include <math.h>

template <typename T> class FAbsTest : public __llvm_libc::testing::Test {

DECLARE_SPECIAL_CONSTANTS(T)

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

void testSpecialNumbers(FabsFunc func) {
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, func(aNaN));

EXPECT_FP_EQ_ALL_ROUNDING(inf, func(inf));
EXPECT_FP_EQ_ALL_ROUNDING(inf, func(neg_inf));

EXPECT_FP_EQ_ALL_ROUNDING(zero, func(zero));
EXPECT_FP_EQ_ALL_ROUNDING(zero, func(neg_zero));

EXPECT_FP_EQ_ALL_ROUNDING(T(1), func(T(1)));
EXPECT_FP_EQ_ALL_ROUNDING(T(1), func(T(-1)));
}
};

#define LIST_FABS_TESTS(T, func) \
using LlvmLibcFAbsTest = FAbsTest<T>; \
TEST_F(LlvmLibcFAbsTest, SpecialNumbers) { testSpecialNumbers(&func); }
82 changes: 82 additions & 0 deletions libc/test/src/math/smoke/FDimTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//===-- Utility class to test different flavors of fdim ---------*- 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
//
//===---------------------------------------------------------------------===//

#include "src/__support/FPUtil/BasicOperations.h"
#include "src/__support/FPUtil/FPBits.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
#include <math.h>

template <typename T>
class FDimTestTemplate : public __llvm_libc::testing::Test {
public:
using FuncPtr = T (*)(T, T);
using FPBits = __llvm_libc::fputil::FPBits<T>;
using UIntType = typename FPBits::UIntType;

void test_na_n_arg(FuncPtr func) {
EXPECT_FP_EQ(nan, func(nan, inf));
EXPECT_FP_EQ(nan, func(neg_inf, nan));
EXPECT_FP_EQ(nan, func(nan, zero));
EXPECT_FP_EQ(nan, func(neg_zero, nan));
EXPECT_FP_EQ(nan, func(nan, T(-1.2345)));
EXPECT_FP_EQ(nan, func(T(1.2345), nan));
EXPECT_FP_EQ(func(nan, nan), nan);
}

void test_inf_arg(FuncPtr func) {
EXPECT_FP_EQ(zero, func(neg_inf, inf));
EXPECT_FP_EQ(inf, func(inf, zero));
EXPECT_FP_EQ(zero, func(neg_zero, inf));
EXPECT_FP_EQ(inf, func(inf, T(1.2345)));
EXPECT_FP_EQ(zero, func(T(-1.2345), inf));
}

void test_neg_inf_arg(FuncPtr func) {
EXPECT_FP_EQ(inf, func(inf, neg_inf));
EXPECT_FP_EQ(zero, func(neg_inf, zero));
EXPECT_FP_EQ(inf, func(neg_zero, neg_inf));
EXPECT_FP_EQ(zero, func(neg_inf, T(-1.2345)));
EXPECT_FP_EQ(inf, func(T(1.2345), neg_inf));
}

void test_both_zero(FuncPtr func) {
EXPECT_FP_EQ(zero, func(zero, zero));
EXPECT_FP_EQ(zero, func(zero, neg_zero));
EXPECT_FP_EQ(zero, func(neg_zero, zero));
EXPECT_FP_EQ(zero, func(neg_zero, neg_zero));
}

void test_in_range(FuncPtr func) {
constexpr UIntType COUNT = 100'001;
constexpr UIntType STEP = UIntType(-1) / COUNT;
for (UIntType i = 0, v = 0, w = UIntType(-1); i <= COUNT;
++i, v += STEP, w -= STEP) {
T x = T(FPBits(v)), y = T(FPBits(w));
if (isnan(x) || isinf(x))
continue;
if (isnan(y) || isinf(y))
continue;

if (x > y) {
EXPECT_FP_EQ(x - y, func(x, y));
} else {
EXPECT_FP_EQ(zero, func(x, y));
}
}
}

private:
// constexpr does not work on FPBits yet, so we cannot have these constants as
// static.
const T nan = T(__llvm_libc::fputil::FPBits<T>::build_quiet_nan(1));
const T inf = T(__llvm_libc::fputil::FPBits<T>::inf());
const T neg_inf = T(__llvm_libc::fputil::FPBits<T>::neg_inf());
const T zero = T(__llvm_libc::fputil::FPBits<T>::zero());
const T neg_zero = T(__llvm_libc::fputil::FPBits<T>::neg_zero());
};
82 changes: 82 additions & 0 deletions libc/test/src/math/smoke/FMaxTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//===-- Utility class to test fmin[f|l] -------------------------*- 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
//
//===----------------------------------------------------------------------===//

#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"

#include <math.h>

template <typename T> class FMaxTest : public __llvm_libc::testing::Test {

DECLARE_SPECIAL_CONSTANTS(T)

public:
typedef T (*FMaxFunc)(T, T);

void testNaN(FMaxFunc func) {
EXPECT_FP_EQ(inf, func(aNaN, inf));
EXPECT_FP_EQ(neg_inf, func(neg_inf, aNaN));
EXPECT_FP_EQ(0.0, func(aNaN, 0.0));
EXPECT_FP_EQ(-0.0, func(-0.0, aNaN));
EXPECT_FP_EQ(T(-1.2345), func(aNaN, T(-1.2345)));
EXPECT_FP_EQ(T(1.2345), func(T(1.2345), aNaN));
EXPECT_FP_EQ(aNaN, func(aNaN, aNaN));
}

void testInfArg(FMaxFunc func) {
EXPECT_FP_EQ(inf, func(neg_inf, inf));
EXPECT_FP_EQ(inf, func(inf, 0.0));
EXPECT_FP_EQ(inf, func(-0.0, inf));
EXPECT_FP_EQ(inf, func(inf, T(1.2345)));
EXPECT_FP_EQ(inf, func(T(-1.2345), inf));
}

void testNegInfArg(FMaxFunc func) {
EXPECT_FP_EQ(inf, func(inf, neg_inf));
EXPECT_FP_EQ(0.0, func(neg_inf, 0.0));
EXPECT_FP_EQ(-0.0, func(-0.0, neg_inf));
EXPECT_FP_EQ(T(-1.2345), func(neg_inf, T(-1.2345)));
EXPECT_FP_EQ(T(1.2345), func(T(1.2345), neg_inf));
}

void testBothZero(FMaxFunc func) {
EXPECT_FP_EQ(0.0, func(0.0, 0.0));
EXPECT_FP_EQ(0.0, func(-0.0, 0.0));
EXPECT_FP_EQ(0.0, func(0.0, -0.0));
EXPECT_FP_EQ(-0.0, func(-0.0, -0.0));
}

void testRange(FMaxFunc func) {
constexpr UIntType COUNT = 100'001;
constexpr UIntType STEP = UIntType(-1) / COUNT;
for (UIntType i = 0, v = 0, w = UIntType(-1); i <= COUNT;
++i, v += STEP, w -= STEP) {
T x = T(FPBits(v)), y = T(FPBits(w));
if (isnan(x) || isinf(x))
continue;
if (isnan(y) || isinf(y))
continue;
if ((x == 0) && (y == 0))
continue;

if (x > y) {
EXPECT_FP_EQ(x, func(x, y));
} else {
EXPECT_FP_EQ(y, func(x, y));
}
}
}
};

#define LIST_FMAX_TESTS(T, func) \
using LlvmLibcFMaxTest = FMaxTest<T>; \
TEST_F(LlvmLibcFMaxTest, NaN) { testNaN(&func); } \
TEST_F(LlvmLibcFMaxTest, InfArg) { testInfArg(&func); } \
TEST_F(LlvmLibcFMaxTest, NegInfArg) { testNegInfArg(&func); } \
TEST_F(LlvmLibcFMaxTest, BothZero) { testBothZero(&func); } \
TEST_F(LlvmLibcFMaxTest, Range) { testRange(&func); }
82 changes: 82 additions & 0 deletions libc/test/src/math/smoke/FMinTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//===-- Utility class to test fmin[f|l] -------------------------*- 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
//
//===----------------------------------------------------------------------===//

#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"

#include <math.h>

template <typename T> class FMinTest : public __llvm_libc::testing::Test {

DECLARE_SPECIAL_CONSTANTS(T)

public:
typedef T (*FMinFunc)(T, T);

void testNaN(FMinFunc func) {
EXPECT_FP_EQ(inf, func(aNaN, inf));
EXPECT_FP_EQ(neg_inf, func(neg_inf, aNaN));
EXPECT_FP_EQ(0.0, func(aNaN, 0.0));
EXPECT_FP_EQ(-0.0, func(-0.0, aNaN));
EXPECT_FP_EQ(T(-1.2345), func(aNaN, T(-1.2345)));
EXPECT_FP_EQ(T(1.2345), func(T(1.2345), aNaN));
EXPECT_FP_EQ(aNaN, func(aNaN, aNaN));
}

void testInfArg(FMinFunc func) {
EXPECT_FP_EQ(neg_inf, func(neg_inf, inf));
EXPECT_FP_EQ(0.0, func(inf, 0.0));
EXPECT_FP_EQ(-0.0, func(-0.0, inf));
EXPECT_FP_EQ(T(1.2345), func(inf, T(1.2345)));
EXPECT_FP_EQ(T(-1.2345), func(T(-1.2345), inf));
}

void testNegInfArg(FMinFunc func) {
EXPECT_FP_EQ(neg_inf, func(inf, neg_inf));
EXPECT_FP_EQ(neg_inf, func(neg_inf, 0.0));
EXPECT_FP_EQ(neg_inf, func(-0.0, neg_inf));
EXPECT_FP_EQ(neg_inf, func(neg_inf, T(-1.2345)));
EXPECT_FP_EQ(neg_inf, func(T(1.2345), neg_inf));
}

void testBothZero(FMinFunc func) {
EXPECT_FP_EQ(0.0, func(0.0, 0.0));
EXPECT_FP_EQ(-0.0, func(-0.0, 0.0));
EXPECT_FP_EQ(-0.0, func(0.0, -0.0));
EXPECT_FP_EQ(-0.0, func(-0.0, -0.0));
}

void testRange(FMinFunc func) {
constexpr UIntType COUNT = 100'001;
constexpr UIntType STEP = UIntType(-1) / COUNT;
for (UIntType i = 0, v = 0, w = UIntType(-1); i <= COUNT;
++i, v += STEP, w -= STEP) {
T x = T(FPBits(v)), y = T(FPBits(w));
if (isnan(x) || isinf(x))
continue;
if (isnan(y) || isinf(y))
continue;
if ((x == 0) && (y == 0))
continue;

if (x > y) {
EXPECT_FP_EQ(y, func(x, y));
} else {
EXPECT_FP_EQ(x, func(x, y));
}
}
}
};

#define LIST_FMIN_TESTS(T, func) \
using LlvmLibcFMinTest = FMinTest<T>; \
TEST_F(LlvmLibcFMinTest, NaN) { testNaN(&func); } \
TEST_F(LlvmLibcFMinTest, InfArg) { testInfArg(&func); } \
TEST_F(LlvmLibcFMinTest, NegInfArg) { testNegInfArg(&func); } \
TEST_F(LlvmLibcFMinTest, BothZero) { testBothZero(&func); } \
TEST_F(LlvmLibcFMinTest, Range) { testRange(&func); }
270 changes: 270 additions & 0 deletions libc/test/src/math/smoke/FModTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
//===-- Utility class to test fmod special numbers ------------------------===//
//
// 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_FMODTEST_H
#define LLVM_LIBC_TEST_SRC_MATH_FMODTEST_H

#include "src/__support/FPUtil/BasicOperations.h"
#include "src/__support/FPUtil/NearestIntegerOperations.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"

#include <limits>
#include <math.h>

#define TEST_SPECIAL(x, y, expected, dom_err, expected_exception) \
EXPECT_FP_EQ(expected, f(x, y)); \
EXPECT_MATH_ERRNO((dom_err) ? EDOM : 0); \
EXPECT_FP_EXCEPTION(expected_exception); \
__llvm_libc::fputil::clear_except(FE_ALL_EXCEPT)

#define TEST_REGULAR(x, y, expected) TEST_SPECIAL(x, y, expected, false, 0)

template <typename T> class FmodTest : public __llvm_libc::testing::Test {

DECLARE_SPECIAL_CONSTANTS(T)

public:
typedef T (*FModFunc)(T, T);

void testSpecialNumbers(FModFunc f) {
using nl = std::numeric_limits<T>;

// fmod (+0, y) == +0 for y != 0.
TEST_SPECIAL(0.0, 3.0, 0.0, false, 0);
TEST_SPECIAL(0.0, nl::denorm_min(), 0.0, false, 0);
TEST_SPECIAL(0.0, -nl::denorm_min(), 0.0, false, 0);
TEST_SPECIAL(0.0, nl::min(), 0.0, false, 0);
TEST_SPECIAL(0.0, -nl::min(), 0.0, false, 0);
TEST_SPECIAL(0.0, nl::max(), 0.0, false, 0);
TEST_SPECIAL(0.0, -nl::max(), 0.0, false, 0);

// fmod (-0, y) == -0 for y != 0.
TEST_SPECIAL(neg_zero, 3.0, neg_zero, false, 0);
TEST_SPECIAL(neg_zero, nl::denorm_min(), neg_zero, false, 0);
TEST_SPECIAL(neg_zero, -nl::denorm_min(), neg_zero, false, 0);
TEST_SPECIAL(neg_zero, nl::min(), neg_zero, false, 0);
TEST_SPECIAL(neg_zero, -nl::min(), neg_zero, false, 0);
TEST_SPECIAL(neg_zero, nl::max(), neg_zero, false, 0);
TEST_SPECIAL(neg_zero, -nl::max(), neg_zero, false, 0);

// fmod (+inf, y) == nl::quiet_NaN() plus invalid exception.
TEST_SPECIAL(inf, 3.0, nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(inf, -1.1L, nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(inf, 0.0, nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(inf, neg_zero, nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(inf, nl::denorm_min(), nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(inf, nl::min(), nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(inf, nl::max(), nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(inf, inf, nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(inf, neg_inf, nl::quiet_NaN(), true, FE_INVALID);

// fmod (-inf, y) == nl::quiet_NaN() plus invalid exception.
TEST_SPECIAL(neg_inf, 3.0, nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(neg_inf, -1.1L, nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(neg_inf, 0.0, nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(neg_inf, neg_zero, nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(neg_inf, nl::denorm_min(), nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(neg_inf, nl::min(), nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(neg_inf, nl::max(), nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(neg_inf, inf, nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(neg_inf, neg_inf, nl::quiet_NaN(), true, FE_INVALID);

// fmod (x, +0) == nl::quiet_NaN() plus invalid exception.
TEST_SPECIAL(3.0, 0.0, nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(-1.1L, 0.0, nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(0.0, 0.0, nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(neg_zero, 0.0, nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(nl::denorm_min(), 0.0, nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(nl::min(), 0.0, nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(nl::max(), 0.0, nl::quiet_NaN(), true, FE_INVALID);

// fmod (x, -0) == nl::quiet_NaN() plus invalid exception.
TEST_SPECIAL(3.0, neg_zero, nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(-1.1L, neg_zero, nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(0.0, neg_zero, nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(neg_zero, neg_zero, nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(nl::denorm_min(), neg_zero, nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(nl::min(), neg_zero, nl::quiet_NaN(), true, FE_INVALID);
TEST_SPECIAL(nl::max(), neg_zero, nl::quiet_NaN(), true, FE_INVALID);

// fmod (x, +inf) == x for x not infinite.
TEST_SPECIAL(0.0, inf, 0.0, false, 0);
TEST_SPECIAL(neg_zero, inf, neg_zero, false, 0);
TEST_SPECIAL(nl::denorm_min(), inf, nl::denorm_min(), false, 0);
TEST_SPECIAL(nl::min(), inf, nl::min(), false, 0);
TEST_SPECIAL(nl::max(), inf, nl::max(), false, 0);
TEST_SPECIAL(3.0, inf, 3.0, false, 0);
// fmod (x, -inf) == x for x not infinite.
TEST_SPECIAL(0.0, neg_inf, 0.0, false, 0);
TEST_SPECIAL(neg_zero, neg_inf, neg_zero, false, 0);
TEST_SPECIAL(nl::denorm_min(), neg_inf, nl::denorm_min(), false, 0);
TEST_SPECIAL(nl::min(), neg_inf, nl::min(), false, 0);
TEST_SPECIAL(nl::max(), neg_inf, nl::max(), false, 0);
TEST_SPECIAL(3.0, neg_inf, 3.0, false, 0);

TEST_SPECIAL(0.0, nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
TEST_SPECIAL(0.0, -nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
TEST_SPECIAL(neg_zero, nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
TEST_SPECIAL(neg_zero, -nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
TEST_SPECIAL(1.0, nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
TEST_SPECIAL(1.0, -nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
TEST_SPECIAL(inf, nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
TEST_SPECIAL(inf, -nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
TEST_SPECIAL(neg_inf, nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
TEST_SPECIAL(neg_inf, -nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
TEST_SPECIAL(0.0, nl::signaling_NaN(), nl::quiet_NaN(), false, FE_INVALID);
TEST_SPECIAL(0.0, -nl::signaling_NaN(), nl::quiet_NaN(), false, FE_INVALID);
TEST_SPECIAL(neg_zero, nl::signaling_NaN(), nl::quiet_NaN(), false,
FE_INVALID);
TEST_SPECIAL(neg_zero, -nl::signaling_NaN(), nl::quiet_NaN(), false,
FE_INVALID);
TEST_SPECIAL(1.0, nl::signaling_NaN(), nl::quiet_NaN(), false, FE_INVALID);
TEST_SPECIAL(1.0, -nl::signaling_NaN(), nl::quiet_NaN(), false, FE_INVALID);
TEST_SPECIAL(inf, nl::signaling_NaN(), nl::quiet_NaN(), false, FE_INVALID);
TEST_SPECIAL(inf, -nl::signaling_NaN(), nl::quiet_NaN(), false, FE_INVALID);
TEST_SPECIAL(neg_inf, nl::signaling_NaN(), nl::quiet_NaN(), false,
FE_INVALID);
TEST_SPECIAL(neg_inf, -nl::signaling_NaN(), nl::quiet_NaN(), false,
FE_INVALID);
TEST_SPECIAL(nl::quiet_NaN(), 0.0, nl::quiet_NaN(), false, 0);
TEST_SPECIAL(-nl::quiet_NaN(), 0.0, nl::quiet_NaN(), false, 0);
TEST_SPECIAL(nl::quiet_NaN(), neg_zero, nl::quiet_NaN(), false, 0);
TEST_SPECIAL(-nl::quiet_NaN(), neg_zero, nl::quiet_NaN(), false, 0);
TEST_SPECIAL(nl::quiet_NaN(), 1.0, nl::quiet_NaN(), false, 0);
TEST_SPECIAL(-nl::quiet_NaN(), 1.0, nl::quiet_NaN(), false, 0);
TEST_SPECIAL(nl::quiet_NaN(), inf, nl::quiet_NaN(), false, 0);
TEST_SPECIAL(-nl::quiet_NaN(), inf, nl::quiet_NaN(), false, 0);
TEST_SPECIAL(nl::quiet_NaN(), neg_inf, nl::quiet_NaN(), false, 0);
TEST_SPECIAL(-nl::quiet_NaN(), neg_inf, nl::quiet_NaN(), false, 0);
TEST_SPECIAL(nl::signaling_NaN(), 0.0, nl::quiet_NaN(), false, FE_INVALID);
TEST_SPECIAL(-nl::signaling_NaN(), 0.0, nl::quiet_NaN(), false, FE_INVALID);
TEST_SPECIAL(nl::signaling_NaN(), neg_zero, nl::quiet_NaN(), false,
FE_INVALID);
TEST_SPECIAL(-nl::signaling_NaN(), neg_zero, nl::quiet_NaN(), false,
FE_INVALID);
TEST_SPECIAL(nl::signaling_NaN(), 1.0, nl::quiet_NaN(), false, FE_INVALID);
TEST_SPECIAL(-nl::signaling_NaN(), 1.0, nl::quiet_NaN(), false, FE_INVALID);
TEST_SPECIAL(nl::signaling_NaN(), inf, nl::quiet_NaN(), false, FE_INVALID);
TEST_SPECIAL(-nl::signaling_NaN(), inf, nl::quiet_NaN(), false, FE_INVALID);
TEST_SPECIAL(nl::signaling_NaN(), neg_inf, nl::quiet_NaN(), false,
FE_INVALID);
TEST_SPECIAL(-nl::signaling_NaN(), neg_inf, nl::quiet_NaN(), false,
FE_INVALID);
TEST_SPECIAL(nl::quiet_NaN(), nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
TEST_SPECIAL(nl::quiet_NaN(), -nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
TEST_SPECIAL(-nl::quiet_NaN(), nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
TEST_SPECIAL(-nl::quiet_NaN(), -nl::quiet_NaN(), nl::quiet_NaN(), false, 0);
TEST_SPECIAL(nl::quiet_NaN(), nl::signaling_NaN(), nl::quiet_NaN(), false,
FE_INVALID);
TEST_SPECIAL(nl::quiet_NaN(), -nl::signaling_NaN(), nl::quiet_NaN(), false,
FE_INVALID);
TEST_SPECIAL(-nl::quiet_NaN(), nl::signaling_NaN(), nl::quiet_NaN(), false,
FE_INVALID);
TEST_SPECIAL(-nl::quiet_NaN(), -nl::signaling_NaN(), nl::quiet_NaN(), false,
FE_INVALID);
TEST_SPECIAL(nl::signaling_NaN(), nl::quiet_NaN(), nl::quiet_NaN(), false,
FE_INVALID);
TEST_SPECIAL(nl::signaling_NaN(), -nl::quiet_NaN(), nl::quiet_NaN(), false,
FE_INVALID);
TEST_SPECIAL(-nl::signaling_NaN(), nl::quiet_NaN(), nl::quiet_NaN(), false,
FE_INVALID);
TEST_SPECIAL(-nl::signaling_NaN(), -nl::quiet_NaN(), nl::quiet_NaN(), false,
FE_INVALID);
TEST_SPECIAL(nl::signaling_NaN(), nl::signaling_NaN(), nl::quiet_NaN(),
false, FE_INVALID);
TEST_SPECIAL(nl::signaling_NaN(), -nl::signaling_NaN(), nl::quiet_NaN(),
false, FE_INVALID);
TEST_SPECIAL(-nl::signaling_NaN(), nl::signaling_NaN(), nl::quiet_NaN(),
false, FE_INVALID);
TEST_SPECIAL(-nl::signaling_NaN(), -nl::signaling_NaN(), nl::quiet_NaN(),
false, FE_INVALID);

TEST_SPECIAL(6.5, 2.25L, 2.0L, false, 0);
TEST_SPECIAL(-6.5, 2.25L, -2.0L, false, 0);
TEST_SPECIAL(6.5, -2.25L, 2.0L, false, 0);
TEST_SPECIAL(-6.5, -2.25L, -2.0L, false, 0);

TEST_SPECIAL(nl::max(), nl::max(), 0.0, false, 0);
TEST_SPECIAL(nl::max(), -nl::max(), 0.0, false, 0);
TEST_SPECIAL(nl::max(), nl::min(), 0.0, false, 0);
TEST_SPECIAL(nl::max(), -nl::min(), 0.0, false, 0);
TEST_SPECIAL(nl::max(), nl::denorm_min(), 0.0, false, 0);
TEST_SPECIAL(nl::max(), -nl::denorm_min(), 0.0, false, 0);
TEST_SPECIAL(-nl::max(), nl::max(), neg_zero, false, 0);
TEST_SPECIAL(-nl::max(), -nl::max(), neg_zero, false, 0);
TEST_SPECIAL(-nl::max(), nl::min(), neg_zero, false, 0);
TEST_SPECIAL(-nl::max(), -nl::min(), neg_zero, false, 0);
TEST_SPECIAL(-nl::max(), nl::denorm_min(), neg_zero, false, 0);
TEST_SPECIAL(-nl::max(), -nl::denorm_min(), neg_zero, false, 0);

TEST_SPECIAL(nl::min(), nl::max(), nl::min(), false, 0);
TEST_SPECIAL(nl::min(), -nl::max(), nl::min(), false, 0);
TEST_SPECIAL(nl::min(), nl::min(), 0.0, false, 0);
TEST_SPECIAL(nl::min(), -nl::min(), 0.0, false, 0);
TEST_SPECIAL(nl::min(), nl::denorm_min(), 0.0, false, 0);
TEST_SPECIAL(nl::min(), -nl::denorm_min(), 0.0, false, 0);
TEST_SPECIAL(-nl::min(), nl::max(), -nl::min(), false, 0);
TEST_SPECIAL(-nl::min(), -nl::max(), -nl::min(), false, 0);
TEST_SPECIAL(-nl::min(), nl::min(), neg_zero, false, 0);
TEST_SPECIAL(-nl::min(), -nl::min(), neg_zero, false, 0);
TEST_SPECIAL(-nl::min(), nl::denorm_min(), neg_zero, false, 0);
TEST_SPECIAL(-nl::min(), -nl::denorm_min(), neg_zero, false, 0);

TEST_SPECIAL(nl::denorm_min(), nl::max(), nl::denorm_min(), false, 0);
TEST_SPECIAL(nl::denorm_min(), -nl::max(), nl::denorm_min(), false, 0);
TEST_SPECIAL(nl::denorm_min(), nl::min(), nl::denorm_min(), false, 0);
TEST_SPECIAL(nl::denorm_min(), -nl::min(), nl::denorm_min(), false, 0);
TEST_SPECIAL(nl::denorm_min(), nl::denorm_min(), 0.0, false, 0);
TEST_SPECIAL(nl::denorm_min(), -nl::denorm_min(), 0.0, false, 0);
TEST_SPECIAL(-nl::denorm_min(), nl::max(), -nl::denorm_min(), false, 0);
TEST_SPECIAL(-nl::denorm_min(), -nl::max(), -nl::denorm_min(), false, 0);
TEST_SPECIAL(-nl::denorm_min(), nl::min(), -nl::denorm_min(), false, 0);
TEST_SPECIAL(-nl::denorm_min(), -nl::min(), -nl::denorm_min(), false, 0);
TEST_SPECIAL(-nl::denorm_min(), nl::denorm_min(), neg_zero, false, 0);
TEST_SPECIAL(-nl::denorm_min(), -nl::denorm_min(), neg_zero, false, 0);
}

void testRegularExtreme(FModFunc f) {

TEST_REGULAR(0x1p127L, 0x3p-149L, 0x1p-149L);
TEST_REGULAR(0x1p127L, -0x3p-149L, 0x1p-149L);
TEST_REGULAR(0x1p127L, 0x3p-148L, 0x1p-147L);
TEST_REGULAR(0x1p127L, -0x3p-148L, 0x1p-147L);
TEST_REGULAR(0x1p127L, 0x3p-126L, 0x1p-125L);
TEST_REGULAR(0x1p127L, -0x3p-126L, 0x1p-125L);
TEST_REGULAR(-0x1p127L, 0x3p-149L, -0x1p-149L);
TEST_REGULAR(-0x1p127L, -0x3p-149L, -0x1p-149L);
TEST_REGULAR(-0x1p127L, 0x3p-148L, -0x1p-147L);
TEST_REGULAR(-0x1p127L, -0x3p-148L, -0x1p-147L);
TEST_REGULAR(-0x1p127L, 0x3p-126L, -0x1p-125L);
TEST_REGULAR(-0x1p127L, -0x3p-126L, -0x1p-125L);

if constexpr (sizeof(T) >= sizeof(double)) {
TEST_REGULAR(0x1p1023L, 0x3p-1074L, 0x1p-1073L);
TEST_REGULAR(0x1p1023L, -0x3p-1074L, 0x1p-1073L);
TEST_REGULAR(0x1p1023L, 0x3p-1073L, 0x1p-1073L);
TEST_REGULAR(0x1p1023L, -0x3p-1073L, 0x1p-1073L);
TEST_REGULAR(0x1p1023L, 0x3p-1022L, 0x1p-1021L);
TEST_REGULAR(0x1p1023L, -0x3p-1022L, 0x1p-1021L);
TEST_REGULAR(-0x1p1023L, 0x3p-1074L, -0x1p-1073L);
TEST_REGULAR(-0x1p1023L, -0x3p-1074L, -0x1p-1073L);
TEST_REGULAR(-0x1p1023L, 0x3p-1073L, -0x1p-1073L);
TEST_REGULAR(-0x1p1023L, -0x3p-1073L, -0x1p-1073L);
TEST_REGULAR(-0x1p1023L, 0x3p-1022L, -0x1p-1021L);
TEST_REGULAR(-0x1p1023L, -0x3p-1022L, -0x1p-1021L);
}
}
};

#define LIST_FMOD_TESTS(T, func) \
using LlvmLibcFmodTest = FmodTest<T>; \
TEST_F(LlvmLibcFmodTest, SpecialNumbers) { testSpecialNumbers(&func); } \
TEST_F(LlvmLibcFmodTest, RegularExtreme) { testRegularExtreme(&func); }

#endif // LLVM_LIBC_TEST_SRC_MATH_FMODTEST_H
68 changes: 68 additions & 0 deletions libc/test/src/math/smoke/FloorTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//===-- Utility class to test floor[f|l] ------------------------*- 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
//
//===----------------------------------------------------------------------===//

#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"

#include <math.h>

template <typename T> class FloorTest : public __llvm_libc::testing::Test {

DECLARE_SPECIAL_CONSTANTS(T)

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

void testSpecialNumbers(FloorFunc func) {
EXPECT_FP_EQ(zero, func(zero));
EXPECT_FP_EQ(neg_zero, func(neg_zero));

EXPECT_FP_EQ(inf, func(inf));
EXPECT_FP_EQ(neg_inf, func(neg_inf));

EXPECT_FP_EQ(aNaN, func(aNaN));
}

void testRoundedNumbers(FloorFunc func) {
EXPECT_FP_EQ(T(1.0), func(T(1.0)));
EXPECT_FP_EQ(T(-1.0), func(T(-1.0)));
EXPECT_FP_EQ(T(10.0), func(T(10.0)));
EXPECT_FP_EQ(T(-10.0), func(T(-10.0)));
EXPECT_FP_EQ(T(1234.0), func(T(1234.0)));
EXPECT_FP_EQ(T(-1234.0), func(T(-1234.0)));
}

void testFractions(FloorFunc func) {
EXPECT_FP_EQ(T(0.0), func(T(0.5)));
EXPECT_FP_EQ(T(-1.0), func(T(-0.5)));
EXPECT_FP_EQ(T(0.0), func(T(0.115)));
EXPECT_FP_EQ(T(-1.0), func(T(-0.115)));
EXPECT_FP_EQ(T(0.0), func(T(0.715)));
EXPECT_FP_EQ(T(-1.0), func(T(-0.715)));
EXPECT_FP_EQ(T(1.0), func(T(1.3)));
EXPECT_FP_EQ(T(-2.0), func(T(-1.3)));
EXPECT_FP_EQ(T(1.0), func(T(1.5)));
EXPECT_FP_EQ(T(-2.0), func(T(-1.5)));
EXPECT_FP_EQ(T(1.0), func(T(1.75)));
EXPECT_FP_EQ(T(-2.0), func(T(-1.75)));
EXPECT_FP_EQ(T(10.0), func(T(10.32)));
EXPECT_FP_EQ(T(-11.0), func(T(-10.32)));
EXPECT_FP_EQ(T(10.0), func(T(10.65)));
EXPECT_FP_EQ(T(-11.0), func(T(-10.65)));
EXPECT_FP_EQ(T(1234.0), func(T(1234.38)));
EXPECT_FP_EQ(T(-1235.0), func(T(-1234.38)));
EXPECT_FP_EQ(T(1234.0), func(T(1234.96)));
EXPECT_FP_EQ(T(-1235.0), func(T(-1234.96)));
}
};

#define LIST_FLOOR_TESTS(T, func) \
using LlvmLibcFloorTest = FloorTest<T>; \
TEST_F(LlvmLibcFloorTest, SpecialNumbers) { testSpecialNumbers(&func); } \
TEST_F(LlvmLibcFloorTest, RoundedNubmers) { testRoundedNumbers(&func); } \
TEST_F(LlvmLibcFloorTest, Fractions) { testFractions(&func); }
57 changes: 57 additions & 0 deletions libc/test/src/math/smoke/FmaTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//===-- Utility class to test different flavors of fma --------------------===//
//
// 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_FMATEST_H
#define LLVM_LIBC_TEST_SRC_MATH_FMATEST_H

#include "src/__support/FPUtil/FPBits.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"

template <typename T>
class FmaTestTemplate : public __llvm_libc::testing::Test {
private:
using Func = T (*)(T, T, T);
using FPBits = __llvm_libc::fputil::FPBits<T>;
using UIntType = typename FPBits::UIntType;
const T nan = T(__llvm_libc::fputil::FPBits<T>::build_quiet_nan(1));
const T inf = T(__llvm_libc::fputil::FPBits<T>::inf());
const T neg_inf = T(__llvm_libc::fputil::FPBits<T>::neg_inf());
const T zero = T(__llvm_libc::fputil::FPBits<T>::zero());
const T neg_zero = T(__llvm_libc::fputil::FPBits<T>::neg_zero());

public:
void test_special_numbers(Func func) {
EXPECT_FP_EQ(func(zero, zero, zero), zero);
EXPECT_FP_EQ(func(zero, neg_zero, neg_zero), neg_zero);
EXPECT_FP_EQ(func(inf, inf, zero), inf);
EXPECT_FP_EQ(func(neg_inf, inf, neg_inf), neg_inf);
EXPECT_FP_EQ(func(inf, zero, zero), nan);
EXPECT_FP_EQ(func(inf, neg_inf, inf), nan);
EXPECT_FP_EQ(func(nan, zero, inf), nan);
EXPECT_FP_EQ(func(inf, neg_inf, nan), nan);

// Test underflow rounding up.
EXPECT_FP_EQ(func(T(0.5), T(FPBits(FPBits::MIN_SUBNORMAL)),
T(FPBits(FPBits::MIN_SUBNORMAL))),
T(FPBits(UIntType(2))));
// Test underflow rounding down.
T v = T(FPBits(FPBits::MIN_NORMAL + UIntType(1)));
EXPECT_FP_EQ(func(T(1) / T(FPBits::MIN_NORMAL << 1), v,
T(FPBits(FPBits::MIN_NORMAL))),
v);
// Test overflow.
T z = T(FPBits(FPBits::MAX_NORMAL));
EXPECT_FP_EQ(func(T(1.75), z, -z), T(0.75) * z);
// Exact cancellation.
EXPECT_FP_EQ(func(T(3.0), T(5.0), -T(15.0)), T(0.0));
EXPECT_FP_EQ(func(T(-3.0), T(5.0), T(15.0)), T(0.0));
}
};

#endif // LLVM_LIBC_TEST_SRC_MATH_FMATEST_H
96 changes: 96 additions & 0 deletions libc/test/src/math/smoke/FrexpTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//===-- Utility class to test frexp[f|l] ------------------------*- 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
//
//===----------------------------------------------------------------------===//

#include "src/__support/FPUtil/BasicOperations.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"

#include <math.h>

template <typename T> class FrexpTest : public __llvm_libc::testing::Test {

DECLARE_SPECIAL_CONSTANTS(T)

static constexpr UIntType HIDDEN_BIT =
UIntType(1) << __llvm_libc::fputil::MantissaWidth<T>::VALUE;

public:
typedef T (*FrexpFunc)(T, int *);

void testSpecialNumbers(FrexpFunc func) {
int exponent;
ASSERT_FP_EQ(aNaN, func(aNaN, &exponent));
ASSERT_FP_EQ(inf, func(inf, &exponent));
ASSERT_FP_EQ(neg_inf, func(neg_inf, &exponent));

ASSERT_FP_EQ(0.0, func(0.0, &exponent));
ASSERT_EQ(exponent, 0);

ASSERT_FP_EQ(-0.0, func(-0.0, &exponent));
ASSERT_EQ(exponent, 0);
}

void testPowersOfTwo(FrexpFunc func) {
int exponent;

EXPECT_FP_EQ(T(0.5), func(T(1.0), &exponent));
EXPECT_EQ(exponent, 1);
EXPECT_FP_EQ(T(-0.5), func(T(-1.0), &exponent));
EXPECT_EQ(exponent, 1);

EXPECT_FP_EQ(T(0.5), func(T(2.0), &exponent));
EXPECT_EQ(exponent, 2);
EXPECT_FP_EQ(T(-0.5), func(T(-2.0), &exponent));
EXPECT_EQ(exponent, 2);

EXPECT_FP_EQ(T(0.5), func(T(4.0), &exponent));
EXPECT_EQ(exponent, 3);
EXPECT_FP_EQ(T(-0.5), func(T(-4.0), &exponent));
EXPECT_EQ(exponent, 3);

EXPECT_FP_EQ(T(0.5), func(T(8.0), &exponent));
EXPECT_EQ(exponent, 4);
EXPECT_FP_EQ(T(-0.5), func(T(-8.0), &exponent));
EXPECT_EQ(exponent, 4);

EXPECT_FP_EQ(T(0.5), func(T(16.0), &exponent));
EXPECT_EQ(exponent, 5);
EXPECT_FP_EQ(T(-0.5), func(T(-16.0), &exponent));
EXPECT_EQ(exponent, 5);

EXPECT_FP_EQ(T(0.5), func(T(32.0), &exponent));
EXPECT_EQ(exponent, 6);
EXPECT_FP_EQ(T(-0.5), func(T(-32.0), &exponent));
EXPECT_EQ(exponent, 6);
}

void testSomeIntegers(FrexpFunc func) {
int exponent;

EXPECT_FP_EQ(T(0.75), func(T(24.0), &exponent));
EXPECT_EQ(exponent, 5);
EXPECT_FP_EQ(T(-0.75), func(T(-24.0), &exponent));
EXPECT_EQ(exponent, 5);

EXPECT_FP_EQ(T(0.625), func(T(40.0), &exponent));
EXPECT_EQ(exponent, 6);
EXPECT_FP_EQ(T(-0.625), func(T(-40.0), &exponent));
EXPECT_EQ(exponent, 6);

EXPECT_FP_EQ(T(0.78125), func(T(800.0), &exponent));
EXPECT_EQ(exponent, 10);
EXPECT_FP_EQ(T(-0.78125), func(T(-800.0), &exponent));
EXPECT_EQ(exponent, 10);
}
};

#define LIST_FREXP_TESTS(T, func) \
using LlvmLibcFrexpTest = FrexpTest<T>; \
TEST_F(LlvmLibcFrexpTest, SpecialNumbers) { testSpecialNumbers(&func); } \
TEST_F(LlvmLibcFrexpTest, PowersOfTwo) { testPowersOfTwo(&func); } \
TEST_F(LlvmLibcFrexpTest, SomeIntegers) { testSomeIntegers(&func); }\
60 changes: 60 additions & 0 deletions libc/test/src/math/smoke/HypotTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//===-- Utility class to test different flavors of hypot ------------------===//
//
// 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_HYPOTTEST_H
#define LLVM_LIBC_TEST_SRC_MATH_HYPOTTEST_H

#include "src/__support/FPUtil/FPBits.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"

#include <math.h>

template <typename T>
class HypotTestTemplate : public __llvm_libc::testing::Test {
private:
using Func = T (*)(T, T);
using FPBits = __llvm_libc::fputil::FPBits<T>;
using UIntType = typename FPBits::UIntType;
const T nan = T(FPBits::build_quiet_nan(1));
const T inf = T(FPBits::inf());
const T neg_inf = T(FPBits::neg_inf());
const T zero = T(FPBits::zero());
const T neg_zero = T(FPBits::neg_zero());
const T max_normal = T(FPBits(FPBits::MAX_NORMAL));
const T min_normal = T(FPBits(FPBits::MIN_NORMAL));
const T max_subnormal = T(FPBits(FPBits::MAX_SUBNORMAL));
const T min_subnormal = T(FPBits(FPBits::MIN_SUBNORMAL));

public:
void test_special_numbers(Func func) {
constexpr int N = 4;
// Pythagorean triples.
constexpr T PYT[N][3] = {{3, 4, 5}, {5, 12, 13}, {8, 15, 17}, {7, 24, 25}};

EXPECT_FP_EQ(func(inf, nan), inf);
EXPECT_FP_EQ(func(nan, neg_inf), inf);
EXPECT_FP_EQ(func(nan, nan), nan);
EXPECT_FP_EQ(func(nan, zero), nan);
EXPECT_FP_EQ(func(neg_zero, nan), nan);

for (int i = 0; i < N; ++i) {
EXPECT_FP_EQ_ALL_ROUNDING(PYT[i][2], func(PYT[i][0], PYT[i][1]));
EXPECT_FP_EQ_ALL_ROUNDING(PYT[i][2], func(-PYT[i][0], PYT[i][1]));
EXPECT_FP_EQ_ALL_ROUNDING(PYT[i][2], func(PYT[i][0], -PYT[i][1]));
EXPECT_FP_EQ_ALL_ROUNDING(PYT[i][2], func(-PYT[i][0], -PYT[i][1]));

EXPECT_FP_EQ_ALL_ROUNDING(PYT[i][2], func(PYT[i][1], PYT[i][0]));
EXPECT_FP_EQ_ALL_ROUNDING(PYT[i][2], func(-PYT[i][1], PYT[i][0]));
EXPECT_FP_EQ_ALL_ROUNDING(PYT[i][2], func(PYT[i][1], -PYT[i][0]));
EXPECT_FP_EQ_ALL_ROUNDING(PYT[i][2], func(-PYT[i][1], -PYT[i][0]));
}
}
};

#endif // LLVM_LIBC_TEST_SRC_MATH_HYPOTTEST_H
115 changes: 115 additions & 0 deletions libc/test/src/math/smoke/ILogbTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
//===-- 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 "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/ManipulationFunctions.h"
#include "test/UnitTest/Test.h"
#include <math.h>

#include <limits.h>

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

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

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

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

template <typename T>
void test_powers_of_two(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 test_some_integers(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 test_subnormal_range(typename ILogbFunc<T>::Func func) {
using FPBits = __llvm_libc::fputil::FPBits<T>;
using UIntType = typename FPBits::UIntType;
constexpr UIntType COUNT = 10'001;
constexpr UIntType STEP =
(UIntType(FPBits::MAX_SUBNORMAL) - UIntType(FPBits::MIN_SUBNORMAL)) /
COUNT;
for (UIntType v = FPBits::MIN_SUBNORMAL; v <= FPBits::MAX_SUBNORMAL;
v += STEP) {
T x = T(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 test_normal_range(typename ILogbFunc<T>::Func func) {
using FPBits = __llvm_libc::fputil::FPBits<T>;
using UIntType = typename FPBits::UIntType;
constexpr UIntType COUNT = 10'001;
constexpr UIntType STEP =
(UIntType(FPBits::MAX_NORMAL) - UIntType(FPBits::MIN_NORMAL)) / COUNT;
for (UIntType v = FPBits::MIN_NORMAL; v <= FPBits::MAX_NORMAL; v += STEP) {
T x = T(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
166 changes: 166 additions & 0 deletions libc/test/src/math/smoke/LdExpTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
//===-- Utility class to test different flavors of ldexp --------*- 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_LDEXPTEST_H
#define LLVM_LIBC_TEST_SRC_MATH_LDEXPTEST_H

#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/NormalFloat.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"

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

template <typename T>
class LdExpTestTemplate : public __llvm_libc::testing::Test {
using FPBits = __llvm_libc::fputil::FPBits<T>;
using NormalFloat = __llvm_libc::fputil::NormalFloat<T>;
using UIntType = typename FPBits::UIntType;
static constexpr UIntType MANTISSA_WIDTH =
__llvm_libc::fputil::MantissaWidth<T>::VALUE;
// A normalized mantissa to be used with tests.
static constexpr UIntType MANTISSA = NormalFloat::ONE + 0x1234;

const T zero = T(__llvm_libc::fputil::FPBits<T>::zero());
const T neg_zero = T(__llvm_libc::fputil::FPBits<T>::neg_zero());
const T inf = T(__llvm_libc::fputil::FPBits<T>::inf());
const T neg_inf = T(__llvm_libc::fputil::FPBits<T>::neg_inf());
const T nan = T(__llvm_libc::fputil::FPBits<T>::build_quiet_nan(1));

public:
typedef T (*LdExpFunc)(T, int);

void testSpecialNumbers(LdExpFunc func) {
int exp_array[5] = {-INT_MAX - 1, -10, 0, 10, INT_MAX};
for (int exp : exp_array) {
ASSERT_FP_EQ(zero, func(zero, exp));
ASSERT_FP_EQ(neg_zero, func(neg_zero, exp));
ASSERT_FP_EQ(inf, func(inf, exp));
ASSERT_FP_EQ(neg_inf, func(neg_inf, exp));
ASSERT_FP_EQ(nan, func(nan, exp));
}
}

void testPowersOfTwo(LdExpFunc func) {
int32_t exp_array[5] = {1, 2, 3, 4, 5};
int32_t val_array[6] = {1, 2, 4, 8, 16, 32};
for (int32_t exp : exp_array) {
for (int32_t val : val_array) {
ASSERT_FP_EQ(T(val << exp), func(T(val), exp));
ASSERT_FP_EQ(T(-1 * (val << exp)), func(T(-val), exp));
}
}
}

void testOverflow(LdExpFunc func) {
NormalFloat x(FPBits::MAX_EXPONENT - 10, NormalFloat::ONE + 0xF00BA, 0);
for (int32_t exp = 10; exp < 100; ++exp) {
ASSERT_FP_EQ(inf, func(T(x), exp));
ASSERT_FP_EQ(neg_inf, func(-T(x), exp));
}
}

void testUnderflowToZeroOnNormal(LdExpFunc func) {
// In this test, we pass a normal nubmer to func and expect zero
// to be returned due to underflow.
int32_t base_exponent = FPBits::EXPONENT_BIAS + int32_t(MANTISSA_WIDTH);
int32_t exp_array[] = {base_exponent + 5, base_exponent + 4,
base_exponent + 3, base_exponent + 2,
base_exponent + 1};
T x = NormalFloat(0, MANTISSA, 0);
for (int32_t exp : exp_array) {
ASSERT_FP_EQ(func(x, -exp), x > 0 ? zero : neg_zero);
}
}

void testUnderflowToZeroOnSubnormal(LdExpFunc func) {
// In this test, we pass a normal nubmer to func and expect zero
// to be returned due to underflow.
int32_t base_exponent = FPBits::EXPONENT_BIAS + int32_t(MANTISSA_WIDTH);
int32_t exp_array[] = {base_exponent + 5, base_exponent + 4,
base_exponent + 3, base_exponent + 2,
base_exponent + 1};
T x = NormalFloat(-FPBits::EXPONENT_BIAS, MANTISSA, 0);
for (int32_t exp : exp_array) {
ASSERT_FP_EQ(func(x, -exp), x > 0 ? zero : neg_zero);
}
}

void testNormalOperation(LdExpFunc func) {
T val_array[] = {
// Normal numbers
NormalFloat(100, MANTISSA, 0), NormalFloat(-100, MANTISSA, 0),
NormalFloat(100, MANTISSA, 1), NormalFloat(-100, MANTISSA, 1),
// Subnormal numbers
NormalFloat(-FPBits::EXPONENT_BIAS, MANTISSA, 0),
NormalFloat(-FPBits::EXPONENT_BIAS, MANTISSA, 1)};
for (int32_t exp = 0; exp <= static_cast<int32_t>(MANTISSA_WIDTH); ++exp) {
for (T x : val_array) {
// We compare the result of ldexp with the result
// of the native multiplication/division instruction.

// We need to use a NormalFloat here (instead of 1 << exp), because
// there are 32 bit systems that don't support 128bit long ints but
// support long doubles. This test can do 1 << 64, which would fail
// in these systems.
NormalFloat two_to_exp = NormalFloat(static_cast<T>(1.L));
two_to_exp = two_to_exp.mul2(exp);

ASSERT_FP_EQ(func(x, exp), x * two_to_exp);
ASSERT_FP_EQ(func(x, -exp), x / two_to_exp);
}
}

// Normal which trigger mantissa overflow.
T x = NormalFloat(-FPBits::EXPONENT_BIAS + 1,
UIntType(2) * NormalFloat::ONE - UIntType(1), 0);
ASSERT_FP_EQ(func(x, -1), x / 2);
ASSERT_FP_EQ(func(-x, -1), -x / 2);

// Start with a normal number high exponent but pass a very low number for
// exp. The result should be a subnormal number.
x = NormalFloat(FPBits::EXPONENT_BIAS, NormalFloat::ONE, 0);
int exp = -FPBits::MAX_EXPONENT - 5;
T result = func(x, exp);
FPBits result_bits(result);
ASSERT_FALSE(result_bits.is_zero());
// Verify that the result is indeed subnormal.
ASSERT_EQ(result_bits.get_unbiased_exponent(), uint16_t(0));
// But if the exp is so less that normalization leads to zero, then
// the result should be zero.
result = func(x, -FPBits::MAX_EXPONENT - int(MANTISSA_WIDTH) - 5);
ASSERT_TRUE(FPBits(result).is_zero());

// Start with a subnormal number but pass a very high number for exponent.
// The result should not be infinity.
x = NormalFloat(-FPBits::EXPONENT_BIAS + 1, NormalFloat::ONE >> 10, 0);
exp = FPBits::MAX_EXPONENT + 5;
ASSERT_FALSE(FPBits(func(x, exp)).is_inf());
// But if the exp is large enough to oversome than the normalization shift,
// then it should result in infinity.
exp = FPBits::MAX_EXPONENT + 15;
ASSERT_FP_EQ(func(x, exp), inf);
}
};

#define LIST_LDEXP_TESTS(T, func) \
using LlvmLibcLdExpTest = LdExpTestTemplate<T>; \
TEST_F(LlvmLibcLdExpTest, SpecialNumbers) { testSpecialNumbers(&func); } \
TEST_F(LlvmLibcLdExpTest, PowersOfTwo) { testPowersOfTwo(&func); } \
TEST_F(LlvmLibcLdExpTest, OverFlow) { testOverflow(&func); } \
TEST_F(LlvmLibcLdExpTest, UnderflowToZeroOnNormal) { \
testUnderflowToZeroOnNormal(&func); \
} \
TEST_F(LlvmLibcLdExpTest, UnderflowToZeroOnSubnormal) { \
testUnderflowToZeroOnSubnormal(&func); \
} \
TEST_F(LlvmLibcLdExpTest, NormalOperation) { testNormalOperation(&func); }

#endif // LLVM_LIBC_TEST_SRC_MATH_LDEXPTEST_H
91 changes: 91 additions & 0 deletions libc/test/src/math/smoke/LogbTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//===-- Utility class to test logb[f|l] -------------------------*- 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
//
//===----------------------------------------------------------------------===//

#include "src/__support/FPUtil/ManipulationFunctions.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"

#include <math.h>

template <typename T> class LogbTest : public __llvm_libc::testing::Test {

DECLARE_SPECIAL_CONSTANTS(T)

static constexpr UIntType HIDDEN_BIT =
UIntType(1) << __llvm_libc::fputil::MantissaWidth<T>::VALUE;

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

void testSpecialNumbers(LogbFunc func) {
ASSERT_FP_EQ(aNaN, func(aNaN));
ASSERT_FP_EQ(inf, func(inf));
ASSERT_FP_EQ(inf, func(neg_inf));
ASSERT_FP_EQ(neg_inf, func(0.0));
ASSERT_FP_EQ(neg_inf, func(-0.0));
}

void testPowersOfTwo(LogbFunc func) {
EXPECT_FP_EQ(T(0.0), func(T(1.0)));
EXPECT_FP_EQ(T(0.0), func(T(-1.0)));

EXPECT_FP_EQ(T(1.0), func(T(2.0)));
EXPECT_FP_EQ(T(1.0), func(T(-2.0)));

EXPECT_FP_EQ(T(2.0), func(T(4.0)));
EXPECT_FP_EQ(T(2.0), func(T(-4.0)));

EXPECT_FP_EQ(T(3.0), func(T(8.0)));
EXPECT_FP_EQ(T(3.0), func(T(-8.0)));

EXPECT_FP_EQ(T(4.0), func(T(16.0)));
EXPECT_FP_EQ(T(4.0), func(T(-16.0)));

EXPECT_FP_EQ(T(5.0), func(T(32.0)));
EXPECT_FP_EQ(T(5.0), func(T(-32.0)));
}

void testSomeIntegers(LogbFunc func) {
EXPECT_FP_EQ(T(1.0), func(T(3.0)));
EXPECT_FP_EQ(T(1.0), func(T(-3.0)));

EXPECT_FP_EQ(T(2.0), func(T(7.0)));
EXPECT_FP_EQ(T(2.0), func(T(-7.0)));

EXPECT_FP_EQ(T(3.0), func(T(10.0)));
EXPECT_FP_EQ(T(3.0), func(T(-10.0)));

EXPECT_FP_EQ(T(4.0), func(T(31.0)));
EXPECT_FP_EQ(T(4.0), func(T(-31.0)));

EXPECT_FP_EQ(T(5.0), func(T(55.0)));
EXPECT_FP_EQ(T(5.0), func(T(-55.0)));
}

void testRange(LogbFunc func) {
using UIntType = typename FPBits::UIntType;
constexpr UIntType COUNT = 100'000;
constexpr UIntType STEP = UIntType(-1) / COUNT;
for (UIntType i = 0, v = 0; i <= COUNT; ++i, v += STEP) {
T x = static_cast<T>(FPBits(v));
if (isnan(x) || isinf(x) || x == 0.0l)
continue;

int exponent;
__llvm_libc::fputil::frexp(x, exponent);
ASSERT_FP_EQ(T(exponent), func(x) + T(1.0));
}
}
};

#define LIST_LOGB_TESTS(T, func) \
using LlvmLibcLogbTest = LogbTest<T>; \
TEST_F(LlvmLibcLogbTest, SpecialNumbers) { testSpecialNumbers(&func); } \
TEST_F(LlvmLibcLogbTest, PowersOfTwo) { testPowersOfTwo(&func); } \
TEST_F(LlvmLibcLogbTest, SomeIntegers) { testSomeIntegers(&func); } \
TEST_F(LlvmLibcLogbTest, InRange) { testRange(&func); }
105 changes: 105 additions & 0 deletions libc/test/src/math/smoke/ModfTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
//===-- Utility class to test floor[f|l] ------------------------*- 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
//
//===----------------------------------------------------------------------===//

#include "src/__support/FPUtil/BasicOperations.h"
#include "src/__support/FPUtil/NearestIntegerOperations.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"

#include <math.h>

template <typename T> class ModfTest : public __llvm_libc::testing::Test {

DECLARE_SPECIAL_CONSTANTS(T)

public:
typedef T (*ModfFunc)(T, T *);

void testSpecialNumbers(ModfFunc func) {
T integral;

EXPECT_FP_EQ(zero, func(zero, &integral));
EXPECT_FP_EQ(integral, zero);
EXPECT_FP_EQ(neg_zero, func(neg_zero, &integral));
EXPECT_FP_EQ(integral, neg_zero);

EXPECT_FP_EQ(zero, func(inf, &integral));
EXPECT_FP_EQ(inf, integral);
EXPECT_FP_EQ(neg_zero, func(neg_inf, &integral));
EXPECT_FP_EQ(neg_inf, integral);

EXPECT_FP_EQ(aNaN, func(aNaN, &integral));
}

void testIntegers(ModfFunc func) {
T integral;

EXPECT_FP_EQ(T(0.0), func(T(1.0), &integral));
EXPECT_FP_EQ(T(1.0), integral);

EXPECT_FP_EQ(T(-0.0), func(T(-1.0), &integral));
EXPECT_FP_EQ(T(-1.0), integral);

EXPECT_FP_EQ(T(0.0), func(T(10.0), &integral));
EXPECT_FP_EQ(T(10.0), integral);

EXPECT_FP_EQ(T(-0.0), func(T(-10.0), &integral));
EXPECT_FP_EQ(T(-10.0), integral);

EXPECT_FP_EQ(T(0.0), func(T(12345.0), &integral));
EXPECT_FP_EQ(T(12345.0), integral);

EXPECT_FP_EQ(T(-0.0), func(T(-12345.0), &integral));
EXPECT_FP_EQ(T(-12345.0), integral);
}

void testFractions(ModfFunc func) {
T integral;

EXPECT_FP_EQ(T(0.5), func(T(1.5), &integral));
EXPECT_FP_EQ(integral, T(1.0));

EXPECT_FP_EQ(T(-0.5), func(T(-1.5), &integral));
EXPECT_FP_EQ(integral, T(-1.0));

EXPECT_FP_EQ(T(0.75), func(T(10.75), &integral));
EXPECT_FP_EQ(integral, T(10.0));

EXPECT_FP_EQ(T(-0.75), func(T(-10.75), &integral));
EXPECT_FP_EQ(integral, T(-10.0));

EXPECT_FP_EQ(T(0.125), func(T(100.125), &integral));
EXPECT_FP_EQ(integral, T(100.0));

EXPECT_FP_EQ(T(-0.125), func(T(-100.125), &integral));
EXPECT_FP_EQ(integral, T(-100.0));
}

void testRange(ModfFunc func) {
constexpr UIntType COUNT = 100'000;
constexpr UIntType STEP = UIntType(-1) / COUNT;
for (UIntType i = 0, v = 0; i <= COUNT; ++i, v += STEP) {
T x = T(FPBits(v));
if (isnan(x) || isinf(x) || x == T(0.0))
continue;

T integral;
T frac = func(x, &integral);
ASSERT_TRUE(__llvm_libc::fputil::abs(frac) < 1.0l);
ASSERT_TRUE(__llvm_libc::fputil::trunc(x) == integral);
ASSERT_TRUE(integral + frac == x);
}
}
};

#define LIST_MODF_TESTS(T, func) \
using LlvmLibcModfTest = ModfTest<T>; \
TEST_F(LlvmLibcModfTest, SpecialNumbers) { testSpecialNumbers(&func); } \
TEST_F(LlvmLibcModfTest, RoundedNubmers) { testIntegers(&func); } \
TEST_F(LlvmLibcModfTest, Fractions) { testFractions(&func); } \
TEST_F(LlvmLibcModfTest, Range) { testRange(&func); }
198 changes: 198 additions & 0 deletions libc/test/src/math/smoke/NextAfterTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
//===-- Utility class to test different flavors of nextafter ----*- 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_NEXTAFTERTEST_H
#define LLVM_LIBC_TEST_SRC_MATH_NEXTAFTERTEST_H

#include "src/__support/CPP/bit.h"
#include "src/__support/CPP/type_traits.h"
#include "src/__support/FPUtil/BasicOperations.h"
#include "src/__support/FPUtil/FPBits.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
#include <math.h>

template <typename T>
class NextAfterTestTemplate : public __llvm_libc::testing::Test {
using FPBits = __llvm_libc::fputil::FPBits<T>;
using MantissaWidth = __llvm_libc::fputil::MantissaWidth<T>;
using UIntType = typename FPBits::UIntType;

static constexpr int BIT_WIDTH_OF_TYPE =
__llvm_libc::fputil::FloatProperties<T>::BIT_WIDTH;

const T zero = T(FPBits::zero());
const T neg_zero = T(FPBits::neg_zero());
const T inf = T(FPBits::inf());
const T neg_inf = T(FPBits::neg_inf());
const T nan = T(FPBits::build_quiet_nan(1));
const UIntType min_subnormal = FPBits::MIN_SUBNORMAL;
const UIntType max_subnormal = FPBits::MAX_SUBNORMAL;
const UIntType min_normal = FPBits::MIN_NORMAL;
const UIntType max_normal = FPBits::MAX_NORMAL;

public:
typedef T (*NextAfterFunc)(T, T);

void testNaN(NextAfterFunc func) {
ASSERT_FP_EQ(func(nan, 0), nan);
ASSERT_FP_EQ(func(0, nan), nan);
}

void testBoundaries(NextAfterFunc func) {
ASSERT_FP_EQ(func(zero, neg_zero), neg_zero);
ASSERT_FP_EQ(func(neg_zero, zero), zero);

// 'from' is zero|neg_zero.
T x = zero;
T result = func(x, T(1));
UIntType expected_bits = 1;
T expected = __llvm_libc::cpp::bit_cast<T>(expected_bits);
ASSERT_FP_EQ(result, expected);

result = func(x, T(-1));
expected_bits = (UIntType(1) << (BIT_WIDTH_OF_TYPE - 1)) + 1;
expected = __llvm_libc::cpp::bit_cast<T>(expected_bits);
ASSERT_FP_EQ(result, expected);

x = neg_zero;
result = func(x, 1);
expected_bits = 1;
expected = __llvm_libc::cpp::bit_cast<T>(expected_bits);
ASSERT_FP_EQ(result, expected);

result = func(x, -1);
expected_bits = (UIntType(1) << (BIT_WIDTH_OF_TYPE - 1)) + 1;
expected = __llvm_libc::cpp::bit_cast<T>(expected_bits);
ASSERT_FP_EQ(result, expected);

// 'from' is max subnormal value.
x = __llvm_libc::cpp::bit_cast<T>(max_subnormal);
result = func(x, 1);
expected = __llvm_libc::cpp::bit_cast<T>(min_normal);
ASSERT_FP_EQ(result, expected);

result = func(x, 0);
expected_bits = max_subnormal - 1;
expected = __llvm_libc::cpp::bit_cast<T>(expected_bits);
ASSERT_FP_EQ(result, expected);

x = -x;

result = func(x, -1);
expected_bits = (UIntType(1) << (BIT_WIDTH_OF_TYPE - 1)) + min_normal;
expected = __llvm_libc::cpp::bit_cast<T>(expected_bits);
ASSERT_FP_EQ(result, expected);

result = func(x, 0);
expected_bits =
(UIntType(1) << (BIT_WIDTH_OF_TYPE - 1)) + max_subnormal - 1;
expected = __llvm_libc::cpp::bit_cast<T>(expected_bits);
ASSERT_FP_EQ(result, expected);

// 'from' is min subnormal value.
x = __llvm_libc::cpp::bit_cast<T>(min_subnormal);
result = func(x, 1);
expected_bits = min_subnormal + 1;
expected = __llvm_libc::cpp::bit_cast<T>(expected_bits);
ASSERT_FP_EQ(result, expected);
ASSERT_FP_EQ(func(x, 0), 0);

x = -x;
result = func(x, -1);
expected_bits =
(UIntType(1) << (BIT_WIDTH_OF_TYPE - 1)) + min_subnormal + 1;
expected = __llvm_libc::cpp::bit_cast<T>(expected_bits);
ASSERT_FP_EQ(result, expected);
ASSERT_FP_EQ(func(x, 0), T(-0.0));

// 'from' is min normal.
x = __llvm_libc::cpp::bit_cast<T>(min_normal);
result = func(x, 0);
expected_bits = max_subnormal;
expected = __llvm_libc::cpp::bit_cast<T>(expected_bits);
ASSERT_FP_EQ(result, expected);

result = func(x, inf);
expected_bits = min_normal + 1;
expected = __llvm_libc::cpp::bit_cast<T>(expected_bits);
ASSERT_FP_EQ(result, expected);

x = -x;
result = func(x, 0);
expected_bits = (UIntType(1) << (BIT_WIDTH_OF_TYPE - 1)) + max_subnormal;
expected = __llvm_libc::cpp::bit_cast<T>(expected_bits);
ASSERT_FP_EQ(result, expected);

result = func(x, -inf);
expected_bits = (UIntType(1) << (BIT_WIDTH_OF_TYPE - 1)) + min_normal + 1;
expected = __llvm_libc::cpp::bit_cast<T>(expected_bits);
ASSERT_FP_EQ(result, expected);

// 'from' is max normal and 'to' is infinity.
x = __llvm_libc::cpp::bit_cast<T>(max_normal);
result = func(x, inf);
ASSERT_FP_EQ(result, inf);

result = func(-x, -inf);
ASSERT_FP_EQ(result, -inf);

// 'from' is infinity.
x = inf;
result = func(x, 0);
expected_bits = max_normal;
expected = __llvm_libc::cpp::bit_cast<T>(expected_bits);
ASSERT_FP_EQ(result, expected);
ASSERT_FP_EQ(func(x, inf), inf);

x = neg_inf;
result = func(x, 0);
expected_bits = (UIntType(1) << (BIT_WIDTH_OF_TYPE - 1)) + max_normal;
expected = __llvm_libc::cpp::bit_cast<T>(expected_bits);
ASSERT_FP_EQ(result, expected);
ASSERT_FP_EQ(func(x, neg_inf), neg_inf);

// 'from' is a power of 2.
x = T(32.0);
result = func(x, 0);
FPBits x_bits = FPBits(x);
FPBits result_bits = FPBits(result);
ASSERT_EQ(result_bits.get_unbiased_exponent(),
uint16_t(x_bits.get_unbiased_exponent() - 1));
ASSERT_EQ(result_bits.get_mantissa(),
(UIntType(1) << MantissaWidth::VALUE) - 1);

result = func(x, T(33.0));
result_bits = FPBits(result);
ASSERT_EQ(result_bits.get_unbiased_exponent(),
x_bits.get_unbiased_exponent());
ASSERT_EQ(result_bits.get_mantissa(), x_bits.get_mantissa() + UIntType(1));

x = -x;

result = func(x, 0);
result_bits = FPBits(result);
ASSERT_EQ(result_bits.get_unbiased_exponent(),
uint16_t(x_bits.get_unbiased_exponent() - 1));
ASSERT_EQ(result_bits.get_mantissa(),
(UIntType(1) << MantissaWidth::VALUE) - 1);

result = func(x, T(-33.0));
result_bits = FPBits(result);
ASSERT_EQ(result_bits.get_unbiased_exponent(),
x_bits.get_unbiased_exponent());
ASSERT_EQ(result_bits.get_mantissa(), x_bits.get_mantissa() + UIntType(1));
}
};

#define LIST_NEXTAFTER_TESTS(T, func) \
using LlvmLibcNextAfterTest = NextAfterTestTemplate<T>; \
TEST_F(LlvmLibcNextAfterTest, TestNaN) { testNaN(&func); } \
TEST_F(LlvmLibcNextAfterTest, TestBoundaries) { testBoundaries(&func); }

#endif // LLVM_LIBC_TEST_SRC_MATH_NEXTAFTERTEST_H
56 changes: 56 additions & 0 deletions libc/test/src/math/smoke/RIntTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//===-- Utility class to test different flavors of rint ---------*- 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_RINTTEST_H
#define LLVM_LIBC_TEST_SRC_MATH_RINTTEST_H

#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"

#include <fenv.h>
#include <math.h>
#include <stdio.h>

static constexpr int ROUNDING_MODES[4] = {FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO,
FE_TONEAREST};

template <typename T>
class RIntTestTemplate : public __llvm_libc::testing::Test {
public:
typedef T (*RIntFunc)(T);

private:
using FPBits = __llvm_libc::fputil::FPBits<T>;
using UIntType = typename FPBits::UIntType;

const T zero = T(FPBits::zero());
const T neg_zero = T(FPBits::neg_zero());
const T inf = T(FPBits::inf());
const T neg_inf = T(FPBits::neg_inf());
const T nan = T(FPBits::build_quiet_nan(1));

public:
void testSpecialNumbers(RIntFunc func) {
for (int mode : ROUNDING_MODES) {
__llvm_libc::fputil::set_round(mode);
ASSERT_FP_EQ(inf, func(inf));
ASSERT_FP_EQ(neg_inf, func(neg_inf));
ASSERT_FP_EQ(nan, func(nan));
ASSERT_FP_EQ(zero, func(zero));
ASSERT_FP_EQ(neg_zero, func(neg_zero));
}
}
};

#define LIST_RINT_TESTS(F, func) \
using LlvmLibcRIntTest = RIntTestTemplate<F>; \
TEST_F(LlvmLibcRIntTest, specialNumbers) { testSpecialNumbers(&func); }

#endif // LLVM_LIBC_TEST_SRC_MATH_RINTTEST_H
102 changes: 102 additions & 0 deletions libc/test/src/math/smoke/RemQuoTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//===-- Utility class to test different flavors of remquo -------*- 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_REMQUOTEST_H
#define LLVM_LIBC_TEST_SRC_MATH_REMQUOTEST_H

#include "src/__support/FPUtil/BasicOperations.h"
#include "src/__support/FPUtil/FPBits.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
#include <math.h>

template <typename T>
class RemQuoTestTemplate : public __llvm_libc::testing::Test {
using FPBits = __llvm_libc::fputil::FPBits<T>;
using UIntType = typename FPBits::UIntType;

const T zero = T(__llvm_libc::fputil::FPBits<T>::zero());
const T neg_zero = T(__llvm_libc::fputil::FPBits<T>::neg_zero());
const T inf = T(__llvm_libc::fputil::FPBits<T>::inf());
const T neg_inf = T(__llvm_libc::fputil::FPBits<T>::neg_inf());
const T nan = T(__llvm_libc::fputil::FPBits<T>::build_quiet_nan(1));

public:
typedef T (*RemQuoFunc)(T, T, int *);

void testSpecialNumbers(RemQuoFunc func) {
int quotient;
T x, y;

y = T(1.0);
x = inf;
EXPECT_FP_EQ(nan, func(x, y, &quotient));
x = neg_inf;
EXPECT_FP_EQ(nan, func(x, y, &quotient));

x = T(1.0);
y = zero;
EXPECT_FP_EQ(nan, func(x, y, &quotient));
y = neg_zero;
EXPECT_FP_EQ(nan, func(x, y, &quotient));

y = nan;
x = T(1.0);
EXPECT_FP_EQ(nan, func(x, y, &quotient));

y = T(1.0);
x = nan;
EXPECT_FP_EQ(nan, func(x, y, &quotient));

x = nan;
y = nan;
EXPECT_FP_EQ(nan, func(x, y, &quotient));

x = zero;
y = T(1.0);
EXPECT_FP_EQ(func(x, y, &quotient), zero);

x = neg_zero;
y = T(1.0);
EXPECT_FP_EQ(func(x, y, &quotient), neg_zero);

x = T(1.125);
y = inf;
EXPECT_FP_EQ(func(x, y, &quotient), x);
EXPECT_EQ(quotient, 0);
}

void testEqualNumeratorAndDenominator(RemQuoFunc func) {
T x = T(1.125), y = T(1.125);
int q;

// When the remainder is zero, the standard requires it to
// have the same sign as x.

EXPECT_FP_EQ(func(x, y, &q), zero);
EXPECT_EQ(q, 1);

EXPECT_FP_EQ(func(x, -y, &q), zero);
EXPECT_EQ(q, -1);

EXPECT_FP_EQ(func(-x, y, &q), neg_zero);
EXPECT_EQ(q, -1);

EXPECT_FP_EQ(func(-x, -y, &q), neg_zero);
EXPECT_EQ(q, 1);
}
};

#define LIST_REMQUO_TESTS(T, func) \
using LlvmLibcRemQuoTest = RemQuoTestTemplate<T>; \
TEST_F(LlvmLibcRemQuoTest, SpecialNumbers) { testSpecialNumbers(&func); } \
TEST_F(LlvmLibcRemQuoTest, EqualNumeratorAndDenominator) { \
testEqualNumeratorAndDenominator(&func); \
}

#endif // LLVM_LIBC_TEST_SRC_MATH_REMQUOTEST_H
68 changes: 68 additions & 0 deletions libc/test/src/math/smoke/RoundTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//===-- Utility class to test round[f|l] ------------------------*- 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
//
//===----------------------------------------------------------------------===//

#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"

#include <math.h>

template <typename T> class RoundTest : public __llvm_libc::testing::Test {

DECLARE_SPECIAL_CONSTANTS(T)

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

void testSpecialNumbers(RoundFunc func) {
EXPECT_FP_EQ(zero, func(zero));
EXPECT_FP_EQ(neg_zero, func(neg_zero));

EXPECT_FP_EQ(inf, func(inf));
EXPECT_FP_EQ(neg_inf, func(neg_inf));

EXPECT_FP_EQ(aNaN, func(aNaN));
}

void testRoundedNumbers(RoundFunc func) {
EXPECT_FP_EQ(T(1.0), func(T(1.0)));
EXPECT_FP_EQ(T(-1.0), func(T(-1.0)));
EXPECT_FP_EQ(T(10.0), func(T(10.0)));
EXPECT_FP_EQ(T(-10.0), func(T(-10.0)));
EXPECT_FP_EQ(T(1234.0), func(T(1234.0)));
EXPECT_FP_EQ(T(-1234.0), func(T(-1234.0)));
}

void testFractions(RoundFunc func) {
EXPECT_FP_EQ(T(1.0), func(T(0.5)));
EXPECT_FP_EQ(T(-1.0), func(T(-0.5)));
EXPECT_FP_EQ(T(0.0), func(T(0.115)));
EXPECT_FP_EQ(T(-0.0), func(T(-0.115)));
EXPECT_FP_EQ(T(1.0), func(T(0.715)));
EXPECT_FP_EQ(T(-1.0), func(T(-0.715)));
EXPECT_FP_EQ(T(1.0), func(T(1.3)));
EXPECT_FP_EQ(T(-1.0), func(T(-1.3)));
EXPECT_FP_EQ(T(2.0), func(T(1.5)));
EXPECT_FP_EQ(T(-2.0), func(T(-1.5)));
EXPECT_FP_EQ(T(2.0), func(T(1.75)));
EXPECT_FP_EQ(T(-2.0), func(T(-1.75)));
EXPECT_FP_EQ(T(10.0), func(T(10.32)));
EXPECT_FP_EQ(T(-10.0), func(T(-10.32)));
EXPECT_FP_EQ(T(11.0), func(T(10.65)));
EXPECT_FP_EQ(T(-11.0), func(T(-10.65)));
EXPECT_FP_EQ(T(1234.0), func(T(1234.38)));
EXPECT_FP_EQ(T(-1234.0), func(T(-1234.38)));
EXPECT_FP_EQ(T(1235.0), func(T(1234.96)));
EXPECT_FP_EQ(T(-1235.0), func(T(-1234.96)));
}
};

#define LIST_ROUND_TESTS(T, func) \
using LlvmLibcRoundTest = RoundTest<T>; \
TEST_F(LlvmLibcRoundTest, SpecialNumbers) { testSpecialNumbers(&func); } \
TEST_F(LlvmLibcRoundTest, RoundedNubmers) { testRoundedNumbers(&func); } \
TEST_F(LlvmLibcRoundTest, Fractions) { testFractions(&func); }
168 changes: 168 additions & 0 deletions libc/test/src/math/smoke/RoundToIntegerTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
//===-- Utility class to test different flavors of [l|ll]round --*- 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_ROUNDTOINTEGERTEST_H
#define LLVM_LIBC_TEST_SRC_MATH_ROUNDTOINTEGERTEST_H

#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"

#include <errno.h>
#include <math.h>

static constexpr int ROUNDING_MODES[4] = {FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO,
FE_TONEAREST};

template <typename F, typename I, bool TestModes = false>
class RoundToIntegerTestTemplate : public __llvm_libc::testing::Test {
public:
typedef I (*RoundToIntegerFunc)(F);

private:
using FPBits = __llvm_libc::fputil::FPBits<F>;
using UIntType = typename FPBits::UIntType;

const F zero = F(__llvm_libc::fputil::FPBits<F>::zero());
const F neg_zero = F(__llvm_libc::fputil::FPBits<F>::neg_zero());
const F inf = F(__llvm_libc::fputil::FPBits<F>::inf());
const F neg_inf = F(__llvm_libc::fputil::FPBits<F>::neg_inf());
const F nan = F(__llvm_libc::fputil::FPBits<F>::build_quiet_nan(1));
static constexpr I INTEGER_MIN = I(1) << (sizeof(I) * 8 - 1);
static constexpr I INTEGER_MAX = -(INTEGER_MIN + 1);

void test_one_input(RoundToIntegerFunc func, F input, I expected,
bool expectError) {
libc_errno = 0;
__llvm_libc::fputil::clear_except(FE_ALL_EXCEPT);

ASSERT_EQ(func(input), expected);

if (expectError) {
ASSERT_FP_EXCEPTION(FE_INVALID);
ASSERT_MATH_ERRNO(EDOM);
} else {
ASSERT_FP_EXCEPTION(0);
ASSERT_MATH_ERRNO(0);
}
}

public:
void SetUp() override {
if (math_errhandling & MATH_ERREXCEPT) {
// We will disable all exceptions so that the test will not
// crash with SIGFPE. We can still use fetestexcept to check
// if the appropriate flag was raised.
__llvm_libc::fputil::disable_except(FE_ALL_EXCEPT);
}
}

void do_infinity_and_na_n_test(RoundToIntegerFunc func) {
test_one_input(func, inf, INTEGER_MAX, true);
test_one_input(func, neg_inf, INTEGER_MIN, true);
// This is currently never enabled, the
// LLVM_LIBC_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR CMake option in
// libc/CMakeLists.txt is not forwarded to C++.
#if LIBC_COPT_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR
// Result is not well-defined, we always returns INTEGER_MAX
test_one_input(func, nan, INTEGER_MAX, true);
#endif // LIBC_COPT_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR
}

void testInfinityAndNaN(RoundToIntegerFunc func) {
if (TestModes) {
for (int mode : ROUNDING_MODES) {
__llvm_libc::fputil::set_round(mode);
do_infinity_and_na_n_test(func);
}
} else {
do_infinity_and_na_n_test(func);
}
}

void do_round_numbers_test(RoundToIntegerFunc func) {
test_one_input(func, zero, I(0), false);
test_one_input(func, neg_zero, I(0), false);
test_one_input(func, F(1.0), I(1), false);
test_one_input(func, F(-1.0), I(-1), false);
test_one_input(func, F(10.0), I(10), false);
test_one_input(func, F(-10.0), I(-10), false);
test_one_input(func, F(1234.0), I(1234), false);
test_one_input(func, F(-1234.0), I(-1234), false);
}

void testRoundNumbers(RoundToIntegerFunc func) {
if (TestModes) {
for (int mode : ROUNDING_MODES) {
__llvm_libc::fputil::set_round(mode);
do_round_numbers_test(func);
}
} else {
do_round_numbers_test(func);
}
}

void testSubnormalRange(RoundToIntegerFunc func) {
constexpr UIntType COUNT = 1'000'001;
constexpr UIntType STEP =
(UIntType(FPBits::MAX_SUBNORMAL) - UIntType(FPBits::MIN_SUBNORMAL)) /
COUNT;
for (UIntType i = FPBits::MIN_SUBNORMAL; i <= FPBits::MAX_SUBNORMAL;
i += STEP) {
F x = F(FPBits(i));
if (x == F(0.0))
continue;
// All subnormal numbers should round to zero.
if (TestModes) {
if (x > 0) {
__llvm_libc::fputil::set_round(FE_UPWARD);
test_one_input(func, x, I(1), false);
__llvm_libc::fputil::set_round(FE_DOWNWARD);
test_one_input(func, x, I(0), false);
__llvm_libc::fputil::set_round(FE_TOWARDZERO);
test_one_input(func, x, I(0), false);
__llvm_libc::fputil::set_round(FE_TONEAREST);
test_one_input(func, x, I(0), false);
} else {
__llvm_libc::fputil::set_round(FE_UPWARD);
test_one_input(func, x, I(0), false);
__llvm_libc::fputil::set_round(FE_DOWNWARD);
test_one_input(func, x, I(-1), false);
__llvm_libc::fputil::set_round(FE_TOWARDZERO);
test_one_input(func, x, I(0), false);
__llvm_libc::fputil::set_round(FE_TONEAREST);
test_one_input(func, x, I(0), false);
}
} else {
test_one_input(func, x, 0L, false);
}
}
}
};

#define LIST_ROUND_TO_INTEGER_TESTS_HELPER(F, I, func, TestModes) \
using LlvmLibcRoundToIntegerTest = \
RoundToIntegerTestTemplate<F, I, TestModes>; \
TEST_F(LlvmLibcRoundToIntegerTest, InfinityAndNaN) { \
testInfinityAndNaN(&func); \
} \
TEST_F(LlvmLibcRoundToIntegerTest, RoundNumbers) { \
testRoundNumbers(&func); \
} \
TEST_F(LlvmLibcRoundToIntegerTest, SubnormalRange) { \
testSubnormalRange(&func); \
}

#define LIST_ROUND_TO_INTEGER_TESTS(F, I, func) \
LIST_ROUND_TO_INTEGER_TESTS_HELPER(F, I, func, false)

#define LIST_ROUND_TO_INTEGER_TESTS_WITH_MODES(F, I, func) \
LIST_ROUND_TO_INTEGER_TESTS_HELPER(F, I, func, true)

#endif // LLVM_LIBC_TEST_SRC_MATH_ROUNDTOINTEGERTEST_H
28 changes: 28 additions & 0 deletions libc/test/src/math/smoke/ScalbnTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//===-- Utility class to test different flavors of scalbn -------*- 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_SCALBN_H
#define LLVM_LIBC_TEST_SRC_MATH_SCALBN_H

#include "LdExpTest.h"
#include "test/UnitTest/Test.h"

#define LIST_SCALBN_TESTS(T, func) \
using LlvmLibcScalbnTest = LdExpTestTemplate<T>; \
TEST_F(LlvmLibcScalbnTest, SpecialNumbers) { testSpecialNumbers(&func); } \
TEST_F(LlvmLibcScalbnTest, PowersOfTwo) { testPowersOfTwo(&func); } \
TEST_F(LlvmLibcScalbnTest, OverFlow) { testOverflow(&func); } \
TEST_F(LlvmLibcScalbnTest, UnderflowToZeroOnNormal) { \
testUnderflowToZeroOnNormal(&func); \
} \
TEST_F(LlvmLibcScalbnTest, UnderflowToZeroOnSubnormal) { \
testUnderflowToZeroOnSubnormal(&func); \
} \
TEST_F(LlvmLibcScalbnTest, NormalOperation) { testNormalOperation(&func); }

#endif // LLVM_LIBC_TEST_SRC_MATH_SCALBN_H
40 changes: 40 additions & 0 deletions libc/test/src/math/smoke/SqrtTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//===-- Utility class to test sqrt[f|l] -------------------------*- 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
//
//===----------------------------------------------------------------------===//

#include "src/__support/CPP/bit.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"

#include <math.h>

template <typename T> class SqrtTest : public __llvm_libc::testing::Test {

DECLARE_SPECIAL_CONSTANTS(T)

static constexpr UIntType HIDDEN_BIT =
UIntType(1) << __llvm_libc::fputil::MantissaWidth<T>::VALUE;

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)));
}
};

#define LIST_SQRT_TESTS(T, func) \
using LlvmLibcSqrtTest = SqrtTest<T>; \
TEST_F(LlvmLibcSqrtTest, SpecialNumbers) { test_special_numbers(&func); }
68 changes: 68 additions & 0 deletions libc/test/src/math/smoke/TruncTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//===-- Utility class to test trunc[f|l] ------------------------*- 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
//
//===----------------------------------------------------------------------===//

#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"

#include <math.h>

template <typename T> class TruncTest : public __llvm_libc::testing::Test {

DECLARE_SPECIAL_CONSTANTS(T)

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

void testSpecialNumbers(TruncFunc func) {
EXPECT_FP_EQ(zero, func(zero));
EXPECT_FP_EQ(neg_zero, func(neg_zero));

EXPECT_FP_EQ(inf, func(inf));
EXPECT_FP_EQ(neg_inf, func(neg_inf));

EXPECT_FP_EQ(aNaN, func(aNaN));
}

void testRoundedNumbers(TruncFunc func) {
EXPECT_FP_EQ(T(1.0), func(T(1.0)));
EXPECT_FP_EQ(T(-1.0), func(T(-1.0)));
EXPECT_FP_EQ(T(10.0), func(T(10.0)));
EXPECT_FP_EQ(T(-10.0), func(T(-10.0)));
EXPECT_FP_EQ(T(1234.0), func(T(1234.0)));
EXPECT_FP_EQ(T(-1234.0), func(T(-1234.0)));
}

void testFractions(TruncFunc func) {
EXPECT_FP_EQ(T(0.0), func(T(0.5)));
EXPECT_FP_EQ(T(-0.0), func(T(-0.5)));
EXPECT_FP_EQ(T(0.0), func(T(0.115)));
EXPECT_FP_EQ(T(-0.0), func(T(-0.115)));
EXPECT_FP_EQ(T(0.0), func(T(0.715)));
EXPECT_FP_EQ(T(-0.0), func(T(-0.715)));
EXPECT_FP_EQ(T(1.0), func(T(1.3)));
EXPECT_FP_EQ(T(-1.0), func(T(-1.3)));
EXPECT_FP_EQ(T(1.0), func(T(1.5)));
EXPECT_FP_EQ(T(-1.0), func(T(-1.5)));
EXPECT_FP_EQ(T(1.0), func(T(1.75)));
EXPECT_FP_EQ(T(-1.0), func(T(-1.75)));
EXPECT_FP_EQ(T(10.0), func(T(10.32)));
EXPECT_FP_EQ(T(-10.0), func(T(-10.32)));
EXPECT_FP_EQ(T(10.0), func(T(10.65)));
EXPECT_FP_EQ(T(-10.0), func(T(-10.65)));
EXPECT_FP_EQ(T(1234.0), func(T(1234.38)));
EXPECT_FP_EQ(T(-1234.0), func(T(-1234.38)));
EXPECT_FP_EQ(T(1234.0), func(T(1234.96)));
EXPECT_FP_EQ(T(-1234.0), func(T(-1234.96)));
}
};

#define LIST_TRUNC_TESTS(T, func) \
using LlvmLibcTruncTest = TruncTest<T>; \
TEST_F(LlvmLibcTruncTest, SpecialNumbers) { testSpecialNumbers(&func); } \
TEST_F(LlvmLibcTruncTest, RoundedNubmers) { testRoundedNumbers(&func); } \
TEST_F(LlvmLibcTruncTest, Fractions) { testFractions(&func); }
43 changes: 43 additions & 0 deletions libc/test/src/math/smoke/acosf_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//===-- Unittests for acosf -----------------------------------------------===//
//
// 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/FPUtil/FPBits.h"
#include "src/errno/libc_errno.h"
#include "src/math/acosf.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
#include <math.h>

#include <errno.h>
#include <stdint.h>

using FPBits = __llvm_libc::fputil::FPBits<float>;

DECLARE_SPECIAL_CONSTANTS(float)

TEST(LlvmLibcAcosfTest, SpecialNumbers) {
libc_errno = 0;

EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::acosf(aNaN));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::acosf(inf));
EXPECT_MATH_ERRNO(EDOM);

EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::acosf(neg_inf));
EXPECT_MATH_ERRNO(EDOM);

EXPECT_FP_EQ_ALL_ROUNDING(zero, __llvm_libc::acosf(1.0f));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::acosf(2.0f));
EXPECT_MATH_ERRNO(EDOM);

EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::acosf(-2.0f));
EXPECT_MATH_ERRNO(EDOM);
}
40 changes: 40 additions & 0 deletions libc/test/src/math/smoke/acoshf_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//===-- Unittests for acoshf ----------------------------------------------===//
//
// 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/FPUtil/FPBits.h"
#include "src/errno/libc_errno.h"
#include "src/math/acoshf.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
#include <math.h>

#include <errno.h>
#include <stdint.h>

using FPBits_t = __llvm_libc::fputil::FPBits<float>;

DECLARE_SPECIAL_CONSTANTS(float)

TEST(LlvmLibcAcoshfTest, SpecialNumbers) {
libc_errno = 0;

EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::acoshf(aNaN));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::acoshf(0.0f));
EXPECT_MATH_ERRNO(EDOM);

EXPECT_FP_EQ_ALL_ROUNDING(0.0f, __llvm_libc::acoshf(1.0f));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(inf, __llvm_libc::acoshf(inf));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::acoshf(neg_inf));
EXPECT_MATH_ERRNO(EDOM);
}
46 changes: 46 additions & 0 deletions libc/test/src/math/smoke/asinf_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//===-- Unittests for asinf -----------------------------------------------===//
//
// 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/FPUtil/FPBits.h"
#include "src/errno/libc_errno.h"
#include "src/math/asinf.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
#include <math.h>

#include <errno.h>
#include <stdint.h>

using FPBits = __llvm_libc::fputil::FPBits<float>;

DECLARE_SPECIAL_CONSTANTS(float)

TEST(LlvmLibcAsinfTest, SpecialNumbers) {
libc_errno = 0;

EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::asinf(aNaN));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(0.0f, __llvm_libc::asinf(0.0f));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(-0.0f, __llvm_libc::asinf(-0.0f));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::asinf(inf));
EXPECT_MATH_ERRNO(EDOM);

EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::asinf(neg_inf));
EXPECT_MATH_ERRNO(EDOM);

EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::asinf(2.0f));
EXPECT_MATH_ERRNO(EDOM);

EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::asinf(-2.0f));
EXPECT_MATH_ERRNO(EDOM);
}
40 changes: 40 additions & 0 deletions libc/test/src/math/smoke/asinhf_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//===-- Unittests for asinhf ----------------------------------------------===//
//
// 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/FPUtil/FPBits.h"
#include "src/errno/libc_errno.h"
#include "src/math/asinhf.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
#include <math.h>

#include <errno.h>
#include <stdint.h>

using FPBits_t = __llvm_libc::fputil::FPBits<float>;

DECLARE_SPECIAL_CONSTANTS(float)

TEST(LlvmLibcAsinhfTest, SpecialNumbers) {
libc_errno = 0;

EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::asinhf(aNaN));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(0.0f, __llvm_libc::asinhf(0.0f));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(-0.0f, __llvm_libc::asinhf(-0.0f));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(inf, __llvm_libc::asinhf(inf));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(neg_inf, __llvm_libc::asinhf(neg_inf));
EXPECT_MATH_ERRNO(0);
}
40 changes: 40 additions & 0 deletions libc/test/src/math/smoke/atanf_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//===-- Unittests for atanf -----------------------------------------------===//
//
// 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/FPUtil/FPBits.h"
#include "src/errno/libc_errno.h"
#include "src/math/atanf.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
#include <math.h>

#include <errno.h>
#include <stdint.h>

using FPBits = __llvm_libc::fputil::FPBits<float>;

DECLARE_SPECIAL_CONSTANTS(float)

TEST(LlvmLibcAtanfTest, SpecialNumbers) {
libc_errno = 0;

__llvm_libc::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::atanf(aNaN));
EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);

__llvm_libc::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(0.0f, __llvm_libc::atanf(0.0f));
EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);

__llvm_libc::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(-0.0f, __llvm_libc::atanf(-0.0f));
EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);
}
72 changes: 72 additions & 0 deletions libc/test/src/math/smoke/atanhf_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//===-- Unittests for atanhf ----------------------------------------------===//
//
// 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/FPUtil/FPBits.h"
#include "src/errno/libc_errno.h"
#include "src/math/atanhf.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
#include <math.h>

#include <errno.h>
#include <stdint.h>

using FPBits = __llvm_libc::fputil::FPBits<float>;

DECLARE_SPECIAL_CONSTANTS(float)

TEST(LlvmLibcAtanhfTest, SpecialNumbers) {
libc_errno = 0;

__llvm_libc::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::atanhf(aNaN));
EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);

__llvm_libc::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(0.0f, __llvm_libc::atanhf(0.0f));
EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);

__llvm_libc::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ_ALL_ROUNDING(-0.0f, __llvm_libc::atanhf(-0.0f));
EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_WITH_EXCEPTION(inf, __llvm_libc::atanhf(1.0f), FE_DIVBYZERO);
EXPECT_MATH_ERRNO(ERANGE);

EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, __llvm_libc::atanhf(-1.0f),
FE_DIVBYZERO);
EXPECT_MATH_ERRNO(ERANGE);

auto bt = FPBits(1.0f);
bt.bits += 1;

EXPECT_FP_IS_NAN_WITH_EXCEPTION(__llvm_libc::atanhf(bt.get_val()),
FE_INVALID);
EXPECT_MATH_ERRNO(EDOM);

bt.set_sign(true);
EXPECT_FP_IS_NAN_WITH_EXCEPTION(__llvm_libc::atanhf(bt.get_val()),
FE_INVALID);
EXPECT_MATH_ERRNO(EDOM);

EXPECT_FP_IS_NAN_WITH_EXCEPTION(__llvm_libc::atanhf(2.0f), FE_INVALID);
EXPECT_MATH_ERRNO(EDOM);

EXPECT_FP_IS_NAN_WITH_EXCEPTION(__llvm_libc::atanhf(-2.0f), FE_INVALID);
EXPECT_MATH_ERRNO(EDOM);

EXPECT_FP_IS_NAN_WITH_EXCEPTION(__llvm_libc::atanhf(inf), FE_INVALID);
EXPECT_MATH_ERRNO(EDOM);

bt.set_sign(true);
EXPECT_FP_IS_NAN_WITH_EXCEPTION(__llvm_libc::atanhf(neg_inf), FE_INVALID);
EXPECT_MATH_ERRNO(EDOM);
}
13 changes: 13 additions & 0 deletions libc/test/src/math/smoke/ceil_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for ceil ------------------------------------------------===//
//
// 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 "CeilTest.h"

#include "src/math/ceil.h"

LIST_CEIL_TESTS(double, __llvm_libc::ceil)
13 changes: 13 additions & 0 deletions libc/test/src/math/smoke/ceilf_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for ceilf -----------------------------------------------===//
//
// 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 "CeilTest.h"

#include "src/math/ceilf.h"

LIST_CEIL_TESTS(float, __llvm_libc::ceilf)
13 changes: 13 additions & 0 deletions libc/test/src/math/smoke/ceill_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for ceill -----------------------------------------------===//
//
// 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 "CeilTest.h"

#include "src/math/ceill.h"

LIST_CEIL_TESTS(long double, __llvm_libc::ceill)
13 changes: 13 additions & 0 deletions libc/test/src/math/smoke/copysign_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for copysign --------------------------------------------===//
//
// 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 "CopySignTest.h"

#include "src/math/copysign.h"

LIST_COPYSIGN_TESTS(double, __llvm_libc::copysign)
13 changes: 13 additions & 0 deletions libc/test/src/math/smoke/copysignf_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for copysignf -------------------------------------------===//
//
// 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 "CopySignTest.h"

#include "src/math/copysignf.h"

LIST_COPYSIGN_TESTS(float, __llvm_libc::copysignf)
13 changes: 13 additions & 0 deletions libc/test/src/math/smoke/copysignl_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for copysignl -------------------------------------------===//
//
// 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 "CopySignTest.h"

#include "src/math/copysignl.h"

LIST_COPYSIGN_TESTS(long double, __llvm_libc::copysignl)
40 changes: 40 additions & 0 deletions libc/test/src/math/smoke/cosf_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//===-- Unittests for cosf ------------------------------------------------===//
//
// 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/FPUtil/FPBits.h"
#include "src/errno/libc_errno.h"
#include "src/math/cosf.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
#include <math.h>

#include <errno.h>
#include <stdint.h>

using FPBits = __llvm_libc::fputil::FPBits<float>;

DECLARE_SPECIAL_CONSTANTS(float)

TEST(LlvmLibcCosfTest, SpecialNumbers) {
libc_errno = 0;

EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::cosf(aNaN));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(1.0f, __llvm_libc::cosf(0.0f));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(1.0f, __llvm_libc::cosf(-0.0f));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::cosf(inf));
EXPECT_MATH_ERRNO(EDOM);

EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::cosf(neg_inf));
EXPECT_MATH_ERRNO(EDOM);
}
56 changes: 56 additions & 0 deletions libc/test/src/math/smoke/coshf_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//===-- Unittests for coshf -----------------------------------------------===//
//
// 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/CPP/array.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/errno/libc_errno.h"
#include "src/math/coshf.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
#include <math.h>

#include <errno.h>
#include <stdint.h>

using FPBits = __llvm_libc::fputil::FPBits<float>;

DECLARE_SPECIAL_CONSTANTS(float)

TEST(LlvmLibcCoshfTest, SpecialNumbers) {
libc_errno = 0;

EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::coshf(aNaN));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(inf, __llvm_libc::coshf(inf));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(inf, __llvm_libc::coshf(neg_inf));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(1.0f, __llvm_libc::coshf(0.0f));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(1.0f, __llvm_libc::coshf(-0.0f));
EXPECT_MATH_ERRNO(0);
}

TEST(LlvmLibcCoshfTest, Overflow) {
libc_errno = 0;
EXPECT_FP_EQ_WITH_EXCEPTION(
inf, __llvm_libc::coshf(float(FPBits(0x7f7fffffU))), FE_OVERFLOW);
EXPECT_MATH_ERRNO(ERANGE);

EXPECT_FP_EQ_WITH_EXCEPTION(
inf, __llvm_libc::coshf(float(FPBits(0x42cffff8U))), FE_OVERFLOW);
EXPECT_MATH_ERRNO(ERANGE);

EXPECT_FP_EQ_WITH_EXCEPTION(
inf, __llvm_libc::coshf(float(FPBits(0x42d00008U))), FE_OVERFLOW);
EXPECT_MATH_ERRNO(ERANGE);
}
28 changes: 28 additions & 0 deletions libc/test/src/math/smoke/erff_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//===-- Unittests for erff ------------------------------------------------===//
//
// 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/FPUtil/FPBits.h"
#include "src/math/erff.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
#include <math.h>

#include <errno.h>
#include <stdint.h>

using __llvm_libc::testing::tlog;

DECLARE_SPECIAL_CONSTANTS(float)

TEST(LlvmLibcErffTest, SpecialNumbers) {
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::erff(aNaN));
EXPECT_FP_EQ_ALL_ROUNDING(1.0f, __llvm_libc::erff(inf));
EXPECT_FP_EQ_ALL_ROUNDING(-1.0f, __llvm_libc::erff(neg_inf));
EXPECT_FP_EQ_ALL_ROUNDING(zero, __llvm_libc::erff(zero));
EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, __llvm_libc::erff(neg_zero));
}
36 changes: 36 additions & 0 deletions libc/test/src/math/smoke/exp10_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//===-- Unittests for 10^x ------------------------------------------------===//
//
// 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/FPUtil/FPBits.h"
#include "src/errno/libc_errno.h"
#include "src/math/exp10.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
#include <math.h>

#include <errno.h>
#include <stdint.h>

using __llvm_libc::testing::tlog;

DECLARE_SPECIAL_CONSTANTS(double)

TEST(LlvmLibcExp10Test, SpecialNumbers) {
EXPECT_FP_EQ(aNaN, __llvm_libc::exp10(aNaN));
EXPECT_FP_EQ(inf, __llvm_libc::exp10(inf));
EXPECT_FP_EQ_ALL_ROUNDING(zero, __llvm_libc::exp10(neg_inf));
EXPECT_FP_EQ_WITH_EXCEPTION(zero, __llvm_libc::exp10(-0x1.0p20),
FE_UNDERFLOW);
EXPECT_FP_EQ_WITH_EXCEPTION(inf, __llvm_libc::exp10(0x1.0p20), FE_OVERFLOW);
EXPECT_FP_EQ_ALL_ROUNDING(1.0, __llvm_libc::exp10(0.0));
EXPECT_FP_EQ_ALL_ROUNDING(1.0, __llvm_libc::exp10(-0.0));

EXPECT_FP_EQ_ALL_ROUNDING(10.0, __llvm_libc::exp10(1.0));
EXPECT_FP_EQ_ALL_ROUNDING(100.0, __llvm_libc::exp10(2.0));
EXPECT_FP_EQ_ALL_ROUNDING(1000.0, __llvm_libc::exp10(3.0));
}
Loading