11a126472SRobin Caloudis //===----------------------------------------------------------------------===// 21a126472SRobin Caloudis // 31a126472SRobin Caloudis // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 41a126472SRobin Caloudis // See https://llvm.org/LICENSE.txt for license information. 51a126472SRobin Caloudis // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61a126472SRobin Caloudis // 71a126472SRobin Caloudis //===----------------------------------------------------------------------===// 81a126472SRobin Caloudis 91a126472SRobin Caloudis // bool signbit(floating-point-type x); // constexpr since C++23 101a126472SRobin Caloudis 111a126472SRobin Caloudis // We don't control the implementation on windows 121a126472SRobin Caloudis // UNSUPPORTED: windows 131a126472SRobin Caloudis 141a126472SRobin Caloudis // These compilers don't support constexpr `__builtin_signbit` yet. 15*7f845cbaSNikolas Klauser // UNSUPPORTED: clang-18, clang-19, apple-clang-15, apple-clang-16 161a126472SRobin Caloudis 17b9a2658aSNikolas Klauser // XFAIL: FROZEN-CXX03-HEADERS-FIXME 18b9a2658aSNikolas Klauser 191a126472SRobin Caloudis #include <cassert> 201a126472SRobin Caloudis #include <cmath> 211a126472SRobin Caloudis #include <limits> 221a126472SRobin Caloudis 231a126472SRobin Caloudis #include "test_macros.h" 241a126472SRobin Caloudis #include "type_algorithms.h" 251a126472SRobin Caloudis 261a126472SRobin Caloudis struct TestFloat { 271a126472SRobin Caloudis template <class T> 281a126472SRobin Caloudis static TEST_CONSTEXPR_CXX23 bool test() { 291a126472SRobin Caloudis assert(!std::signbit(T(0))); 301a126472SRobin Caloudis assert(!std::signbit(std::numeric_limits<T>::min())); 311a126472SRobin Caloudis assert(!std::signbit(std::numeric_limits<T>::denorm_min())); 321a126472SRobin Caloudis assert(!std::signbit(std::numeric_limits<T>::max())); 331a126472SRobin Caloudis assert(!std::signbit(std::numeric_limits<T>::infinity())); 341a126472SRobin Caloudis assert(!std::signbit(std::numeric_limits<T>::quiet_NaN())); 351a126472SRobin Caloudis assert(!std::signbit(std::numeric_limits<T>::signaling_NaN())); 361a126472SRobin Caloudis assert(std::signbit(-T(0))); 371a126472SRobin Caloudis assert(std::signbit(-std::numeric_limits<T>::infinity())); 381a126472SRobin Caloudis assert(std::signbit(std::numeric_limits<T>::lowest())); 391a126472SRobin Caloudis 401a126472SRobin Caloudis return true; 411a126472SRobin Caloudis } 421a126472SRobin Caloudis 431a126472SRobin Caloudis template <class T> 441a126472SRobin Caloudis TEST_CONSTEXPR_CXX23 void operator()() { 451a126472SRobin Caloudis test<T>(); 461a126472SRobin Caloudis #if TEST_STD_VER >= 23 471a126472SRobin Caloudis static_assert(test<T>()); 481a126472SRobin Caloudis #endif 491a126472SRobin Caloudis } 501a126472SRobin Caloudis }; 511a126472SRobin Caloudis 521a126472SRobin Caloudis struct TestInt { 531a126472SRobin Caloudis template <class T> 541a126472SRobin Caloudis static TEST_CONSTEXPR_CXX23 bool test() { 551a126472SRobin Caloudis assert(!std::signbit(std::numeric_limits<T>::max())); 561a126472SRobin Caloudis assert(!std::signbit(T(0))); 571a126472SRobin Caloudis if (std::is_unsigned<T>::value) { 581a126472SRobin Caloudis assert(!std::signbit(std::numeric_limits<T>::lowest())); 591a126472SRobin Caloudis } else { 601a126472SRobin Caloudis assert(std::signbit(std::numeric_limits<T>::lowest())); 611a126472SRobin Caloudis } 621a126472SRobin Caloudis 631a126472SRobin Caloudis return true; 641a126472SRobin Caloudis } 651a126472SRobin Caloudis 661a126472SRobin Caloudis template <class T> 671a126472SRobin Caloudis TEST_CONSTEXPR_CXX23 void operator()() { 681a126472SRobin Caloudis test<T>(); 691a126472SRobin Caloudis #if TEST_STD_VER >= 23 701a126472SRobin Caloudis static_assert(test<T>()); 711a126472SRobin Caloudis #endif 721a126472SRobin Caloudis } 731a126472SRobin Caloudis }; 741a126472SRobin Caloudis 75c6b2aa18SRobin Caloudis template <typename T> 76c6b2aa18SRobin Caloudis struct ConvertibleTo { 77c6b2aa18SRobin Caloudis operator T() const { return T(); } 78c6b2aa18SRobin Caloudis }; 79c6b2aa18SRobin Caloudis 801a126472SRobin Caloudis int main(int, char**) { 811a126472SRobin Caloudis types::for_each(types::floating_point_types(), TestFloat()); 821a126472SRobin Caloudis types::for_each(types::integral_types(), TestInt()); 831a126472SRobin Caloudis 84c6b2aa18SRobin Caloudis // Make sure we can call `std::signbit` with convertible types. This checks 85c6b2aa18SRobin Caloudis // whether overloads for all cv-unqualified floating-point types are working 86c6b2aa18SRobin Caloudis // as expected. 87c6b2aa18SRobin Caloudis { 88c6b2aa18SRobin Caloudis assert(!std::signbit(ConvertibleTo<float>())); 89c6b2aa18SRobin Caloudis assert(!std::signbit(ConvertibleTo<double>())); 90c6b2aa18SRobin Caloudis assert(!std::signbit(ConvertibleTo<long double>())); 91c6b2aa18SRobin Caloudis } 921a126472SRobin Caloudis return 0; 931a126472SRobin Caloudis } 94