diff --git a/libcxx/docs/Cxx2aStatusPaperStatus.csv b/libcxx/docs/Cxx2aStatusPaperStatus.csv new file mode 100644 --- /dev/null +++ b/libcxx/docs/Cxx2aStatusPaperStatus.csv @@ -0,0 +1,195 @@ +"Paper #","Group","Paper Name","Meeting","Status","First released version" +"`P0463R1 `__","LWG","Endian just Endian","Toronto","|Complete|","7.0" +"`P0674R1 `__","LWG","Extending make_shared to Support Arrays","Toronto","","" +"","","","","","" +"`P0020R6 `__","LWG","Floating Point Atomic","Albuquerque","","" +"`P0053R7 `__","LWG","C++ Synchronized Buffered Ostream","Albuquerque","","" +"`P0202R3 `__","LWG","Add constexpr modifiers to functions in and Headers","Albuquerque","|Complete|","12.0" +"`P0415R1 `__","LWG","Constexpr for ``std::complex``\ ","Albuquerque","|Complete|","13.0" +"`P0439R0 `__","LWG","Make ``std::memory_order``\ a scoped enumeration","Albuquerque","|Complete|","" +"`P0457R2 `__","LWG","String Prefix and Suffix Checking","Albuquerque","|Complete|","6.0" +"`P0550R2 `__","LWG","Transformation Trait ``remove_cvref``\ ","Albuquerque","|Complete|","6.0" +"`P0600R1 `__","LWG","nodiscard in the Library","Albuquerque","|In Progress| [#note-P0600]_","7.0" +"`P0616R0 `__","LWG","de-pessimize legacy algorithms with std::move","Albuquerque","|Complete|","12.0" +"`P0653R2 `__","LWG","Utility to convert a pointer to a raw pointer","Albuquerque","|Complete|","6.0" +"`P0718R2 `__","LWG","Atomic shared_ptr","Albuquerque","","" +"`P0767R1 `__","CWG","Deprecate POD","Albuquerque","|Complete|","7.0" +"`P0768R1 `__","CWG","Library Support for the Spaceship (Comparison) Operator","Albuquerque","|Complete|","" +"`P0777R1 `__","LWG","Treating Unnecessary ``decay``\ ","Albuquerque","|Complete|","7.0" +"`P0122R7 `__","LWG","","Jacksonville","|Complete|","7.0" +"`P0355R7 `__","LWG","Extending chrono to Calendars and Time Zones","Jacksonville","|In Progress|","" +"`P0551R3 `__","LWG","Thou Shalt Not Specialize ``std``\ Function Templates!","Jacksonville","|Complete|","11.0" +"`P0753R2 `__","LWG","Manipulators for C++ Synchronized Buffered Ostream","Jacksonville","","" +"`P0754R2 `__","LWG","","Jacksonville","|Complete|","7.0" +"`P0809R0 `__","LWG","Comparing Unordered Containers","Jacksonville","|Nothing To Do|","" +"`P0858R0 `__","LWG","Constexpr iterator requirements","Jacksonville","","" +"`P0905R1 `__","CWG","Symmetry for spaceship","Jacksonville","","" +"`P0966R1 `__","LWG","``string::reserve``\ Should Not Shrink","Jacksonville","|Complete| [#note-P0966]_","12.0" +"","","","","","" +"`P0019R8 `__","LWG","Atomic Ref","Rapperswil","","" +"`P0458R2 `__","LWG","Checking for Existence of an Element in Associative Containers","Rapperswil","|Complete|","" +"`P0475R1 `__","LWG","LWG 2511: guaranteed copy elision for piecewise construction","Rapperswil","|Complete|","" +"`P0476R2 `__","LWG","Bit-casting object representations","Rapperswil","","" +"`P0528R3 `__","CWG","The Curious Case of Padding Bits, Featuring Atomic Compare-and-Exchange","Rapperswil","","" +"`P0542R5 `__","CWG","Support for contract based programming in C++","Rapperswil","*Removed in Cologne*","n/a" +"`P0556R3 `__","LWG","Integral power-of-2 operations","Rapperswil","|Complete|","9.0" +"`P0619R4 `__","LWG","Reviewing Deprecated Facilities of C++17 for C++20","Rapperswil","|Partial| [#note-P0619]_","" +"`P0646R1 `__","LWG","Improving the Return Value of Erase-Like Algorithms","Rapperswil","|Complete|","10.0" +"`P0722R3 `__","CWG","Efficient sized delete for variable sized classes","Rapperswil","|Complete|","9.0" +"`P0758R1 `__","LWG","Implicit conversion traits and utility functions","Rapperswil","|Complete|","" +"`P0759R1 `__","LWG","fpos Requirements","Rapperswil","|Complete|","11.0" +"`P0769R2 `__","LWG","Add shift to ","Rapperswil","|Complete|","12.0" +"`P0788R3 `__","LWG","Standard Library Specification in a Concepts and Contracts World","Rapperswil","*Removed in Cologne*","n/a" +"`P0879R0 `__","LWG","Constexpr for swap and swap related functions Also resolves LWG issue 2800.","Rapperswil","|Complete|","13.0" +"`P0887R1 `__","LWG","The identity metafunction","Rapperswil","|Complete|","8.0" +"`P0892R2 `__","CWG","explicit(bool)","Rapperswil","","" +"`P0898R3 `__","LWG","Standard Library Concepts","Rapperswil","|In Progress|","" +"`P0935R0 `__","LWG","Eradicating unnecessarily explicit default constructors from the standard library","Rapperswil","|Complete|","12.0" +"`P0941R2 `__","CWG","Integrating feature-test macros into the C++ WD","Rapperswil","|In Progress|","" +"`P1023R0 `__","LWG","constexpr comparison operators for std::array","Rapperswil","|Complete|","8.0" +"`P1025R1 `__","CWG","Update The Reference To The Unicode Standard","Rapperswil","","" +"`P1120R0 `__","CWG","Consistency improvements for <=> and other comparison operators","Rapperswil","","" +"","","","","","" +"`P0318R1 `__","LWG","unwrap_ref_decay and unwrap_reference","San Diego","|Complete|","8.0" +"`P0356R5 `__","LWG","Simplified partial function application","San Diego","|Complete|","13.0" +"`P0357R3 `__","LWG","reference_wrapper for incomplete types","San Diego","|Complete|","8.0" +"`P0482R6 `__","CWG","char8_t: A type for UTF-8 characters and strings","San Diego","|In Progress|","" +"`P0487R1 `__","LWG","Fixing ``operator>>(basic_istream&, CharT*)``\ (LWG 2499)","San Diego","|Complete|","8.0" +"`P0591R4 `__","LWG","Utility functions to implement uses-allocator construction","San Diego","* *","" +"`P0595R2 `__","CWG","P0595R2 std::is_constant_evaluated()","San Diego","|Complete|","9.0" +"`P0602R4 `__","LWG","variant and optional should propagate copy/move triviality","San Diego","|Complete|","8.0" +"`P0608R3 `__","LWG","A sane variant converting constructor","San Diego","|Complete|","9.0" +"`P0655R1 `__","LWG","visit: Explicit Return Type for visit","San Diego","|Complete|","12.0" +"`P0771R1 `__","LWG","std::function move constructor should be noexcept","San Diego","|Complete|","6.0" +"`P0896R4 `__","LWG","The One Ranges Proposal","San Diego","* *","" +"`P0899R1 `__","LWG","P0899R1 - LWG 3016 is not a defect","San Diego","|Nothing To Do|","" +"`P0919R3 `__","LWG","Heterogeneous lookup for unordered containers","San Diego","|Complete|","12.0" +"`P0972R0 `__","LWG"," ``zero()``\ , ``min()``\ , and ``max()``\ should be noexcept","San Diego","|Complete|","8.0" +"`P1006R1 `__","LWG","Constexpr in std::pointer_traits","San Diego","|Complete|","8.0" +"`P1007R3 `__","LWG","``std::assume_aligned``\ ","San Diego","* *","" +"`P1020R1 `__","LWG","Smart pointer creation with default initialization","San Diego","* *","" +"`P1032R1 `__","LWG","Misc constexpr bits","San Diego","|Complete|","13.0" +"`P1085R2 `__","LWG","Should Span be Regular?","San Diego","|Complete|","8.0" +"`P1123R0 `__","LWG","Editorial Guidance for merging P0019r8 and P0528r3","San Diego","* *","" +"`P1148R0 `__","LWG","Cleaning up Clause 20","San Diego","* *","" +"`P1165R1 `__","LWG","Make stateful allocator propagation more consistent for ``operator+(basic_string)``\ ","San Diego","* *","" +"`P1209R0 `__","LWG","Adopt Consistent Container Erasure from Library Fundamentals 2 for C++20","San Diego","|Complete|","8.0" +"`P1210R0 `__","LWG","Completing the Rebase of Library Fundamentals, Version 3, Working Draft","San Diego","* *","" +"`P1236R1 `__","CWG","Alternative Wording for P0907R4 Signed Integers are Two's Complement","San Diego","* *","" +"`P1248R1 `__","LWG","Remove CommonReference requirement from StrictWeakOrdering (a.k.a Fixing Relations)","San Diego","* *","" +"`P1285R0 `__","LWG","Improving Completeness Requirements for Type Traits","San Diego","* *","" +"`P1353R0 `__","CWG","Missing feature test macros","San Diego","* *","" +"","","","","","" +"`P0339R6 `__","LWG","polymorphic_allocator<> as a vocabulary type","Kona","","" +"`P0340R3 `__","LWG","Making std::underlying_type SFINAE-friendly","Kona","|Complete|","9.0" +"`P0738R2 `__","LWG","I Stream, You Stream, We All Stream for istream_iterator","Kona","","" +"`P0811R3 `__","LWG","Well-behaved interpolation for numbers and pointers","Kona","|Complete|","9.0" +"`P0920R2 `__","LWG","Precalculated hash values in lookup","Kona","Reverted by `P1661 `__","" +"`P1001R2 `__","LWG","Target Vectorization Policies from Parallelism V2 TS to C++20","Kona","","" +"`P1024R3 `__","LWG","Usability Enhancements for std::span","Kona","|Complete|","9.0" +"`P1164R1 `__","LWG","Make create_directory() Intuitive","Kona","|Complete|","12.0" +"`P1227R2 `__","LWG","Signed ssize() functions, unsigned size() functions","Kona","|Complete|","9.0" +"`P1252R2 `__","LWG","Ranges Design Cleanup","Kona","","" +"`P1286R2 `__","CWG","Contra CWG DR1778","Kona","","" +"`P1357R1 `__","LWG","Traits for [Un]bounded Arrays","Kona","|Complete|","9.0" +"`P1458R1 `__","LWG","Mandating the Standard Library: Clause 16 - Language support library","Kona","|Complete|","9.0" +"`P1459R1 `__","LWG","Mandating the Standard Library: Clause 18 - Diagnostics library","Kona","|Complete|","9.0" +"`P1462R1 `__","LWG","Mandating the Standard Library: Clause 20 - Strings library","Kona","|Complete|","9.0" +"`P1463R1 `__","LWG","Mandating the Standard Library: Clause 21 - Containers library","Kona","","" +"`P1464R1 `__","LWG","Mandating the Standard Library: Clause 22 - Iterators library","Kona","|Complete|","9.0" +"","","","","","" +"`P0325 `__","LWG","to_array from LFTS with updates","Cologne","|Complete|","10.0" +"`P0408 `__","LWG","Efficient Access to basic_stringbuf's Buffer","Cologne","","" +"`P0466 `__","LWG","Layout-compatibility and Pointer-interconvertibility Traits","Cologne","","" +"`P0553 `__","LWG","Bit operations","Cologne","|Complete|","9.0" +"`P0631 `__","LWG","Math Constants","Cologne","|Complete|","11.0" +"`P0645 `__","LWG","Text Formatting","Cologne","|In Progress|","" +"`P0660 `__","LWG","Stop Token and Joining Thread, Rev 10","Cologne","","" +"`P0784 `__","CWG","More constexpr containers","Cologne","|Complete|","12.0" +"`P0980 `__","LWG","Making std::string constexpr","Cologne","","" +"`P1004 `__","LWG","Making std::vector constexpr","Cologne","","" +"`P1035 `__","LWG","Input Range Adaptors","Cologne","","" +"`P1065 `__","LWG","Constexpr INVOKE","Cologne","|Complete|","12.0" +"`P1135 `__","LWG","The C++20 Synchronization Library","Cologne","|Complete|","11.0" +"`P1207 `__","LWG","Movability of Single-pass Iterators","Cologne","","" +"`P1208 `__","LWG","Adopt source_location for C++20","Cologne","","" +"`P1355 `__","LWG","Exposing a narrow contract for ceil2","Cologne","|Complete|","9.0" +"`P1361 `__","LWG","Integration of chrono with text formatting","Cologne","","" +"`P1423 `__","LWG","char8_t backward compatibility remediation","Cologne","|In Progress|","" +"`P1424 `__","LWG","'constexpr' feature macro concerns","Cologne","Superseded by `P1902 `__","" +"`P1466 `__","LWG","Miscellaneous minor fixes for chrono","Cologne","","" +"`P1474 `__","LWG","Helpful pointers for ContiguousIterator","Cologne","","" +"`P1502 `__","LWG","Standard library header units for C++20","Cologne","","" +"`P1522 `__","LWG","Iterator Difference Type and Integer Overflow","Cologne","","" +"`P1523 `__","LWG","Views and Size Types","Cologne","","" +"`P1612 `__","LWG","Relocate Endian's Specification","Cologne","|Complete|","10.0" +"`P1614 `__","LWG","The Mothership has Landed","Cologne","|In Progress|","" +"`P1638 `__","LWG","basic_istream_view::iterator should not be copyable","Cologne","","" +"`P1643 `__","LWG","Add wait/notify to atomic_ref","Cologne","","" +"`P1644 `__","LWG","Add wait/notify to atomic","Cologne","","" +"`P1650 `__","LWG","Output std::chrono::days with 'd' suffix","Cologne","","" +"`P1651 `__","LWG","bind_front should not unwrap reference_wrapper","Cologne","|Complete|","13.0" +"`P1652 `__","LWG","Printf corner cases in std::format","Cologne","","" +"`P1661 `__","LWG","Remove dedicated precalculated hash lookup interface","Cologne","|Nothing To Do|","" +"`P1754 `__","LWG","Rename concepts to standard_case for C++20, while we still can","Cologne","|In Progress|","" +"","","","","","" +"`P0883 `__","LWG","Fixing Atomic Initialization","Belfast","* *","" +"`P1391 `__","LWG","Range constructor for std::string_view","Belfast","* *","" +"`P1394 `__","LWG","Range constructor for std::span","Belfast","* *","" +"`P1456 `__","LWG","Move-only views","Belfast","* *","" +"`P1622 `__","LWG","Mandating the Standard Library: Clause 32 - Thread support library","Belfast","* *","" +"`P1645 `__","LWG","constexpr for numeric algorithms","Belfast","|Complete|","12.0" +"`P1664 `__","LWG","reconstructible_range - a concept for putting ranges back together","Belfast","* *","" +"`P1686 `__","LWG","Mandating the Standard Library: Clause 27 - Time library","Belfast","* *","" +"`P1690 `__","LWG","Refinement Proposal for P0919 Heterogeneous lookup for unordered containers","Belfast","|Complete|","12.0" +"`P1716 `__","LWG","ranges compare algorithm are over-constrained","Belfast","* *","" +"`P1718 `__","LWG","Mandating the Standard Library: Clause 25 - Algorithms library","Belfast","* *","" +"`P1719 `__","LWG","Mandating the Standard Library: Clause 26 - Numerics library","Belfast","* *","" +"`P1720 `__","LWG","Mandating the Standard Library: Clause 28 - Localization library","Belfast","* *","" +"`P1721 `__","LWG","Mandating the Standard Library: Clause 29 - Input/Output library","Belfast","* *","" +"`P1722 `__","LWG","Mandating the Standard Library: Clause 30 - Regular Expression library","Belfast","* *","" +"`P1723 `__","LWG","Mandating the Standard Library: Clause 31 - Atomics library","Belfast","* *","" +"`P1855 `__","LWG","Make ````\ freestanding","Belfast","* *","" +"`P1862 `__","LWG","Ranges adaptors for non-copyable iterators","Belfast","* *","" +"`P1865 `__","LWG","Add max() to latch and barrier","Belfast","|Complete|","11.0" +"`P1869 `__","LWG","Rename 'condition_variable_any' interruptible wait methods","Belfast","* *","" +"`P1870 `__","LWG","forwarding-range is too subtle","Belfast","* *","" +"`P1871 `__","LWG","Should concepts be enabled or disabled?","Belfast","* *","" +"`P1872 `__","LWG","span should have size_type, not index_type","Belfast","|Complete|","10.0" +"`P1878 `__","LWG","Constraining Readable Types","Belfast","* *","" +"`P1892 `__","LWG","Extended locale-specific presentation specifiers for std::format","Belfast","* *","" +"`P1902 `__","LWG","Missing feature-test macros 2018-2019","Belfast","* *","" +"`P1959 `__","LWG","Remove std::weak_equality and std::strong_equality","Belfast","* *","" +"`P1960 `__","LWG","NB Comment Changes Reviewed by SG1","Belfast","* *","" +"`P1961 `__","LWG","Harmonizing the definitions of total order for pointers","Belfast","* *","" +"`P1965 `__","LWG","Blanket Wording for Specifying ""Hidden Friends""","Belfast","* *","" +"","","","","","" +"`P0586 `__","LWG","Safe integral comparisons","Prague","* *","" +"`P0593 `__","CWG","Implicit creation of objects for low-level object manipulation","Prague","* *","" +"`P1115 `__","LWG","Improving the Return Value of Erase-Like Algorithms II: Free erase/erase if","Prague","|Complete|","11.0" +"`P1243 `__","LWG","Rangify New Algorithms","Prague","* *","" +"`P1460 `__","LWG","Mandating the Standard Library: Clause 20 - Utilities library","Prague","* *","" +"`P1739 `__","LWG","Avoid template bloat for safe_ranges in combination with ""subrange-y"" view adaptors","Prague","* *","" +"`P1831 `__","LWG","Deprecating volatile: library","Prague","* *","" +"`P1868 `__","LWG","width: clarifying units of width and precision in std::format","Prague","* *","" +"`P1908 `__","CWG","Reserving Attribute Namespaces for Future Use","Prague","* *","" +"`P1937 `__","CWG","Fixing inconsistencies between constexpr and consteval functions","Prague","* *","" +"`P1956 `__","LWG","On the names of low-level bit manipulation functions","Prague","|Complete|","12.0" +"`P1957 `__","CWG","Converting from ``T*``\ to bool should be considered narrowing (re: US 212)","Prague","* *","" +"`P1963 `__","LWG","Fixing US 313","Prague","* *","" +"`P1964 `__","LWG","Wording for boolean-testable","Prague","* *","" +"`P1970 `__","LWG","Consistency for size() functions: Add ranges::ssize","Prague","* *","" +"`P1973 `__","LWG","Rename ""_default_init"" Functions, Rev1","Prague","* *","" +"`P1976 `__","LWG","Fixed-size span construction from dynamic range","Prague","|Complete|","11.0" +"`P1981 `__","LWG","Rename leap to leap_second","Prague","* *","" +"`P1982 `__","LWG","Rename link to time_zone_link","Prague","* *","" +"`P1983 `__","LWG","Wording for GB301, US296, US292, US291, and US283","Prague","* *","" +"`P1994 `__","LWG","elements_view needs its own sentinel","Prague","* *","" +"`P2002 `__","CWG","Defaulted comparison specification cleanups","Prague","* *","" +"`P2045 `__","LWG","Missing Mandates for the standard library","Prague","* *","" +"`P2085 `__","CWG","Consistent defaulted comparisons","Prague","* *","" +"`P2091 `__","LWG","Issues with range access CPOs","Prague","* *","" +"`P2101 `__","LWG","'Models' subsumes 'satisfies' (Wording for US298 and US300)","Prague","* *","" +"`P2102 `__","LWG","Make 'implicit expression variations' more explicit (Wording for US185)","Prague","* *","" +"`P2106 `__","LWG","Alternative wording for GB315 and GB316","Prague","* *","" +"`P2116 `__","LWG","Remove tuple-like protocol support from fixed-extent span","Prague","|Complete|","11.0" diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -202,7 +202,7 @@ ------------------------------------------------- ----------------- ``__cpp_lib_constexpr_algorithms`` ``201806L`` ------------------------------------------------- ----------------- - ``__cpp_lib_constexpr_complex`` *unimplemented* + ``__cpp_lib_constexpr_complex`` ``201711L`` ------------------------------------------------- ----------------- ``__cpp_lib_constexpr_dynamic_alloc`` ``201907L`` ------------------------------------------------- ----------------- diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -50,6 +50,7 @@ - P0600R1 - ``nodiscard`` in the library - P0339R6 - ``polymorphic_allocator<>`` as a vocabulary type - P1169R4 - ``static operator()`` +- P0415R1 - ``constexpr`` for ``std::complex`` Improvements and New Features ----------------------------- diff --git a/libcxx/docs/Status/Cxx20Papers.csv b/libcxx/docs/Status/Cxx20Papers.csv --- a/libcxx/docs/Status/Cxx20Papers.csv +++ b/libcxx/docs/Status/Cxx20Papers.csv @@ -5,7 +5,7 @@ "`P0020R6 `__","LWG","Floating Point Atomic","Albuquerque","","" "`P0053R7 `__","LWG","C++ Synchronized Buffered Ostream","Albuquerque","","" "`P0202R3 `__","LWG","Add constexpr modifiers to functions in and Headers","Albuquerque","|Complete|","12.0" -"`P0415R1 `__","LWG","Constexpr for ``std::complex``\ ","Albuquerque","|In Progress|","7.0" +"`P0415R1 `__","LWG","Constexpr for ``std::complex``\ ","Albuquerque","|Complete|","16.0" "`P0439R0 `__","LWG","Make ``std::memory_order``\ a scoped enumeration","Albuquerque","|Complete|","" "`P0457R2 `__","LWG","String Prefix and Suffix Checking","Albuquerque","|Complete|","6.0" "`P0550R2 `__","LWG","Transformation Trait ``remove_cvref``\ ","Albuquerque","|Complete|","6.0" diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -196,6 +196,10 @@ # define __has_cpp_attribute(__x) 0 # endif +# ifndef __has_constexpr_builtin +# define __has_constexpr_builtin(x) 0 +# endif + // '__is_identifier' returns '0' if '__x' is a reserved identifier provided by // the compiler and '1' otherwise. # ifndef __is_identifier diff --git a/libcxx/include/cmath b/libcxx/include/cmath --- a/libcxx/include/cmath +++ b/libcxx/include/cmath @@ -619,7 +619,120 @@ _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type __constexpr_isfinite(_A1 __lcpp_x) _NOEXCEPT { - return isfinite(__lcpp_x); + return __builtin_isfinite(__lcpp_x); +} + +_LIBCPP_CONSTEXPR inline _LIBCPP_HIDE_FROM_ABI float __constexpr_copysign(float __x, float __y) _NOEXCEPT { + return __builtin_copysignf(__x, __y); +} + +_LIBCPP_CONSTEXPR inline _LIBCPP_HIDE_FROM_ABI double __constexpr_copysign(double __x, double __y) _NOEXCEPT { + return __builtin_copysign(__x, __y); +} + +_LIBCPP_CONSTEXPR inline _LIBCPP_HIDE_FROM_ABI long double +__constexpr_copysign(long double __x, long double __y) _NOEXCEPT { + return __builtin_copysignl(__x, __y); +} + +template +_LIBCPP_CONSTEXPR inline _LIBCPP_HIDE_FROM_ABI + typename std::__enable_if_t::value && std::is_arithmetic<_A2>::value, + std::__promote<_A1, _A2> >::type + __constexpr_copysign(_A1 __x, _A2 __y) _NOEXCEPT { + typedef typename std::__promote<_A1, _A2>::type __result_type; + static_assert((!(std::_IsSame<_A1, __result_type>::value && std::_IsSame<_A2, __result_type>::value)), ""); + return __builtin_copysign((__result_type)__x, (__result_type)__y); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR float __constexpr_fabs(float __x) _NOEXCEPT { + return __builtin_fabsf(__x); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR double __constexpr_fabs(double __x) _NOEXCEPT { + return __builtin_fabs(__x); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR long double __constexpr_fabs(long double __x) _NOEXCEPT { + return __builtin_fabsl(__x); +} + +template ::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp __constexpr_fabs(_Tp __x) _NOEXCEPT { + return __builtin_fabs(__x); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp __constexpr_fmax(_Tp __x, _Tp __y) _NOEXCEPT { + return __builtin_fmax(__x, __y); +} + +template +_LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __constexpr_logb(_Tp __x) { +#if !__has_constexpr_builtin(__builtin_logb) && !defined(_LIBCPP_COMPILER_GCC) + if (__libcpp_is_constant_evaluated()) { + if (__x == _Tp(0)) { + // raise FE_DIVBYZERO + return -_Tp(INFINITY); + } + + if (std::__constexpr_isinf(__x)) + return _Tp(INFINITY); + + if (std::__constexpr_isnan(__x)) + return _Tp(NAN); + + __x = std::__constexpr_fabs(__x); + unsigned long long __exp = 0; + while (__x >= numeric_limits<_Tp>::radix) { + __x /= numeric_limits<_Tp>::radix; + __exp += 1; + } + return _Tp(__exp); + } +#endif // _LIBCPP_STD_VER > 17 + return __builtin_logb(__x); +} + +template +_LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp __constexpr_scalbn(_Tp __x, int __exp) { +#if !__has_constexpr_builtin(__builtin_scalbln) && !defined(_LIBCPP_COMPILER_GCC) + if (__libcpp_is_constant_evaluated()) { + if (__x == _Tp(0)) + return __x; + + if (std::__constexpr_isinf(__x)) + return __x; + + if (__exp == _Tp(0)) + return __x; + + if (std::__constexpr_isnan(__x)) + return _Tp(NAN); + + _Tp __mult(1); + if (__exp > 0) { + __mult = numeric_limits<_Tp>::radix; + --__exp; + } else { + ++__exp; + __exp = -__exp; + __mult /= numeric_limits<_Tp>::radix; + } + + while (__exp > 0) { + if (!(__exp & 1)) { + __mult *= __mult; + __exp >>= 1; + } else { + __x *= __mult; + --__exp; + } + } + return __x; + } +#endif // _LIBCPP_STD_VER > 17 + return __builtin_scalbn(__x, __exp); } #if _LIBCPP_STD_VER > 17 diff --git a/libcxx/include/complex b/libcxx/include/complex --- a/libcxx/include/complex +++ b/libcxx/include/complex @@ -29,21 +29,21 @@ T real() const; // constexpr in C++14 T imag() const; // constexpr in C++14 - void real(T); - void imag(T); - - complex& operator= (const T&); - complex& operator+=(const T&); - complex& operator-=(const T&); - complex& operator*=(const T&); - complex& operator/=(const T&); - - complex& operator=(const complex&); - template complex& operator= (const complex&); - template complex& operator+=(const complex&); - template complex& operator-=(const complex&); - template complex& operator*=(const complex&); - template complex& operator/=(const complex&); + void real(T); // constexpr in C++20 + void imag(T); // constexpr in C++20 + + complex& operator= (const T&); // constexpr in C++20 + complex& operator+=(const T&); // constexpr in C++20 + complex& operator-=(const T&); // constexpr in C++20 + complex& operator*=(const T&); // constexpr in C++20 + complex& operator/=(const T&); // constexpr in C++20 + + complex& operator=(const complex&); // constexpr in C++20 + template complex& operator= (const complex&); // constexpr in C++20 + template complex& operator+=(const complex&); // constexpr in C++20 + template complex& operator-=(const complex&); // constexpr in C++20 + template complex& operator*=(const complex&); // constexpr in C++20 + template complex& operator/=(const complex&); // constexpr in C++20 }; template<> @@ -57,22 +57,22 @@ explicit constexpr complex(const complex&); constexpr float real() const; - void real(float); + void real(float); // constexpr in C++20 constexpr float imag() const; - void imag(float); - - complex& operator= (float); - complex& operator+=(float); - complex& operator-=(float); - complex& operator*=(float); - complex& operator/=(float); - - complex& operator=(const complex&); - template complex& operator= (const complex&); - template complex& operator+=(const complex&); - template complex& operator-=(const complex&); - template complex& operator*=(const complex&); - template complex& operator/=(const complex&); + void imag(float); // constexpr in C++20 + + complex& operator= (float); // constexpr in C++20 + complex& operator+=(float); // constexpr in C++20 + complex& operator-=(float); // constexpr in C++20 + complex& operator*=(float); // constexpr in C++20 + complex& operator/=(float); // constexpr in C++20 + + complex& operator=(const complex&); // constexpr in C++20 + template complex& operator= (const complex&); // constexpr in C++20 + template complex& operator+=(const complex&); // constexpr in C++20 + template complex& operator-=(const complex&); // constexpr in C++20 + template complex& operator*=(const complex&); // constexpr in C++20 + template complex& operator/=(const complex&); // constexpr in C++20 }; template<> @@ -86,22 +86,22 @@ explicit constexpr complex(const complex&); constexpr double real() const; - void real(double); + void real(double); // constexpr in C++20 constexpr double imag() const; - void imag(double); - - complex& operator= (double); - complex& operator+=(double); - complex& operator-=(double); - complex& operator*=(double); - complex& operator/=(double); - complex& operator=(const complex&); - - template complex& operator= (const complex&); - template complex& operator+=(const complex&); - template complex& operator-=(const complex&); - template complex& operator*=(const complex&); - template complex& operator/=(const complex&); + void imag(double); // constexpr in C++20 + + complex& operator= (double); // constexpr in C++20 + complex& operator+=(double); // constexpr in C++20 + complex& operator-=(double); // constexpr in C++20 + complex& operator*=(double); // constexpr in C++20 + complex& operator/=(double); // constexpr in C++20 + complex& operator=(const complex&); // constexpr in C++20 + + template complex& operator= (const complex&); // constexpr in C++20 + template complex& operator+=(const complex&); // constexpr in C++20 + template complex& operator-=(const complex&); // constexpr in C++20 + template complex& operator*=(const complex&); // constexpr in C++20 + template complex& operator/=(const complex&); // constexpr in C++20 }; template<> @@ -115,39 +115,39 @@ constexpr complex(const complex&); constexpr long double real() const; - void real(long double); + void real(long double); // constexpr in C++20 constexpr long double imag() const; - void imag(long double); - - complex& operator=(const complex&); - complex& operator= (long double); - complex& operator+=(long double); - complex& operator-=(long double); - complex& operator*=(long double); - complex& operator/=(long double); - - template complex& operator= (const complex&); - template complex& operator+=(const complex&); - template complex& operator-=(const complex&); - template complex& operator*=(const complex&); - template complex& operator/=(const complex&); + void imag(long double); // constexpr in C++20 + + complex& operator=(const complex&); // constexpr in C++20 + complex& operator= (long double); // constexpr in C++20 + complex& operator+=(long double); // constexpr in C++20 + complex& operator-=(long double); // constexpr in C++20 + complex& operator*=(long double); // constexpr in C++20 + complex& operator/=(long double); // constexpr in C++20 + + template complex& operator= (const complex&); // constexpr in C++20 + template complex& operator+=(const complex&); // constexpr in C++20 + template complex& operator-=(const complex&); // constexpr in C++20 + template complex& operator*=(const complex&); // constexpr in C++20 + template complex& operator/=(const complex&); // constexpr in C++20 }; // 26.3.6 operators: -template complex operator+(const complex&, const complex&); -template complex operator+(const complex&, const T&); -template complex operator+(const T&, const complex&); -template complex operator-(const complex&, const complex&); -template complex operator-(const complex&, const T&); -template complex operator-(const T&, const complex&); -template complex operator*(const complex&, const complex&); -template complex operator*(const complex&, const T&); -template complex operator*(const T&, const complex&); -template complex operator/(const complex&, const complex&); -template complex operator/(const complex&, const T&); -template complex operator/(const T&, const complex&); -template complex operator+(const complex&); -template complex operator-(const complex&); +template complex operator+(const complex&, const complex&); // constexpr in C++20 +template complex operator+(const complex&, const T&); // constexpr in C++20 +template complex operator+(const T&, const complex&); // constexpr in C++20 +template complex operator-(const complex&, const complex&); // constexpr in C++20 +template complex operator-(const complex&, const T&); // constexpr in C++20 +template complex operator-(const T&, const complex&); // constexpr in C++20 +template complex operator*(const complex&, const complex&); // constexpr in C++20 +template complex operator*(const complex&, const T&); // constexpr in C++20 +template complex operator*(const T&, const complex&); // constexpr in C++20 +template complex operator/(const complex&, const complex&); // constexpr in C++20 +template complex operator/(const complex&, const T&); // constexpr in C++20 +template complex operator/(const T&, const complex&); // constexpr in C++20 +template complex operator+(const complex&); // constexpr in C++20 +template complex operator-(const complex&); // constexpr in C++20 template bool operator==(const complex&, const complex&); // constexpr in C++14 template bool operator==(const complex&, const T&); // constexpr in C++14 template bool operator==(const T&, const complex&); // constexpr in C++14 @@ -184,17 +184,17 @@ template double arg(T); float arg(float); -template T norm(const complex&); - long double norm(long double); - double norm(double); -template double norm(T); - float norm(float); +template T norm(const complex&); // constexpr in C++20 + long double norm(long double); // constexpr in C++20 + double norm(double); // constexpr in C++20 +template double norm(T); // constexpr in C++20 + float norm(float); // constexpr in C++20 -template complex conj(const complex&); - complex conj(long double); - complex conj(double); -template complex conj(T); - complex conj(float); +template complex conj(const complex&); // constexpr in C++20 + complex conj(long double); // constexpr in C++20 + complex conj(double); // constexpr in C++20 +template complex conj(T); // constexpr in C++20 + complex conj(float); // constexpr in C++20 template complex proj(const complex&); complex proj(long double); @@ -251,8 +251,8 @@ template class _LIBCPP_TEMPLATE_VIS complex; -template _LIBCPP_HIDE_FROM_ABI complex<_Tp> operator*(const complex<_Tp>& __z, const complex<_Tp>& __w); -template _LIBCPP_HIDE_FROM_ABI complex<_Tp> operator/(const complex<_Tp>& __x, const complex<_Tp>& __y); +template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator*(const complex<_Tp>& __z, const complex<_Tp>& __w); +template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator/(const complex<_Tp>& __x, const complex<_Tp>& __y); template class _LIBCPP_TEMPLATE_VIS complex @@ -273,40 +273,40 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 value_type real() const {return __re_;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 value_type imag() const {return __im_;} - _LIBCPP_INLINE_VISIBILITY void real(value_type __re) {__re_ = __re;} - _LIBCPP_INLINE_VISIBILITY void imag(value_type __im) {__im_ = __im;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) {__re_ = __re;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) {__im_ = __im;} - _LIBCPP_INLINE_VISIBILITY complex& operator= (const value_type& __re) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (const value_type& __re) {__re_ = __re; __im_ = value_type(); return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator+=(const value_type& __re) {__re_ += __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator-=(const value_type& __re) {__re_ -= __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator*=(const value_type& __re) {__re_ *= __re; __im_ *= __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator/=(const value_type& __re) {__re_ /= __re; __im_ /= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(const value_type& __re) {__re_ += __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(const value_type& __re) {__re_ -= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(const value_type& __re) {__re_ *= __re; __im_ *= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(const value_type& __re) {__re_ /= __re; __im_ /= __re; return *this;} - template _LIBCPP_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (const complex<_Xp>& __c) { __re_ = __c.real(); __im_ = __c.imag(); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(const complex<_Xp>& __c) { __re_ += __c.real(); __im_ += __c.imag(); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(const complex<_Xp>& __c) { __re_ -= __c.real(); __im_ -= __c.imag(); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(const complex<_Xp>& __c) { *this = *this * complex(__c.real(), __c.imag()); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(const complex<_Xp>& __c) { *this = *this / complex(__c.real(), __c.imag()); return *this; @@ -334,40 +334,40 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR float real() const {return __re_;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR float imag() const {return __im_;} - _LIBCPP_INLINE_VISIBILITY void real(value_type __re) {__re_ = __re;} - _LIBCPP_INLINE_VISIBILITY void imag(value_type __im) {__im_ = __im;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) {__re_ = __re;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) {__im_ = __im;} - _LIBCPP_INLINE_VISIBILITY complex& operator= (float __re) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (float __re) {__re_ = __re; __im_ = value_type(); return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator+=(float __re) {__re_ += __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator-=(float __re) {__re_ -= __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator*=(float __re) {__re_ *= __re; __im_ *= __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator/=(float __re) {__re_ /= __re; __im_ /= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(float __re) {__re_ += __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(float __re) {__re_ -= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(float __re) {__re_ *= __re; __im_ *= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(float __re) {__re_ /= __re; __im_ /= __re; return *this;} - template _LIBCPP_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (const complex<_Xp>& __c) { __re_ = __c.real(); __im_ = __c.imag(); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(const complex<_Xp>& __c) { __re_ += __c.real(); __im_ += __c.imag(); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(const complex<_Xp>& __c) { __re_ -= __c.real(); __im_ -= __c.imag(); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(const complex<_Xp>& __c) { *this = *this * complex(__c.real(), __c.imag()); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(const complex<_Xp>& __c) { *this = *this / complex(__c.real(), __c.imag()); return *this; @@ -392,40 +392,40 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR double real() const {return __re_;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR double imag() const {return __im_;} - _LIBCPP_INLINE_VISIBILITY void real(value_type __re) {__re_ = __re;} - _LIBCPP_INLINE_VISIBILITY void imag(value_type __im) {__im_ = __im;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) {__re_ = __re;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) {__im_ = __im;} - _LIBCPP_INLINE_VISIBILITY complex& operator= (double __re) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (double __re) {__re_ = __re; __im_ = value_type(); return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator+=(double __re) {__re_ += __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator-=(double __re) {__re_ -= __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator*=(double __re) {__re_ *= __re; __im_ *= __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator/=(double __re) {__re_ /= __re; __im_ /= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(double __re) {__re_ += __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(double __re) {__re_ -= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(double __re) {__re_ *= __re; __im_ *= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(double __re) {__re_ /= __re; __im_ /= __re; return *this;} - template _LIBCPP_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (const complex<_Xp>& __c) { __re_ = __c.real(); __im_ = __c.imag(); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(const complex<_Xp>& __c) { __re_ += __c.real(); __im_ += __c.imag(); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(const complex<_Xp>& __c) { __re_ -= __c.real(); __im_ -= __c.imag(); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(const complex<_Xp>& __c) { *this = *this * complex(__c.real(), __c.imag()); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(const complex<_Xp>& __c) { *this = *this / complex(__c.real(), __c.imag()); return *this; @@ -450,40 +450,40 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR long double real() const {return __re_;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR long double imag() const {return __im_;} - _LIBCPP_INLINE_VISIBILITY void real(value_type __re) {__re_ = __re;} - _LIBCPP_INLINE_VISIBILITY void imag(value_type __im) {__im_ = __im;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) {__re_ = __re;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) {__im_ = __im;} - _LIBCPP_INLINE_VISIBILITY complex& operator= (long double __re) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (long double __re) {__re_ = __re; __im_ = value_type(); return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator+=(long double __re) {__re_ += __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator-=(long double __re) {__re_ -= __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator*=(long double __re) {__re_ *= __re; __im_ *= __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator/=(long double __re) {__re_ /= __re; __im_ /= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(long double __re) {__re_ += __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(long double __re) {__re_ -= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(long double __re) {__re_ *= __re; __im_ *= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(long double __re) {__re_ /= __re; __im_ /= __re; return *this;} - template _LIBCPP_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (const complex<_Xp>& __c) { __re_ = __c.real(); __im_ = __c.imag(); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(const complex<_Xp>& __c) { __re_ += __c.real(); __im_ += __c.imag(); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(const complex<_Xp>& __c) { __re_ -= __c.real(); __im_ -= __c.imag(); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(const complex<_Xp>& __c) { *this = *this * complex(__c.real(), __c.imag()); return *this; } - template _LIBCPP_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(const complex<_Xp>& __c) { *this = *this / complex(__c.real(), __c.imag()); return *this; @@ -523,7 +523,7 @@ // 26.3.6 operators: template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator+(const complex<_Tp>& __x, const complex<_Tp>& __y) { @@ -533,7 +533,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator+(const complex<_Tp>& __x, const _Tp& __y) { @@ -543,7 +543,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator+(const _Tp& __x, const complex<_Tp>& __y) { @@ -553,7 +553,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator-(const complex<_Tp>& __x, const complex<_Tp>& __y) { @@ -563,7 +563,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator-(const complex<_Tp>& __x, const _Tp& __y) { @@ -573,7 +573,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator-(const _Tp& __x, const complex<_Tp>& __y) { @@ -583,53 +583,86 @@ } template -_LIBCPP_HIDE_FROM_ABI complex<_Tp> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator*(const complex<_Tp>& __z, const complex<_Tp>& __w) { _Tp __a = __z.real(); _Tp __b = __z.imag(); _Tp __c = __w.real(); _Tp __d = __w.imag(); + + // Avoid floating point operations that are invalid during constant evaluation + if (__libcpp_is_constant_evaluated()) { + bool __z_zero = __a == _Tp(0) && __b == _Tp(0); + bool __w_zero = __c == _Tp(0) && __d == _Tp(0); + bool __z_inf = std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b); + bool __w_inf = std::__constexpr_isinf(__c) || std::__constexpr_isinf(__d); + bool __z_nan = !__z_inf && ( + (std::__constexpr_isnan(__a) && std::__constexpr_isnan(__b)) + || (std::__constexpr_isnan(__a) && __b == _Tp(0)) + || (__a == _Tp(0) && std::__constexpr_isnan(__b)) + ); + bool __w_nan = !__w_inf && ( + (std::__constexpr_isnan(__c) && std::__constexpr_isnan(__d)) + || (std::__constexpr_isnan(__c) && __d == _Tp(0)) + || (__c == _Tp(0) && std::__constexpr_isnan(__d)) + ); + if (__z_nan || __w_nan) { + return complex<_Tp>(_Tp(NAN), _Tp(0)); + } + if (__z_inf || __w_inf) { + if (__z_zero || __w_zero) { + return complex<_Tp>(_Tp(NAN), _Tp(0)); + } + return complex<_Tp>(_Tp(INFINITY), _Tp(INFINITY)); + } + bool __z_nonzero_nan = !__z_inf && !__z_nan && (std::__constexpr_isnan(__a) || std::__constexpr_isnan(__b)); + bool __w_nonzero_nan = !__w_inf && !__w_nan && (std::__constexpr_isnan(__c) || std::__constexpr_isnan(__d)); + if (__z_nonzero_nan || __w_nonzero_nan) { + return complex<_Tp>(_Tp(NAN), _Tp(0)); + } + } + _Tp __ac = __a * __c; _Tp __bd = __b * __d; _Tp __ad = __a * __d; _Tp __bc = __b * __c; _Tp __x = __ac - __bd; _Tp __y = __ad + __bc; - if (__constexpr_isnan(__x) && __constexpr_isnan(__y)) + if (std::__constexpr_isnan(__x) && std::__constexpr_isnan(__y)) { bool __recalc = false; - if (__constexpr_isinf(__a) || __constexpr_isinf(__b)) + if (std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b)) { - __a = copysign(__constexpr_isinf(__a) ? _Tp(1) : _Tp(0), __a); - __b = copysign(__constexpr_isinf(__b) ? _Tp(1) : _Tp(0), __b); - if (__constexpr_isnan(__c)) - __c = copysign(_Tp(0), __c); - if (__constexpr_isnan(__d)) - __d = copysign(_Tp(0), __d); + __a = std::__constexpr_copysign(std::__constexpr_isinf(__a) ? _Tp(1) : _Tp(0), __a); + __b = std::__constexpr_copysign(std::__constexpr_isinf(__b) ? _Tp(1) : _Tp(0), __b); + if (std::__constexpr_isnan(__c)) + __c = std::__constexpr_copysign(_Tp(0), __c); + if (std::__constexpr_isnan(__d)) + __d = std::__constexpr_copysign(_Tp(0), __d); __recalc = true; } - if (__constexpr_isinf(__c) || __constexpr_isinf(__d)) + if (std::__constexpr_isinf(__c) || std::__constexpr_isinf(__d)) { - __c = copysign(__constexpr_isinf(__c) ? _Tp(1) : _Tp(0), __c); - __d = copysign(__constexpr_isinf(__d) ? _Tp(1) : _Tp(0), __d); - if (__constexpr_isnan(__a)) - __a = copysign(_Tp(0), __a); - if (__constexpr_isnan(__b)) - __b = copysign(_Tp(0), __b); + __c = std::__constexpr_copysign(std::__constexpr_isinf(__c) ? _Tp(1) : _Tp(0), __c); + __d = std::__constexpr_copysign(std::__constexpr_isinf(__d) ? _Tp(1) : _Tp(0), __d); + if (std::__constexpr_isnan(__a)) + __a = std::__constexpr_copysign(_Tp(0), __a); + if (std::__constexpr_isnan(__b)) + __b = std::__constexpr_copysign(_Tp(0), __b); __recalc = true; } - if (!__recalc && (__constexpr_isinf(__ac) || __constexpr_isinf(__bd) || - __constexpr_isinf(__ad) || __constexpr_isinf(__bc))) + if (!__recalc && (std::__constexpr_isinf(__ac) || std::__constexpr_isinf(__bd) || + std::__constexpr_isinf(__ad) || std::__constexpr_isinf(__bc))) { - if (__constexpr_isnan(__a)) - __a = copysign(_Tp(0), __a); - if (__constexpr_isnan(__b)) - __b = copysign(_Tp(0), __b); - if (__constexpr_isnan(__c)) - __c = copysign(_Tp(0), __c); - if (__constexpr_isnan(__d)) - __d = copysign(_Tp(0), __d); + if (std::__constexpr_isnan(__a)) + __a = std::__constexpr_copysign(_Tp(0), __a); + if (std::__constexpr_isnan(__b)) + __b = std::__constexpr_copysign(_Tp(0), __b); + if (std::__constexpr_isnan(__c)) + __c = std::__constexpr_copysign(_Tp(0), __c); + if (std::__constexpr_isnan(__d)) + __d = std::__constexpr_copysign(_Tp(0), __d); __recalc = true; } if (__recalc) @@ -642,7 +675,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator*(const complex<_Tp>& __x, const _Tp& __y) { @@ -652,7 +685,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator*(const _Tp& __x, const complex<_Tp>& __y) { @@ -662,7 +695,7 @@ } template -_LIBCPP_HIDE_FROM_ABI complex<_Tp> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator/(const complex<_Tp>& __z, const complex<_Tp>& __w) { int __ilogbw = 0; @@ -670,34 +703,74 @@ _Tp __b = __z.imag(); _Tp __c = __w.real(); _Tp __d = __w.imag(); - _Tp __logbw = logb(fmax(fabs(__c), fabs(__d))); - if (__constexpr_isfinite(__logbw)) + _Tp __logbw = std::__constexpr_logb(std::__constexpr_fmax(std::__constexpr_fabs(__c), std::__constexpr_fabs(__d))); + if (std::__constexpr_isfinite(__logbw)) { __ilogbw = static_cast(__logbw); - __c = scalbn(__c, -__ilogbw); - __d = scalbn(__d, -__ilogbw); + __c = std::__constexpr_scalbn(__c, -__ilogbw); + __d = std::__constexpr_scalbn(__d, -__ilogbw); } + + // Avoid floating point operations that are invalid during constant evaluation + if (__libcpp_is_constant_evaluated()) { + bool __z_zero = __a == _Tp(0) && __b == _Tp(0); + bool __w_zero = __c == _Tp(0) && __d == _Tp(0); + bool __z_inf = std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b); + bool __w_inf = std::__constexpr_isinf(__c) || std::__constexpr_isinf(__d); + bool __z_nan = !__z_inf && ( + (std::__constexpr_isnan(__a) && std::__constexpr_isnan(__b)) + || (std::__constexpr_isnan(__a) && __b == _Tp(0)) + || (__a == _Tp(0) && std::__constexpr_isnan(__b)) + ); + bool __w_nan = !__w_inf && ( + (std::__constexpr_isnan(__c) && std::__constexpr_isnan(__d)) + || (std::__constexpr_isnan(__c) && __d == _Tp(0)) + || (__c == _Tp(0) && std::__constexpr_isnan(__d)) + ); + if ((__z_nan || __w_nan) || (__z_inf && __w_inf)) { + return complex<_Tp>(_Tp(NAN), _Tp(0)); + } + bool __z_nonzero_nan = !__z_inf && !__z_nan && (std::__constexpr_isnan(__a) || std::__constexpr_isnan(__b)); + bool __w_nonzero_nan = !__w_inf && !__w_nan && (std::__constexpr_isnan(__c) || std::__constexpr_isnan(__d)); + if (__z_nonzero_nan || __w_nonzero_nan) { + if (__w_zero) { + return complex<_Tp>(_Tp(INFINITY), _Tp(INFINITY)); + } + return complex<_Tp>(_Tp(NAN), _Tp(0)); + } + if (__w_inf) { + return complex<_Tp>(_Tp(0), _Tp(0)); + } + if (__z_inf) { + return complex<_Tp>(_Tp(INFINITY), _Tp(INFINITY)); + } + if (__w_zero) { + if (__z_zero) { + return complex<_Tp>(_Tp(NAN), _Tp(0)); + } + return complex<_Tp>(_Tp(INFINITY), _Tp(INFINITY)); + } + } + _Tp __denom = __c * __c + __d * __d; - _Tp __x = scalbn((__a * __c + __b * __d) / __denom, -__ilogbw); - _Tp __y = scalbn((__b * __c - __a * __d) / __denom, -__ilogbw); - if (__constexpr_isnan(__x) && __constexpr_isnan(__y)) + _Tp __x = std::__constexpr_scalbn((__a * __c + __b * __d) / __denom, -__ilogbw); + _Tp __y = std::__constexpr_scalbn((__b * __c - __a * __d) / __denom, -__ilogbw); + if (std::__constexpr_isnan(__x) && std::__constexpr_isnan(__y)) { - if ((__denom == _Tp(0)) && (!__constexpr_isnan(__a) || !__constexpr_isnan(__b))) + if ((__denom == _Tp(0)) && (!std::__constexpr_isnan(__a) || !std::__constexpr_isnan(__b))) { - __x = copysign(_Tp(INFINITY), __c) * __a; - __y = copysign(_Tp(INFINITY), __c) * __b; - } - else if ((__constexpr_isinf(__a) || __constexpr_isinf(__b)) && __constexpr_isfinite(__c) && __constexpr_isfinite(__d)) - { - __a = copysign(__constexpr_isinf(__a) ? _Tp(1) : _Tp(0), __a); - __b = copysign(__constexpr_isinf(__b) ? _Tp(1) : _Tp(0), __b); + __x = std::__constexpr_copysign(_Tp(INFINITY), __c) * __a; + __y = std::__constexpr_copysign(_Tp(INFINITY), __c) * __b; + } else if ((std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b)) && std::__constexpr_isfinite(__c) && + std::__constexpr_isfinite(__d)) { + __a = std::__constexpr_copysign(std::__constexpr_isinf(__a) ? _Tp(1) : _Tp(0), __a); + __b = std::__constexpr_copysign(std::__constexpr_isinf(__b) ? _Tp(1) : _Tp(0), __b); __x = _Tp(INFINITY) * (__a * __c + __b * __d); __y = _Tp(INFINITY) * (__b * __c - __a * __d); - } - else if (__constexpr_isinf(__logbw) && __logbw > _Tp(0) && __constexpr_isfinite(__a) && __constexpr_isfinite(__b)) - { - __c = copysign(__constexpr_isinf(__c) ? _Tp(1) : _Tp(0), __c); - __d = copysign(__constexpr_isinf(__d) ? _Tp(1) : _Tp(0), __d); + } else if (std::__constexpr_isinf(__logbw) && __logbw > _Tp(0) && std::__constexpr_isfinite(__a) && + std::__constexpr_isfinite(__b)) { + __c = std::__constexpr_copysign(std::__constexpr_isinf(__c) ? _Tp(1) : _Tp(0), __c); + __d = std::__constexpr_copysign(std::__constexpr_isinf(__d) ? _Tp(1) : _Tp(0), __d); __x = _Tp(0) * (__a * __c + __b * __d); __y = _Tp(0) * (__b * __c - __a * __d); } @@ -706,7 +779,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator/(const complex<_Tp>& __x, const _Tp& __y) { @@ -714,7 +787,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator/(const _Tp& __x, const complex<_Tp>& __y) { @@ -724,7 +797,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator+(const complex<_Tp>& __x) { @@ -732,7 +805,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator-(const complex<_Tp>& __x) { @@ -903,7 +976,7 @@ // norm template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp norm(const complex<_Tp>& __c) { @@ -915,7 +988,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __libcpp_complex_overload_traits<_Tp>::_ValueType norm(_Tp __re) { @@ -926,7 +999,7 @@ // conj template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> conj(const complex<_Tp>& __c) { @@ -934,7 +1007,7 @@ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __libcpp_complex_overload_traits<_Tp>::_ComplexType conj(_Tp __re) { diff --git a/libcxx/include/math.h b/libcxx/include/math.h --- a/libcxx/include/math.h +++ b/libcxx/include/math.h @@ -1028,43 +1028,12 @@ // copysign -_LIBCPP_CONSTEXPR -inline _LIBCPP_HIDE_FROM_ABI float __libcpp_copysign(float __x, float __y) _NOEXCEPT { - return __builtin_copysignf(__x, __y); -} - -_LIBCPP_CONSTEXPR -inline _LIBCPP_HIDE_FROM_ABI double __libcpp_copysign(double __x, double __y) _NOEXCEPT { - return __builtin_copysign(__x, __y); -} - -_LIBCPP_CONSTEXPR -inline _LIBCPP_HIDE_FROM_ABI long double __libcpp_copysign(long double __x, long double __y) _NOEXCEPT { - return __builtin_copysignl(__x, __y); -} - -template -_LIBCPP_CONSTEXPR -inline _LIBCPP_HIDE_FROM_ABI -typename std::__enable_if_t -< - std::is_arithmetic<_A1>::value && - std::is_arithmetic<_A2>::value, - std::__promote<_A1, _A2> ->::type -__libcpp_copysign(_A1 __x, _A2 __y) _NOEXCEPT { - typedef typename std::__promote<_A1, _A2>::type __result_type; - static_assert((!(std::_IsSame<_A1, __result_type>::value && - std::_IsSame<_A2, __result_type>::value)), ""); - return __builtin_copysign((__result_type)__x, (__result_type)__y); -} - inline _LIBCPP_HIDE_FROM_ABI float copysign(float __x, float __y) _NOEXCEPT { - return ::__libcpp_copysign(__x, __y); + return ::__builtin_copysignf(__x, __y); } inline _LIBCPP_HIDE_FROM_ABI long double copysign(long double __x, long double __y) _NOEXCEPT { - return ::__libcpp_copysign(__x, __y); + return ::__builtin_copysignl(__x, __y); } template @@ -1076,7 +1045,7 @@ std::__promote<_A1, _A2> >::type copysign(_A1 __x, _A2 __y) _NOEXCEPT { - return ::__libcpp_copysign(__x, __y); + return ::__builtin_copysign(__x, __y); } // erf diff --git a/libcxx/include/version b/libcxx/include/version --- a/libcxx/include/version +++ b/libcxx/include/version @@ -317,7 +317,7 @@ # endif # define __cpp_lib_concepts 202002L # define __cpp_lib_constexpr_algorithms 201806L -// # define __cpp_lib_constexpr_complex 201711L +# define __cpp_lib_constexpr_complex 201711L # define __cpp_lib_constexpr_dynamic_alloc 201907L # define __cpp_lib_constexpr_functional 201907L # define __cpp_lib_constexpr_iterator 201811L diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/complex.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/complex.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/complex.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/complex.version.compile.pass.cpp @@ -68,17 +68,11 @@ # error "__cpp_lib_complex_udls should have the value 201309L in c++20" # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_constexpr_complex -# error "__cpp_lib_constexpr_complex should be defined in c++20" -# endif -# if __cpp_lib_constexpr_complex != 201711L -# error "__cpp_lib_constexpr_complex should have the value 201711L in c++20" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_constexpr_complex -# error "__cpp_lib_constexpr_complex should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_constexpr_complex +# error "__cpp_lib_constexpr_complex should be defined in c++20" +# endif +# if __cpp_lib_constexpr_complex != 201711L +# error "__cpp_lib_constexpr_complex should have the value 201711L in c++20" # endif #elif TEST_STD_VER > 20 @@ -90,17 +84,11 @@ # error "__cpp_lib_complex_udls should have the value 201309L in c++2b" # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_constexpr_complex -# error "__cpp_lib_constexpr_complex should be defined in c++2b" -# endif -# if __cpp_lib_constexpr_complex != 201711L -# error "__cpp_lib_constexpr_complex should have the value 201711L in c++2b" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_constexpr_complex -# error "__cpp_lib_constexpr_complex should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_constexpr_complex +# error "__cpp_lib_constexpr_complex should be defined in c++2b" +# endif +# if __cpp_lib_constexpr_complex != 201711L +# error "__cpp_lib_constexpr_complex should have the value 201711L in c++2b" # endif #endif // TEST_STD_VER > 20 diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp @@ -2705,17 +2705,11 @@ # error "__cpp_lib_constexpr_cmath should not be defined before c++2b" # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_constexpr_complex -# error "__cpp_lib_constexpr_complex should be defined in c++20" -# endif -# if __cpp_lib_constexpr_complex != 201711L -# error "__cpp_lib_constexpr_complex should have the value 201711L in c++20" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_constexpr_complex -# error "__cpp_lib_constexpr_complex should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_constexpr_complex +# error "__cpp_lib_constexpr_complex should be defined in c++20" +# endif +# if __cpp_lib_constexpr_complex != 201711L +# error "__cpp_lib_constexpr_complex should have the value 201711L in c++20" # endif # ifndef __cpp_lib_constexpr_dynamic_alloc @@ -3931,17 +3925,11 @@ # endif # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_constexpr_complex -# error "__cpp_lib_constexpr_complex should be defined in c++2b" -# endif -# if __cpp_lib_constexpr_complex != 201711L -# error "__cpp_lib_constexpr_complex should have the value 201711L in c++2b" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_constexpr_complex -# error "__cpp_lib_constexpr_complex should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_constexpr_complex +# error "__cpp_lib_constexpr_complex should be defined in c++2b" +# endif +# if __cpp_lib_constexpr_complex != 201711L +# error "__cpp_lib_constexpr_complex should have the value 201711L in c++2b" # endif # ifndef __cpp_lib_constexpr_dynamic_alloc diff --git a/libcxx/test/std/numerics/complex.number/cases.h b/libcxx/test/std/numerics/complex.number/cases.h --- a/libcxx/test/std/numerics/complex.number/cases.h +++ b/libcxx/test/std/numerics/complex.number/cases.h @@ -13,10 +13,13 @@ #ifndef CASES_H #define CASES_H -#include #include +#include +#include -const std::complex testcases[] = +#include "test_macros.h" + +TEST_CONSTEXPR_CXX20 const std::complex testcases[] = { std::complex( 1.e-6, 1.e-6), std::complex(-1.e-6, 1.e-6), @@ -191,23 +194,34 @@ enum {zero, non_zero, inf, NaN, non_zero_nan}; +template ::value, int>::type = 0> +TEST_CONSTEXPR_CXX20 bool test_isinf(T v) { + return v == std::numeric_limits::infinity() || v == -std::numeric_limits::infinity(); +} + +template ::value, int>::type = 0> +TEST_CONSTEXPR_CXX20 bool test_isnan(T v) { + return v != v; +} + template +TEST_CONSTEXPR_CXX20 int classify(const std::complex& x) { if (x == std::complex()) return zero; - if (std::isinf(x.real()) || std::isinf(x.imag())) + if (test_isinf(x.real()) || test_isinf(x.imag())) return inf; - if (std::isnan(x.real()) && std::isnan(x.imag())) + if (test_isnan(x.real()) && test_isnan(x.imag())) return NaN; - if (std::isnan(x.real())) + if (test_isnan(x.real())) { if (x.imag() == T(0)) return NaN; return non_zero_nan; } - if (std::isnan(x.imag())) + if (test_isnan(x.imag())) { if (x.real() == T(0)) return NaN; diff --git a/libcxx/test/std/numerics/complex.number/cmplx.over/conj.pass.cpp b/libcxx/test/std/numerics/complex.number/cmplx.over/conj.pass.cpp --- a/libcxx/test/std/numerics/complex.number/cmplx.over/conj.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/cmplx.over/conj.pass.cpp @@ -8,11 +8,11 @@ // -// template complex conj(const complex&); -// complex conj(long double); -// complex conj(double); -// template complex conj(T); -// complex conj(float); +// template complex conj(const complex&); // constexpr in C++20 +// complex conj(long double); // constexpr in C++20 +// complex conj(double); // constexpr in C++20 +// template complex conj(T); // constexpr in C++20 +// complex conj(float); // constexpr in C++20 #include #include @@ -22,6 +22,7 @@ #include "../cases.h" template +TEST_CONSTEXPR_CXX20 void test(T x, typename std::enable_if::value>::type* = 0) { @@ -30,6 +31,7 @@ } template +TEST_CONSTEXPR_CXX20 void test(T x, typename std::enable_if::value>::type* = 0) { @@ -38,6 +40,7 @@ } template +TEST_CONSTEXPR_CXX20 void test(T x, typename std::enable_if::value && !std::is_floating_point::value>::type* = 0) @@ -47,12 +50,14 @@ } template -void +TEST_CONSTEXPR_CXX20 +bool test() { test(0); test(1); test(10); + return true; } int main(int, char**) @@ -64,5 +69,14 @@ test(); test(); - return 0; +#if TEST_STD_VER >= 20 + static_assert(test()); + static_assert(test()); + static_assert(test()); + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif + + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/cmplx.over/norm.pass.cpp b/libcxx/test/std/numerics/complex.number/cmplx.over/norm.pass.cpp --- a/libcxx/test/std/numerics/complex.number/cmplx.over/norm.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/cmplx.over/norm.pass.cpp @@ -10,7 +10,7 @@ // template // T -// norm(T x); +// norm(T x); // constexpr in C++20 #include #include @@ -20,6 +20,7 @@ #include "../cases.h" template +TEST_CONSTEXPR_CXX20 void test(T x, typename std::enable_if::value>::type* = 0) { @@ -28,6 +29,7 @@ } template +TEST_CONSTEXPR_CXX20 void test(T x, typename std::enable_if::value>::type* = 0) { @@ -36,12 +38,14 @@ } template -void +TEST_CONSTEXPR_CXX20 +bool test() { test(0); test(1); test(10); + return true; } int main(int, char**) @@ -53,5 +57,14 @@ test(); test(); - return 0; +#if TEST_STD_VER >= 20 + static_assert(test()); + static_assert(test()); + static_assert(test()); + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif + + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.member.ops/assignment_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.member.ops/assignment_complex.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.member.ops/assignment_complex.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.member.ops/assignment_complex.pass.cpp @@ -9,7 +9,7 @@ // // complex& operator=(const complex&); -// template complex& operator= (const complex&); +// template complex& operator= (const complex&); // constexpr in C++20 #include #include @@ -17,7 +17,8 @@ #include "test_macros.h" template -void +TEST_CONSTEXPR_CXX20 +bool test() { std::complex c; @@ -31,6 +32,7 @@ c = c3; assert(c.real() == 3.5); assert(c.imag() == -4.5); + return true; } int main(int, char**) @@ -47,5 +49,19 @@ test(); test(); +#if TEST_STD_VER >= 20 + static_assert(test()); + static_assert(test()); + static_assert(test()); + + static_assert(test()); + static_assert(test()); + static_assert(test()); + + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.member.ops/assignment_scalar.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.member.ops/assignment_scalar.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.member.ops/assignment_scalar.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.member.ops/assignment_scalar.pass.cpp @@ -8,7 +8,7 @@ // -// complex& operator= (const T&); +// complex& operator= (const T&); // constexpr in C++20 #include #include @@ -16,7 +16,8 @@ #include "test_macros.h" template -void +TEST_CONSTEXPR_CXX20 +bool test() { std::complex c; @@ -28,6 +29,7 @@ c = -1.5; assert(c.real() == -1.5); assert(c.imag() == 0); + return true; } int main(int, char**) @@ -36,5 +38,11 @@ test(); test(); +#if TEST_STD_VER >= 20 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_complex.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_complex.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_complex.pass.cpp @@ -8,7 +8,7 @@ // -// complex& operator/=(const complex& rhs); +// complex& operator/=(const complex& rhs); // constexpr in C++20 #include #include @@ -16,7 +16,8 @@ #include "test_macros.h" template -void +TEST_CONSTEXPR_CXX20 +bool test() { std::complex c(-4, 7.5); @@ -35,15 +36,15 @@ c3 = c; std::complex ic (1,1); c3 /= ic; - assert(c3.real() == 0.5); + assert(c3.real() == 0.5); assert(c3.imag() == -0.5); c3 = c; std::complex fc (1,1); c3 /= fc; - assert(c3.real() == 0.5); + assert(c3.real() == 0.5); assert(c3.imag() == -0.5); - + return true; } int main(int, char**) @@ -52,5 +53,11 @@ test(); test(); - return 0; +#if TEST_STD_VER >= 20 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif + + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_scalar.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_scalar.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_scalar.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_scalar.pass.cpp @@ -8,7 +8,7 @@ // -// complex& operator/=(const T& rhs); +// complex& operator/=(const T& rhs); // constexpr in C++20 #include #include @@ -16,7 +16,8 @@ #include "test_macros.h" template -void +TEST_CONSTEXPR_CXX20 +bool test() { std::complex c(1); @@ -35,6 +36,7 @@ c /= 0.5; assert(c.real() == -16); assert(c.imag() == 4); + return true; } int main(int, char**) @@ -43,5 +45,11 @@ test(); test(); +#if TEST_STD_VER >= 20 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.member.ops/minus_equal_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.member.ops/minus_equal_complex.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.member.ops/minus_equal_complex.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.member.ops/minus_equal_complex.pass.cpp @@ -8,7 +8,7 @@ // -// complex& operator-=(const complex& rhs); +// complex& operator-=(const complex& rhs); // constexpr in C++20 #include #include @@ -16,7 +16,8 @@ #include "test_macros.h" template -void +TEST_CONSTEXPR_CXX20 +bool test() { std::complex c; @@ -43,6 +44,7 @@ c3 -= fc; assert(c3.real() == -4); assert(c3.imag() == -6); + return true; } int main(int, char**) @@ -51,5 +53,11 @@ test(); test(); - return 0; +#if TEST_STD_VER >= 20 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif + + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.member.ops/minus_equal_scalar.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.member.ops/minus_equal_scalar.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.member.ops/minus_equal_scalar.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.member.ops/minus_equal_scalar.pass.cpp @@ -8,7 +8,7 @@ // -// complex& operator-=(const T& rhs); +// complex& operator-=(const T& rhs); // constexpr in C++20 #include #include @@ -16,7 +16,8 @@ #include "test_macros.h" template -void +TEST_CONSTEXPR_CXX20 +bool test() { std::complex c; @@ -31,6 +32,7 @@ c -= -1.5; assert(c.real() == -1.5); assert(c.imag() == 0); + return true; } int main(int, char**) @@ -39,5 +41,11 @@ test(); test(); +#if TEST_STD_VER >= 20 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.member.ops/plus_equal_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.member.ops/plus_equal_complex.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.member.ops/plus_equal_complex.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.member.ops/plus_equal_complex.pass.cpp @@ -8,7 +8,7 @@ // -// complex& operator+=(const complex& rhs); +// complex& operator+=(const complex& rhs); // constexpr in C++20 #include #include @@ -16,7 +16,8 @@ #include "test_macros.h" template -void +TEST_CONSTEXPR_CXX20 +bool test() { std::complex c; @@ -43,6 +44,7 @@ c3 += fc; assert(c3.real() == 4); assert(c3.imag() == 6); + return true; } int main(int, char**) @@ -51,5 +53,11 @@ test(); test(); - return 0; +#if TEST_STD_VER >= 20 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif + + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.member.ops/plus_equal_scalar.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.member.ops/plus_equal_scalar.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.member.ops/plus_equal_scalar.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.member.ops/plus_equal_scalar.pass.cpp @@ -8,7 +8,7 @@ // -// complex& operator+=(const T& rhs); +// complex& operator+=(const T& rhs); // constexpr in C++20 #include #include @@ -16,7 +16,8 @@ #include "test_macros.h" template -void +TEST_CONSTEXPR_CXX20 +bool test() { std::complex c; @@ -31,6 +32,7 @@ c += -1.5; assert(c.real() == 1.5); assert(c.imag() == 0); + return true; } int main(int, char**) @@ -39,5 +41,11 @@ test(); test(); +#if TEST_STD_VER >= 20 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.member.ops/times_equal_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.member.ops/times_equal_complex.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.member.ops/times_equal_complex.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.member.ops/times_equal_complex.pass.cpp @@ -8,7 +8,7 @@ // -// complex& operator*=(const complex& rhs); +// complex& operator*=(const complex& rhs); // constexpr in C++20 #include #include @@ -16,7 +16,8 @@ #include "test_macros.h" template -void +TEST_CONSTEXPR_CXX20 +bool test() { std::complex c(1); @@ -36,13 +37,14 @@ std::complex ic (1,1); c3 *= ic; assert(c3.real() == -11.5); - assert(c3.imag() == 3.5); + assert(c3.imag() == 3.5); c3 = c; std::complex fc (1,1); c3 *= fc; assert(c3.real() == -11.5); - assert(c3.imag() == 3.5); + assert(c3.imag() == 3.5); + return true; } int main(int, char**) @@ -51,5 +53,11 @@ test(); test(); - return 0; +#if TEST_STD_VER >= 20 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif + + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.member.ops/times_equal_scalar.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.member.ops/times_equal_scalar.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.member.ops/times_equal_scalar.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.member.ops/times_equal_scalar.pass.cpp @@ -8,7 +8,7 @@ // -// complex& operator*=(const T& rhs); +// complex& operator*=(const T& rhs); // constexpr in C++20 #include #include @@ -16,7 +16,8 @@ #include "test_macros.h" template -void +TEST_CONSTEXPR_CXX20 +bool test() { std::complex c(1); @@ -35,6 +36,7 @@ c *= 1.5; assert(c.real() == -5.0625); assert(c.imag() == 3); + return true; } int main(int, char**) @@ -43,5 +45,11 @@ test(); test(); +#if TEST_STD_VER >= 20 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.members/real_imag.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.members/real_imag.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.members/real_imag.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.members/real_imag.pass.cpp @@ -8,8 +8,8 @@ // -// void real(T val); -// void imag(T val); +// void real(T val); // constexpr in C++20 +// void imag(T val); // constexpr in C++20 #include #include @@ -17,6 +17,7 @@ #include "test_macros.h" template +TEST_CONSTEXPR_CXX20 void test_constexpr() { @@ -34,7 +35,8 @@ } template -void +TEST_CONSTEXPR_CXX20 +bool test() { std::complex c; @@ -53,15 +55,21 @@ assert(c.real() == -4.5); assert(c.imag() == -5.5); - test_constexpr (); + test_constexpr(); + return true; } -int main(int, char**) -{ +int main(int, char**) { test(); test(); test(); - test_constexpr (); + test_constexpr(); + +#if TEST_STD_VER >= 20 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_complex.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_complex.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_complex.pass.cpp @@ -10,7 +10,9 @@ // template // complex -// operator/(const complex& lhs, const complex& rhs); +// operator/(const complex& lhs, const complex& rhs); // constexpr in C++20 + +// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=5000000 #include #include @@ -19,135 +21,128 @@ #include "../cases.h" template -void -test(const std::complex& lhs, const std::complex& rhs, std::complex x) -{ - assert(lhs / rhs == x); -} - -template -void +TEST_CONSTEXPR_CXX20 +bool test() { - std::complex lhs(-4.0, 7.5); - std::complex rhs(1.5, 2.5); - std::complex x(1.5, 2.5); - test(lhs, rhs, x); + const std::complex lhs(-4.0, 7.5); + const std::complex rhs(1.5, 2.5); + assert(lhs / rhs == std::complex(1.5, 2.5)); + return true; } -void test_edges() +TEST_CONSTEXPR_CXX20 +bool +test_edges() { - const unsigned N = sizeof(testcases) / sizeof(testcases[0]); - for (unsigned i = 0; i < N; ++i) - { - for (unsigned j = 0; j < N; ++j) - { - std::complex r = testcases[i] / testcases[j]; - switch (classify(testcases[i])) - { - case zero: - switch (classify(testcases[j])) - { - case zero: - assert(classify(r) == NaN); - break; - case non_zero: - assert(classify(r) == zero); - break; - case inf: - assert(classify(r) == zero); - break; - case NaN: - assert(classify(r) == NaN); - break; - case non_zero_nan: - assert(classify(r) == NaN); - break; - } - break; - case non_zero: - switch (classify(testcases[j])) - { - case zero: - assert(classify(r) == inf); - break; - case non_zero: - assert(classify(r) == non_zero); - break; - case inf: - assert(classify(r) == zero); - break; - case NaN: - assert(classify(r) == NaN); - break; - case non_zero_nan: - assert(classify(r) == NaN); - break; - } - break; - case inf: - switch (classify(testcases[j])) - { - case zero: - assert(classify(r) == inf); - break; - case non_zero: - assert(classify(r) == inf); - break; - case inf: - assert(classify(r) == NaN); - break; - case NaN: - assert(classify(r) == NaN); - break; - case non_zero_nan: - assert(classify(r) == NaN); - break; - } - break; - case NaN: - switch (classify(testcases[j])) - { - case zero: - assert(classify(r) == NaN); - break; - case non_zero: - assert(classify(r) == NaN); - break; - case inf: - assert(classify(r) == NaN); - break; - case NaN: - assert(classify(r) == NaN); - break; - case non_zero_nan: - assert(classify(r) == NaN); - break; - } - break; - case non_zero_nan: - switch (classify(testcases[j])) - { - case zero: - assert(classify(r) == inf); - break; - case non_zero: - assert(classify(r) == NaN); - break; - case inf: - assert(classify(r) == NaN); - break; - case NaN: - assert(classify(r) == NaN); - break; - case non_zero_nan: - assert(classify(r) == NaN); - break; - } - break; - } + const unsigned N = sizeof(testcases) / sizeof(testcases[0]); + int classification[N]; + for (unsigned i=0; i < N; ++i) + classification[i] = classify(testcases[i]); + + for (unsigned i = 0; i < N; ++i) { + for (unsigned j = 0; j < N; ++j) { + std::complex r = testcases[i] / testcases[j]; + switch (classification[i]) { + case zero: + switch (classification[j]) { + case zero: + assert(classify(r) == NaN); + break; + case non_zero: + assert(classify(r) == zero); + break; + case inf: + assert(classify(r) == zero); + break; + case NaN: + assert(classify(r) == NaN); + break; + case non_zero_nan: + assert(classify(r) == NaN); + break; } + break; + case non_zero: + switch (classification[j]) { + case zero: + assert(classify(r) == inf); + break; + case non_zero: + assert(classify(r) == non_zero); + break; + case inf: + assert(classify(r) == zero); + break; + case NaN: + assert(classify(r) == NaN); + break; + case non_zero_nan: + assert(classify(r) == NaN); + break; + } + break; + case inf: + switch (classification[j]) { + case zero: + assert(classify(r) == inf); + break; + case non_zero: + assert(classify(r) == inf); + break; + case inf: + assert(classify(r) == NaN); + break; + case NaN: + assert(classify(r) == NaN); + break; + case non_zero_nan: + assert(classify(r) == NaN); + break; + } + break; + case NaN: + switch (classification[j]) { + case zero: + assert(classify(r) == NaN); + break; + case non_zero: + assert(classify(r) == NaN); + break; + case inf: + assert(classify(r) == NaN); + break; + case NaN: + assert(classify(r) == NaN); + break; + case non_zero_nan: + assert(classify(r) == NaN); + break; + } + break; + case non_zero_nan: + switch (classification[j]) { + case zero: + assert(classify(r) == inf); + break; + case non_zero: + assert(classify(r) == NaN); + break; + case inf: + assert(classify(r) == NaN); + break; + case NaN: + assert(classify(r) == NaN); + break; + case non_zero_nan: + assert(classify(r) == NaN); + break; + } + break; + } } + } + return true; } int main(int, char**) @@ -157,5 +152,12 @@ test(); test_edges(); - return 0; +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); + static_assert(test_edges()); +#endif + + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_scalar.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_scalar.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_scalar.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_scalar.pass.cpp @@ -10,7 +10,7 @@ // template // complex -// operator/(const complex& lhs, const T& rhs); +// operator/(const complex& lhs, const T& rhs); // constexpr in C++20 #include #include @@ -18,20 +18,14 @@ #include "test_macros.h" template -void -test(const std::complex& lhs, const T& rhs, std::complex x) -{ - assert(lhs / rhs == x); -} - -template -void +TEST_CONSTEXPR_CXX20 +bool test() { - std::complex lhs(-4.0, 7.5); - T rhs(2); - std::complex x(-2, 3.75); - test(lhs, rhs, x); + const std::complex lhs(-4.0, 7.5); + const T rhs(2); + assert(lhs / rhs == std::complex(-2, 3.75)); + return true; } int main(int, char**) @@ -40,5 +34,11 @@ test(); test(); - return 0; +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif + + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_equals_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_equals_complex.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_equals_complex.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_equals_complex.pass.cpp @@ -18,25 +18,8 @@ #include "test_macros.h" template -void -test_constexpr() -{ -#if TEST_STD_VER > 11 - { - constexpr std::complex lhs(1.5, 2.5); - constexpr std::complex rhs(1.5, -2.5); - static_assert( !(lhs == rhs), ""); - } - { - constexpr std::complex lhs(1.5, 2.5); - constexpr std::complex rhs(1.5, 2.5); - static_assert(lhs == rhs, ""); - } -#endif -} - -template -void +TEST_CONSTEXPR_CXX20 +bool test() { { @@ -49,7 +32,7 @@ std::complex rhs(1.5, 2.5); assert(lhs == rhs); } - test_constexpr (); + return true; } int main(int, char**) @@ -57,7 +40,11 @@ test(); test(); test(); -// test_constexpr (); +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_equals_scalar.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_equals_scalar.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_equals_scalar.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_equals_scalar.pass.cpp @@ -18,6 +18,7 @@ #include "test_macros.h" template +TEST_CONSTEXPR_CXX20 void test_constexpr() { @@ -46,7 +47,8 @@ } template -void +TEST_CONSTEXPR_CXX20 +bool test() { { @@ -71,14 +73,20 @@ } test_constexpr (); - } + return true; +} int main(int, char**) { test(); test(); test(); -// test_constexpr (); + +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_minus_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_minus_complex.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_minus_complex.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_minus_complex.pass.cpp @@ -10,7 +10,7 @@ // template // complex -// operator-(const complex& lhs, const complex& rhs); +// operator-(const complex& lhs, const complex& rhs); // constexpr in C++20 #include #include @@ -18,28 +18,21 @@ #include "test_macros.h" template -void -test(const std::complex& lhs, const std::complex& rhs, std::complex x) -{ - assert(lhs - rhs == x); -} - -template -void +TEST_CONSTEXPR_CXX20 +bool test() { { - std::complex lhs(1.5, 2.5); - std::complex rhs(3.5, 4.5); - std::complex x(-2.0, -2.0); - test(lhs, rhs, x); + const std::complex lhs(1.5, 2.5); + const std::complex rhs(3.5, 4.5); + assert(lhs - rhs == std::complex(-2.0, -2.0)); } { - std::complex lhs(1.5, -2.5); - std::complex rhs(-3.5, 4.5); - std::complex x(5.0, -7.0); - test(lhs, rhs, x); + const std::complex lhs(1.5, -2.5); + const std::complex rhs(-3.5, 4.5); + assert(lhs - rhs == std::complex(5.0, -7.0)); } + return true; } int main(int, char**) @@ -48,5 +41,11 @@ test(); test(); +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_minus_scalar.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_minus_scalar.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_minus_scalar.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_minus_scalar.pass.cpp @@ -10,7 +10,7 @@ // template // complex -// operator-(const complex& lhs, const T& rhs); +// operator-(const complex& lhs, const T& rhs); // constexpr in C++20 #include #include @@ -18,28 +18,21 @@ #include "test_macros.h" template -void -test(const std::complex& lhs, const T& rhs, std::complex x) -{ - assert(lhs - rhs == x); -} - -template -void +TEST_CONSTEXPR_CXX20 +bool test() { { - std::complex lhs(1.5, 2.5); - T rhs(3.5); - std::complex x(-2.0, 2.5); - test(lhs, rhs, x); + const std::complex lhs(1.5, 2.5); + const T rhs(3.5); + assert(lhs - rhs == std::complex(-2.0, 2.5)); } { - std::complex lhs(1.5, -2.5); - T rhs(-3.5); - std::complex x(5.0, -2.5); - test(lhs, rhs, x); + const std::complex lhs(1.5, -2.5); + const T rhs(-3.5); + assert(lhs - rhs == std::complex(5.0, -2.5)); } + return true; } int main(int, char**) @@ -48,5 +41,11 @@ test(); test(); +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_not_equals_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_not_equals_complex.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_not_equals_complex.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_not_equals_complex.pass.cpp @@ -18,6 +18,7 @@ #include "test_macros.h" template +TEST_CONSTEXPR_CXX20 void test_constexpr() { @@ -35,31 +36,37 @@ #endif } - template -void +TEST_CONSTEXPR_CXX20 +bool test() { { - std::complex lhs(1.5, 2.5); - std::complex rhs(1.5, -2.5); + const std::complex lhs(1.5, 2.5); + const std::complex rhs(1.5, -2.5); assert(lhs != rhs); } { - std::complex lhs(1.5, 2.5); - std::complex rhs(1.5, 2.5); + const std::complex lhs(1.5, 2.5); + const std::complex rhs(1.5, 2.5); assert(!(lhs != rhs)); } test_constexpr (); - } + return true; +} int main(int, char**) { test(); test(); test(); -// test_constexpr (); + +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_not_equals_scalar.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_not_equals_scalar.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_not_equals_scalar.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_not_equals_scalar.pass.cpp @@ -18,6 +18,7 @@ #include "test_macros.h" template +TEST_CONSTEXPR_CXX20 void test_constexpr() { @@ -46,7 +47,8 @@ } template -void +TEST_CONSTEXPR_CXX20 +bool test() { { @@ -71,6 +73,7 @@ } test_constexpr (); + return true; } int main(int, char**) @@ -78,7 +81,12 @@ test(); test(); test(); -// test_constexpr (); + +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_plus_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_plus_complex.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_plus_complex.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_plus_complex.pass.cpp @@ -10,7 +10,7 @@ // template // complex -// operator+(const complex& lhs, const complex& rhs); +// operator+(const complex& lhs, const complex& rhs); // constexpr in C++20 #include #include @@ -18,28 +18,22 @@ #include "test_macros.h" template -void -test(const std::complex& lhs, const std::complex& rhs, std::complex x) -{ - assert(lhs + rhs == x); -} - -template -void +TEST_CONSTEXPR_CXX20 +bool test() { { - std::complex lhs(1.5, 2.5); - std::complex rhs(3.5, 4.5); - std::complex x(5.0, 7.0); - test(lhs, rhs, x); + const std::complex lhs(1.5, 2.5); + const std::complex rhs(3.5, 4.5); + assert(lhs + rhs == std::complex(5.0, 7.0)); } { - std::complex lhs(1.5, -2.5); - std::complex rhs(-3.5, 4.5); - std::complex x(-2.0, 2.0); - test(lhs, rhs, x); + const std::complex lhs(1.5, -2.5); + const std::complex rhs(-3.5, 4.5); + assert(lhs + rhs == std::complex(-2.0, 2.0)); } + + return true; } int main(int, char**) @@ -48,5 +42,11 @@ test(); test(); +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_plus_scalar.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_plus_scalar.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_plus_scalar.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_plus_scalar.pass.cpp @@ -10,7 +10,7 @@ // template // complex -// operator+(const complex& lhs, const T& rhs); +// operator+(const complex& lhs, const T& rhs); // constexpr in C++20 #include #include @@ -18,28 +18,22 @@ #include "test_macros.h" template -void -test(const std::complex& lhs, const T& rhs, std::complex x) -{ - assert(lhs + rhs == x); -} - -template -void +TEST_CONSTEXPR_CXX20 +bool test() { { - std::complex lhs(1.5, 2.5); - T rhs(3.5); - std::complex x(5.0, 2.5); - test(lhs, rhs, x); + const std::complex lhs(1.5, 2.5); + const T rhs(3.5); + assert(lhs + rhs == std::complex(5.0, 2.5)); } { - std::complex lhs(1.5, -2.5); - T rhs(-3.5); - std::complex x(-2.0, -2.5); - test(lhs, rhs, x); + const std::complex lhs(1.5, -2.5); + const T rhs(-3.5); + assert(lhs + rhs == std::complex(-2.0, -2.5)); } + + return true; } int main(int, char**) @@ -48,5 +42,11 @@ test(); test(); +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_times_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_times_complex.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_times_complex.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_times_complex.pass.cpp @@ -10,7 +10,9 @@ // template // complex -// operator*(const complex& lhs, const complex& rhs); +// operator*(const complex& lhs, const complex& rhs); // constexpr in C++20 + +// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=5000000 #include #include @@ -19,56 +21,48 @@ #include "../cases.h" template -void -test(const std::complex& lhs, const std::complex& rhs, std::complex x) -{ - assert(lhs * rhs == x); -} - -template -void +TEST_CONSTEXPR_CXX20 +bool test() { - std::complex lhs(1.5, 2.5); - std::complex rhs(1.5, 2.5); - std::complex x(-4.0, 7.5); - test(lhs, rhs, x); + const std::complex lhs(1.5, 2.5); + const std::complex rhs(1.5, 2.5); + assert(lhs * rhs == std::complex(-4.0, 7.5)); + return true; } // test edges -void test_edges() +TEST_CONSTEXPR_CXX20 bool test_edges() { const unsigned N = sizeof(testcases) / sizeof(testcases[0]); + int classification[N]; + for (unsigned i=0; i < N; ++i) + classification[i] = classify(testcases[i]); + for (unsigned i = 0; i < N; ++i) { for (unsigned j = 0; j < N; ++j) { std::complex r = testcases[i] * testcases[j]; - switch (classify(testcases[i])) + switch (classification[i]) { case zero: - switch (classify(testcases[j])) + switch (classification[j]) { case zero: - assert(classify(r) == zero); - break; case non_zero: assert(classify(r) == zero); break; case inf: - assert(classify(r) == NaN); - break; case NaN: - assert(classify(r) == NaN); - break; case non_zero_nan: assert(classify(r) == NaN); break; } break; case non_zero: - switch (classify(testcases[j])) + switch (classification[j]) { case zero: assert(classify(r) == zero); @@ -80,68 +74,37 @@ assert(classify(r) == inf); break; case NaN: - assert(classify(r) == NaN); - break; case non_zero_nan: assert(classify(r) == NaN); break; } break; case inf: - switch (classify(testcases[j])) + switch (classification[j]) { case zero: + case NaN: assert(classify(r) == NaN); break; case non_zero: - assert(classify(r) == inf); - break; case inf: - assert(classify(r) == inf); - break; - case NaN: - assert(classify(r) == NaN); - break; case non_zero_nan: assert(classify(r) == inf); break; } break; case NaN: - switch (classify(testcases[j])) - { - case zero: - assert(classify(r) == NaN); - break; - case non_zero: - assert(classify(r) == NaN); - break; - case inf: - assert(classify(r) == NaN); - break; - case NaN: - assert(classify(r) == NaN); - break; - case non_zero_nan: - assert(classify(r) == NaN); - break; - } + assert(classify(r) == NaN); break; case non_zero_nan: - switch (classify(testcases[j])) + switch (classification[j]) { - case zero: - assert(classify(r) == NaN); - break; - case non_zero: - assert(classify(r) == NaN); - break; case inf: assert(classify(r) == inf); break; + case zero: + case non_zero: case NaN: - assert(classify(r) == NaN); - break; case non_zero_nan: assert(classify(r) == NaN); break; @@ -150,6 +113,7 @@ } } } + return true; } int main(int, char**) @@ -159,5 +123,12 @@ test(); test_edges(); +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); + static_assert(test_edges()); +#endif + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_times_scalar.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_times_scalar.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_times_scalar.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_times_scalar.pass.cpp @@ -10,7 +10,7 @@ // template // complex -// operator*(const complex& lhs, const T& rhs); +// operator*(const complex& lhs, const T& rhs); // constexpr in C++20 #include #include @@ -18,20 +18,14 @@ #include "test_macros.h" template -void -test(const std::complex& lhs, const T& rhs, std::complex x) -{ - assert(lhs * rhs == x); -} - -template -void +TEST_CONSTEXPR_CXX20 +bool test() { - std::complex lhs(1.5, 2.5); - T rhs(1.5); - std::complex x(2.25, 3.75); - test(lhs, rhs, x); + const std::complex lhs(1.5, 2.5); + const T rhs(1.5); + assert(lhs * rhs == std::complex(2.25, 3.75)); + return true; } int main(int, char**) @@ -40,5 +34,11 @@ test(); test(); +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_divide_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_divide_complex.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_divide_complex.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_divide_complex.pass.cpp @@ -10,7 +10,7 @@ // template // complex -// operator/(const T& lhs, const complex& rhs); +// operator/(const T& lhs, const complex& rhs); // constexpr in C++20 #include #include @@ -18,20 +18,14 @@ #include "test_macros.h" template -void -test(const T& lhs, const std::complex& rhs, std::complex x) -{ - assert(lhs / rhs == x); -} - -template -void +TEST_CONSTEXPR_CXX20 +bool test() { - T lhs(-8.5); - std::complex rhs(1.5, 2.5); - std::complex x(-1.5, 2.5); - test(lhs, rhs, x); + const T lhs(-8.5); + const std::complex rhs(1.5, 2.5); + assert(lhs / rhs == std::complex(-1.5, 2.5)); + return true; } int main(int, char**) @@ -40,5 +34,11 @@ test(); test(); +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_equals_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_equals_complex.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_equals_complex.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_equals_complex.pass.cpp @@ -18,6 +18,7 @@ #include "test_macros.h" template +TEST_CONSTEXPR_CXX20 void test_constexpr() { @@ -46,7 +47,8 @@ } template -void +TEST_CONSTEXPR_CXX20 +bool test() { { @@ -71,6 +73,7 @@ } test_constexpr (); + return true; } int main(int, char**) @@ -78,7 +81,12 @@ test(); test(); test(); -// test_constexpr(); + +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_minus_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_minus_complex.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_minus_complex.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_minus_complex.pass.cpp @@ -10,7 +10,7 @@ // template // complex -// operator-(const T& lhs, const complex& rhs); +// operator-(const T& lhs, const complex& rhs); // constexpr in C++20 #include #include @@ -18,35 +18,33 @@ #include "test_macros.h" template -void -test(const T& lhs, const std::complex& rhs, std::complex x) -{ - assert(lhs - rhs == x); -} - -template -void +TEST_CONSTEXPR_CXX20 +bool test() { { - T lhs(1.5); - std::complex rhs(3.5, 4.5); - std::complex x(-2.0, -4.5); - test(lhs, rhs, x); + const T lhs(1.5); + const std::complex rhs(3.5, 4.5); + assert(lhs - rhs == std::complex(-2.0, -4.5)); } { - T lhs(1.5); - std::complex rhs(-3.5, 4.5); - std::complex x(5.0, -4.5); - test(lhs, rhs, x); + const T lhs(1.5); + const std::complex rhs(-3.5, 4.5); + assert(lhs - rhs == std::complex(5.0, -4.5)); } + return true; } -int main(int, char**) -{ +int main(int, char**) { test(); test(); test(); +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_not_equals_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_not_equals_complex.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_not_equals_complex.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_not_equals_complex.pass.cpp @@ -18,6 +18,7 @@ #include "test_macros.h" template +TEST_CONSTEXPR_CXX20 void test_constexpr() { @@ -46,7 +47,8 @@ } template -void +TEST_CONSTEXPR_CXX20 +bool test() { { @@ -71,14 +73,20 @@ } test_constexpr (); - } + return true; +} int main(int, char**) { test(); test(); test(); -// test_constexpr(); + +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_plus_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_plus_complex.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_plus_complex.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_plus_complex.pass.cpp @@ -10,7 +10,7 @@ // template // complex -// operator+(const T& lhs, const complex& rhs); +// operator+(const T& lhs, const complex& rhs); // constexpr in C++20 #include #include @@ -18,28 +18,21 @@ #include "test_macros.h" template -void -test(const T& lhs, const std::complex& rhs, std::complex x) -{ - assert(lhs + rhs == x); -} - -template -void +TEST_CONSTEXPR_CXX20 +bool test() { { - T lhs(1.5); - std::complex rhs(3.5, 4.5); - std::complex x(5.0, 4.5); - test(lhs, rhs, x); + const T lhs(1.5); + const std::complex rhs(3.5, 4.5); + assert(lhs + rhs == std::complex(5.0, 4.5)); } { - T lhs(1.5); - std::complex rhs(-3.5, 4.5); - std::complex x(-2.0, 4.5); - test(lhs, rhs, x); + const T lhs(1.5); + const std::complex rhs(-3.5, 4.5); + assert(lhs + rhs == std::complex(-2.0, 4.5)); } + return true; } int main(int, char**) @@ -48,5 +41,11 @@ test(); test(); +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_times_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_times_complex.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_times_complex.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_times_complex.pass.cpp @@ -10,7 +10,7 @@ // template // complex -// operator*(const T& lhs, const complex& rhs); +// operator*(const T& lhs, const complex& rhs); // constexpr in C++20 #include #include @@ -18,20 +18,14 @@ #include "test_macros.h" template -void -test(const T& lhs, const std::complex& rhs, std::complex x) -{ - assert(lhs * rhs == x); -} - -template -void +TEST_CONSTEXPR_CXX20 +bool test() { - T lhs(1.5); - std::complex rhs(1.5, 2.5); - std::complex x(2.25, 3.75); - test(lhs, rhs, x); + const T lhs(1.5); + const std::complex rhs(1.5, 2.5); + assert(lhs * rhs == std::complex(2.25, 3.75)); + return true; } int main(int, char**) @@ -40,5 +34,11 @@ test(); test(); +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/unary_minus.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/unary_minus.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.ops/unary_minus.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.ops/unary_minus.pass.cpp @@ -10,7 +10,7 @@ // template // complex -// operator-(const complex& lhs); +// operator-(const complex& lhs); // constexpr in C++20 #include #include @@ -18,15 +18,13 @@ #include "test_macros.h" template -void +TEST_CONSTEXPR_CXX20 +bool test() { - std::complex z(1.5, 2.5); - assert(z.real() == 1.5); - assert(z.imag() == 2.5); - std::complex c = -z; - assert(c.real() == -1.5); - assert(c.imag() == -2.5); + assert(-std::complex(1.5, -2.5) == std::complex(-1.5, 2.5)); + assert(-std::complex(-1.5, 2.5) == std::complex(1.5, -2.5)); + return true; } int main(int, char**) @@ -35,5 +33,11 @@ test(); test(); +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/unary_plus.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/unary_plus.pass.cpp --- a/libcxx/test/std/numerics/complex.number/complex.ops/unary_plus.pass.cpp +++ b/libcxx/test/std/numerics/complex.number/complex.ops/unary_plus.pass.cpp @@ -10,7 +10,7 @@ // template // complex -// operator+(const complex&); +// operator+(const complex&); // constexpr in C++20 #include #include @@ -18,22 +18,26 @@ #include "test_macros.h" template -void +TEST_CONSTEXPR_CXX20 +bool test() { - std::complex z(1.5, 2.5); - assert(z.real() == 1.5); - assert(z.imag() == 2.5); - std::complex c = +z; - assert(c.real() == 1.5); - assert(c.imag() == 2.5); + assert(+std::complex(1.5, -2.5) == std::complex(1.5, -2.5)); + assert(+std::complex(-1.5, 2.5) == std::complex(-1.5, 2.5)); + return true; } int main(int, char**) { - test(); - test(); - test(); + test(); + test(); + test(); + +#if TEST_STD_VER > 17 + static_assert(test()); + static_assert(test()); + static_assert(test()); +#endif return 0; } diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -231,7 +231,6 @@ "name": "__cpp_lib_constexpr_complex", "values": { "c++20": 201711 }, "headers": ["complex"], - "unimplemented": True, }, { "name": "__cpp_lib_constexpr_dynamic_alloc", "values": { "c++20": 201907 },