diff --git a/SingleSource/UnitTests/CMakeLists.txt b/SingleSource/UnitTests/CMakeLists.txt --- a/SingleSource/UnitTests/CMakeLists.txt +++ b/SingleSource/UnitTests/CMakeLists.txt @@ -1,6 +1,7 @@ include(CheckCCompilerFlag) add_subdirectory(C++11) +add_subdirectory(Float) add_subdirectory(SignlessTypes) add_subdirectory(Threads) add_subdirectory(Vector) diff --git a/SingleSource/UnitTests/Float/CMakeLists.txt b/SingleSource/UnitTests/Float/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/SingleSource/UnitTests/Float/CMakeLists.txt @@ -0,0 +1 @@ +llvm_singlesource() diff --git a/SingleSource/UnitTests/Float/classify.cpp b/SingleSource/UnitTests/Float/classify.cpp new file mode 100644 --- /dev/null +++ b/SingleSource/UnitTests/Float/classify.cpp @@ -0,0 +1,306 @@ +//===--- classify.cpp - Tess for FP classification intrinsics ---*- 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 +// +//===----------------------------------------------------------------------===// +// +// This is a general test for floating point classification intrinsic. +// +//===----------------------------------------------------------------------===// + +#undef NDEBUG +#include +#include +#include +#include +#include + +#define DimOf(x) (sizeof(x) / sizeof(x[0])) + +#define F32_SIGN 0x80000000U +#define F32_EXP_MASK 0x7F800000U +#define F32_MANTISSA_MASK 0x007FFFFFU +#define F32_QNAN_BIT 0x00400000U +#define F32_PAYLOAD_MASK F32_MANTISSA_MASK + +#define F64_SIGN 0x8000000000000000ULL +#define F64_EXP_MASK 0x7FF0000000000000ULL +#define F64_MANTISSA_MASK 0x000FFFFFFFFFFFFFULL +#define F64_QNAN_BIT 0x0008000000000000ULL +#define F64_PAYLOAD_MASK F64_MANTISSA_MASK + + +uint32_t FloatNaNValues[] = { + F32_SIGN | F32_EXP_MASK | F32_QNAN_BIT | F32_PAYLOAD_MASK, + F32_EXP_MASK | F32_QNAN_BIT | F32_PAYLOAD_MASK, + F32_SIGN | F32_EXP_MASK | F32_PAYLOAD_MASK, + F32_EXP_MASK | F32_PAYLOAD_MASK, + F32_SIGN | F32_EXP_MASK | F32_QNAN_BIT, + F32_EXP_MASK | F32_QNAN_BIT, + F32_SIGN | F32_EXP_MASK | F32_QNAN_BIT | 0x00200000U, + F32_EXP_MASK | F32_QNAN_BIT | 0x00100000U, + F32_SIGN | F32_EXP_MASK | 0x00200000U, + F32_EXP_MASK | 0x00100000U, + F32_SIGN | F32_EXP_MASK | F32_QNAN_BIT | 0x00000001U, + F32_EXP_MASK | F32_QNAN_BIT | 0x00000002U, + F32_SIGN | F32_EXP_MASK | 0x00000001U, + F32_EXP_MASK | 0x00000002U, +}; + +uint32_t FloatInfValues[] = { + F32_SIGN | F32_EXP_MASK, // -Inf + F32_EXP_MASK // +Inf +}; + +uint32_t FloatZeroValues[] = { + F32_SIGN, // -0.0 + 0 // +0.0 +}; + +uint32_t FloatDenormValues[] = { + F32_SIGN | 0x00000001U, // smallest negative denornal number + 0x00000001U, // smallest positive denornal number + F32_SIGN | 0x007FFFFFU, // largest negative denormal number + 0x007FFFFFU, // largest positive normal number +}; + +uint32_t FloatNormalValues[] = { + F32_SIGN | 0x00800000U, // smallest negative normal number + 0x00800000U, // smallest positive normal number + F32_SIGN | 0x7F7FFFFFU, // largest negative normal number + 0x7F7FFFFFU, // largest positive normal number + F32_SIGN | 0x3F7FFFFFU, // smallest number larger than -1 + F32_SIGN | 0x3F800000U, // -1 + F32_SIGN | 0x3F800001U, // largest number less than -1 + 0x3F7FFFFFU, // largest number less than 1 + 0x3F800000U, // +1 + 0x3F800001U, // smallest number larger than 1 +}; + +int test_float() { + for (unsigned i = 0; i < DimOf(FloatNaNValues); i++) { + float *FPtr = (float *)&FloatNaNValues[i]; + assert(__builtin_isnan(*FPtr)); + assert(!__builtin_isinf(*FPtr)); + assert(!__builtin_isfinite(*FPtr)); + assert(!__builtin_isnormal(*FPtr)); + assert(__builtin_fpclassify(0, 1, 2, 3, 4, *FPtr) == 0); + } + for (unsigned i = 0; i < DimOf(FloatInfValues); i++) { + float *FPtr = (float *)&FloatInfValues[i]; + assert(!__builtin_isnan(*FPtr)); + assert(__builtin_isinf(*FPtr)); + assert(!__builtin_isfinite(*FPtr)); + assert(!__builtin_isnormal(*FPtr)); + assert(__builtin_fpclassify(0, 1, 2, 3, 4, *FPtr) == 1); + } + for (unsigned i = 0; i < DimOf(FloatZeroValues); i++) { + float *FPtr = (float *)&FloatZeroValues[i]; + assert(!__builtin_isnan(*FPtr)); + assert(!__builtin_isinf(*FPtr)); + assert(__builtin_isfinite(*FPtr)); + assert(!__builtin_isnormal(*FPtr)); + assert(__builtin_fpclassify(0, 1, 2, 3, 4, *FPtr) == 4); + } + for (unsigned i = 0; i < DimOf(FloatDenormValues); i++) { + float *FPtr = (float *)&FloatDenormValues[i]; + assert(!__builtin_isnan(*FPtr)); + assert(!__builtin_isinf(*FPtr)); + assert(__builtin_isfinite(*FPtr)); + assert(!__builtin_isnormal(*FPtr)); + assert(__builtin_fpclassify(0, 1, 2, 3, 4, *FPtr) == 3); + } + for (unsigned i = 0; i < DimOf(FloatNormalValues); i++) { + float *FPtr = (float *)&FloatNormalValues[i]; + assert(!__builtin_isnan(*FPtr)); + assert(!__builtin_isinf(*FPtr)); + assert(__builtin_isfinite(*FPtr)); + assert(__builtin_isnormal(*FPtr)); + assert(__builtin_fpclassify(0, 1, 2, 3, 4, *FPtr) == 2); + } + return 0; +} + + +uint64_t DoubleNaNValues[] = { + F64_SIGN | F64_EXP_MASK | F64_QNAN_BIT | F64_PAYLOAD_MASK, + F64_EXP_MASK | F64_QNAN_BIT | F64_PAYLOAD_MASK, + F64_SIGN | F64_EXP_MASK | F64_PAYLOAD_MASK, + F64_EXP_MASK | F64_PAYLOAD_MASK, + F64_SIGN | F64_EXP_MASK | F64_QNAN_BIT, + F64_EXP_MASK | F64_QNAN_BIT, + F64_SIGN | F64_EXP_MASK | F64_QNAN_BIT | 0x0004000000000000ULL, + F64_EXP_MASK | F64_QNAN_BIT | 0x0002000000000000ULL, + F64_SIGN | F64_EXP_MASK | 0x0004000000000000ULL, + F64_EXP_MASK | 0x0002000000000000ULL, + F64_SIGN | F64_EXP_MASK | F64_QNAN_BIT | 0x00000000000000001ULL, + F64_EXP_MASK | F64_QNAN_BIT | 0x00000000000000002ULL, + F64_SIGN | F64_EXP_MASK | 0x00000000000000001ULL, + F64_EXP_MASK | 0x00000000000000002ULL, +}; + +uint64_t DoubleInfValues[] = { + F64_SIGN | F64_EXP_MASK, // -Inf + F64_EXP_MASK // +Inf +}; + +uint64_t DoubleZeroValues[] = { + F64_SIGN, // -0.0 + 0 // +0.0 +}; + +uint64_t DoubleDenormValues[] = { + F64_SIGN | 0x0000000000000001ULL, // smallest negative denornal number + 0x0000000000000001ULL, // smallest positive denornal number + F64_SIGN | 0x000FFFFFFFFFFFFFULL, // largest negative denormal number + 0x000FFFFFFFFFFFFFULL, // largest positive normal number +}; + +uint64_t DoubleNormalValues[] = { + F64_SIGN | 0x0010000000000000ULL, // smallest negative normal number + 0x0010000000000000ULL, // smallest positive normal number + F64_SIGN | 0x7FEFFFFFFFFFFFFFULL, // largest negative normal number + 0x7FEFFFFFFFFFFFFFULL, // largest positive normal number + F64_SIGN | 0x3FEFFFFFFFFFFFFFULL, // smallest number larger than -1 + F64_SIGN | 0x3FF0000000000000ULL, // -1 + F64_SIGN | 0x3FF0000000000001ULL, // largest number less than -1 + 0x3FEFFFFFFFFFFFFFULL, // largest number less than 1 + 0x3FF0000000000000ULL, // +1 + 0x3FF0000000000001ULL, // smallest number larger than 1 +}; + +int test_double() { + for (unsigned i = 0; i < DimOf(DoubleNaNValues); i++) { + double *FPtr = (double *)&DoubleNaNValues[i]; + assert(__builtin_isnan(*FPtr)); + assert(!__builtin_isinf(*FPtr)); + assert(!__builtin_isfinite(*FPtr)); + assert(!__builtin_isnormal(*FPtr)); + assert(__builtin_fpclassify(0, 1, 2, 3, 4, *FPtr) == 0); + } + for (unsigned i = 0; i < DimOf(DoubleInfValues); i++) { + double *FPtr = (double *)&DoubleInfValues[i]; + assert(!__builtin_isnan(*FPtr)); + assert(__builtin_isinf(*FPtr)); + assert(!__builtin_isfinite(*FPtr)); + assert(!__builtin_isnormal(*FPtr)); + assert(__builtin_fpclassify(0, 1, 2, 3, 4, *FPtr) == 1); + } + for (unsigned i = 0; i < DimOf(DoubleZeroValues); i++) { + double *FPtr = (double *)&DoubleZeroValues[i]; + assert(!__builtin_isnan(*FPtr)); + assert(!__builtin_isinf(*FPtr)); + assert(__builtin_isfinite(*FPtr)); + assert(!__builtin_isnormal(*FPtr)); + assert(__builtin_fpclassify(0, 1, 2, 3, 4, *FPtr) == 4); + } + for (unsigned i = 0; i < DimOf(DoubleDenormValues); i++) { + double *FPtr = (double *)&DoubleDenormValues[i]; + assert(!__builtin_isnan(*FPtr)); + assert(!__builtin_isinf(*FPtr)); + assert(__builtin_isfinite(*FPtr)); + assert(!__builtin_isnormal(*FPtr)); + assert(__builtin_fpclassify(0, 1, 2, 3, 4, *FPtr) == 3); + } + for (unsigned i = 0; i < DimOf(DoubleNormalValues); i++) { + double *FPtr = (double *)&DoubleNormalValues[i]; + assert(!__builtin_isnan(*FPtr)); + assert(!__builtin_isinf(*FPtr)); + assert(__builtin_isfinite(*FPtr)); + assert(__builtin_isnormal(*FPtr)); + assert(__builtin_fpclassify(0, 1, 2, 3, 4, *FPtr) == 2); + } + return 0; +} + + +long double LongDoubleNaNValues[] = { + __builtin_nanl(""), + -__builtin_nanl(""), + __builtin_nanl("0x01"), + -__builtin_nanl("0x01"), + __builtin_nansl(""), + -__builtin_nansl(""), + __builtin_nansl("0x01"), + -__builtin_nansl("0x01") +}; + +long double LongDoubleInfValues[] = { + __builtin_infl(), + -__builtin_infl() +}; + +long double LongDoubleZeroValues[] = { + 0.0L, + -0.0L +}; + +long double LongDoubleDenormValues[] = { + std::numeric_limits::denorm_min(), + -std::numeric_limits::denorm_min(), +}; + +long double LongDoubleNormalValues[] = { + 1.0L, + -1.0L, + std::numeric_limits::max(), + -std::numeric_limits::max(), + std::numeric_limits::min(), + -std::numeric_limits::min() +}; + +int test_ldouble() { + for (unsigned i = 0; i < DimOf(LongDoubleNaNValues); i++) { + long double *FPtr = &LongDoubleNaNValues[i]; + assert(__builtin_isnan(*FPtr)); + assert(!__builtin_isinf(*FPtr)); + assert(!__builtin_isfinite(*FPtr)); + assert(!__builtin_isnormal(*FPtr)); + assert(__builtin_fpclassify(0, 1, 2, 3, 4, *FPtr) == 0); + } + for (unsigned i = 0; i < DimOf(LongDoubleInfValues); i++) { + long double *FPtr = &LongDoubleInfValues[i]; + assert(!__builtin_isnan(*FPtr)); + assert(__builtin_isinf(*FPtr)); + assert(!__builtin_isfinite(*FPtr)); + assert(!__builtin_isnormal(*FPtr)); + assert(__builtin_fpclassify(0, 1, 2, 3, 4, *FPtr) == 1); + } + for (unsigned i = 0; i < DimOf(LongDoubleZeroValues); i++) { + long double *FPtr = &LongDoubleZeroValues[i]; + assert(!__builtin_isnan(*FPtr)); + assert(!__builtin_isinf(*FPtr)); + assert(__builtin_isfinite(*FPtr)); + assert(!__builtin_isnormal(*FPtr)); + assert(__builtin_fpclassify(0, 1, 2, 3, 4, *FPtr) == 4); + } + for (unsigned i = 0; i < DimOf(LongDoubleDenormValues); i++) { + long double *FPtr = &LongDoubleDenormValues[i]; + assert(!__builtin_isnan(*FPtr)); + assert(!__builtin_isinf(*FPtr)); + assert(__builtin_isfinite(*FPtr)); + assert(!__builtin_isnormal(*FPtr)); + assert(__builtin_fpclassify(0, 1, 2, 3, 4, *FPtr) == 3); + } + for (unsigned i = 0; i < DimOf(LongDoubleNormalValues); i++) { + long double *FPtr = &LongDoubleNormalValues[i]; + assert(!__builtin_isnan(*FPtr)); + assert(!__builtin_isinf(*FPtr)); + assert(__builtin_isfinite(*FPtr)); + assert(__builtin_isnormal(*FPtr)); + assert(__builtin_fpclassify(0, 1, 2, 3, 4, *FPtr) == 2); + } + return 0; +} + + +int main() +{ + test_float(); + test_double(); + test_ldouble(); + return 0; +} + diff --git a/SingleSource/UnitTests/Float/classify.reference_output b/SingleSource/UnitTests/Float/classify.reference_output new file mode 100644 --- /dev/null +++ b/SingleSource/UnitTests/Float/classify.reference_output @@ -0,0 +1 @@ +exit 0