diff --git a/libcxx/include/__algorithm/inplace_merge.h b/libcxx/include/__algorithm/inplace_merge.h index 1fc31b66f4bd6..fbfe89936d554 100644 --- a/libcxx/include/__algorithm/inplace_merge.h +++ b/libcxx/include/__algorithm/inplace_merge.h @@ -22,6 +22,7 @@ #include <__functional/identity.h> #include <__iterator/iterator_traits.h> #include <__iterator/reverse_iterator.h> +#include <__memory/construct_at.h> #include <__memory/destruct_n.h> #include <__memory/unique_ptr.h> #include <__memory/unique_temporary_buffer.h> @@ -106,13 +107,13 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __buffered_inplace_merg value_type* __p = __buff; for (_BidirectionalIterator __i = __first; __i != __middle; __d.template __incr(), (void)++__i, (void)++__p) - ::new ((void*)__p) value_type(_IterOps<_AlgPolicy>::__iter_move(__i)); + std::__construct_at(__p, _IterOps<_AlgPolicy>::__iter_move(__i)); std::__half_inplace_merge<_AlgPolicy>(__buff, __p, __middle, __last, __first, __comp); } else { value_type* __p = __buff; for (_BidirectionalIterator __i = __middle; __i != __last; __d.template __incr(), (void)++__i, (void)++__p) - ::new ((void*)__p) value_type(_IterOps<_AlgPolicy>::__iter_move(__i)); + std::__construct_at(__p, _IterOps<_AlgPolicy>::__iter_move(__i)); typedef reverse_iterator<_BidirectionalIterator> _RBi; typedef reverse_iterator _Rv; typedef __invert<_Compare> _Inverted; @@ -203,7 +204,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX26 void __inplace_merge( } template -_LIBCPP_HIDE_FROM_ABI void __inplace_merge( +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __inplace_merge( _BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, _Compare&& __comp) { typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; @@ -223,14 +224,14 @@ _LIBCPP_HIDE_FROM_ABI void __inplace_merge( } template -inline _LIBCPP_HIDE_FROM_ABI void inplace_merge( +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void inplace_merge( _BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, _Compare __comp) { std::__inplace_merge<_ClassicAlgPolicy>( std::move(__first), std::move(__middle), std::move(__last), static_cast<__comp_ref_type<_Compare> >(__comp)); } template -inline _LIBCPP_HIDE_FROM_ABI void +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last) { std::inplace_merge(std::move(__first), std::move(__middle), std::move(__last), __less<>()); } diff --git a/libcxx/include/algorithm b/libcxx/include/algorithm index 7dcafbc838edd..aea24e53019cc 100644 --- a/libcxx/include/algorithm +++ b/libcxx/include/algorithm @@ -1609,11 +1609,11 @@ template - void + constexpr void // constexpr since C++26 inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last); template - void + constexpr void // constexpr since C++26 inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Compare comp); template diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge.pass.cpp index 87bf9dc3854b3..fb0d592bca656 100644 --- a/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge.pass.cpp +++ b/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge.pass.cpp @@ -8,116 +8,130 @@ // -// template -// requires ShuffleIterator -// && LessThanComparable -// void -// inplace_merge(Iter first, Iter middle, Iter last); +// template +// constexpr void // constexpr since C++26 +// inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last); #include #include -#include #include #include "count_new.h" +#include "constexpr_random.h" #include "test_iterators.h" #include "test_macros.h" #if TEST_STD_VER >= 11 struct S { - S() : i_(0) {} - S(int i) : i_(i) {} - - S(const S& rhs) : i_(rhs.i_) {} - S( S&& rhs) : i_(rhs.i_) { rhs.i_ = -1; } - - S& operator =(const S& rhs) { i_ = rhs.i_; return *this; } - S& operator =( S&& rhs) { i_ = rhs.i_; rhs.i_ = -2; assert(this != &rhs); return *this; } - S& operator =(int i) { i_ = i; return *this; } - - bool operator <(const S& rhs) const { return i_ < rhs.i_; } - bool operator ==(const S& rhs) const { return i_ == rhs.i_; } - bool operator ==(int i) const { return i_ == i; } - - void set(int i) { i_ = i; } - - int i_; - }; + TEST_CONSTEXPR_CXX26 S() : i_(0) {} + TEST_CONSTEXPR_CXX26 S(int i) : i_(i) {} + + TEST_CONSTEXPR_CXX26 S(const S& rhs) : i_(rhs.i_) {} + TEST_CONSTEXPR_CXX26 S(S&& rhs) : i_(rhs.i_) { rhs.i_ = -1; } + + TEST_CONSTEXPR_CXX26 S& operator=(const S& rhs) { + i_ = rhs.i_; + return *this; + } + TEST_CONSTEXPR_CXX26 S& operator=(S&& rhs) { + i_ = rhs.i_; + rhs.i_ = -2; + assert(this != &rhs); + return *this; + } + TEST_CONSTEXPR_CXX26 S& operator=(int i) { + i_ = i; + return *this; + } + + TEST_CONSTEXPR_CXX26 bool operator<(const S& rhs) const { return i_ < rhs.i_; } + TEST_CONSTEXPR_CXX26 bool operator==(const S& rhs) const { return i_ == rhs.i_; } + TEST_CONSTEXPR_CXX26 bool operator==(int i) const { return i_ == i; } + + TEST_CONSTEXPR_CXX26 void set(int i) { i_ = i; } + + int i_; +}; #endif -std::mt19937 randomness; - -template -void -test_one(unsigned N, unsigned M) -{ - typedef typename std::iterator_traits::value_type value_type; - assert(M <= N); - value_type* ia = new value_type[N]; - for (unsigned i = 0; i < N; ++i) - ia[i] = i; - std::shuffle(ia, ia+N, randomness); - std::sort(ia, ia+M); - std::sort(ia+M, ia+N); - std::inplace_merge(Iter(ia), Iter(ia+M), Iter(ia+N)); - if(N > 0) - { - assert(ia[0] == 0); - assert(ia[N-1] == static_cast(N-1)); - assert(std::is_sorted(ia, ia+N)); - } - delete [] ia; +template +TEST_CONSTEXPR_CXX26 void test_one(unsigned N, unsigned M, RandSrc& randomness) { + assert(M <= N); + + typedef typename std::iterator_traits::value_type value_type; + value_type* ia = new value_type[N]; + for (unsigned i = 0; i < N; ++i) + ia[i] = i; + support::shuffle(ia, ia + N, randomness); + std::sort(ia, ia + M); + std::sort(ia + M, ia + N); + std::inplace_merge(Iter(ia), Iter(ia + M), Iter(ia + N)); + if (N > 0) { + assert(ia[0] == 0); + assert(ia[N - 1] == static_cast(N - 1)); + assert(std::is_sorted(ia, ia + N)); + } + delete[] ia; } -template -void -test(unsigned N) -{ - test_one(N, 0); - test_one(N, N/4); - test_one(N, N/2); - test_one(N, 3*N/4); - test_one(N, N); +template +TEST_CONSTEXPR_CXX26 void test(unsigned N, RandSrc& randomness) { + test_one(N, 0, randomness); + test_one(N, N / 4, randomness); + test_one(N, N / 2, randomness); + test_one(N, 3 * N / 4, randomness); + test_one(N, N, randomness); } -template -void -test() -{ - test_one(0, 0); - test_one(1, 0); - test_one(1, 1); - test_one(2, 0); - test_one(2, 1); - test_one(2, 2); - test_one(3, 0); - test_one(3, 1); - test_one(3, 2); - test_one(3, 3); - test(4); - test(100); - test(1000); +template +TEST_CONSTEXPR_CXX26 void test(RandSrc& randomness) { + test_one(0, 0, randomness); + test_one(1, 0, randomness); + test_one(1, 1, randomness); + test_one(2, 0, randomness); + test_one(2, 1, randomness); + test_one(2, 2, randomness); + test_one(3, 0, randomness); + test_one(3, 1, randomness); + test_one(3, 2, randomness); + test_one(3, 3, randomness); + test(4, randomness); + test(50, randomness); + if (!TEST_IS_CONSTANT_EVALUATED) { // avoid exceeding the constant evaluation step limit + test(100, randomness); + test(1000, randomness); + } } -int main(int, char**) -{ - test >(); - test >(); - test(); +TEST_CONSTEXPR_CXX26 bool test() { + support::simple_random_generator randomness; + + test >(randomness); + test >(randomness); + test(randomness); #if TEST_STD_VER >= 11 - test >(); - test >(); - test(); + test >(randomness); + test >(randomness); + test(randomness); #endif + return true; +} + +int main(int, char**) { + test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif // TEST_STD_VER >= 26 + #if TEST_STD_VER >= 11 && !defined(TEST_HAS_NO_EXCEPTIONS) - { - std::vector vec(150, 3); - getGlobalMemCounter()->throw_after = 0; - std::inplace_merge(vec.begin(), vec.begin() + 100, vec.end()); - assert(std::all_of(vec.begin(), vec.end(), [](int i) { return i == 3; })); - } + if (!TEST_IS_CONSTANT_EVALUATED) { + std::vector vec(150, 3); + getGlobalMemCounter()->throw_after = 0; + std::inplace_merge(vec.begin(), vec.begin() + 100, vec.end()); + assert(std::all_of(vec.begin(), vec.end(), [](int i) { return i == 3; })); + } #endif // TEST_STD_VER >= 11 && !defined(TEST_HAS_NO_EXCEPTIONS) return 0; diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp index bcde2323ad1de..03824df2be2fe 100644 --- a/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp +++ b/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp @@ -8,18 +8,16 @@ // -// template Compare> -// requires ShuffleIterator -// && CopyConstructible -// void -// inplace_merge(Iter first, Iter middle, Iter last, Compare comp); +// template +// constexpr void // constexpr since C++26 +// inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Compare comp); #include #include #include -#include #include +#include "constexpr_random.h" #include "test_macros.h" #if TEST_STD_VER >= 11 @@ -27,149 +25,161 @@ struct indirect_less { template - bool operator()(const P& x, const P& y) const { + TEST_CONSTEXPR_CXX26 bool operator()(const P& x, const P& y) const { return *x < *y; } }; struct S { - S() : i_(0) {} - S(int i) : i_(i) {} + TEST_CONSTEXPR_CXX26 S() : i_(0) {} + TEST_CONSTEXPR_CXX26 S(int i) : i_(i) {} - S(const S& rhs) : i_(rhs.i_) {} - S( S&& rhs) : i_(rhs.i_) { rhs.i_ = -1; } + TEST_CONSTEXPR_CXX26 S(const S& rhs) : i_(rhs.i_) {} + TEST_CONSTEXPR_CXX26 S(S&& rhs) : i_(rhs.i_) { rhs.i_ = -1; } - S& operator =(const S& rhs) { i_ = rhs.i_; return *this; } - S& operator =( S&& rhs) { i_ = rhs.i_; rhs.i_ = -2; assert(this != &rhs); return *this; } - S& operator =(int i) { i_ = i; return *this; } - - bool operator <(const S& rhs) const { return i_ < rhs.i_; } - bool operator >(const S& rhs) const { return i_ > rhs.i_; } - bool operator ==(const S& rhs) const { return i_ == rhs.i_; } - bool operator ==(int i) const { return i_ == i; } + TEST_CONSTEXPR_CXX26 S& operator=(const S& rhs) { + i_ = rhs.i_; + return *this; + } + TEST_CONSTEXPR_CXX26 S& operator=(S&& rhs) { + i_ = rhs.i_; + rhs.i_ = -2; + assert(this != &rhs); + return *this; + } + TEST_CONSTEXPR_CXX26 S& operator=(int i) { + i_ = i; + return *this; + } - void set(int i) { i_ = i; } + TEST_CONSTEXPR_CXX26 bool operator<(const S& rhs) const { return i_ < rhs.i_; } + TEST_CONSTEXPR_CXX26 bool operator>(const S& rhs) const { return i_ > rhs.i_; } + TEST_CONSTEXPR_CXX26 bool operator==(const S& rhs) const { return i_ == rhs.i_; } + TEST_CONSTEXPR_CXX26 bool operator==(int i) const { return i_ == i; } - int i_; - }; + TEST_CONSTEXPR_CXX26 void set(int i) { i_ = i; } + int i_; +}; #endif // TEST_STD_VER >= 11 #include "test_iterators.h" #include "counting_predicates.h" -std::mt19937 randomness; - -template -void -test_one(unsigned N, unsigned M) -{ - assert(M <= N); - typedef typename std::iterator_traits::value_type value_type; - value_type* ia = new value_type[N]; - for (unsigned i = 0; i < N; ++i) - ia[i] = i; - std::shuffle(ia, ia+N, randomness); - std::sort(ia, ia+M, std::greater()); - std::sort(ia+M, ia+N, std::greater()); - binary_counting_predicate, value_type, value_type> pred((std::greater())); - std::inplace_merge(Iter(ia), Iter(ia+M), Iter(ia+N), std::ref(pred)); - if(N > 0) - { - assert(ia[0] == static_cast(N)-1); - assert(ia[N-1] == 0); - assert(std::is_sorted(ia, ia+N, std::greater())); +template +TEST_CONSTEXPR_CXX26 void test_one(unsigned N, unsigned M, RandSrc& randomness) { + assert(M <= N); + typedef typename std::iterator_traits::value_type value_type; + value_type* ia = new value_type[N]; + for (unsigned i = 0; i < N; ++i) + ia[i] = i; + support::shuffle(ia, ia + N, randomness); + std::sort(ia, ia + M, std::greater()); + std::sort(ia + M, ia + N, std::greater()); + binary_counting_predicate, value_type, value_type> pred((std::greater())); + std::inplace_merge(Iter(ia), Iter(ia + M), Iter(ia + N), std::ref(pred)); + if (N > 0) { + assert(ia[0] == static_cast(N) - 1); + assert(ia[N - 1] == 0); + assert(std::is_sorted(ia, ia + N, std::greater())); #if defined(_LIBCPP_HARDENING_MODE) && _LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_DEBUG - assert(pred.count() <= (N-1)); + assert(pred.count() <= (N - 1)); #endif - } - delete [] ia; + } + delete[] ia; } -template -void -test(unsigned N) -{ - test_one(N, 0); - test_one(N, N/4); - test_one(N, N/2); - test_one(N, 3*N/4); - test_one(N, N); +template +TEST_CONSTEXPR_CXX26 void test(unsigned N, RandSrc& randomness) { + test_one(N, 0, randomness); + test_one(N, N / 4, randomness); + test_one(N, N / 2, randomness); + test_one(N, 3 * N / 4, randomness); + test_one(N, N, randomness); } -template -void -test() -{ - test_one(0, 0); - test_one(1, 0); - test_one(1, 1); - test_one(2, 0); - test_one(2, 1); - test_one(2, 2); - test_one(3, 0); - test_one(3, 1); - test_one(3, 2); - test_one(3, 3); - test(4); - test(20); - test(100); - test(1000); +template +TEST_CONSTEXPR_CXX26 void test(RandSrc& randomness) { + test_one(0, 0, randomness); + test_one(1, 0, randomness); + test_one(1, 1, randomness); + test_one(2, 0, randomness); + test_one(2, 1, randomness); + test_one(2, 2, randomness); + test_one(3, 0, randomness); + test_one(3, 1, randomness); + test_one(3, 2, randomness); + test_one(3, 3, randomness); + test(4, randomness); + test(20, randomness); + test(50, randomness); + if (!TEST_IS_CONSTANT_EVALUATED) { // avoid exceeding the constant evaluation step limit + test(100, randomness); + test(1000, randomness); + } } struct less_by_first { template - bool operator()(const Pair& lhs, const Pair& rhs) const { + TEST_CONSTEXPR_CXX26 bool operator()(const Pair& lhs, const Pair& rhs) const { return std::less()(lhs.first, rhs.first); } }; -void test_PR31166 () -{ - typedef std::pair P; - typedef std::vector

