Skip to content

Commit 84a6b98

Browse files
committed
[libc++] Introduce __specialized_algorithms
1 parent 898d6fe commit 84a6b98

File tree

5 files changed

+102
-43
lines changed

5 files changed

+102
-43
lines changed

libcxx/include/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ set(files
194194
__algorithm/simd_utils.h
195195
__algorithm/sort.h
196196
__algorithm/sort_heap.h
197+
__algorithm/specialized_algorithms.h
197198
__algorithm/stable_partition.h
198199
__algorithm/stable_sort.h
199200
__algorithm/swap_ranges.h

libcxx/include/__algorithm/fill_n.h

Lines changed: 17 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@
1010
#define _LIBCPP___ALGORITHM_FILL_N_H
1111

1212
#include <__algorithm/for_each_n_segment.h>
13-
#include <__algorithm/min.h>
13+
#include <__algorithm/specialized_algorithms.h>
1414
#include <__config>
15-
#include <__fwd/bit_reference.h>
1615
#include <__iterator/iterator_traits.h>
1716
#include <__iterator/segmented_iterator.h>
18-
#include <__memory/pointer_traits.h>
17+
#include <__type_traits/enable_if.h>
1918
#include <__utility/convert_to_integral.h>
19+
#include <__utility/move.h>
2020

2121
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2222
# pragma GCC system_header
@@ -29,7 +29,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD
2929

3030
// fill_n isn't specialized for std::memset, because the compiler already optimizes the loop to a call to std::memset.
3131

32-
template <class _OutputIterator, class _Size, class _Tp>
32+
template <
33+
class _OutputIterator,
34+
class _Size,
35+
class _Tp,
36+
__enable_if_t<!__specialized_algorithm<_Algorithm::__fill_n, __single_iterator<_OutputIterator> >::__has_algorithm,
37+
int> = 0>
3338
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
3439
__fill_n(_OutputIterator __first, _Size __n, const _Tp& __value) {
3540
#ifndef _LIBCPP_CXX03_LANG
@@ -47,42 +52,14 @@ __fill_n(_OutputIterator __first, _Size __n, const _Tp& __value) {
4752
return __first;
4853
}
4954

50-
template <bool _FillVal, class _Cp>
51-
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
52-
__fill_n_bool(__bit_iterator<_Cp, false> __first, typename __size_difference_type_traits<_Cp>::size_type __n) {
53-
using _It = __bit_iterator<_Cp, false>;
54-
using __storage_type = typename _It::__storage_type;
55-
56-
const int __bits_per_word = _It::__bits_per_word;
57-
// do first partial word
58-
if (__first.__ctz_ != 0) {
59-
__storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_);
60-
__storage_type __dn = std::min(__clz_f, __n);
61-
std::__fill_masked_range(std::__to_address(__first.__seg_), __clz_f - __dn, __first.__ctz_, _FillVal);
62-
__n -= __dn;
63-
++__first.__seg_;
64-
}
65-
// do middle whole words
66-
__storage_type __nw = __n / __bits_per_word;
67-
std::__fill_n(std::__to_address(__first.__seg_), __nw, _FillVal ? static_cast<__storage_type>(-1) : 0);
68-
__n -= __nw * __bits_per_word;
69-
// do last partial word
70-
if (__n > 0) {
71-
__first.__seg_ += __nw;
72-
std::__fill_masked_range(std::__to_address(__first.__seg_), __bits_per_word - __n, 0u, _FillVal);
73-
}
74-
}
75-
76-
template <class _Cp, class _Size>
77-
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, false>
78-
__fill_n(__bit_iterator<_Cp, false> __first, _Size __n, const bool& __value) {
79-
if (__n > 0) {
80-
if (__value)
81-
std::__fill_n_bool<true>(__first, __n);
82-
else
83-
std::__fill_n_bool<false>(__first, __n);
84-
}
85-
return __first + __n;
55+
template <class _OutIter,
56+
class _Size,
57+
class _Tp,
58+
__enable_if_t<__specialized_algorithm<_Algorithm::__fill_n, __single_iterator<_OutIter> >::__has_algorithm,
59+
int> = 0>
60+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutIter __fill_n(_OutIter __first, _Size __n, const _Tp& __value) {
61+
return __specialized_algorithm<_Algorithm::__fill_n, __single_iterator<_OutIter> >()(
62+
std::move(__first), __n, __value);
8663
}
8764

8865
template <class _OutputIterator, class _Size, class _Tp>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef _LIBCPP___ALGORITHM_SPECIALIZED_ALGORITHMS_H
10+
#define _LIBCPP___ALGORITHM_SPECIALIZED_ALGORITHMS_H
11+
12+
#include <__config>
13+
14+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
15+
# pragma GCC system_header
16+
#endif
17+
18+
_LIBCPP_BEGIN_NAMESPACE_STD
19+
20+
// FIXME: This should really be an enum
21+
namespace _Algorithm {
22+
struct __fill_n {};
23+
} // namespace _Algorithm
24+
25+
template <class>
26+
struct __single_iterator;
27+
28+
template <class _Alg, class... _Ranges>
29+
struct __specialized_algorithm {
30+
static const bool __has_algorithm = false;
31+
};
32+
33+
_LIBCPP_END_NAMESPACE_STD
34+
35+
#endif // _LIBCPP___ALGORITHM_SPECIALIZED_ALGORITHMS_H

libcxx/include/__bit_reference

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
#include <__algorithm/copy_backward.h>
1616
#include <__algorithm/copy_n.h>
1717
#include <__algorithm/equal.h>
18+
#include <__algorithm/fill_n.h>
1819
#include <__algorithm/min.h>
1920
#include <__algorithm/rotate.h>
21+
#include <__algorithm/specialized_algorithms.h>
2022
#include <__algorithm/swap_ranges.h>
2123
#include <__assert>
2224
#include <__bit/countr.h>
@@ -531,12 +533,55 @@ private:
531533
_Pred&,
532534
_Proj1&,
533535
_Proj2&);
534-
template <bool _ToFind, class _Dp, bool _IC>
535-
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, _IC>
536-
__find_bool(__bit_iterator<_Dp, _IC>, typename __size_difference_type_traits<_Dp>::size_type);
537536
template <bool _ToCount, class _Dp, bool _IC>
538537
friend typename __bit_iterator<_Dp, _IC>::difference_type _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
539538
__count_bool(__bit_iterator<_Dp, _IC>, typename __size_difference_type_traits<_Dp>::size_type);
539+
540+
template <class, class...>
541+
friend struct __specialized_algorithm;
542+
};
543+
544+
template <class _Cp>
545+
struct __specialized_algorithm<_Algorithm::__fill_n, __single_iterator<__bit_iterator<_Cp, false> > > {
546+
static const bool __has_algorithm = true;
547+
548+
template <bool _FillVal>
549+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static void
550+
__impl(__bit_iterator<_Cp, false> __first, typename __size_difference_type_traits<_Cp>::size_type __n) {
551+
using _It = __bit_iterator<_Cp, false>;
552+
using __storage_type = typename _It::__storage_type;
553+
554+
const int __bits_per_word = _It::__bits_per_word;
555+
// do first partial word
556+
if (__first.__ctz_ != 0) {
557+
__storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_);
558+
__storage_type __dn = std::min(__clz_f, __n);
559+
std::__fill_masked_range(std::__to_address(__first.__seg_), __clz_f - __dn, __first.__ctz_, _FillVal);
560+
__n -= __dn;
561+
++__first.__seg_;
562+
}
563+
// do middle whole words
564+
__storage_type __nw = __n / __bits_per_word;
565+
std::__fill_n(std::__to_address(__first.__seg_), __nw, _FillVal ? static_cast<__storage_type>(-1) : 0);
566+
__n -= __nw * __bits_per_word;
567+
// do last partial word
568+
if (__n > 0) {
569+
__first.__seg_ += __nw;
570+
std::__fill_masked_range(std::__to_address(__first.__seg_), __bits_per_word - __n, 0u, _FillVal);
571+
}
572+
}
573+
574+
template <class _Size, class _Tp>
575+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static __bit_iterator<_Cp, false>
576+
operator()(__bit_iterator<_Cp, false> __first, _Size __n, const _Tp& __value) {
577+
if (__n > 0) {
578+
if (__value)
579+
__impl<true>(__first, __n);
580+
else
581+
__impl<false>(__first, __n);
582+
}
583+
return __first + __n;
584+
}
540585
};
541586

542587
_LIBCPP_END_NAMESPACE_STD

libcxx/include/module.modulemap.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,7 @@ module std [system] {
839839
module simd_utils { header "__algorithm/simd_utils.h" }
840840
module sort_heap { header "__algorithm/sort_heap.h" }
841841
module sort { header "__algorithm/sort.h" }
842+
module specialized_algorithms { header "__algorithm/specialized_algorithms.h" }
842843
module stable_partition { header "__algorithm/stable_partition.h" }
843844
module stable_sort {
844845
header "__algorithm/stable_sort.h"

0 commit comments

Comments
 (0)