mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-23 05:40:09 +00:00
[libc][math] Implement nan(f|l) functions (#76690)
Specification: https://en.cppreference.com/w/c/numeric/math/nan
This commit is contained in:
parent
f7f7574afe
commit
0504e93288
@ -193,6 +193,9 @@ set(TARGET_LIBM_ENTRYPOINTS
|
||||
libc.src.math.modf
|
||||
libc.src.math.modff
|
||||
libc.src.math.modfl
|
||||
libc.src.math.nan
|
||||
libc.src.math.nanf
|
||||
libc.src.math.nanl
|
||||
libc.src.math.nearbyint
|
||||
libc.src.math.nearbyintf
|
||||
libc.src.math.nearbyintl
|
||||
|
@ -172,6 +172,9 @@ set(TARGET_LIBM_ENTRYPOINTS
|
||||
#libc.src.math.modf
|
||||
#libc.src.math.modff
|
||||
#libc.src.math.modfl
|
||||
#libc.src.math.nan
|
||||
#libc.src.math.nanf
|
||||
#libc.src.math.nanl
|
||||
#libc.src.math.nearbyint
|
||||
#libc.src.math.nearbyintf
|
||||
#libc.src.math.nearbyintl
|
||||
|
@ -215,6 +215,8 @@ set(TARGET_LIBM_ENTRYPOINTS
|
||||
libc.src.math.lroundf
|
||||
libc.src.math.modf
|
||||
libc.src.math.modff
|
||||
libc.src.math.nan
|
||||
libc.src.math.nanf
|
||||
libc.src.math.nearbyint
|
||||
libc.src.math.nearbyintf
|
||||
libc.src.math.nextafter
|
||||
|
@ -313,6 +313,9 @@ set(TARGET_LIBM_ENTRYPOINTS
|
||||
libc.src.math.modf
|
||||
libc.src.math.modff
|
||||
libc.src.math.modfl
|
||||
libc.src.math.nan
|
||||
libc.src.math.nanf
|
||||
libc.src.math.nanl
|
||||
libc.src.math.nearbyint
|
||||
libc.src.math.nearbyintf
|
||||
libc.src.math.nearbyintl
|
||||
|
@ -322,6 +322,9 @@ set(TARGET_LIBM_ENTRYPOINTS
|
||||
libc.src.math.modf
|
||||
libc.src.math.modff
|
||||
libc.src.math.modfl
|
||||
libc.src.math.nan
|
||||
libc.src.math.nanf
|
||||
libc.src.math.nanl
|
||||
libc.src.math.nearbyint
|
||||
libc.src.math.nearbyintf
|
||||
libc.src.math.nearbyintl
|
||||
|
@ -323,6 +323,9 @@ set(TARGET_LIBM_ENTRYPOINTS
|
||||
libc.src.math.modf
|
||||
libc.src.math.modff
|
||||
libc.src.math.modfl
|
||||
libc.src.math.nan
|
||||
libc.src.math.nanf
|
||||
libc.src.math.nanl
|
||||
libc.src.math.nearbyint
|
||||
libc.src.math.nearbyintf
|
||||
libc.src.math.nearbyintl
|
||||
|
@ -192,6 +192,9 @@ set(TARGET_LIBM_ENTRYPOINTS
|
||||
libc.src.math.modf
|
||||
libc.src.math.modff
|
||||
libc.src.math.modfl
|
||||
libc.src.math.nan
|
||||
libc.src.math.nanf
|
||||
libc.src.math.nanl
|
||||
libc.src.math.nearbyint
|
||||
libc.src.math.nearbyintf
|
||||
libc.src.math.nearbyintl
|
||||
|
@ -212,11 +212,11 @@ Basic Operations
|
||||
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
|
||||
| modfl | |check| | |check| | | |check| | |check| | | | |check| | | | | |
|
||||
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
|
||||
| nan | | | | | | | | | | | | |
|
||||
| nan | |check| | |check| | | |check| | |check| | | | |check| | | | | |
|
||||
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
|
||||
| nanf | | | | | | | | | | | | |
|
||||
| nanf | |check| | |check| | | |check| | |check| | | | |check| | | | | |
|
||||
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
|
||||
| nanl | | | | | | | | | | | | |
|
||||
| nanl | |check| | |check| | | |check| | |check| | | | |check| | | | | |
|
||||
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
|
||||
| nearbyint | |check| | |check| | | |check| | |check| | | | |check| | | | | |
|
||||
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
|
||||
|
@ -515,6 +515,10 @@ def StdC : StandardSpec<"stdc"> {
|
||||
FunctionSpec<"scalbn", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>]>,
|
||||
FunctionSpec<"scalbnf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>]>,
|
||||
FunctionSpec<"scalbnl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>]>,
|
||||
|
||||
FunctionSpec<"nanf", RetValSpec<FloatType>, [ArgSpec<ConstCharPtr>]>,
|
||||
FunctionSpec<"nan", RetValSpec<DoubleType>, [ArgSpec<ConstCharPtr>]>,
|
||||
FunctionSpec<"nanl", RetValSpec<LongDoubleType>, [ArgSpec<ConstCharPtr>]>,
|
||||
]
|
||||
>;
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "src/__support/CPP/bit.h"
|
||||
#include "src/__support/CPP/limits.h"
|
||||
#include "src/__support/CPP/optional.h"
|
||||
#include "src/__support/CPP/string_view.h"
|
||||
#include "src/__support/FPUtil/FEnvImpl.h"
|
||||
#include "src/__support/FPUtil/FPBits.h"
|
||||
#include "src/__support/FPUtil/dyadic_float.h"
|
||||
@ -1044,6 +1045,27 @@ hexadecimal_string_to_float(const char *__restrict src,
|
||||
return output;
|
||||
}
|
||||
|
||||
LIBC_INLINE uint64_t
|
||||
nan_mantissa_from_ncharseq(const cpp::string_view ncharseq) {
|
||||
uint64_t nan_mantissa = 0;
|
||||
|
||||
if (ncharseq.data() != nullptr && isdigit(ncharseq[0])) {
|
||||
// This is to prevent errors when StorageType is larger than 64
|
||||
// bits, since strtointeger only supports up to 64 bits. This is
|
||||
// actually more than is required by the specification, which says
|
||||
// for the input type "NAN(n-char-sequence)" that "the meaning of
|
||||
// the n-char sequence is implementation-defined."
|
||||
auto strtoint_result = strtointeger<uint64_t>(ncharseq.data(), 0);
|
||||
if (!strtoint_result.has_error())
|
||||
nan_mantissa = strtoint_result.value;
|
||||
|
||||
if (strtoint_result.parsed_len != static_cast<ptrdiff_t>(ncharseq.size()))
|
||||
nan_mantissa = 0;
|
||||
}
|
||||
|
||||
return nan_mantissa;
|
||||
}
|
||||
|
||||
// Takes a pointer to a string and a pointer to a string pointer. This function
|
||||
// is used as the backend for all of the string to float functions.
|
||||
template <class T>
|
||||
@ -1136,31 +1158,18 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
|
||||
++index;
|
||||
if (src[index] == ')') {
|
||||
++index;
|
||||
if (isdigit(src[left_paren + 1])) {
|
||||
// This is to prevent errors when StorageType is larger than 64
|
||||
// bits, since strtointeger only supports up to 64 bits. This is
|
||||
// actually more than is required by the specification, which says
|
||||
// for the input type "NAN(n-char-sequence)" that "the meaning of
|
||||
// the n-char sequence is implementation-defined."
|
||||
|
||||
auto strtoint_result =
|
||||
strtointeger<uint64_t>(src + (left_paren + 1), 0);
|
||||
if (strtoint_result.has_error()) {
|
||||
error = strtoint_result.error;
|
||||
}
|
||||
nan_mantissa = static_cast<StorageType>(strtoint_result.value);
|
||||
if (src[left_paren + 1 + strtoint_result.parsed_len] != ')')
|
||||
nan_mantissa = 0;
|
||||
}
|
||||
auto nan_mantissa_result = nan_mantissa_from_ncharseq(
|
||||
cpp::string_view(src + (left_paren + 1), index - left_paren - 2));
|
||||
nan_mantissa = static_cast<StorageType>(nan_mantissa_result);
|
||||
} else {
|
||||
index = left_paren;
|
||||
}
|
||||
}
|
||||
|
||||
if (result.get_sign()) {
|
||||
result = FPBits(result.build_quiet_nan(nan_mantissa));
|
||||
result.set_sign(true);
|
||||
} else {
|
||||
result.set_sign(false);
|
||||
result = FPBits(result.build_quiet_nan(nan_mantissa));
|
||||
}
|
||||
}
|
||||
@ -1195,6 +1204,28 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
|
||||
return {T(result), index, error};
|
||||
}
|
||||
|
||||
template <class T> LIBC_INLINE StrToNumResult<T> strtonan(const char *arg) {
|
||||
using FPBits = typename fputil::FPBits<T>;
|
||||
using StorageType = typename FPBits::StorageType;
|
||||
|
||||
FPBits result;
|
||||
int error = 0;
|
||||
StorageType nan_mantissa = 0;
|
||||
|
||||
ptrdiff_t index = 0;
|
||||
while (isalnum(arg[index]) || arg[index] == '_')
|
||||
++index;
|
||||
|
||||
if (arg[index] == '\0') {
|
||||
auto nan_mantissa_result =
|
||||
nan_mantissa_from_ncharseq(cpp::string_view(arg, index));
|
||||
nan_mantissa = static_cast<StorageType>(nan_mantissa_result);
|
||||
}
|
||||
|
||||
result = FPBits(result.build_quiet_nan(nan_mantissa));
|
||||
return {T(result), 0, error};
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace LIBC_NAMESPACE
|
||||
|
||||
|
@ -179,6 +179,10 @@ add_math_entrypoint_object(modf)
|
||||
add_math_entrypoint_object(modff)
|
||||
add_math_entrypoint_object(modfl)
|
||||
|
||||
add_math_entrypoint_object(nan)
|
||||
add_math_entrypoint_object(nanf)
|
||||
add_math_entrypoint_object(nanl)
|
||||
|
||||
add_math_entrypoint_object(nearbyint)
|
||||
add_math_entrypoint_object(nearbyintf)
|
||||
add_math_entrypoint_object(nearbyintl)
|
||||
|
@ -1437,6 +1437,45 @@ add_entrypoint_object(
|
||||
-O3
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
nan
|
||||
SRCS
|
||||
nan.cpp
|
||||
HDRS
|
||||
../nan.h
|
||||
DEPENDS
|
||||
libc.src.__support.str_to_float
|
||||
libc.src.errno.errno
|
||||
COMPILE_OPTIONS
|
||||
-O3
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
nanf
|
||||
SRCS
|
||||
nanf.cpp
|
||||
HDRS
|
||||
../nanf.h
|
||||
DEPENDS
|
||||
libc.src.__support.str_to_float
|
||||
libc.src.errno.errno
|
||||
COMPILE_OPTIONS
|
||||
-O3
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
nanl
|
||||
SRCS
|
||||
nanl.cpp
|
||||
HDRS
|
||||
../nanl.h
|
||||
DEPENDS
|
||||
libc.src.__support.str_to_float
|
||||
libc.src.errno.errno
|
||||
COMPILE_OPTIONS
|
||||
-O3
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
nextafter
|
||||
SRCS
|
||||
|
23
libc/src/math/generic/nan.cpp
Normal file
23
libc/src/math/generic/nan.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
//===-- Implementation of nan function ------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/math/nan.h"
|
||||
#include "src/__support/common.h"
|
||||
#include "src/__support/str_to_float.h"
|
||||
#include "src/errno/libc_errno.h"
|
||||
|
||||
namespace LIBC_NAMESPACE {
|
||||
|
||||
LLVM_LIBC_FUNCTION(double, nan, (const char *arg)) {
|
||||
auto result = internal::strtonan<double>(arg);
|
||||
if (result.has_error())
|
||||
libc_errno = result.error;
|
||||
return result.value;
|
||||
}
|
||||
|
||||
} // namespace LIBC_NAMESPACE
|
23
libc/src/math/generic/nanf.cpp
Normal file
23
libc/src/math/generic/nanf.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
//===-- Implementation of nanf function -----------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/math/nanf.h"
|
||||
#include "src/__support/common.h"
|
||||
#include "src/__support/str_to_float.h"
|
||||
#include "src/errno/libc_errno.h"
|
||||
|
||||
namespace LIBC_NAMESPACE {
|
||||
|
||||
LLVM_LIBC_FUNCTION(float, nanf, (const char *arg)) {
|
||||
auto result = internal::strtonan<float>(arg);
|
||||
if (result.has_error())
|
||||
libc_errno = result.error;
|
||||
return result.value;
|
||||
}
|
||||
|
||||
} // namespace LIBC_NAMESPACE
|
23
libc/src/math/generic/nanl.cpp
Normal file
23
libc/src/math/generic/nanl.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
//===-- Implementation of nanl function -----------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/math/nanl.h"
|
||||
#include "src/__support/common.h"
|
||||
#include "src/__support/str_to_float.h"
|
||||
#include "src/errno/libc_errno.h"
|
||||
|
||||
namespace LIBC_NAMESPACE {
|
||||
|
||||
LLVM_LIBC_FUNCTION(long double, nanl, (const char *arg)) {
|
||||
auto result = internal::strtonan<long double>(arg);
|
||||
if (result.has_error())
|
||||
libc_errno = result.error;
|
||||
return result.value;
|
||||
}
|
||||
|
||||
} // namespace LIBC_NAMESPACE
|
18
libc/src/math/nan.h
Normal file
18
libc/src/math/nan.h
Normal file
@ -0,0 +1,18 @@
|
||||
//===-- Implementation header for nan ---------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_MATH_NAN_H
|
||||
#define LLVM_LIBC_SRC_MATH_NAN_H
|
||||
|
||||
namespace LIBC_NAMESPACE {
|
||||
|
||||
double nan(const char *arg);
|
||||
|
||||
} // namespace LIBC_NAMESPACE
|
||||
|
||||
#endif // LLVM_LIBC_SRC_MATH_NAN_H
|
18
libc/src/math/nanf.h
Normal file
18
libc/src/math/nanf.h
Normal file
@ -0,0 +1,18 @@
|
||||
//===-- Implementation header for nanf --------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_MATH_NANF_H
|
||||
#define LLVM_LIBC_SRC_MATH_NANF_H
|
||||
|
||||
namespace LIBC_NAMESPACE {
|
||||
|
||||
float nanf(const char *arg);
|
||||
|
||||
} // namespace LIBC_NAMESPACE
|
||||
|
||||
#endif // LLVM_LIBC_SRC_MATH_NANF_H
|
18
libc/src/math/nanl.h
Normal file
18
libc/src/math/nanl.h
Normal file
@ -0,0 +1,18 @@
|
||||
//===-- Implementation header for nanl --------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_MATH_NANL_H
|
||||
#define LLVM_LIBC_SRC_MATH_NANL_H
|
||||
|
||||
namespace LIBC_NAMESPACE {
|
||||
|
||||
long double nanl(const char *arg);
|
||||
|
||||
} // namespace LIBC_NAMESPACE
|
||||
|
||||
#endif // LLVM_LIBC_SRC_MATH_NANL_H
|
@ -1203,6 +1203,45 @@ add_fp_unittest(
|
||||
libc.src.__support.FPUtil.fp_bits
|
||||
)
|
||||
|
||||
add_fp_unittest(
|
||||
nanf_test
|
||||
SUITE
|
||||
libc-math-smoke-tests
|
||||
SRCS
|
||||
nanf_test.cpp
|
||||
DEPENDS
|
||||
libc.include.math
|
||||
libc.include.signal
|
||||
libc.src.math.nanf
|
||||
libc.src.__support.FPUtil.fp_bits
|
||||
)
|
||||
|
||||
add_fp_unittest(
|
||||
nan_test
|
||||
SUITE
|
||||
libc-math-smoke-tests
|
||||
SRCS
|
||||
nan_test.cpp
|
||||
DEPENDS
|
||||
libc.include.math
|
||||
libc.include.signal
|
||||
libc.src.math.nan
|
||||
libc.src.__support.FPUtil.fp_bits
|
||||
)
|
||||
|
||||
add_fp_unittest(
|
||||
nanl_test
|
||||
SUITE
|
||||
libc-math-smoke-tests
|
||||
SRCS
|
||||
nanl_test.cpp
|
||||
DEPENDS
|
||||
libc.include.math
|
||||
libc.include.signal
|
||||
libc.src.math.nanl
|
||||
libc.src.__support.FPUtil.fp_bits
|
||||
)
|
||||
|
||||
# FIXME: These tests are currently spurious for NVPTX.
|
||||
if(NOT LIBC_GPU_TARGET_ARCHITECTURE_IS_NVPTX)
|
||||
add_fp_unittest(
|
||||
|
47
libc/test/src/math/smoke/nan_test.cpp
Normal file
47
libc/test/src/math/smoke/nan_test.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
//===-- Unittests for nan -------------------------------------------------===//
|
||||
//
|
||||
// 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/nan.h"
|
||||
#include "test/UnitTest/FPMatcher.h"
|
||||
#include "test/UnitTest/Test.h"
|
||||
#include <signal.h>
|
||||
|
||||
class LlvmLibcNanTest : public LIBC_NAMESPACE::testing::Test {
|
||||
public:
|
||||
using StorageType = LIBC_NAMESPACE::fputil::FPBits<double>::StorageType;
|
||||
|
||||
void run_test(const char *input_str, StorageType bits) {
|
||||
double result = LIBC_NAMESPACE::nan(input_str);
|
||||
auto actual_fp = LIBC_NAMESPACE::fputil::FPBits<double>(result);
|
||||
auto expected_fp = LIBC_NAMESPACE::fputil::FPBits<double>(bits);
|
||||
EXPECT_EQ(actual_fp.bits, expected_fp.bits);
|
||||
};
|
||||
};
|
||||
|
||||
TEST_F(LlvmLibcNanTest, NCharSeq) {
|
||||
run_test("", 0x7ff8000000000000);
|
||||
run_test("1234", 0x7ff80000000004d2);
|
||||
run_test("0x1234", 0x7ff8000000001234);
|
||||
run_test("1a", 0x7ff8000000000000);
|
||||
run_test("1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM_",
|
||||
0x7ff8000000000000);
|
||||
run_test("10000000000000000000000000000000000000000000000000",
|
||||
0x7ff8000000000000);
|
||||
}
|
||||
|
||||
TEST_F(LlvmLibcNanTest, RandomString) {
|
||||
run_test(" 1234", 0x7ff8000000000000);
|
||||
run_test("-1234", 0x7ff8000000000000);
|
||||
run_test("asd&f", 0x7ff8000000000000);
|
||||
run_test("123 ", 0x7ff8000000000000);
|
||||
}
|
||||
|
||||
TEST_F(LlvmLibcNanTest, InvalidInput) {
|
||||
EXPECT_DEATH([] { LIBC_NAMESPACE::nan(nullptr); }, WITH_SIGNAL(SIGSEGV));
|
||||
}
|
46
libc/test/src/math/smoke/nanf_test.cpp
Normal file
46
libc/test/src/math/smoke/nanf_test.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
//===-- Unittests for nanf ------------------------------------------------===//
|
||||
//
|
||||
// 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/nanf.h"
|
||||
#include "test/UnitTest/FPMatcher.h"
|
||||
#include "test/UnitTest/Test.h"
|
||||
#include <signal.h>
|
||||
|
||||
class LlvmLibcNanfTest : public LIBC_NAMESPACE::testing::Test {
|
||||
public:
|
||||
using StorageType = LIBC_NAMESPACE::fputil::FPBits<float>::StorageType;
|
||||
|
||||
void run_test(const char *input_str, StorageType bits) {
|
||||
float result = LIBC_NAMESPACE::nanf(input_str);
|
||||
auto actual_fp = LIBC_NAMESPACE::fputil::FPBits<float>(result);
|
||||
auto expected_fp = LIBC_NAMESPACE::fputil::FPBits<float>(bits);
|
||||
EXPECT_EQ(actual_fp.bits, expected_fp.bits);
|
||||
};
|
||||
};
|
||||
|
||||
TEST_F(LlvmLibcNanfTest, NCharSeq) {
|
||||
run_test("", 0x7fc00000);
|
||||
run_test("1234", 0x7fc004d2);
|
||||
run_test("0x1234", 0x7fc01234);
|
||||
run_test("1a", 0x7fc00000);
|
||||
run_test("1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM_",
|
||||
0x7fc00000);
|
||||
run_test("10000000000000000000000000000000000000000000000000", 0x7fc00000);
|
||||
}
|
||||
|
||||
TEST_F(LlvmLibcNanfTest, RandomString) {
|
||||
run_test(" 1234", 0x7fc00000);
|
||||
run_test("-1234", 0x7fc00000);
|
||||
run_test("asd&f", 0x7fc00000);
|
||||
run_test("123 ", 0x7fc00000);
|
||||
}
|
||||
|
||||
TEST_F(LlvmLibcNanfTest, InvalidInput) {
|
||||
EXPECT_DEATH([] { LIBC_NAMESPACE::nanf(nullptr); }, WITH_SIGNAL(SIGSEGV));
|
||||
}
|
72
libc/test/src/math/smoke/nanl_test.cpp
Normal file
72
libc/test/src/math/smoke/nanl_test.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
//===-- Unittests for nanl ------------------------------------------------===//
|
||||
//
|
||||
// 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/nanl.h"
|
||||
#include "test/UnitTest/FPMatcher.h"
|
||||
#include "test/UnitTest/Test.h"
|
||||
#include <signal.h>
|
||||
|
||||
#if defined(LIBC_LONG_DOUBLE_IS_FLOAT64)
|
||||
#define SELECT_LONG_DOUBLE(val, _, __) val
|
||||
#elif defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80)
|
||||
#define SELECT_LONG_DOUBLE(_, val, __) val
|
||||
#else
|
||||
#define SELECT_LONG_DOUBLE(_, __, val) val
|
||||
#endif
|
||||
|
||||
class LlvmLibcNanlTest : public LIBC_NAMESPACE::testing::Test {
|
||||
public:
|
||||
using StorageType = LIBC_NAMESPACE::fputil::FPBits<long double>::StorageType;
|
||||
|
||||
void run_test(const char *input_str, StorageType bits) {
|
||||
long double result = LIBC_NAMESPACE::nanl(input_str);
|
||||
auto actual_fp = LIBC_NAMESPACE::fputil::FPBits<long double>(result);
|
||||
auto expected_fp = LIBC_NAMESPACE::fputil::FPBits<long double>(bits);
|
||||
EXPECT_EQ(actual_fp.bits, expected_fp.bits);
|
||||
};
|
||||
};
|
||||
|
||||
TEST_F(LlvmLibcNanlTest, NCharSeq) {
|
||||
run_test("",
|
||||
SELECT_LONG_DOUBLE(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
|
||||
(UInt128(0x7fff800000000000) << 64)));
|
||||
run_test("1234", SELECT_LONG_DOUBLE(
|
||||
0x7ff80000000004d2,
|
||||
(UInt128(0x7fffc00000) << 40) + UInt128(0x4d2),
|
||||
(UInt128(0x7fff800000000000) << 64) + UInt128(0x4d2)));
|
||||
run_test("0x1234",
|
||||
SELECT_LONG_DOUBLE(0x7ff8000000001234,
|
||||
(UInt128(0x7fffc00000) << 40) + UInt128(0x1234),
|
||||
(UInt128(0x7fff800000000000) << 64) +
|
||||
UInt128(0x1234)));
|
||||
run_test("1a",
|
||||
SELECT_LONG_DOUBLE(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
|
||||
(UInt128(0x7fff800000000000) << 64)));
|
||||
run_test("1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM_",
|
||||
SELECT_LONG_DOUBLE(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
|
||||
(UInt128(0x7fff800000000000) << 64)));
|
||||
run_test("10000000000000000000000000000000000000000000000000",
|
||||
SELECT_LONG_DOUBLE(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
|
||||
(UInt128(0x7fff800000000000) << 64)));
|
||||
}
|
||||
|
||||
TEST_F(LlvmLibcNanlTest, RandomString) {
|
||||
StorageType expected =
|
||||
SELECT_LONG_DOUBLE(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
|
||||
(UInt128(0x7fff800000000000) << 64));
|
||||
|
||||
run_test(" 1234", expected);
|
||||
run_test("-1234", expected);
|
||||
run_test("asd&f", expected);
|
||||
run_test("123 ", expected);
|
||||
}
|
||||
|
||||
TEST_F(LlvmLibcNanlTest, InvalidInput) {
|
||||
EXPECT_DEATH([] { LIBC_NAMESPACE::nanl(nullptr); }, WITH_SIGNAL(SIGSEGV));
|
||||
}
|
@ -1874,6 +1874,12 @@ libc_math_function(name = "llroundf")
|
||||
|
||||
libc_math_function(name = "llroundl")
|
||||
|
||||
libc_math_function(name = "nan")
|
||||
|
||||
libc_math_function(name = "nanf")
|
||||
|
||||
libc_math_function(name = "nanl")
|
||||
|
||||
libc_math_function(name = "nearbyint")
|
||||
|
||||
libc_math_function(name = "nearbyintf")
|
||||
|
Loading…
Reference in New Issue
Block a user