V; - P vec[5] = {P(1, 0), P(2, 0), P(2, 1), P(2, 2), P(2, 3)}; - for ( int i = 0; i < 5; ++i ) { - V res(vec, vec + 5); - std::inplace_merge(res.begin(), res.begin() + i, res.end(), less_by_first()); - assert(res.size() == 5); - assert(std::equal(res.begin(), res.end(), vec)); - } +TEST_CONSTEXPR_CXX26 void test_PR31166() { + typedef std::pair P; + typedef std::vector

V; + P vec[5] = {P(1, 0), P(2, 0), P(2, 1), P(2, 2), P(2, 3)}; + for (int i = 0; i < 5; ++i) { + V res(vec, vec + 5); + std::inplace_merge(res.begin(), res.begin() + i, res.end(), less_by_first()); + assert(res.size() == 5); + assert(std::equal(res.begin(), res.end(), vec)); + } } -int main(int, char**) -{ - test >(); - test >(); - test(); +TEST_CONSTEXPR_CXX26 bool test() { + support::simple_random_generator randomness; + + test >(randomness); + test >(randomness); + test(randomness); #if TEST_STD_VER >= 11 - test >(); - test >(); - test(); + test >(randomness); + test >(randomness); + test(randomness); - { - int N = 100; - unsigned M = 50; + { + constexpr int N = 100; + constexpr int M = 50; std::unique_ptr* ia = new std::unique_ptr[N]; for (int i = 0; i < N; ++i) - ia[i].reset(new int(i)); - std::shuffle(ia, ia+N, randomness); - std::sort(ia, ia+M, indirect_less()); - std::sort(ia+M, ia+N, indirect_less()); - std::inplace_merge(ia, ia+M, ia+N, indirect_less()); - if(N > 0) - { - assert(*ia[0] == 0); - assert(*ia[N-1] == N-1); - assert(std::is_sorted(ia, ia+N, indirect_less())); - } - delete [] ia; + ia[i].reset(new int(i)); + support::shuffle(ia, ia + N, randomness); + std::sort(ia, ia + M, indirect_less()); + std::sort(ia + M, ia + N, indirect_less()); + std::inplace_merge(ia, ia + M, ia + N, indirect_less()); + if (N > 0) { + assert(*ia[0] == 0); + assert(*ia[N - 1] == N - 1); + assert(std::is_sorted(ia, ia + N, indirect_less())); } + delete[] ia; + } #endif // TEST_STD_VER >= 11 - test_PR31166(); + test_PR31166(); + + return true; +} + +int main(int, char**) { + test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif // TEST_STD_VER >= 26 return 0; } diff --git a/libcxx/test/std/algorithms/robust_re_difference_type.compile.pass.cpp b/libcxx/test/std/algorithms/robust_re_difference_type.compile.pass.cpp index 187113b0bdeae..b2e30ce88b618 100644 --- a/libcxx/test/std/algorithms/robust_re_difference_type.compile.pass.cpp +++ b/libcxx/test/std/algorithms/robust_re_difference_type.compile.pass.cpp @@ -141,8 +141,13 @@ TEST_CONSTEXPR_CXX20 bool all_the_algorithms() (void)std::is_sorted(first, last, std::less()); (void)std::is_sorted_until(first, last); (void)std::is_sorted_until(first, last, std::less()); - if (!TEST_IS_CONSTANT_EVALUATED) (void)std::inplace_merge(first, mid, last); - if (!TEST_IS_CONSTANT_EVALUATED) (void)std::inplace_merge(first, mid, last, std::less()); +#if TEST_STD_VER < 26 + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + { + (void)std::inplace_merge(first, mid, last); + (void)std::inplace_merge(first, mid, last, std::less()); + } (void)std::iter_swap(first, mid); (void)std::lexicographical_compare(first, last, first2, last2); (void)std::lexicographical_compare(first, last, first2, last2, std::less()); diff --git a/libcxx/test/support/constexpr_random.h b/libcxx/test/support/constexpr_random.h new file mode 100644 index 0000000000000..9fa923e11ce34 --- /dev/null +++ b/libcxx/test/support/constexpr_random.h @@ -0,0 +1,438 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef TEST_SUPPORT_CONSTEXPR_RANDOM_H +#define TEST_SUPPORT_CONSTEXPR_RANDOM_H + +#include +#include +#include +#include +#include +#include +#include + +#include "test_macros.h" + +namespace support { + +namespace detail { + +template +struct is_valid_integer_type_for_random : std::false_type {}; +template <> +struct is_valid_integer_type_for_random : std::true_type {}; +template <> +struct is_valid_integer_type_for_random : std::true_type {}; +template <> +struct is_valid_integer_type_for_random : std::true_type {}; +template <> +struct is_valid_integer_type_for_random : std::true_type {}; +template <> +struct is_valid_integer_type_for_random : std::true_type {}; +template <> +struct is_valid_integer_type_for_random : std::true_type {}; +template <> +struct is_valid_integer_type_for_random : std::true_type {}; +template <> +struct is_valid_integer_type_for_random : std::true_type {}; +template <> +struct is_valid_integer_type_for_random : std::true_type {}; +template <> +struct is_valid_integer_type_for_random : std::true_type {}; + +#ifndef TEST_HAS_NO_INT128 +template <> +struct is_valid_integer_type_for_random<__int128_t> : std::true_type {}; +template <> +struct is_valid_integer_type_for_random<__uint128_t> : std::true_type {}; +#endif // TEST_HAS_NO_INT128 + +template +struct is_valid_urng : std::false_type {}; +template +struct is_valid_urng< + Gen, + typename std::enable_if::value && + std::is_same()()), typename Gen::result_type>::value>::type> + : std::true_type {}; + +template +struct meta_log2_imp; + +template +struct meta_log2_imp { + static const std::size_t value = + N & ((unsigned long long)(1) << R) ? R : meta_log2_imp::value; +}; + +template +struct meta_log2_imp { + static const std::size_t value = 0; +}; + +template +struct meta_log2_imp { + static const std::size_t value = R + 1; +}; + +#ifndef TEST_HAS_NO_INT128 +template <__uint128_t N, std::size_t R> +struct meta_log2_imp<__uint128_t, N, R> { + static const size_t value = + (N >> 64) ? (64 + meta_log2_imp> 64), 63>::value) + : meta_log2_imp::value; +}; +#endif // TEST_HAS_NO_INT128 + +template +struct meta_log2 { + static const size_t value = meta_log2_imp< +#ifndef TEST_HAS_NO_INT128 + typename std::conditional::type, +#else + unsigned long long, +#endif // TEST_HAS_NO_INT128 + N, + sizeof(UIntType) * CHAR_BIT - 1 >::value; +}; + +#ifdef TEST_COMPILER_MSVC +template ::type = 0> +TEST_CONSTEXPR int countl_zero_div_conq(T n) TEST_NOEXCEPT { + return static_cast(~n) & 1; +} + +template 1), int>::type = 0> +TEST_CONSTEXPR int countl_zero_div_conq(T n) TEST_NOEXCEPT { + return n >= (static_cast(1) << (Width / 2)) + ? detail::countl_zero_div_conq(n >> (Width / 2)) + : detail::countl_zero_div_conq(n) + Width / 2; +} +#endif + +template ::value, int>::type = 0> +TEST_CONSTEXPR int countl_zero(T n) TEST_NOEXCEPT { +#ifdef TEST_COMPILER_MSVC + return detail::countl_zero_div_conq::digits>(n); +#else + return __builtin_clz(n); +#endif +} + +template ::value, int>::type = 0> +TEST_CONSTEXPR_CXX14 int countl_zero(T n) TEST_NOEXCEPT { +#ifdef TEST_COMPILER_MSVC + return detail::countl_zero_div_conq::digits>(n); +#else + return __builtin_clzl(n); +#endif +} + +template ::value, int>::type = 0> +TEST_CONSTEXPR int countl_zero(T n) TEST_NOEXCEPT { +#ifdef TEST_COMPILER_MSVC + return detail::countl_zero_div_conq::digits>(n); +#else + return __builtin_clzll(n); +#endif +} + +#ifndef TEST_HAS_NO_INT128 +template ::value, int>::type = 0> +TEST_CONSTEXPR int countl_zero(T n) TEST_NOEXCEPT { + return n > std::numeric_limits::max() + ? detail::countl_zero(static_cast(n >> 64)) + : detail::countl_zero(static_cast(n)) + 64; +} +#endif // TEST_HAS_NO_INT128 + +template ::value || std::is_same::value, + int>::type = 0> +TEST_CONSTEXPR int countl_zero(T n) TEST_NOEXCEPT { + return detail::countl_zero(static_cast(n)) - + (std::numeric_limits::digits - std::numeric_limits::digits); +} + +template +class independent_bits_engine { +public: + typedef UIntType result_type; + +private: + typedef typename Engine::result_type engine_result_type; + typedef + typename std::conditional:: + type working_result_type; + + Engine& eng_; + std::size_t width_; + std::size_t wid0_; + std::size_t round_count_all_; + std::size_t round_count_regular_; + working_result_type y0_; + working_result_type y1_; + engine_result_type mask0_; + engine_result_type mask1_; + +#if TEST_STD_VER >= 11 + static constexpr working_result_type rp = Engine::max() - Engine::min() + working_result_type(1); +#else + static const working_result_type rp = Engine::max_value - Engine::min_value + working_result_type(1); +#endif + static TEST_CONSTEXPR const std::size_t rp_log2 = meta_log2::value; + static TEST_CONSTEXPR const std::size_t w_digits = std::numeric_limits::digits; + static TEST_CONSTEXPR const std::size_t e_digits = std::numeric_limits::digits; + +public: + // constructors and seeding functions + TEST_CONSTEXPR_CXX14 independent_bits_engine(Engine& eng, std::size_t width) + : eng_(eng), + width_(width), + wid0_(), + round_count_all_(), + round_count_regular_(), + y0_(), + y1_(), + mask0_(), + mask1_() { + round_count_all_ = width_ / rp_log2 + (width_ % rp_log2 != 0); + wid0_ = width_ / round_count_all_; + if TEST_CONSTEXPR_CXX17 (rp == 0) { + y0_ = rp; + } else { + if (wid0_ < w_digits) + y0_ = (rp >> wid0_) << wid0_; + else + y0_ = 0; + } + if (rp - y0_ > y0_ / round_count_all_) { + ++round_count_all_; + wid0_ = width_ / round_count_all_; + if (wid0_ < w_digits) + y0_ = (rp >> wid0_) << wid0_; + else + y0_ = 0; + } + round_count_regular_ = round_count_all_ - width_ % round_count_all_; + if (wid0_ < w_digits - 1) + y1_ = (rp >> (wid0_ + 1)) << (wid0_ + 1); + else + y1_ = 0; + mask0_ = wid0_ > 0 ? static_cast(engine_result_type(~0) >> (e_digits - wid0_)) + : engine_result_type(0); + mask1_ = wid0_ < e_digits - 1 ? static_cast(engine_result_type(~0) >> (e_digits - (wid0_ + 1))) + : engine_result_type(~0); + } + + // generating functions + TEST_CONSTEXPR_CXX14 result_type operator()() { return generate(std::integral_constant()); } + +private: + TEST_CONSTEXPR_CXX14 result_type generate(std::false_type) { return static_cast(eng_() & mask0_); } + + TEST_CONSTEXPR_CXX14 result_type generate(std::true_type) { + const std::size_t r_digits = std::numeric_limits::digits; + result_type result = 0; + for (std::size_t k = 0; k < round_count_regular_; ++k) { + engine_result_type eng_result = 0; + do { + eng_result = static_cast(eng_() - Engine::min()); + } while (eng_result >= y0_); + if (wid0_ < r_digits) + result <<= wid0_; + else + result = 0; + result += eng_result & mask0_; + } + for (std::size_t k = round_count_regular_; k < round_count_all_; ++k) { + engine_result_type eng_result = 0; + do { + eng_result = static_cast(eng_() - Engine::min()); + } while (eng_result >= y1_); + if (wid0_ < r_digits - 1) + result <<= wid0_ + 1; + else + result = 0; + result += eng_result & mask1_; + } + return result; + } +}; + +} // namespace detail + +template +class uniform_int_distribution { + static_assert(detail::is_valid_integer_type_for_random::value, "IntType must be a supported integer type"); + +public: + // types + typedef IntType result_type; + + class param_type { + result_type a_; + result_type b_; + + public: + typedef uniform_int_distribution distribution_type; + +#if TEST_STD_VER >= 11 + constexpr param_type() : param_type(0) {} +#else + param_type() : a_(0), b_(std::numeric_limits::max()) {} +#endif + TEST_CONSTEXPR explicit param_type(result_type ax, result_type bx = std::numeric_limits::max()) + : a_(ax), b_(bx) {} + + TEST_CONSTEXPR result_type a() const { return a_; } + TEST_CONSTEXPR result_type b() const { return b_; } + +#if TEST_STD_VER >= 20 + friend bool operator==(const param_type&, const param_type&) = default; +#else + TEST_CONSTEXPR friend bool operator==(const param_type& lhs, const param_type& rhs) { + return lhs.a_ == rhs.a_ && lhs.b_ == rhs.b_; + } + TEST_CONSTEXPR friend bool operator!=(const param_type& lhs, const param_type& rhs) { return !(lhs == rhs); } +#endif + }; + +private: + param_type param_; + +public: + // constructors and reset functions +#if TEST_STD_VER >= 11 + uniform_int_distribution() = default; +#else + uniform_int_distribution() {} +#endif + TEST_CONSTEXPR explicit uniform_int_distribution(result_type ax, + result_type bx = std::numeric_limits::max()) + : param_(ax, bx) {} + TEST_CONSTEXPR explicit uniform_int_distribution(const param_type& param) : param_(param) {} + TEST_CONSTEXPR_CXX14 void reset() {} + + // generating functions + template + TEST_CONSTEXPR_CXX14 result_type operator()(URNG& gen) { + return (*this)(gen, param_); + } + +#if TEST_HAS_FEATURE(no_sanitize) && !defined(TEST_COMPILER_GCC) +# define TEST_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK __attribute__((__no_sanitize__("unsigned-integer-overflow"))) +#else +# define TEST_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK +#endif + template + TEST_CONSTEXPR_CXX14 result_type operator()(URNG& gen, const param_type& param) + TEST_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK { + static_assert(detail::is_valid_urng::value, "invalid uniform random bit generator used"); + typedef typename std::conditional::type>::type UIntType; + const UIntType rp = UIntType(param.b()) - UIntType(param.a()) + UIntType(1); + if (rp == 1) + return param.a(); + const std::size_t ur_digits = std::numeric_limits::digits; + typedef detail::independent_bits_engine Eng; + if (rp == 0) + return static_cast(Eng(gen, ur_digits)()); + std::size_t width = ur_digits - detail::countl_zero(rp) - 1; + if ((rp & (std::numeric_limits::max() >> (ur_digits - width))) != 0) + ++width; + Eng eng(gen, width); + UIntType eng_result = 0; + do { + eng_result = eng(); + } while (eng_result >= rp); + return static_cast(eng_result + param.a()); + } +#undef TEST_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK + + // property functions + TEST_CONSTEXPR result_type a() const { return param_.a(); } + TEST_CONSTEXPR result_type b() const { return param_.b(); } + + TEST_CONSTEXPR param_type param() const { return param_; } + TEST_CONSTEXPR_CXX14 void param(const param_type& param) { param_ = param; } + + TEST_CONSTEXPR result_type min() const { return a(); } + TEST_CONSTEXPR result_type max() const { return b(); } + +#if TEST_STD_VER >= 20 + friend bool operator==(const uniform_int_distribution&, const uniform_int_distribution&) = default; +#else + TEST_CONSTEXPR friend bool operator==(const uniform_int_distribution& lhs, const uniform_int_distribution& rhs) { + return lhs.param_ == rhs.param_; + } + TEST_CONSTEXPR friend bool operator!=(const uniform_int_distribution& lhs, const uniform_int_distribution& rhs) { + return !(lhs == rhs); + } +#endif +}; + +class simple_random_generator { // A linear congruential generator, using the constants used by MS UCRT. +private: + std::uint32_t status_; + +public: + typedef std::uint16_t result_type; + + static TEST_CONSTEXPR result_type min() TEST_NOEXCEPT { return 0; } + static TEST_CONSTEXPR result_type max() TEST_NOEXCEPT { return static_cast(-1); } +#if TEST_STD_VER < 11 + static const result_type min_value = 0; + static const result_type max_value = static_cast(-1); +#endif + static TEST_CONSTEXPR const result_type default_seed = 19937; + +#if TEST_STD_VER >= 11 + constexpr simple_random_generator() noexcept : simple_random_generator(default_seed) {} +#else + simple_random_generator() throw() : status_(default_seed) {} +#endif + TEST_CONSTEXPR explicit simple_random_generator(std::uint16_t s) TEST_NOEXCEPT : status_(s) {} + + TEST_CONSTEXPR_CXX14 result_type operator()() TEST_NOEXCEPT { + status_ = status_ * 214013u + 2531011u; + return static_cast(status_ >> 16); + } +}; + +template +TEST_CONSTEXPR_CXX14 void +#if TEST_STD_VER >= 11 +shuffle(RandomAccessIterator first, RandomAccessIterator last, UniformRandomNumberGenerator&& gen) +#else +shuffle(RandomAccessIterator first, RandomAccessIterator last, UniformRandomNumberGenerator& gen) +#endif +{ + typedef typename std::iterator_traits::difference_type difference_type; + typedef uniform_int_distribution dist; + typedef typename dist::param_type param_type; + + RandomAccessIterator last_iter = last; + difference_type diff = last_iter - first; + if (diff > 1) { + dist uid; + for (--last_iter, (void)--diff; first < last; ++first, (void)--diff) { + difference_type index = uid(gen, param_type(0, diff)); + if (index != difference_type(0)) { + using std::swap; + swap(*first, *(first + index)); + } + } + } +} + +} // namespace support + +#endif // TEST_SUPPORT_CONSTEXPR_RANDOM_H diff --git a/libcxx/test/support/counting_predicates.h b/libcxx/test/support/counting_predicates.h index db7ee481991c4..6f34ce76302a8 100644 --- a/libcxx/test/support/counting_predicates.h +++ b/libcxx/test/support/counting_predicates.h @@ -41,14 +41,15 @@ struct binary_counting_predicate { typedef Arg2 second_argument_type; typedef bool result_type; - binary_counting_predicate ( Predicate p ) : p_(p), count_(0) {} - ~binary_counting_predicate() {} - - bool operator () (const Arg1 &a1, const Arg2 &a2) const { ++count_; return p_(a1, a2); } - std::size_t count() const { return count_; } - void reset() { count_ = 0; } - -private: + TEST_CONSTEXPR binary_counting_predicate(Predicate p) : p_(p), count_(0) {} + TEST_CONSTEXPR_CXX14 bool operator()(const Arg1& a1, const Arg2& a2) const { + ++count_; + return p_(a1, a2); + } + TEST_CONSTEXPR std::size_t count() const { return count_; } + TEST_CONSTEXPR_CXX14 void reset() { count_ = 0; } + + private: Predicate p_; mutable std::size_t count_; };