1// -*- C++ -*-
2//===-- glue_memory_impl.h ------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _PSTL_GLUE_MEMORY_IMPL_H
11#define _PSTL_GLUE_MEMORY_IMPL_H
12
13#include "utils.h"
14#include "algorithm_fwd.h"
15
16namespace std
17{
18
19// [uninitialized.copy]
20
21template <class _ExecutionPolicy, class _InputIterator, class _ForwardIterator>
22__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator>
23uninitialized_copy(_ExecutionPolicy&& __exec, _InputIterator __first, _InputIterator __last, _ForwardIterator __result)
24{
25    typedef typename iterator_traits<_InputIterator>::value_type _ValueType1;
26    typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType2;
27    typedef typename iterator_traits<_InputIterator>::reference _ReferenceType1;
28    typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType2;
29    using namespace __pstl;
30
31    const auto __is_parallel =
32        __internal::__is_parallelization_preferred<_ExecutionPolicy, _InputIterator, _ForwardIterator>(__exec);
33    const auto __is_vector =
34        __internal::__is_vectorization_preferred<_ExecutionPolicy, _InputIterator, _ForwardIterator>(__exec);
35
36    return __internal::__invoke_if_else(
37        std::integral_constant < bool, std::is_trivial<_ValueType1>::value&& std::is_trivial<_ValueType2>::value > (),
38        [&]() {
39            return __internal::__pattern_walk2_brick(
40                std::forward<_ExecutionPolicy>(__exec), __first, __last, __result,
41                [__is_vector](_InputIterator __begin, _InputIterator __end, _ForwardIterator __res) {
42                    return __internal::__brick_copy(__begin, __end, __res, __is_vector);
43                },
44                __is_parallel);
45        },
46        [&]() {
47            return __internal::__pattern_walk2(std::forward<_ExecutionPolicy>(__exec), __first, __last, __result,
48                                               [](_ReferenceType1 __val1, _ReferenceType2 __val2) {
49                                                   ::new (std::addressof(__val2)) _ValueType2(__val1);
50                                               },
51                                               __is_vector, __is_parallel);
52        });
53}
54
55template <class _ExecutionPolicy, class _InputIterator, class _Size, class _ForwardIterator>
56__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator>
57uninitialized_copy_n(_ExecutionPolicy&& __exec, _InputIterator __first, _Size __n, _ForwardIterator __result)
58{
59    typedef typename iterator_traits<_InputIterator>::value_type _ValueType1;
60    typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType2;
61    typedef typename iterator_traits<_InputIterator>::reference _ReferenceType1;
62    typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType2;
63    using namespace __pstl;
64
65    const auto __is_parallel =
66        __internal::__is_parallelization_preferred<_ExecutionPolicy, _InputIterator, _ForwardIterator>(__exec);
67    const auto __is_vector =
68        __internal::__is_vectorization_preferred<_ExecutionPolicy, _InputIterator, _ForwardIterator>(__exec);
69
70    return __internal::__invoke_if_else(
71        std::integral_constant < bool, std::is_trivial<_ValueType1>::value&& std::is_trivial<_ValueType2>::value > (),
72        [&]() {
73            return __internal::__pattern_walk2_brick_n(
74                std::forward<_ExecutionPolicy>(__exec), __first, __n, __result,
75                [__is_vector](_InputIterator __begin, _Size __sz, _ForwardIterator __res) {
76                    return __internal::__brick_copy_n(__begin, __sz, __res, __is_vector);
77                },
78                __is_parallel);
79        },
80        [&]() {
81            return __internal::__pattern_walk2_n(std::forward<_ExecutionPolicy>(__exec), __first, __n, __result,
82                                                 [](_ReferenceType1 __val1, _ReferenceType2 __val2) {
83                                                     ::new (std::addressof(__val2)) _ValueType2(__val1);
84                                                 },
85                                                 __is_vector, __is_parallel);
86        });
87}
88
89// [uninitialized.move]
90
91template <class _ExecutionPolicy, class _InputIterator, class _ForwardIterator>
92__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator>
93uninitialized_move(_ExecutionPolicy&& __exec, _InputIterator __first, _InputIterator __last, _ForwardIterator __result)
94{
95    typedef typename iterator_traits<_InputIterator>::value_type _ValueType1;
96    typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType2;
97    typedef typename iterator_traits<_InputIterator>::reference _ReferenceType1;
98    typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType2;
99    using namespace __pstl;
100
101    const auto __is_parallel =
102        __internal::__is_parallelization_preferred<_ExecutionPolicy, _InputIterator, _ForwardIterator>(__exec);
103    const auto __is_vector =
104        __internal::__is_vectorization_preferred<_ExecutionPolicy, _InputIterator, _ForwardIterator>(__exec);
105
106    return __internal::__invoke_if_else(
107        std::integral_constant < bool, std::is_trivial<_ValueType1>::value&& std::is_trivial<_ValueType2>::value > (),
108        [&]() {
109            return __internal::__pattern_walk2_brick(
110                std::forward<_ExecutionPolicy>(__exec), __first, __last, __result,
111                [__is_vector](_InputIterator __begin, _InputIterator __end, _ForwardIterator __res) {
112                    return __internal::__brick_copy(__begin, __end, __res, __is_vector);
113                },
114                __is_parallel);
115        },
116        [&]() {
117            return __internal::__pattern_walk2(std::forward<_ExecutionPolicy>(__exec), __first, __last, __result,
118                                               [](_ReferenceType1 __val1, _ReferenceType2 __val2) {
119                                                   ::new (std::addressof(__val2)) _ValueType2(std::move(__val1));
120                                               },
121                                               __is_vector, __is_parallel);
122        });
123}
124
125template <class _ExecutionPolicy, class _InputIterator, class _Size, class _ForwardIterator>
126__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator>
127uninitialized_move_n(_ExecutionPolicy&& __exec, _InputIterator __first, _Size __n, _ForwardIterator __result)
128{
129    typedef typename iterator_traits<_InputIterator>::value_type _ValueType1;
130    typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType2;
131    typedef typename iterator_traits<_InputIterator>::reference _ReferenceType1;
132    typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType2;
133    using namespace __pstl;
134
135    const auto __is_parallel =
136        __internal::__is_parallelization_preferred<_ExecutionPolicy, _InputIterator, _ForwardIterator>(__exec);
137    const auto __is_vector =
138        __internal::__is_vectorization_preferred<_ExecutionPolicy, _InputIterator, _ForwardIterator>(__exec);
139
140    return __internal::__invoke_if_else(
141        std::integral_constant < bool, std::is_trivial<_ValueType1>::value&& std::is_trivial<_ValueType2>::value > (),
142        [&]() {
143            return __internal::__pattern_walk2_brick_n(
144                std::forward<_ExecutionPolicy>(__exec), __first, __n, __result,
145                [__is_vector](_InputIterator __begin, _Size __sz, _ForwardIterator __res) {
146                    return __internal::__brick_copy_n(__begin, __sz, __res, __is_vector);
147                },
148                __is_parallel);
149        },
150        [&]() {
151            return __internal::__pattern_walk2_n(std::forward<_ExecutionPolicy>(__exec), __first, __n, __result,
152                                                 [](_ReferenceType1 __val1, _ReferenceType2 __val2) {
153                                                     ::new (std::addressof(__val2)) _ValueType2(std::move(__val1));
154                                                 },
155                                                 __is_vector, __is_parallel);
156        });
157}
158
159// [uninitialized.fill]
160
161template <class _ExecutionPolicy, class _ForwardIterator, class _Tp>
162__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void>
163uninitialized_fill(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value)
164{
165    typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
166    typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType;
167    using namespace __pstl;
168
169    const auto __is_parallel = __internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
170    const auto __is_vector = __internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
171
172    __internal::__invoke_if_else(std::is_arithmetic<_ValueType>(),
173                                 [&]() {
174                                     __internal::__pattern_walk_brick(
175                                         std::forward<_ExecutionPolicy>(__exec), __first, __last,
176                                         [&__value, &__is_vector](_ForwardIterator __begin, _ForwardIterator __end) {
177                                             __internal::__brick_fill(__begin, __end, _ValueType(__value), __is_vector);
178                                         },
179                                         __is_parallel);
180                                 },
181                                 [&]() {
182                                     __internal::__pattern_walk1(std::forward<_ExecutionPolicy>(__exec), __first,
183                                                                 __last,
184                                                                 [&__value](_ReferenceType __val) {
185                                                                     ::new (std::addressof(__val)) _ValueType(__value);
186                                                                 },
187                                                                 __is_vector, __is_parallel);
188                                 });
189}
190
191template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp>
192__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator>
193uninitialized_fill_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __n, const _Tp& __value)
194{
195    typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
196    typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType;
197    using namespace __pstl;
198
199    const auto __is_parallel = __internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
200    const auto __is_vector = __internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
201
202    return __internal::__invoke_if_else(
203        std::is_arithmetic<_ValueType>(),
204        [&]() {
205            return __internal::__pattern_walk_brick_n(
206                std::forward<_ExecutionPolicy>(__exec), __first, __n,
207                [&__value, &__is_vector](_ForwardIterator __begin, _Size __count) {
208                    return __internal::__brick_fill_n(__begin, __count, _ValueType(__value), __is_vector);
209                },
210                __is_parallel);
211        },
212        [&]() {
213            return __internal::__pattern_walk1_n(
214                std::forward<_ExecutionPolicy>(__exec), __first, __n,
215                [&__value](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType(__value); }, __is_vector,
216                __is_parallel);
217        });
218}
219
220// [specialized.destroy]
221
222template <class _ExecutionPolicy, class _ForwardIterator>
223__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void>
224destroy(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last)
225{
226    typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
227    typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType;
228    using namespace __pstl;
229
230    const auto __is_parallel = __internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
231    const auto __is_vector = __internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
232
233    __internal::__invoke_if_not(std::is_trivially_destructible<_ValueType>(), [&]() {
234        __internal::__pattern_walk1(std::forward<_ExecutionPolicy>(__exec), __first, __last,
235                                    [](_ReferenceType __val) { __val.~_ValueType(); }, __is_vector, __is_parallel);
236    });
237}
238
239template <class _ExecutionPolicy, class _ForwardIterator, class _Size>
240__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator>
241destroy_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __n)
242{
243    typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
244    typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType;
245    using namespace __pstl;
246
247    const auto __is_parallel = __internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
248    const auto __is_vector = __internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
249
250    return __internal::__invoke_if_else(
251        std::is_trivially_destructible<_ValueType>(), [&]() { return std::next(__first, __n); },
252        [&]() {
253            return __internal::__pattern_walk1_n(std::forward<_ExecutionPolicy>(__exec), __first, __n,
254                                                 [](_ReferenceType __val) { __val.~_ValueType(); }, __is_vector,
255                                                 __is_parallel);
256        });
257}
258
259// [uninitialized.construct.default]
260
261template <class _ExecutionPolicy, class _ForwardIterator>
262__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void>
263uninitialized_default_construct(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last)
264{
265    typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
266    typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType;
267    using namespace __pstl;
268
269    const auto __is_parallel = __internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
270    const auto __is_vector = __internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
271
272    __internal::__invoke_if_not(std::is_trivial<_ValueType>(), [&]() {
273        __internal::__pattern_walk1(std::forward<_ExecutionPolicy>(__exec), __first, __last,
274                                    [](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType; }, __is_vector,
275                                    __is_parallel);
276    });
277}
278
279template <class _ExecutionPolicy, class _ForwardIterator, class _Size>
280__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator>
281uninitialized_default_construct_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __n)
282{
283    typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
284    typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType;
285    using namespace __pstl;
286
287    const auto __is_parallel = __internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
288    const auto __is_vector = __internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
289
290    return __internal::__invoke_if_else(std::is_trivial<_ValueType>(), [&]() { return std::next(__first, __n); },
291                                        [&]() {
292                                            return __internal::__pattern_walk1_n(
293                                                std::forward<_ExecutionPolicy>(__exec), __first, __n,
294                                                [](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType; },
295                                                __is_vector, __is_parallel);
296                                        });
297}
298
299// [uninitialized.construct.value]
300
301template <class _ExecutionPolicy, class _ForwardIterator>
302__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void>
303uninitialized_value_construct(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last)
304{
305    typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
306    typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType;
307    using namespace __pstl;
308
309    const auto __is_parallel = __internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
310    const auto __is_vector = __internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
311
312    __internal::__invoke_if_else(
313        std::is_trivial<_ValueType>(),
314        [&]() {
315            __internal::__pattern_walk_brick(std::forward<_ExecutionPolicy>(__exec), __first, __last,
316                                             [__is_vector](_ForwardIterator __begin, _ForwardIterator __end) {
317                                                 __internal::__brick_fill(__begin, __end, _ValueType(), __is_vector);
318                                             },
319                                             __is_parallel);
320        },
321        [&]() {
322            __internal::__pattern_walk1(std::forward<_ExecutionPolicy>(__exec), __first, __last,
323                                        [](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType(); },
324                                        __is_vector, __is_parallel);
325        });
326}
327
328template <class _ExecutionPolicy, class _ForwardIterator, class _Size>
329__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator>
330uninitialized_value_construct_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __n)
331{
332    typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
333    typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType;
334    using namespace __pstl;
335
336    const auto __is_parallel = __internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
337    const auto __is_vector = __internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
338
339    return __internal::__invoke_if_else(
340        std::is_trivial<_ValueType>(),
341        [&]() {
342            return __internal::__pattern_walk_brick_n(std::forward<_ExecutionPolicy>(__exec), __first, __n,
343                                                      [__is_vector](_ForwardIterator __begin, _Size __count) {
344                                                          return __internal::__brick_fill_n(__begin, __count,
345                                                                                            _ValueType(), __is_vector);
346                                                      },
347                                                      __is_parallel);
348        },
349        [&]() {
350            return __internal::__pattern_walk1_n(
351                std::forward<_ExecutionPolicy>(__exec), __first, __n,
352                [](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType(); }, __is_vector, __is_parallel);
353        });
354}
355
356} // namespace std
357
358#endif /* _PSTL_GLUE_MEMORY_IMPL_H */
359