-
Notifications
You must be signed in to change notification settings - Fork 115
/
Copy pathiterator_impl.h
1048 lines (934 loc) · 28.1 KB
/
iterator_impl.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// -*- C++ -*-
//===-- iterator_impl.h ---------------------------------------------------===//
//
// Copyright (C) Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// This file incorporates work covered by the following copyright and permission
// notice:
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
//
//===----------------------------------------------------------------------===//
#ifndef _ONEDPL_ITERATOR_IMPL_H
#define _ONEDPL_ITERATOR_IMPL_H
#include <iterator>
#include <tuple>
#include <cassert>
#include <type_traits>
#include "onedpl_config.h"
#include "utils.h"
#include "tuple_impl.h"
namespace oneapi
{
namespace dpl
{
namespace __internal
{
template <size_t _Np>
struct __tuple_util
{
template <typename _TupleType, typename _DifferenceType>
static void
__increment(_TupleType& __it, _DifferenceType __forward)
{
::std::get<_Np - 1>(__it) = ::std::get<_Np - 1>(__it) + __forward;
__tuple_util<_Np - 1>::__increment(__it, __forward);
}
template <typename _TupleType>
static void
__pre_increment(_TupleType& __it)
{
++::std::get<_Np - 1>(__it);
__tuple_util<_Np - 1>::__pre_increment(__it);
}
};
template <>
struct __tuple_util<0>
{
template <typename _TupleType, typename _DifferenceType>
static void
__increment(_TupleType&, _DifferenceType)
{
}
template <typename _TupleType>
static void
__pre_increment(_TupleType&)
{
}
};
template <typename _TupleReturnType>
struct __make_references
{
template <typename _TupleType, ::std::size_t... _Ip>
_TupleReturnType
operator()(const _TupleType& __t, ::std::index_sequence<_Ip...>)
{
return _TupleReturnType(*::std::get<_Ip>(__t)...);
}
};
template <typename _Iter, typename = void>
struct __is_legacy_passed_directly : std::false_type
{
};
template <typename _Iter>
struct __is_legacy_passed_directly<_Iter, ::std::enable_if_t<_Iter::is_passed_directly::value>> : std::true_type
{
};
template <typename _T>
struct __is_reversed_indirectly_device_accessible_it;
template <typename T>
constexpr auto is_onedpl_indirectly_device_accessible_iterator(T)
-> std::disjunction<
#if _ONEDPL_BACKEND_SYCL
oneapi::dpl::__internal::__is_known_usm_vector_iter<std::decay_t<T>>, // USM vector iterator
#endif // _ONEDPL_BACKEND_SYCL
std::is_pointer<std::decay_t<T>>, // USM pointer
oneapi::dpl::__internal::__is_legacy_passed_directly<std::decay_t<T>>, // legacy passed directly iter
oneapi::dpl::__internal::__is_reversed_indirectly_device_accessible_it<std::decay_t<T>>>; // reverse iterator
struct __is_onedpl_indirectly_device_accessible_iterator_fn
{
template <typename T>
constexpr auto
operator()(const T& t) const -> decltype(is_onedpl_indirectly_device_accessible_iterator(t));
};
inline constexpr __is_onedpl_indirectly_device_accessible_iterator_fn __is_onedpl_indirectly_device_accessible_iterator;
//zip_iterator version for forward iterator
//== and != comparison is performed only on the first element of the tuple
//
//zip_forward_iterator is implemented as an internal class and should remain so. Users should never encounter
//this class or be returned a type of its value_type, reference, etc as the tuple-like type used internally
//is variable dependent on the C++ standard library version and could cause an inconsistent ABI due to resulting
//layout changes of this class.
template <typename... _Types>
class zip_forward_iterator
{
template <typename... _Ts>
using __tuple_t =
#if _ONEDPL_CAN_USE_STD_TUPLE_PROXY_ITERATOR
::std::tuple<_Ts...>;
#else
oneapi::dpl::__internal::tuple<_Ts...>;
#endif
static const ::std::size_t __num_types = sizeof...(_Types);
typedef __tuple_t<_Types...> __it_types;
public:
typedef ::std::make_signed_t<::std::size_t> difference_type;
typedef __tuple_t<typename ::std::iterator_traits<_Types>::value_type...> value_type;
typedef __tuple_t<typename ::std::iterator_traits<_Types>::reference...> reference;
typedef __tuple_t<typename ::std::iterator_traits<_Types>::pointer...> pointer;
typedef ::std::forward_iterator_tag iterator_category;
zip_forward_iterator() : __my_it_() {}
explicit zip_forward_iterator(_Types... __args) : __my_it_(__tuple_t<_Types...>{__args...}) {}
// On windows, this requires clause is necessary so that concepts in MSVC STL do not detect the iterator as
// dereferenceable when a source iterator is a sycl_iterator, which is a supported type.
reference
operator*() const _ONEDPL_CPP20_REQUIRES(std::indirectly_readable<_Types> &&...)
{
return __make_references<reference>()(__my_it_, ::std::make_index_sequence<__num_types>());
}
zip_forward_iterator&
operator++()
{
__tuple_util<__num_types>::__pre_increment(__my_it_);
return *this;
}
zip_forward_iterator
operator++(int)
{
zip_forward_iterator __it(*this);
++(*this);
return __it;
}
bool
operator==(const zip_forward_iterator& __it) const
{
return ::std::get<0>(__my_it_) == ::std::get<0>(__it.__my_it_);
}
bool
operator!=(const zip_forward_iterator& __it) const
{
return !(*this == __it);
}
__it_types
base() const
{
return __my_it_;
}
private:
__it_types __my_it_;
};
} // namespace __internal
} // namespace dpl
} // namespace oneapi
namespace oneapi
{
namespace dpl
{
template <typename T>
struct is_indirectly_device_accessible
: decltype(oneapi::dpl::__internal::__is_onedpl_indirectly_device_accessible_iterator(std::declval<T>()))
{
static_assert(
std::is_same_v<decltype(decltype(oneapi::dpl::__internal::__is_onedpl_indirectly_device_accessible_iterator(
std::declval<T>()))::value),
const bool>,
"Return type of is_onedpl_indirectly_device_accessible_iterator does not have the characteristics of a "
"bool_constant");
};
template <typename T>
inline constexpr bool is_indirectly_device_accessible_v = is_indirectly_device_accessible<T>::value;
template <typename _Ip>
class counting_iterator
{
static_assert(::std::is_integral_v<_Ip>, "Cannot instantiate counting_iterator with a non-integer type");
public:
typedef ::std::make_signed_t<_Ip> difference_type;
typedef _Ip value_type;
typedef const _Ip* pointer;
// There is no storage behind the iterator, so we return a value instead of reference.
typedef _Ip reference;
typedef ::std::random_access_iterator_tag iterator_category;
counting_iterator() : __my_counter_() {}
explicit counting_iterator(_Ip __init) : __my_counter_(__init) {}
reference operator*() const { return __my_counter_; }
reference operator[](difference_type __i) const { return *(*this + __i); }
difference_type
operator-(const counting_iterator& __it) const
{
return __my_counter_ - __it.__my_counter_;
}
counting_iterator&
operator+=(difference_type __forward)
{
__my_counter_ += __forward;
return *this;
}
counting_iterator&
operator-=(difference_type __backward)
{
return *this += -__backward;
}
counting_iterator&
operator++()
{
return *this += 1;
}
counting_iterator&
operator--()
{
return *this -= 1;
}
counting_iterator
operator++(int)
{
counting_iterator __it(*this);
++(*this);
return __it;
}
counting_iterator
operator--(int)
{
counting_iterator __it(*this);
--(*this);
return __it;
}
counting_iterator
operator-(difference_type __backward) const
{
return counting_iterator(__my_counter_ - __backward);
}
counting_iterator
operator+(difference_type __forward) const
{
return counting_iterator(__my_counter_ + __forward);
}
friend counting_iterator
operator+(difference_type __forward, const counting_iterator __it)
{
return __it + __forward;
}
bool
operator==(const counting_iterator& __it) const
{
return *this - __it == 0;
}
bool
operator!=(const counting_iterator& __it) const
{
return !(*this == __it);
}
bool
operator<(const counting_iterator& __it) const
{
return *this - __it < 0;
}
bool
operator>(const counting_iterator& __it) const
{
return __it < *this;
}
bool
operator<=(const counting_iterator& __it) const
{
return !(*this > __it);
}
bool
operator>=(const counting_iterator& __it) const
{
return !(*this < __it);
}
friend std::true_type
is_onedpl_indirectly_device_accessible_iterator(const counting_iterator&);
private:
_Ip __my_counter_;
};
template <typename... _Types>
class zip_iterator
{
static_assert(sizeof...(_Types) > 0, "Cannot instantiate zip_iterator with empty template parameter pack");
static const ::std::size_t __num_types = sizeof...(_Types);
typedef oneapi::dpl::__internal::tuple<_Types...> __it_types;
public:
typedef ::std::make_signed_t<::std::size_t> difference_type;
typedef oneapi::dpl::__internal::tuple<typename ::std::iterator_traits<_Types>::value_type...> value_type;
typedef oneapi::dpl::__internal::tuple<typename ::std::iterator_traits<_Types>::reference...> reference;
typedef ::std::tuple<typename ::std::iterator_traits<_Types>::pointer...> pointer;
typedef ::std::random_access_iterator_tag iterator_category;
using is_zip = ::std::true_type;
zip_iterator() : __my_it_() {}
explicit zip_iterator(_Types... __args) : __my_it_(::std::make_tuple(__args...)) {}
explicit zip_iterator(std::tuple<_Types...> __arg) : __my_it_(__arg) {}
// On windows, this requires clause is necessary so that concepts in MSVC STL do not detect the iterator as
// dereferenceable when a source iterator is a sycl_iterator, which is a supported type.
reference
operator*() const _ONEDPL_CPP20_REQUIRES(std::indirectly_readable<_Types> &&...)
{
return oneapi::dpl::__internal::__make_references<reference>()(__my_it_,
::std::make_index_sequence<__num_types>());
}
reference operator[](difference_type __i) const { return *(*this + __i); }
difference_type
operator-(const zip_iterator& __it) const
{
return ::std::get<0>(__my_it_) - ::std::get<0>(__it.__my_it_);
}
zip_iterator&
operator+=(difference_type __forward)
{
oneapi::dpl::__internal::__tuple_util<__num_types>::__increment(__my_it_, __forward);
return *this;
}
zip_iterator&
operator-=(difference_type __backward)
{
return *this += -__backward;
}
zip_iterator&
operator++()
{
return *this += 1;
}
zip_iterator&
operator--()
{
return *this -= 1;
}
zip_iterator
operator++(int)
{
zip_iterator __it(*this);
++(*this);
return __it;
}
zip_iterator
operator--(int)
{
zip_iterator __it(*this);
--(*this);
return __it;
}
zip_iterator
operator-(difference_type __backward) const
{
zip_iterator __it(*this);
return __it -= __backward;
}
zip_iterator
operator+(difference_type __forward) const
{
zip_iterator __it(*this);
return __it += __forward;
}
friend zip_iterator
operator+(difference_type __forward, const zip_iterator& __it)
{
return __it + __forward;
}
bool
operator==(const zip_iterator& __it) const
{
return *this - __it == 0;
}
__it_types
base() const
{
return __my_it_;
}
bool
operator!=(const zip_iterator& __it) const
{
return !(*this == __it);
}
bool
operator<(const zip_iterator& __it) const
{
return *this - __it < 0;
}
bool
operator>(const zip_iterator& __it) const
{
return __it < *this;
}
bool
operator<=(const zip_iterator& __it) const
{
return !(*this > __it);
}
bool
operator>=(const zip_iterator& __it) const
{
return !(*this < __it);
}
friend auto
is_onedpl_indirectly_device_accessible_iterator(const zip_iterator&)
-> std::conjunction<oneapi::dpl::is_indirectly_device_accessible<_Types>...>;
private:
__it_types __my_it_;
};
template <typename... _Tp>
zip_iterator<_Tp...>
make_zip_iterator(_Tp... __args)
{
return zip_iterator<_Tp...>(__args...);
}
template <typename... _Tp>
zip_iterator<_Tp...>
make_zip_iterator(std::tuple<_Tp...> __arg)
{
return zip_iterator<_Tp...>(__arg);
}
template <typename _Iter, typename _UnaryFunc>
class transform_iterator
{
private:
_Iter __my_it_;
_UnaryFunc __my_unary_func_;
static_assert(std::is_invocable_v<const std::decay_t<_UnaryFunc>, typename std::iterator_traits<_Iter>::reference>,
"_UnaryFunc does not have a const-qualified call operator which accepts the reference type of the "
"base iterator as argument.");
public:
typedef typename ::std::iterator_traits<_Iter>::difference_type difference_type;
typedef decltype(__my_unary_func_(::std::declval<typename ::std::iterator_traits<_Iter>::reference>())) reference;
typedef ::std::remove_reference_t<reference> value_type;
typedef typename ::std::iterator_traits<_Iter>::pointer pointer;
typedef typename ::std::iterator_traits<_Iter>::iterator_category iterator_category;
//default constructor will only be present if both the unary functor and iterator are default constructible
transform_iterator() = default;
//only enable this constructor if the unary functor is default constructible
template <typename _UnaryFuncLocal = _UnaryFunc,
std::enable_if_t<std::is_default_constructible_v<_UnaryFuncLocal>, int> = 0>
transform_iterator(_Iter __it) : __my_it_(std::move(__it))
{
}
transform_iterator(_Iter __it, _UnaryFunc __unary_func)
: __my_it_(std::move(__it)), __my_unary_func_(std::move(__unary_func))
{
}
transform_iterator(const transform_iterator&) = default;
transform_iterator&
operator=(const transform_iterator& __input)
{
__my_it_ = __input.__my_it_;
// If copy assignment is available, copy the functor, otherwise skip it.
// For non-copy assignable functors, this copy assignment operator departs from the sycl 2020 specification
// requirement of device copyable types for copy assignment to be the same as a bitwise copy of the object.
// TODO: Explore (ABI breaking) change to use std::optional or similar and using copy constructor to implement
// copy assignment to better comply with SYCL 2020 specification.
if constexpr (std::is_copy_assignable_v<_UnaryFunc>)
{
__my_unary_func_ = __input.__my_unary_func_;
}
return *this;
}
// On windows, this requires clause is necessary so that concepts in MSVC STL do not detect the iterator as
// dereferenceable when the source iterator is a sycl_iterator, which is a supported type.
reference
operator*() const _ONEDPL_CPP20_REQUIRES(std::indirectly_readable<_Iter>)
{
return __my_unary_func_(*__my_it_);
}
reference operator[](difference_type __i) const { return *(*this + __i); }
transform_iterator&
operator++()
{
++__my_it_;
return *this;
}
transform_iterator&
operator--()
{
--__my_it_;
return *this;
}
transform_iterator
operator++(int)
{
transform_iterator __it(*this);
++(*this);
return __it;
}
transform_iterator
operator--(int)
{
transform_iterator __it(*this);
--(*this);
return __it;
}
transform_iterator
operator+(difference_type __forward) const
{
return {__my_it_ + __forward, __my_unary_func_};
}
transform_iterator
operator-(difference_type __backward) const
{
return {__my_it_ - __backward, __my_unary_func_};
}
transform_iterator&
operator+=(difference_type __forward)
{
__my_it_ += __forward;
return *this;
}
transform_iterator&
operator-=(difference_type __backward)
{
__my_it_ -= __backward;
return *this;
}
friend transform_iterator
operator+(difference_type __forward, const transform_iterator& __it)
{
return __it + __forward;
}
difference_type
operator-(const transform_iterator& __it) const
{
return __my_it_ - __it.__my_it_;
}
bool
operator==(const transform_iterator& __it) const
{
return __my_it_ == __it.__my_it_;
}
bool
operator!=(const transform_iterator& __it) const
{
return !(*this == __it);
}
bool
operator<(const transform_iterator& __it) const
{
return *this - __it < 0;
}
bool
operator>(const transform_iterator& __it) const
{
return __it < *this;
}
bool
operator<=(const transform_iterator& __it) const
{
return !(*this > __it);
}
bool
operator>=(const transform_iterator& __it) const
{
return !(*this < __it);
}
_Iter
base() const
{
return __my_it_;
}
_UnaryFunc
functor() const
{
return __my_unary_func_;
}
friend auto
is_onedpl_indirectly_device_accessible_iterator(const transform_iterator&)
-> oneapi::dpl::is_indirectly_device_accessible<_Iter>;
};
template <typename _Iter, typename _UnaryFunc>
transform_iterator<_Iter, _UnaryFunc>
make_transform_iterator(_Iter __it, _UnaryFunc __unary_func)
{
return transform_iterator<_Iter, _UnaryFunc>(__it, __unary_func);
}
namespace __internal
{
//functor concept
struct __functor_concept
{
template <typename _T>
static auto
test(int) -> decltype(::std::declval<_T>()(0), ::std::true_type{});
template <typename _T>
static auto
test(...) -> ::std::false_type;
};
template <typename _T>
inline constexpr bool __is_functor = decltype(__functor_concept::test<_T>(0))::value;
} // namespace __internal
template <typename SourceIterator, typename _Permutation>
class permutation_iterator
{
public:
typedef std::conditional_t<
!__internal::__is_functor<_Permutation>, _Permutation,
transform_iterator<counting_iterator<typename ::std::iterator_traits<SourceIterator>::difference_type>,
_Permutation>>
IndexMap;
typedef typename ::std::iterator_traits<SourceIterator>::difference_type difference_type;
typedef typename ::std::iterator_traits<SourceIterator>::value_type value_type;
typedef typename ::std::iterator_traits<SourceIterator>::pointer pointer;
typedef typename ::std::iterator_traits<SourceIterator>::reference reference;
typedef SourceIterator base_type;
typedef ::std::random_access_iterator_tag iterator_category;
typedef ::std::true_type is_permutation;
permutation_iterator() = default;
template <typename _T = _Permutation, ::std::enable_if_t<!__internal::__is_functor<_T>, int> = 0>
permutation_iterator(SourceIterator input1, _Permutation input2) : my_source_it(input1), my_index(input2)
{
}
template <typename _T = _Permutation, ::std::enable_if_t<__internal::__is_functor<_T>, int> = 0>
permutation_iterator(SourceIterator input1, _Permutation __f, difference_type __idx = 0)
: my_source_it(input1), my_index(counting_iterator<difference_type>(__idx), __f)
{
}
private:
template <typename _T = _Permutation, ::std::enable_if_t<__internal::__is_functor<_T>, int> = 0>
permutation_iterator(SourceIterator input1, IndexMap input2) : my_source_it(input1), my_index(input2)
{
}
public:
SourceIterator
base() const
{
return my_source_it;
}
auto
map() const
{
if constexpr (__internal::__is_functor<_Permutation>)
return my_index.functor();
else
return my_index;
}
// On windows, this requires clause is necessary so that concepts in MSVC STL do not detect the iterator as
// dereferenceable when the source or map iterator is a sycl_iterator, which is a supported type for both.
reference
operator*() const
_ONEDPL_CPP20_REQUIRES(std::indirectly_readable<SourceIterator> && std::indirectly_readable<IndexMap>)
{
return my_source_it[*my_index];
}
reference operator[](difference_type __i) const { return *(*this + __i); }
permutation_iterator&
operator++()
{
++my_index;
return *this;
}
permutation_iterator
operator++(int)
{
permutation_iterator it(*this);
++(*this);
return it;
}
permutation_iterator&
operator--()
{
--my_index;
return *this;
}
permutation_iterator
operator--(int)
{
permutation_iterator it(*this);
--(*this);
return it;
}
permutation_iterator
operator+(difference_type forward) const
{
return permutation_iterator(my_source_it, my_index + forward);
}
permutation_iterator
operator-(difference_type backward) const
{
return permutation_iterator(my_source_it, my_index - backward);
}
permutation_iterator&
operator+=(difference_type forward)
{
my_index += forward;
return *this;
}
permutation_iterator&
operator-=(difference_type forward)
{
my_index -= forward;
return *this;
}
difference_type
operator-(const permutation_iterator& it) const
{
return my_index - it.my_index;
}
friend permutation_iterator
operator+(difference_type forward, const permutation_iterator& it)
{
return permutation_iterator(it.my_source_it, it.my_index + forward);
}
bool
operator==(const permutation_iterator& it) const
{
return *this - it == 0;
}
bool
operator!=(const permutation_iterator& it) const
{
return !(*this == it);
}
bool
operator<(const permutation_iterator& it) const
{
return *this - it < 0;
}
bool
operator>(const permutation_iterator& it) const
{
return it < *this;
}
bool
operator<=(const permutation_iterator& it) const
{
return !(*this > it);
}
bool
operator>=(const permutation_iterator& it) const
{
return !(*this < it);
}
friend auto
is_onedpl_indirectly_device_accessible_iterator(const permutation_iterator&)
-> std::conjunction<oneapi::dpl::is_indirectly_device_accessible<SourceIterator>,
oneapi::dpl::is_indirectly_device_accessible<
typename oneapi::dpl::permutation_iterator<SourceIterator, _Permutation>::IndexMap>>;
private:
SourceIterator my_source_it;
IndexMap my_index;
};
template <typename SourceIterator, typename IndexMap, typename... StartIndex>
permutation_iterator<SourceIterator, IndexMap>
make_permutation_iterator(SourceIterator source, IndexMap map, StartIndex... idx)
{
return permutation_iterator<SourceIterator, IndexMap>(source, map, idx...);
}
namespace internal
{
// Copyable implementation of ignore to allow creation of temporary buffers using the type.
struct ignore_copyable
{
template <typename T>
ignore_copyable&
operator=(T&&)
{
return *this;
}
template <typename T>
const ignore_copyable&
operator=(T&&) const
{
return *this;
}
bool
operator==(const ignore_copyable&) const
{
return true;
}
bool
operator!=(const ignore_copyable& other) const
{
return !(*this == other);
}
};
inline constexpr ignore_copyable ignore{};
} // namespace internal
class discard_iterator
{
public:
typedef ::std::ptrdiff_t difference_type;
typedef internal::ignore_copyable value_type;
typedef void* pointer;
typedef value_type reference;
typedef ::std::random_access_iterator_tag iterator_category;
using is_discard = ::std::true_type;
discard_iterator() : __my_position_() {}
explicit discard_iterator(difference_type __init) : __my_position_(__init) {}
reference operator*() const { return internal::ignore; }
reference operator[](difference_type) const { return internal::ignore; }
// GCC Bug 66297: constexpr non-static member functions of non-literal types
#if __GNUC__ && _ONEDPL_GCC_VERSION < 70200 && !(__INTEL_COMPILER || __clang__)
# define _ONEDPL_CONSTEXPR_FIX
#else
# define _ONEDPL_CONSTEXPR_FIX constexpr
#endif
_ONEDPL_CONSTEXPR_FIX difference_type
operator-(const discard_iterator& __it) const
{
return __my_position_ - __it.__my_position_;
}
_ONEDPL_CONSTEXPR_FIX bool
operator==(const discard_iterator& __it) const
{
return __my_position_ == __it.__my_position_;
}
_ONEDPL_CONSTEXPR_FIX bool
operator!=(const discard_iterator& __it) const
{
return !(*this == __it);
}
#undef _ONEDPL_CONSTEXPR_FIX
bool
operator<(const discard_iterator& __it) const
{
return *this - __it < 0;
}
bool
operator>(const discard_iterator& __it) const
{
return __it < *this;
}
discard_iterator&
operator++()
{
return *this += 1;
}
discard_iterator&
operator--()
{
return *this -= 1;
}
discard_iterator
operator++(int)
{
discard_iterator __it(*this);
++(*this);
return __it;
}
discard_iterator
operator--(int)
{
discard_iterator __it(*this);
--(*this);
return __it;
}
discard_iterator&
operator+=(difference_type __forward)
{
__my_position_ += __forward;
return *this;
}
discard_iterator&
operator-=(difference_type __backward)
{
*this += -__backward;
return *this;
}
discard_iterator
operator+(difference_type __forward) const
{
return discard_iterator(__my_position_ + __forward);
}
discard_iterator
operator-(difference_type __backward) const
{
return discard_iterator(__my_position_ - __backward);
}
friend discard_iterator
operator+(difference_type __forward, const discard_iterator& __it)
{
return __it + __forward;
}
bool
operator<=(const discard_iterator& __it) const
{
return !(*this > __it);
}
bool
operator>=(const discard_iterator& __it) const
{
return !(*this < __it);
}
friend std::true_type
is_onedpl_indirectly_device_accessible_iterator(const discard_iterator&);
private:
difference_type __my_position_;
};