algorithm_impl.h 168 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628
  1. // -*- C++ -*-
  2. //===-- algorithm_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. #ifndef _PSTL_ALGORITHM_IMPL_H
  10. #define _PSTL_ALGORITHM_IMPL_H
  11. #include <iterator>
  12. #include <type_traits>
  13. #include <utility>
  14. #include <functional>
  15. #include <algorithm>
  16. #include "execution_impl.h"
  17. #include "memory_impl.h"
  18. #include "parallel_backend_utils.h"
  19. #include "parallel_backend.h"
  20. #include "parallel_impl.h"
  21. #include "unseq_backend_simd.h"
  22. namespace __pstl
  23. {
  24. namespace __internal
  25. {
  26. //------------------------------------------------------------------------
  27. // any_of
  28. //------------------------------------------------------------------------
  29. template <class _ForwardIterator, class _Pred>
  30. bool
  31. __brick_any_of(const _ForwardIterator __first, const _ForwardIterator __last, _Pred __pred,
  32. /*__is_vector=*/std::false_type) noexcept
  33. {
  34. return std::any_of(__first, __last, __pred);
  35. };
  36. template <class _ForwardIterator, class _Pred>
  37. bool
  38. __brick_any_of(const _ForwardIterator __first, const _ForwardIterator __last, _Pred __pred,
  39. /*__is_vector=*/std::true_type) noexcept
  40. {
  41. return __unseq_backend::__simd_or(__first, __last - __first, __pred);
  42. };
  43. template <class _ExecutionPolicy, class _ForwardIterator, class _Pred, class _IsVector>
  44. bool
  45. __pattern_any_of(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred,
  46. _IsVector __is_vector, /*parallel=*/std::false_type) noexcept
  47. {
  48. return __internal::__brick_any_of(__first, __last, __pred, __is_vector);
  49. }
  50. template <class _ExecutionPolicy, class _ForwardIterator, class _Pred, class _IsVector>
  51. bool
  52. __pattern_any_of(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred,
  53. _IsVector __is_vector, /*parallel=*/std::true_type)
  54. {
  55. return __internal::__except_handler([&]() {
  56. return __internal::__parallel_or(std::forward<_ExecutionPolicy>(__exec), __first, __last,
  57. [__pred, __is_vector](_ForwardIterator __i, _ForwardIterator __j) {
  58. return __internal::__brick_any_of(__i, __j, __pred, __is_vector);
  59. });
  60. });
  61. }
  62. // [alg.foreach]
  63. // for_each_n with no policy
  64. template <class _ForwardIterator, class _Size, class _Function>
  65. _ForwardIterator
  66. __for_each_n_it_serial(_ForwardIterator __first, _Size __n, _Function __f)
  67. {
  68. for (; __n > 0; ++__first, --__n)
  69. __f(__first);
  70. return __first;
  71. }
  72. //------------------------------------------------------------------------
  73. // walk1 (pseudo)
  74. //
  75. // walk1 evaluates f(x) for each dereferenced value x drawn from [first,last)
  76. //------------------------------------------------------------------------
  77. template <class _ForwardIterator, class _Function>
  78. void
  79. __brick_walk1(_ForwardIterator __first, _ForwardIterator __last, _Function __f, /*vector=*/std::false_type) noexcept
  80. {
  81. std::for_each(__first, __last, __f);
  82. }
  83. template <class _RandomAccessIterator, class _Function>
  84. void
  85. __brick_walk1(_RandomAccessIterator __first, _RandomAccessIterator __last, _Function __f,
  86. /*vector=*/std::true_type) noexcept
  87. {
  88. __unseq_backend::__simd_walk_1(__first, __last - __first, __f);
  89. }
  90. template <class _ExecutionPolicy, class _ForwardIterator, class _Function, class _IsVector>
  91. void
  92. __pattern_walk1(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Function __f,
  93. _IsVector __is_vector,
  94. /*parallel=*/std::false_type) noexcept
  95. {
  96. __internal::__brick_walk1(__first, __last, __f, __is_vector);
  97. }
  98. template <class _ExecutionPolicy, class _ForwardIterator, class _Function, class _IsVector>
  99. void
  100. __pattern_walk1(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Function __f,
  101. _IsVector __is_vector,
  102. /*parallel=*/std::true_type)
  103. {
  104. __internal::__except_handler([&]() {
  105. __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last,
  106. [__f, __is_vector](_ForwardIterator __i, _ForwardIterator __j) {
  107. __internal::__brick_walk1(__i, __j, __f, __is_vector);
  108. });
  109. });
  110. }
  111. template <class _ExecutionPolicy, class _ForwardIterator, class _Brick>
  112. void
  113. __pattern_walk_brick(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Brick __brick,
  114. /*parallel=*/std::false_type) noexcept
  115. {
  116. __brick(__first, __last);
  117. }
  118. template <class _ExecutionPolicy, class _ForwardIterator, class _Brick>
  119. void
  120. __pattern_walk_brick(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Brick __brick,
  121. /*parallel=*/std::true_type)
  122. {
  123. __internal::__except_handler([&]() {
  124. __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last,
  125. [__brick](_ForwardIterator __i, _ForwardIterator __j) { __brick(__i, __j); });
  126. });
  127. }
  128. //------------------------------------------------------------------------
  129. // walk1_n
  130. //------------------------------------------------------------------------
  131. template <class _ForwardIterator, class _Size, class _Function>
  132. _ForwardIterator
  133. __brick_walk1_n(_ForwardIterator __first, _Size __n, _Function __f, /*_IsVectorTag=*/std::false_type)
  134. {
  135. return __internal::__for_each_n_it_serial(__first, __n,
  136. [&__f](_ForwardIterator __it) { __f(*__it); }); // calling serial version
  137. }
  138. template <class _RandomAccessIterator, class _DifferenceType, class _Function>
  139. _RandomAccessIterator
  140. __brick_walk1_n(_RandomAccessIterator __first, _DifferenceType __n, _Function __f,
  141. /*vectorTag=*/std::true_type) noexcept
  142. {
  143. return __unseq_backend::__simd_walk_1(__first, __n, __f);
  144. }
  145. template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Function, class _IsVector>
  146. _ForwardIterator
  147. __pattern_walk1_n(_ExecutionPolicy&&, _ForwardIterator __first, _Size __n, _Function __f, _IsVector __is_vector,
  148. /*is_parallel=*/std::false_type) noexcept
  149. {
  150. return __internal::__brick_walk1_n(__first, __n, __f, __is_vector);
  151. }
  152. template <class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Function, class _IsVector>
  153. _RandomAccessIterator
  154. __pattern_walk1_n(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _Size __n, _Function __f,
  155. _IsVector __is_vector,
  156. /*is_parallel=*/std::true_type)
  157. {
  158. __internal::__pattern_walk1(std::forward<_ExecutionPolicy>(__exec), __first, __first + __n, __f, __is_vector,
  159. std::true_type());
  160. return __first + __n;
  161. }
  162. template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Brick>
  163. _ForwardIterator
  164. __pattern_walk_brick_n(_ExecutionPolicy&&, _ForwardIterator __first, _Size __n, _Brick __brick,
  165. /*is_parallel=*/std::false_type) noexcept
  166. {
  167. return __brick(__first, __n);
  168. }
  169. template <class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Brick>
  170. _RandomAccessIterator
  171. __pattern_walk_brick_n(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _Size __n, _Brick __brick,
  172. /*is_parallel=*/std::true_type)
  173. {
  174. return __internal::__except_handler([&]() {
  175. __par_backend::__parallel_for(
  176. std::forward<_ExecutionPolicy>(__exec), __first, __first + __n,
  177. [__brick](_RandomAccessIterator __i, _RandomAccessIterator __j) { __brick(__i, __j - __i); });
  178. return __first + __n;
  179. });
  180. }
  181. //------------------------------------------------------------------------
  182. // walk2 (pseudo)
  183. //
  184. // walk2 evaluates f(x,y) for deferenced values (x,y) drawn from [first1,last1) and [first2,...)
  185. //------------------------------------------------------------------------
  186. template <class _ForwardIterator1, class _ForwardIterator2, class _Function>
  187. _ForwardIterator2
  188. __brick_walk2(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _Function __f,
  189. /*vector=*/std::false_type) noexcept
  190. {
  191. for (; __first1 != __last1; ++__first1, ++__first2)
  192. __f(*__first1, *__first2);
  193. return __first2;
  194. }
  195. template <class _ForwardIterator1, class _ForwardIterator2, class _Function>
  196. _ForwardIterator2
  197. __brick_walk2(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _Function __f,
  198. /*vector=*/std::true_type) noexcept
  199. {
  200. return __unseq_backend::__simd_walk_2(__first1, __last1 - __first1, __first2, __f);
  201. }
  202. template <class _ForwardIterator1, class _Size, class _ForwardIterator2, class _Function>
  203. _ForwardIterator2
  204. __brick_walk2_n(_ForwardIterator1 __first1, _Size __n, _ForwardIterator2 __first2, _Function __f,
  205. /*vector=*/std::false_type) noexcept
  206. {
  207. for (; __n > 0; --__n, ++__first1, ++__first2)
  208. __f(*__first1, *__first2);
  209. return __first2;
  210. }
  211. template <class _ForwardIterator1, class _Size, class _ForwardIterator2, class _Function>
  212. _ForwardIterator2
  213. __brick_walk2_n(_ForwardIterator1 __first1, _Size __n, _ForwardIterator2 __first2, _Function __f,
  214. /*vector=*/std::true_type) noexcept
  215. {
  216. return __unseq_backend::__simd_walk_2(__first1, __n, __first2, __f);
  217. }
  218. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Function, class _IsVector>
  219. _ForwardIterator2
  220. __pattern_walk2(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  221. _Function __f, _IsVector __is_vector, /*parallel=*/std::false_type) noexcept
  222. {
  223. return __internal::__brick_walk2(__first1, __last1, __first2, __f, __is_vector);
  224. }
  225. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Function, class _IsVector>
  226. _ForwardIterator2
  227. __pattern_walk2(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
  228. _ForwardIterator2 __first2, _Function __f, _IsVector __is_vector, /*parallel=*/std::true_type)
  229. {
  230. return __internal::__except_handler([&]() {
  231. __par_backend::__parallel_for(
  232. std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
  233. [__f, __first1, __first2, __is_vector](_ForwardIterator1 __i, _ForwardIterator1 __j) {
  234. __internal::__brick_walk2(__i, __j, __first2 + (__i - __first1), __f, __is_vector);
  235. });
  236. return __first2 + (__last1 - __first1);
  237. });
  238. }
  239. template <class _ExecutionPolicy, class _ForwardIterator1, class _Size, class _ForwardIterator2, class _Function,
  240. class _IsVector>
  241. _ForwardIterator2
  242. __pattern_walk2_n(_ExecutionPolicy&&, _ForwardIterator1 __first1, _Size __n, _ForwardIterator2 __first2, _Function __f,
  243. _IsVector __is_vector, /*parallel=*/std::false_type) noexcept
  244. {
  245. return __internal::__brick_walk2_n(__first1, __n, __first2, __f, __is_vector);
  246. }
  247. template <class _ExecutionPolicy, class _RandomAccessIterator1, class _Size, class _RandomAccessIterator2,
  248. class _Function, class _IsVector>
  249. _RandomAccessIterator2
  250. __pattern_walk2_n(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _Size __n, _RandomAccessIterator2 __first2,
  251. _Function __f, _IsVector __is_vector, /*parallel=*/std::true_type)
  252. {
  253. return __internal::__pattern_walk2(std::forward<_ExecutionPolicy>(__exec), __first1, __first1 + __n, __first2, __f,
  254. __is_vector, std::true_type());
  255. }
  256. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Brick>
  257. _ForwardIterator2
  258. __pattern_walk2_brick(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
  259. _ForwardIterator2 __first2, _Brick __brick, /*parallel=*/std::false_type) noexcept
  260. {
  261. return __brick(__first1, __last1, __first2);
  262. }
  263. template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _Brick>
  264. _RandomAccessIterator2
  265. __pattern_walk2_brick(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1,
  266. _RandomAccessIterator2 __first2, _Brick __brick, /*parallel=*/std::true_type)
  267. {
  268. return __internal::__except_handler([&]() {
  269. __par_backend::__parallel_for(
  270. std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
  271. [__first1, __first2, __brick](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) {
  272. __brick(__i, __j, __first2 + (__i - __first1));
  273. });
  274. return __first2 + (__last1 - __first1);
  275. });
  276. }
  277. template <class _ExecutionPolicy, class _RandomAccessIterator1, class _Size, class _RandomAccessIterator2, class _Brick>
  278. _RandomAccessIterator2
  279. __pattern_walk2_brick_n(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _Size __n,
  280. _RandomAccessIterator2 __first2, _Brick __brick, /*parallel=*/std::true_type)
  281. {
  282. return __internal::__except_handler([&]() {
  283. __par_backend::__parallel_for(
  284. std::forward<_ExecutionPolicy>(__exec), __first1, __first1 + __n,
  285. [__first1, __first2, __brick](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) {
  286. __brick(__i, __j - __i, __first2 + (__i - __first1));
  287. });
  288. return __first2 + __n;
  289. });
  290. }
  291. template <class _ExecutionPolicy, class _ForwardIterator1, class _Size, class _ForwardIterator2, class _Brick>
  292. _ForwardIterator2
  293. __pattern_walk2_brick_n(_ExecutionPolicy&&, _ForwardIterator1 __first1, _Size __n, _ForwardIterator2 __first2,
  294. _Brick __brick, /*parallel=*/std::false_type) noexcept
  295. {
  296. return __brick(__first1, __n, __first2);
  297. }
  298. //------------------------------------------------------------------------
  299. // walk3 (pseudo)
  300. //
  301. // walk3 evaluates f(x,y,z) for (x,y,z) drawn from [first1,last1), [first2,...), [first3,...)
  302. //------------------------------------------------------------------------
  303. template <class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator3, class _Function>
  304. _ForwardIterator3
  305. __brick_walk3(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  306. _ForwardIterator3 __first3, _Function __f, /*vector=*/std::false_type) noexcept
  307. {
  308. for (; __first1 != __last1; ++__first1, ++__first2, ++__first3)
  309. __f(*__first1, *__first2, *__first3);
  310. return __first3;
  311. }
  312. template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _RandomAccessIterator3, class _Function>
  313. _RandomAccessIterator3
  314. __brick_walk3(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2,
  315. _RandomAccessIterator3 __first3, _Function __f, /*vector=*/std::true_type) noexcept
  316. {
  317. return __unseq_backend::__simd_walk_3(__first1, __last1 - __first1, __first2, __first3, __f);
  318. }
  319. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator3,
  320. class _Function, class _IsVector>
  321. _ForwardIterator3
  322. __pattern_walk3(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  323. _ForwardIterator3 __first3, _Function __f, _IsVector __is_vector, /*parallel=*/std::false_type) noexcept
  324. {
  325. return __internal::__brick_walk3(__first1, __last1, __first2, __first3, __f, __is_vector);
  326. }
  327. template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
  328. class _RandomAccessIterator3, class _Function, class _IsVector>
  329. _RandomAccessIterator3
  330. __pattern_walk3(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1,
  331. _RandomAccessIterator2 __first2, _RandomAccessIterator3 __first3, _Function __f, _IsVector __is_vector,
  332. /*parallel=*/std::true_type)
  333. {
  334. return __internal::__except_handler([&]() {
  335. __par_backend::__parallel_for(
  336. std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
  337. [__f, __first1, __first2, __first3, __is_vector](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) {
  338. __internal::__brick_walk3(__i, __j, __first2 + (__i - __first1), __first3 + (__i - __first1), __f,
  339. __is_vector);
  340. });
  341. return __first3 + (__last1 - __first1);
  342. });
  343. }
  344. //------------------------------------------------------------------------
  345. // equal
  346. //------------------------------------------------------------------------
  347. template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
  348. bool
  349. __brick_equal(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  350. _ForwardIterator2 __last2, _BinaryPredicate __p, /* IsVector = */ std::false_type) noexcept
  351. {
  352. return std::equal(__first1, __last1, __first2, __last2, __p);
  353. }
  354. template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate>
  355. bool
  356. __brick_equal(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2,
  357. _RandomAccessIterator2 __last2, _BinaryPredicate __p, /* is_vector = */ std::true_type) noexcept
  358. {
  359. if (__last1 - __first1 != __last2 - __first2)
  360. return false;
  361. return __unseq_backend::__simd_first(__first1, __last1 - __first1, __first2,
  362. __internal::__not_pred<_BinaryPredicate>(__p))
  363. .first == __last1;
  364. }
  365. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate,
  366. class _IsVector>
  367. bool
  368. __pattern_equal(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  369. _ForwardIterator2 __last2, _BinaryPredicate __p, _IsVector __is_vector, /* is_parallel = */
  370. std::false_type) noexcept
  371. {
  372. return __internal::__brick_equal(__first1, __last1, __first2, __last2, __p, __is_vector);
  373. }
  374. template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate,
  375. class _IsVector>
  376. bool
  377. __pattern_equal(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1,
  378. _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, _BinaryPredicate __p,
  379. _IsVector __is_vector, /*is_parallel=*/std::true_type)
  380. {
  381. if (__last1 - __first1 != __last2 - __first2)
  382. return false;
  383. return __internal::__except_handler([&]() {
  384. return !__internal::__parallel_or(
  385. std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
  386. [__first1, __first2, __p, __is_vector](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) {
  387. return !__internal::__brick_equal(__i, __j, __first2 + (__i - __first1), __first2 + (__j - __first1),
  388. __p, __is_vector);
  389. });
  390. });
  391. }
  392. //------------------------------------------------------------------------
  393. // equal version for sequences with equal length
  394. //------------------------------------------------------------------------
  395. template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
  396. bool
  397. __brick_equal(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _BinaryPredicate __p,
  398. /* IsVector = */ std::false_type) noexcept
  399. {
  400. return std::equal(__first1, __last1, __first2, __p);
  401. }
  402. template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate>
  403. bool
  404. __brick_equal(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2,
  405. _BinaryPredicate __p, /* is_vector = */ std::true_type) noexcept
  406. {
  407. return __unseq_backend::__simd_first(__first1, __last1 - __first1, __first2, __not_pred<_BinaryPredicate>(__p))
  408. .first == __last1;
  409. }
  410. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate,
  411. class _IsVector>
  412. bool
  413. __pattern_equal(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  414. _BinaryPredicate __p, _IsVector __is_vector, /* is_parallel = */ std::false_type) noexcept
  415. {
  416. return __internal::__brick_equal(__first1, __last1, __first2, __p, __is_vector);
  417. }
  418. template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate,
  419. class _IsVector>
  420. bool
  421. __pattern_equal(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1,
  422. _RandomAccessIterator2 __first2, _BinaryPredicate __p, _IsVector __is_vector,
  423. /*is_parallel=*/std::true_type)
  424. {
  425. return __internal::__except_handler([&]() {
  426. return !__internal::__parallel_or(
  427. std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
  428. [__first1, __first2, __p, __is_vector](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) {
  429. return !__internal::__brick_equal(__i, __j, __first2 + (__i - __first1), __p, __is_vector);
  430. });
  431. });
  432. }
  433. //------------------------------------------------------------------------
  434. // find_if
  435. //------------------------------------------------------------------------
  436. template <class _ForwardIterator, class _Predicate>
  437. _ForwardIterator
  438. __brick_find_if(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred,
  439. /*is_vector=*/std::false_type) noexcept
  440. {
  441. return std::find_if(__first, __last, __pred);
  442. }
  443. template <class _RandomAccessIterator, class _Predicate>
  444. _RandomAccessIterator
  445. __brick_find_if(_RandomAccessIterator __first, _RandomAccessIterator __last, _Predicate __pred,
  446. /*is_vector=*/std::true_type) noexcept
  447. {
  448. typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _SizeType;
  449. return __unseq_backend::__simd_first(
  450. __first, _SizeType(0), __last - __first,
  451. [&__pred](_RandomAccessIterator __it, _SizeType __i) { return __pred(__it[__i]); });
  452. }
  453. template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate, class _IsVector>
  454. _ForwardIterator
  455. __pattern_find_if(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred,
  456. _IsVector __is_vector,
  457. /*is_parallel=*/std::false_type) noexcept
  458. {
  459. return __internal::__brick_find_if(__first, __last, __pred, __is_vector);
  460. }
  461. template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate, class _IsVector>
  462. _ForwardIterator
  463. __pattern_find_if(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred,
  464. _IsVector __is_vector,
  465. /*is_parallel=*/std::true_type)
  466. {
  467. return __internal::__except_handler([&]() {
  468. return __internal::__parallel_find(
  469. std::forward<_ExecutionPolicy>(__exec), __first, __last,
  470. [__pred, __is_vector](_ForwardIterator __i, _ForwardIterator __j) {
  471. return __internal::__brick_find_if(__i, __j, __pred, __is_vector);
  472. },
  473. std::less<typename std::iterator_traits<_ForwardIterator>::difference_type>(),
  474. /*is_first=*/true);
  475. });
  476. }
  477. //------------------------------------------------------------------------
  478. // find_end
  479. //------------------------------------------------------------------------
  480. // find the first occurrence of the subsequence [s_first, s_last)
  481. // or the last occurrence of the subsequence in the range [first, last)
  482. // b_first determines what occurrence we want to find (first or last)
  483. template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate, class _IsVector>
  484. _RandomAccessIterator1
  485. __find_subrange(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator1 __global_last,
  486. _RandomAccessIterator2 __s_first, _RandomAccessIterator2 __s_last, _BinaryPredicate __pred,
  487. bool __b_first, _IsVector __is_vector) noexcept
  488. {
  489. typedef typename std::iterator_traits<_RandomAccessIterator2>::value_type _ValueType;
  490. auto __n2 = __s_last - __s_first;
  491. if (__n2 < 1)
  492. {
  493. return __b_first ? __first : __last;
  494. }
  495. auto __n1 = __global_last - __first;
  496. if (__n1 < __n2)
  497. {
  498. return __last;
  499. }
  500. auto __cur = __last;
  501. while (__first != __last && (__global_last - __first >= __n2))
  502. {
  503. // find position of *s_first in [first, last) (it can be start of subsequence)
  504. __first = __internal::__brick_find_if(
  505. __first, __last, __equal_value_by_pred<_ValueType, _BinaryPredicate>(*__s_first, __pred), __is_vector);
  506. // if position that was found previously is the start of subsequence
  507. // then we can exit the loop (b_first == true) or keep the position
  508. // (b_first == false)
  509. if (__first != __last && (__global_last - __first >= __n2) &&
  510. __internal::__brick_equal(__s_first + 1, __s_last, __first + 1, __pred, __is_vector))
  511. {
  512. if (__b_first)
  513. {
  514. return __first;
  515. }
  516. else
  517. {
  518. __cur = __first;
  519. }
  520. }
  521. else if (__first == __last)
  522. {
  523. break;
  524. }
  525. else
  526. {
  527. }
  528. // in case of b_first == false we try to find new start position
  529. // for the next subsequence
  530. ++__first;
  531. }
  532. return __cur;
  533. }
  534. template <class _RandomAccessIterator, class _Size, class _Tp, class _BinaryPredicate, class _IsVector>
  535. _RandomAccessIterator
  536. __find_subrange(_RandomAccessIterator __first, _RandomAccessIterator __last, _RandomAccessIterator __global_last,
  537. _Size __count, const _Tp& __value, _BinaryPredicate __pred, _IsVector __is_vector) noexcept
  538. {
  539. if (__global_last - __first < __count || __count < 1)
  540. {
  541. return __last; // According to the standard last shall be returned when count < 1
  542. }
  543. auto __n = __global_last - __first;
  544. auto __unary_pred = __equal_value_by_pred<_Tp, _BinaryPredicate>(__value, __pred);
  545. while (__first != __last && (__global_last - __first >= __count))
  546. {
  547. __first = __internal::__brick_find_if(__first, __last, __unary_pred, __is_vector);
  548. // check that all of elements in [first+1, first+count) equal to value
  549. if (__first != __last && (__global_last - __first >= __count) &&
  550. !__internal::__brick_any_of(__first + 1, __first + __count,
  551. __not_pred<decltype(__unary_pred)>(__unary_pred), __is_vector))
  552. {
  553. return __first;
  554. }
  555. else if (__first == __last)
  556. {
  557. break;
  558. }
  559. else
  560. {
  561. ++__first;
  562. }
  563. }
  564. return __last;
  565. }
  566. template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
  567. _ForwardIterator1
  568. __brick_find_end(_ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first,
  569. _ForwardIterator2 __s_last, _BinaryPredicate __pred, /*__is_vector=*/std::false_type) noexcept
  570. {
  571. return std::find_end(__first, __last, __s_first, __s_last, __pred);
  572. }
  573. template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
  574. _ForwardIterator1
  575. __brick_find_end(_ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first,
  576. _ForwardIterator2 __s_last, _BinaryPredicate __pred, /*__is_vector=*/std::true_type) noexcept
  577. {
  578. return __find_subrange(__first, __last, __last, __s_first, __s_last, __pred, false, std::true_type());
  579. }
  580. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate,
  581. class _IsVector>
  582. _ForwardIterator1
  583. __pattern_find_end(_ExecutionPolicy&&, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first,
  584. _ForwardIterator2 __s_last, _BinaryPredicate __pred, _IsVector __is_vector,
  585. /*is_parallel=*/std::false_type) noexcept
  586. {
  587. return __internal::__brick_find_end(__first, __last, __s_first, __s_last, __pred, __is_vector);
  588. }
  589. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate,
  590. class _IsVector>
  591. _ForwardIterator1
  592. __pattern_find_end(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
  593. _ForwardIterator2 __s_first, _ForwardIterator2 __s_last, _BinaryPredicate __pred,
  594. _IsVector __is_vector, /*is_parallel=*/std::true_type) noexcept
  595. {
  596. if (__last - __first == __s_last - __s_first)
  597. {
  598. const bool __res = __internal::__pattern_equal(std::forward<_ExecutionPolicy>(__exec), __first, __last,
  599. __s_first, __pred, __is_vector, std::true_type());
  600. return __res ? __first : __last;
  601. }
  602. else
  603. {
  604. return __internal::__except_handler([&]() {
  605. return __internal::__parallel_find(
  606. std::forward<_ExecutionPolicy>(__exec), __first, __last,
  607. [__last, __s_first, __s_last, __pred, __is_vector](_ForwardIterator1 __i, _ForwardIterator1 __j) {
  608. return __internal::__find_subrange(__i, __j, __last, __s_first, __s_last, __pred, false,
  609. __is_vector);
  610. },
  611. std::greater<typename std::iterator_traits<_ForwardIterator1>::difference_type>(), /*is_first=*/false);
  612. });
  613. }
  614. }
  615. //------------------------------------------------------------------------
  616. // find_first_of
  617. //------------------------------------------------------------------------
  618. template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
  619. _ForwardIterator1
  620. __brick_find_first_of(_ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first,
  621. _ForwardIterator2 __s_last, _BinaryPredicate __pred, /*__is_vector=*/std::false_type) noexcept
  622. {
  623. return std::find_first_of(__first, __last, __s_first, __s_last, __pred);
  624. }
  625. template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
  626. _ForwardIterator1
  627. __brick_find_first_of(_ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first,
  628. _ForwardIterator2 __s_last, _BinaryPredicate __pred, /*__is_vector=*/std::true_type) noexcept
  629. {
  630. return __unseq_backend::__simd_find_first_of(__first, __last, __s_first, __s_last, __pred);
  631. }
  632. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate,
  633. class _IsVector>
  634. _ForwardIterator1
  635. __pattern_find_first_of(_ExecutionPolicy&&, _ForwardIterator1 __first, _ForwardIterator1 __last,
  636. _ForwardIterator2 __s_first, _ForwardIterator2 __s_last, _BinaryPredicate __pred,
  637. _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept
  638. {
  639. return __internal::__brick_find_first_of(__first, __last, __s_first, __s_last, __pred, __is_vector);
  640. }
  641. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate,
  642. class _IsVector>
  643. _ForwardIterator1
  644. __pattern_find_first_of(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
  645. _ForwardIterator2 __s_first, _ForwardIterator2 __s_last, _BinaryPredicate __pred,
  646. _IsVector __is_vector, /*is_parallel=*/std::true_type) noexcept
  647. {
  648. return __internal::__except_handler([&]() {
  649. return __internal::__parallel_find(
  650. std::forward<_ExecutionPolicy>(__exec), __first, __last,
  651. [__s_first, __s_last, __pred, __is_vector](_ForwardIterator1 __i, _ForwardIterator1 __j) {
  652. return __internal::__brick_find_first_of(__i, __j, __s_first, __s_last, __pred, __is_vector);
  653. },
  654. std::less<typename std::iterator_traits<_ForwardIterator1>::difference_type>(), /*is_first=*/true);
  655. });
  656. }
  657. //------------------------------------------------------------------------
  658. // search
  659. //------------------------------------------------------------------------
  660. template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
  661. _ForwardIterator1
  662. __brick_search(_ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first,
  663. _ForwardIterator2 __s_last, _BinaryPredicate __pred, /*vector=*/std::false_type) noexcept
  664. {
  665. return std::search(__first, __last, __s_first, __s_last, __pred);
  666. }
  667. template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
  668. _ForwardIterator1
  669. __brick_search(_ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first,
  670. _ForwardIterator2 __s_last, _BinaryPredicate __pred, /*vector=*/std::true_type) noexcept
  671. {
  672. return __internal::__find_subrange(__first, __last, __last, __s_first, __s_last, __pred, true, std::true_type());
  673. }
  674. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate,
  675. class _IsVector>
  676. _ForwardIterator1
  677. __pattern_search(_ExecutionPolicy&&, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first,
  678. _ForwardIterator2 __s_last, _BinaryPredicate __pred, _IsVector __is_vector,
  679. /*is_parallel=*/std::false_type) noexcept
  680. {
  681. return __internal::__brick_search(__first, __last, __s_first, __s_last, __pred, __is_vector);
  682. }
  683. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate,
  684. class _IsVector>
  685. _ForwardIterator1
  686. __pattern_search(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
  687. _ForwardIterator2 __s_first, _ForwardIterator2 __s_last, _BinaryPredicate __pred,
  688. _IsVector __is_vector,
  689. /*is_parallel=*/std::true_type) noexcept
  690. {
  691. if (__last - __first == __s_last - __s_first)
  692. {
  693. const bool __res = __internal::__pattern_equal(std::forward<_ExecutionPolicy>(__exec), __first, __last,
  694. __s_first, __pred, __is_vector, std::true_type());
  695. return __res ? __first : __last;
  696. }
  697. else
  698. {
  699. return __internal::__except_handler([&]() {
  700. return __internal::__parallel_find(
  701. std::forward<_ExecutionPolicy>(__exec), __first, __last,
  702. [__last, __s_first, __s_last, __pred, __is_vector](_ForwardIterator1 __i, _ForwardIterator1 __j) {
  703. return __internal::__find_subrange(__i, __j, __last, __s_first, __s_last, __pred, true,
  704. __is_vector);
  705. },
  706. std::less<typename std::iterator_traits<_ForwardIterator1>::difference_type>(), /*is_first=*/true);
  707. });
  708. }
  709. }
  710. //------------------------------------------------------------------------
  711. // search_n
  712. //------------------------------------------------------------------------
  713. template <class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate>
  714. _ForwardIterator
  715. __brick_search_n(_ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value,
  716. _BinaryPredicate __pred, /*vector=*/std::false_type) noexcept
  717. {
  718. return std::search_n(__first, __last, __count, __value, __pred);
  719. }
  720. template <class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate>
  721. _ForwardIterator
  722. __brick_search_n(_ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value,
  723. _BinaryPredicate __pred, /*vector=*/std::true_type) noexcept
  724. {
  725. return __internal::__find_subrange(__first, __last, __last, __count, __value, __pred, std::true_type());
  726. }
  727. template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate,
  728. class _IsVector>
  729. _ForwardIterator
  730. __pattern_search_n(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Size __count,
  731. const _Tp& __value, _BinaryPredicate __pred, _IsVector __is_vector,
  732. /*is_parallel=*/std::false_type) noexcept
  733. {
  734. return __internal::__brick_search_n(__first, __last, __count, __value, __pred, __is_vector);
  735. }
  736. template <class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Tp, class _BinaryPredicate,
  737. class _IsVector>
  738. _RandomAccessIterator
  739. __pattern_search_n(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last,
  740. _Size __count, const _Tp& __value, _BinaryPredicate __pred, _IsVector __is_vector,
  741. /*is_parallel=*/std::true_type) noexcept
  742. {
  743. if (__last - __first == __count)
  744. {
  745. const bool __result = !__internal::__pattern_any_of(
  746. std::forward<_ExecutionPolicy>(__exec), __first, __last,
  747. [&__value, &__pred](const _Tp& __val) { return !__pred(__val, __value); }, __is_vector,
  748. /*is_parallel*/ std::true_type());
  749. return __result ? __first : __last;
  750. }
  751. else
  752. {
  753. return __internal::__except_handler([&__exec, __first, __last, __count, &__value, __pred, __is_vector]() {
  754. return __internal::__parallel_find(
  755. std::forward<_ExecutionPolicy>(__exec), __first, __last,
  756. [__last, __count, &__value, __pred, __is_vector](_RandomAccessIterator __i, _RandomAccessIterator __j) {
  757. return __internal::__find_subrange(__i, __j, __last, __count, __value, __pred, __is_vector);
  758. },
  759. std::less<typename std::iterator_traits<_RandomAccessIterator>::difference_type>(), /*is_first=*/true);
  760. });
  761. }
  762. }
  763. //------------------------------------------------------------------------
  764. // copy_n
  765. //------------------------------------------------------------------------
  766. template <class _ForwardIterator, class _Size, class _OutputIterator>
  767. _OutputIterator
  768. __brick_copy_n(_ForwardIterator __first, _Size __n, _OutputIterator __result, /*vector=*/std::false_type) noexcept
  769. {
  770. return std::copy_n(__first, __n, __result);
  771. }
  772. template <class _ForwardIterator, class _Size, class _OutputIterator>
  773. _OutputIterator
  774. __brick_copy_n(_ForwardIterator __first, _Size __n, _OutputIterator __result, /*vector=*/std::true_type) noexcept
  775. {
  776. return __unseq_backend::__simd_assign(
  777. __first, __n, __result, [](_ForwardIterator __first, _OutputIterator __result) { *__result = *__first; });
  778. }
  779. //------------------------------------------------------------------------
  780. // copy
  781. //------------------------------------------------------------------------
  782. template <class _ForwardIterator, class _OutputIterator>
  783. _OutputIterator
  784. __brick_copy(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result,
  785. /*vector=*/std::false_type) noexcept
  786. {
  787. return std::copy(__first, __last, __result);
  788. }
  789. template <class _RandomAccessIterator, class _OutputIterator>
  790. _OutputIterator
  791. __brick_copy(_RandomAccessIterator __first, _RandomAccessIterator __last, _OutputIterator __result,
  792. /*vector=*/std::true_type) noexcept
  793. {
  794. return __unseq_backend::__simd_assign(
  795. __first, __last - __first, __result,
  796. [](_RandomAccessIterator __first, _OutputIterator __result) { *__result = *__first; });
  797. }
  798. //------------------------------------------------------------------------
  799. // move
  800. //------------------------------------------------------------------------
  801. template <class _ForwardIterator, class _OutputIterator>
  802. _OutputIterator
  803. __brick_move(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result,
  804. /*vector=*/std::false_type) noexcept
  805. {
  806. return std::move(__first, __last, __result);
  807. }
  808. template <class _RandomAccessIterator, class _OutputIterator>
  809. _OutputIterator
  810. __brick_move(_RandomAccessIterator __first, _RandomAccessIterator __last, _OutputIterator __result,
  811. /*vector=*/std::true_type) noexcept
  812. {
  813. return __unseq_backend::__simd_assign(
  814. __first, __last - __first, __result,
  815. [](_RandomAccessIterator __first, _OutputIterator __result) { *__result = std::move(*__first); });
  816. }
  817. //------------------------------------------------------------------------
  818. // swap_ranges
  819. //------------------------------------------------------------------------
  820. template <class _ForwardIterator, class _OutputIterator>
  821. _OutputIterator
  822. __brick_swap_ranges(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result,
  823. /*vector=*/std::false_type) noexcept
  824. {
  825. return std::swap_ranges(__first, __last, __result);
  826. }
  827. template <class _ForwardIterator, class _OutputIterator>
  828. _OutputIterator
  829. __brick_swap_ranges(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result,
  830. /*vector=*/std::true_type) noexcept
  831. {
  832. using std::iter_swap;
  833. return __unseq_backend::__simd_assign(__first, __last - __first, __result,
  834. iter_swap<_ForwardIterator, _OutputIterator>);
  835. }
  836. //------------------------------------------------------------------------
  837. // copy_if
  838. //------------------------------------------------------------------------
  839. template <class _ForwardIterator, class _OutputIterator, class _UnaryPredicate>
  840. _OutputIterator
  841. __brick_copy_if(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, _UnaryPredicate __pred,
  842. /*vector=*/std::false_type) noexcept
  843. {
  844. return std::copy_if(__first, __last, __result, __pred);
  845. }
  846. template <class _ForwardIterator, class _OutputIterator, class _UnaryPredicate>
  847. _OutputIterator
  848. __brick_copy_if(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, _UnaryPredicate __pred,
  849. /*vector=*/std::true_type) noexcept
  850. {
  851. #if (_PSTL_MONOTONIC_PRESENT)
  852. return __unseq_backend::__simd_copy_if(__first, __last - __first, __result, __pred);
  853. #else
  854. return std::copy_if(__first, __last, __result, __pred);
  855. #endif
  856. }
  857. // TODO: Try to use transform_reduce for combining __brick_copy_if_phase1 on IsVector.
  858. template <class _DifferenceType, class _ForwardIterator, class _UnaryPredicate>
  859. std::pair<_DifferenceType, _DifferenceType>
  860. __brick_calc_mask_1(_ForwardIterator __first, _ForwardIterator __last, bool* __restrict __mask, _UnaryPredicate __pred,
  861. /*vector=*/std::false_type) noexcept
  862. {
  863. auto __count_true = _DifferenceType(0);
  864. auto __size = __last - __first;
  865. static_assert(__is_random_access_iterator<_ForwardIterator>::value,
  866. "Pattern-brick error. Should be a random access iterator.");
  867. for (; __first != __last; ++__first, ++__mask)
  868. {
  869. *__mask = __pred(*__first);
  870. if (*__mask)
  871. {
  872. ++__count_true;
  873. }
  874. }
  875. return std::make_pair(__count_true, __size - __count_true);
  876. }
  877. template <class _DifferenceType, class _RandomAccessIterator, class _UnaryPredicate>
  878. std::pair<_DifferenceType, _DifferenceType>
  879. __brick_calc_mask_1(_RandomAccessIterator __first, _RandomAccessIterator __last, bool* __mask, _UnaryPredicate __pred,
  880. /*vector=*/std::true_type) noexcept
  881. {
  882. auto __result = __unseq_backend::__simd_calc_mask_1(__first, __last - __first, __mask, __pred);
  883. return std::make_pair(__result, (__last - __first) - __result);
  884. }
  885. template <class _ForwardIterator, class _OutputIterator, class _Assigner>
  886. void
  887. __brick_copy_by_mask(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, bool* __mask,
  888. _Assigner __assigner, /*vector=*/std::false_type) noexcept
  889. {
  890. for (; __first != __last; ++__first, ++__mask)
  891. {
  892. if (*__mask)
  893. {
  894. __assigner(__first, __result);
  895. ++__result;
  896. }
  897. }
  898. }
  899. template <class _ForwardIterator, class _OutputIterator, class _Assigner>
  900. void
  901. __brick_copy_by_mask(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result,
  902. bool* __restrict __mask, _Assigner __assigner, /*vector=*/std::true_type) noexcept
  903. {
  904. #if (_PSTL_MONOTONIC_PRESENT)
  905. __unseq_backend::__simd_copy_by_mask(__first, __last - __first, __result, __mask, __assigner);
  906. #else
  907. __internal::__brick_copy_by_mask(__first, __last, __result, __mask, __assigner, std::false_type());
  908. #endif
  909. }
  910. template <class _ForwardIterator, class _OutputIterator1, class _OutputIterator2>
  911. void
  912. __brick_partition_by_mask(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator1 __out_true,
  913. _OutputIterator2 __out_false, bool* __mask, /*vector=*/std::false_type) noexcept
  914. {
  915. for (; __first != __last; ++__first, ++__mask)
  916. {
  917. if (*__mask)
  918. {
  919. *__out_true = *__first;
  920. ++__out_true;
  921. }
  922. else
  923. {
  924. *__out_false = *__first;
  925. ++__out_false;
  926. }
  927. }
  928. }
  929. template <class _RandomAccessIterator, class _OutputIterator1, class _OutputIterator2>
  930. void
  931. __brick_partition_by_mask(_RandomAccessIterator __first, _RandomAccessIterator __last, _OutputIterator1 __out_true,
  932. _OutputIterator2 __out_false, bool* __mask, /*vector=*/std::true_type) noexcept
  933. {
  934. #if (_PSTL_MONOTONIC_PRESENT)
  935. __unseq_backend::__simd_partition_by_mask(__first, __last - __first, __out_true, __out_false, __mask);
  936. #else
  937. __internal::__brick_partition_by_mask(__first, __last, __out_true, __out_false, __mask, std::false_type());
  938. #endif
  939. }
  940. template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _UnaryPredicate, class _IsVector>
  941. _OutputIterator
  942. __pattern_copy_if(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result,
  943. _UnaryPredicate __pred, _IsVector __is_vector, /*parallel=*/std::false_type) noexcept
  944. {
  945. return __internal::__brick_copy_if(__first, __last, __result, __pred, __is_vector);
  946. }
  947. template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, class _UnaryPredicate,
  948. class _IsVector>
  949. _OutputIterator
  950. __pattern_copy_if(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last,
  951. _OutputIterator __result, _UnaryPredicate __pred, _IsVector __is_vector, /*parallel=*/std::true_type)
  952. {
  953. typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType;
  954. const _DifferenceType __n = __last - __first;
  955. if (_DifferenceType(1) < __n)
  956. {
  957. __par_backend::__buffer<bool> __mask_buf(__n);
  958. return __internal::__except_handler([&__exec, __n, __first, __result, __is_vector, __pred, &__mask_buf]() {
  959. bool* __mask = __mask_buf.get();
  960. _DifferenceType __m{};
  961. __par_backend::__parallel_strict_scan(
  962. std::forward<_ExecutionPolicy>(__exec), __n, _DifferenceType(0),
  963. [=](_DifferenceType __i, _DifferenceType __len) { // Reduce
  964. return __internal::__brick_calc_mask_1<_DifferenceType>(__first + __i, __first + (__i + __len),
  965. __mask + __i, __pred, __is_vector)
  966. .first;
  967. },
  968. std::plus<_DifferenceType>(), // Combine
  969. [=](_DifferenceType __i, _DifferenceType __len, _DifferenceType __initial) { // Scan
  970. __internal::__brick_copy_by_mask(
  971. __first + __i, __first + (__i + __len), __result + __initial, __mask + __i,
  972. [](_RandomAccessIterator __x, _OutputIterator __z) { *__z = *__x; }, __is_vector);
  973. },
  974. [&__m](_DifferenceType __total) { __m = __total; });
  975. return __result + __m;
  976. });
  977. }
  978. // trivial sequence - use serial algorithm
  979. return __internal::__brick_copy_if(__first, __last, __result, __pred, __is_vector);
  980. }
  981. //------------------------------------------------------------------------
  982. // count
  983. //------------------------------------------------------------------------
  984. template <class _ForwardIterator, class _Predicate>
  985. typename std::iterator_traits<_ForwardIterator>::difference_type
  986. __brick_count(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred,
  987. /* is_vector = */ std::true_type) noexcept
  988. {
  989. return __unseq_backend::__simd_count(__first, __last - __first, __pred);
  990. }
  991. template <class _ForwardIterator, class _Predicate>
  992. typename std::iterator_traits<_ForwardIterator>::difference_type
  993. __brick_count(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred,
  994. /* is_vector = */ std::false_type) noexcept
  995. {
  996. return std::count_if(__first, __last, __pred);
  997. }
  998. template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate, class _IsVector>
  999. typename std::iterator_traits<_ForwardIterator>::difference_type
  1000. __pattern_count(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred,
  1001. /* is_parallel */ std::false_type, _IsVector __is_vector) noexcept
  1002. {
  1003. return __internal::__brick_count(__first, __last, __pred, __is_vector);
  1004. }
  1005. template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate, class _IsVector>
  1006. typename std::iterator_traits<_ForwardIterator>::difference_type
  1007. __pattern_count(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred,
  1008. /* is_parallel */ std::true_type, _IsVector __is_vector)
  1009. {
  1010. typedef typename std::iterator_traits<_ForwardIterator>::difference_type _SizeType;
  1011. return __internal::__except_handler([&]() {
  1012. return __par_backend::__parallel_reduce(
  1013. std::forward<_ExecutionPolicy>(__exec), __first, __last, _SizeType(0),
  1014. [__pred, __is_vector](_ForwardIterator __begin, _ForwardIterator __end, _SizeType __value) -> _SizeType {
  1015. return __value + __internal::__brick_count(__begin, __end, __pred, __is_vector);
  1016. },
  1017. std::plus<_SizeType>());
  1018. });
  1019. }
  1020. //------------------------------------------------------------------------
  1021. // unique
  1022. //------------------------------------------------------------------------
  1023. template <class _ForwardIterator, class _BinaryPredicate>
  1024. _ForwardIterator
  1025. __brick_unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred,
  1026. /*is_vector=*/std::false_type) noexcept
  1027. {
  1028. return std::unique(__first, __last, __pred);
  1029. }
  1030. template <class _ForwardIterator, class _BinaryPredicate>
  1031. _ForwardIterator
  1032. __brick_unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred,
  1033. /*is_vector=*/std::true_type) noexcept
  1034. {
  1035. _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial");
  1036. return std::unique(__first, __last, __pred);
  1037. }
  1038. template <class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate, class _IsVector>
  1039. _ForwardIterator
  1040. __pattern_unique(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred,
  1041. _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept
  1042. {
  1043. return __internal::__brick_unique(__first, __last, __pred, __is_vector);
  1044. }
  1045. // That function is shared between two algorithms - remove_if (__pattern_remove_if) and unique (pattern unique). But a mask calculation is different.
  1046. // So, a caller passes _CalcMask brick into remove_elements.
  1047. template <class _ExecutionPolicy, class _ForwardIterator, class _CalcMask, class _IsVector>
  1048. _ForwardIterator
  1049. __remove_elements(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _CalcMask __calc_mask,
  1050. _IsVector __is_vector)
  1051. {
  1052. typedef typename std::iterator_traits<_ForwardIterator>::difference_type _DifferenceType;
  1053. typedef typename std::iterator_traits<_ForwardIterator>::value_type _Tp;
  1054. _DifferenceType __n = __last - __first;
  1055. __par_backend::__buffer<bool> __mask_buf(__n);
  1056. // 1. find a first iterator that should be removed
  1057. return __internal::__except_handler([&]() {
  1058. bool* __mask = __mask_buf.get();
  1059. _DifferenceType __min = __par_backend::__parallel_reduce(
  1060. std::forward<_ExecutionPolicy>(__exec), _DifferenceType(0), __n, __n,
  1061. [__first, __mask, &__calc_mask, __is_vector](_DifferenceType __i, _DifferenceType __j,
  1062. _DifferenceType __local_min) -> _DifferenceType {
  1063. // Create mask
  1064. __calc_mask(__mask + __i, __mask + __j, __first + __i);
  1065. // if minimum was found in a previous range we shouldn't do anymore
  1066. if (__local_min < __i)
  1067. {
  1068. return __local_min;
  1069. }
  1070. // find first iterator that should be removed
  1071. bool* __result = __internal::__brick_find_if(__mask + __i, __mask + __j,
  1072. [](bool __val) { return !__val; }, __is_vector);
  1073. if (__result - __mask == __j)
  1074. {
  1075. return __local_min;
  1076. }
  1077. return std::min(__local_min, _DifferenceType(__result - __mask));
  1078. },
  1079. [](_DifferenceType __local_min1, _DifferenceType __local_min2) -> _DifferenceType {
  1080. return std::min(__local_min1, __local_min2);
  1081. });
  1082. // No elements to remove - exit
  1083. if (__min == __n)
  1084. {
  1085. return __last;
  1086. }
  1087. __n -= __min;
  1088. __first += __min;
  1089. __par_backend::__buffer<_Tp> __buf(__n);
  1090. _Tp* __result = __buf.get();
  1091. __mask += __min;
  1092. _DifferenceType __m{};
  1093. // 2. Elements that doesn't satisfy pred are moved to result
  1094. __par_backend::__parallel_strict_scan(
  1095. std::forward<_ExecutionPolicy>(__exec), __n, _DifferenceType(0),
  1096. [__mask, __is_vector](_DifferenceType __i, _DifferenceType __len) {
  1097. return __internal::__brick_count(__mask + __i, __mask + __i + __len, [](bool __val) { return __val; },
  1098. __is_vector);
  1099. },
  1100. std::plus<_DifferenceType>(),
  1101. [=](_DifferenceType __i, _DifferenceType __len, _DifferenceType __initial) {
  1102. __internal::__brick_copy_by_mask(
  1103. __first + __i, __first + __i + __len, __result + __initial, __mask + __i,
  1104. [](_ForwardIterator __x, _Tp* __z) {
  1105. __internal::__invoke_if_else(std::is_trivial<_Tp>(), [&]() { *__z = std::move(*__x); },
  1106. [&]() { ::new (std::addressof(*__z)) _Tp(std::move(*__x)); });
  1107. },
  1108. __is_vector);
  1109. },
  1110. [&__m](_DifferenceType __total) { __m = __total; });
  1111. // 3. Elements from result are moved to [first, last)
  1112. __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __result, __result + __m,
  1113. [__result, __first, __is_vector](_Tp* __i, _Tp* __j) {
  1114. __internal::__brick_move(__i, __j, __first + (__i - __result), __is_vector);
  1115. });
  1116. return __first + __m;
  1117. });
  1118. }
  1119. template <class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate, class _IsVector>
  1120. _ForwardIterator
  1121. __pattern_unique(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred,
  1122. _IsVector __is_vector, /*is_parallel=*/std::true_type) noexcept
  1123. {
  1124. typedef typename std::iterator_traits<_ForwardIterator>::reference _ReferenceType;
  1125. if (__first == __last)
  1126. {
  1127. return __last;
  1128. }
  1129. if (__first + 1 == __last || __first + 2 == __last)
  1130. {
  1131. // Trivial sequence - use serial algorithm
  1132. return __internal::__brick_unique(__first, __last, __pred, __is_vector);
  1133. }
  1134. return __internal::__remove_elements(
  1135. std::forward<_ExecutionPolicy>(__exec), ++__first, __last,
  1136. [&__pred, __is_vector](bool* __b, bool* __e, _ForwardIterator __it) {
  1137. __internal::__brick_walk3(
  1138. __b, __e, __it - 1, __it,
  1139. [&__pred](bool& __x, _ReferenceType __y, _ReferenceType __z) { __x = !__pred(__y, __z); }, __is_vector);
  1140. },
  1141. __is_vector);
  1142. }
  1143. //------------------------------------------------------------------------
  1144. // unique_copy
  1145. //------------------------------------------------------------------------
  1146. template <class _ForwardIterator, class OutputIterator, class _BinaryPredicate>
  1147. OutputIterator
  1148. __brick_unique_copy(_ForwardIterator __first, _ForwardIterator __last, OutputIterator __result, _BinaryPredicate __pred,
  1149. /*vector=*/std::false_type) noexcept
  1150. {
  1151. return std::unique_copy(__first, __last, __result, __pred);
  1152. }
  1153. template <class _RandomAccessIterator, class OutputIterator, class _BinaryPredicate>
  1154. OutputIterator
  1155. __brick_unique_copy(_RandomAccessIterator __first, _RandomAccessIterator __last, OutputIterator __result,
  1156. _BinaryPredicate __pred, /*vector=*/std::true_type) noexcept
  1157. {
  1158. #if (_PSTL_MONOTONIC_PRESENT)
  1159. return __unseq_backend::__simd_unique_copy(__first, __last - __first, __result, __pred);
  1160. #else
  1161. return std::unique_copy(__first, __last, __result, __pred);
  1162. #endif
  1163. }
  1164. template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _BinaryPredicate,
  1165. class _IsVector>
  1166. _OutputIterator
  1167. __pattern_unique_copy(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result,
  1168. _BinaryPredicate __pred, _IsVector __is_vector, /*parallel=*/std::false_type) noexcept
  1169. {
  1170. return __internal::__brick_unique_copy(__first, __last, __result, __pred, __is_vector);
  1171. }
  1172. template <class _DifferenceType, class _RandomAccessIterator, class _BinaryPredicate>
  1173. _DifferenceType
  1174. __brick_calc_mask_2(_RandomAccessIterator __first, _RandomAccessIterator __last, bool* __restrict __mask,
  1175. _BinaryPredicate __pred, /*vector=*/std::false_type) noexcept
  1176. {
  1177. _DifferenceType __count = 0;
  1178. for (; __first != __last; ++__first, ++__mask)
  1179. {
  1180. *__mask = !__pred(*__first, *(__first - 1));
  1181. __count += *__mask;
  1182. }
  1183. return __count;
  1184. }
  1185. template <class _DifferenceType, class _RandomAccessIterator, class _BinaryPredicate>
  1186. _DifferenceType
  1187. __brick_calc_mask_2(_RandomAccessIterator __first, _RandomAccessIterator __last, bool* __restrict __mask,
  1188. _BinaryPredicate __pred, /*vector=*/std::true_type) noexcept
  1189. {
  1190. return __unseq_backend::__simd_calc_mask_2(__first, __last - __first, __mask, __pred);
  1191. }
  1192. template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, class _BinaryPredicate,
  1193. class _IsVector>
  1194. _OutputIterator
  1195. __pattern_unique_copy(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last,
  1196. _OutputIterator __result, _BinaryPredicate __pred, _IsVector __is_vector,
  1197. /*parallel=*/std::true_type)
  1198. {
  1199. typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType;
  1200. const _DifferenceType __n = __last - __first;
  1201. if (_DifferenceType(2) < __n)
  1202. {
  1203. __par_backend::__buffer<bool> __mask_buf(__n);
  1204. if (_DifferenceType(2) < __n)
  1205. {
  1206. return __internal::__except_handler([&__exec, __n, __first, __result, __pred, __is_vector, &__mask_buf]() {
  1207. bool* __mask = __mask_buf.get();
  1208. _DifferenceType __m{};
  1209. __par_backend::__parallel_strict_scan(
  1210. std::forward<_ExecutionPolicy>(__exec), __n, _DifferenceType(0),
  1211. [=](_DifferenceType __i, _DifferenceType __len) -> _DifferenceType { // Reduce
  1212. _DifferenceType __extra = 0;
  1213. if (__i == 0)
  1214. {
  1215. // Special boundary case
  1216. __mask[__i] = true;
  1217. if (--__len == 0)
  1218. return 1;
  1219. ++__i;
  1220. ++__extra;
  1221. }
  1222. return __internal::__brick_calc_mask_2<_DifferenceType>(__first + __i, __first + (__i + __len),
  1223. __mask + __i, __pred, __is_vector) +
  1224. __extra;
  1225. },
  1226. std::plus<_DifferenceType>(), // Combine
  1227. [=](_DifferenceType __i, _DifferenceType __len, _DifferenceType __initial) { // Scan
  1228. // Phase 2 is same as for __pattern_copy_if
  1229. __internal::__brick_copy_by_mask(
  1230. __first + __i, __first + (__i + __len), __result + __initial, __mask + __i,
  1231. [](_RandomAccessIterator __x, _OutputIterator __z) { *__z = *__x; }, __is_vector);
  1232. },
  1233. [&__m](_DifferenceType __total) { __m = __total; });
  1234. return __result + __m;
  1235. });
  1236. }
  1237. }
  1238. // trivial sequence - use serial algorithm
  1239. return __internal::__brick_unique_copy(__first, __last, __result, __pred, __is_vector);
  1240. }
  1241. //------------------------------------------------------------------------
  1242. // reverse
  1243. //------------------------------------------------------------------------
  1244. template <class _BidirectionalIterator>
  1245. void
  1246. __brick_reverse(_BidirectionalIterator __first, _BidirectionalIterator __last, /*__is_vector=*/std::false_type) noexcept
  1247. {
  1248. std::reverse(__first, __last);
  1249. }
  1250. template <class _BidirectionalIterator>
  1251. void
  1252. __brick_reverse(_BidirectionalIterator __first, _BidirectionalIterator __last, /*__is_vector=*/std::true_type) noexcept
  1253. {
  1254. typedef typename std::iterator_traits<_BidirectionalIterator>::reference _ReferenceType;
  1255. const auto __n = (__last - __first) / 2;
  1256. __unseq_backend::__simd_walk_2(__first, __n, std::reverse_iterator<_BidirectionalIterator>(__last),
  1257. [](_ReferenceType __x, _ReferenceType __y) {
  1258. using std::swap;
  1259. swap(__x, __y);
  1260. });
  1261. }
  1262. // this brick is called in parallel version, so we can use iterator arithmetic
  1263. template <class _BidirectionalIterator>
  1264. void
  1265. __brick_reverse(_BidirectionalIterator __first, _BidirectionalIterator __last, _BidirectionalIterator __d_last,
  1266. /*is_vector=*/std::false_type) noexcept
  1267. {
  1268. for (--__d_last; __first != __last; ++__first, --__d_last)
  1269. {
  1270. using std::iter_swap;
  1271. iter_swap(__first, __d_last);
  1272. }
  1273. }
  1274. // this brick is called in parallel version, so we can use iterator arithmetic
  1275. template <class _BidirectionalIterator>
  1276. void
  1277. __brick_reverse(_BidirectionalIterator __first, _BidirectionalIterator __last, _BidirectionalIterator __d_last,
  1278. /*is_vector=*/std::true_type) noexcept
  1279. {
  1280. typedef typename std::iterator_traits<_BidirectionalIterator>::reference _ReferenceType;
  1281. __unseq_backend::__simd_walk_2(__first, __last - __first, std::reverse_iterator<_BidirectionalIterator>(__d_last),
  1282. [](_ReferenceType __x, _ReferenceType __y) {
  1283. using std::swap;
  1284. swap(__x, __y);
  1285. });
  1286. }
  1287. template <class _ExecutionPolicy, class _BidirectionalIterator, class _IsVector>
  1288. void
  1289. __pattern_reverse(_ExecutionPolicy&&, _BidirectionalIterator __first, _BidirectionalIterator __last,
  1290. _IsVector _is_vector,
  1291. /*is_parallel=*/std::false_type) noexcept
  1292. {
  1293. __internal::__brick_reverse(__first, __last, _is_vector);
  1294. }
  1295. template <class _ExecutionPolicy, class _BidirectionalIterator, class _IsVector>
  1296. void
  1297. __pattern_reverse(_ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __last,
  1298. _IsVector __is_vector, /*is_parallel=*/std::true_type)
  1299. {
  1300. __par_backend::__parallel_for(
  1301. std::forward<_ExecutionPolicy>(__exec), __first, __first + (__last - __first) / 2,
  1302. [__is_vector, __first, __last](_BidirectionalIterator __inner_first, _BidirectionalIterator __inner_last) {
  1303. __internal::__brick_reverse(__inner_first, __inner_last, __last - (__inner_first - __first), __is_vector);
  1304. });
  1305. }
  1306. //------------------------------------------------------------------------
  1307. // reverse_copy
  1308. //------------------------------------------------------------------------
  1309. template <class _BidirectionalIterator, class _OutputIterator>
  1310. _OutputIterator
  1311. __brick_reverse_copy(_BidirectionalIterator __first, _BidirectionalIterator __last, _OutputIterator __d_first,
  1312. /*is_vector=*/std::false_type) noexcept
  1313. {
  1314. return std::reverse_copy(__first, __last, __d_first);
  1315. }
  1316. template <class _BidirectionalIterator, class _OutputIterator>
  1317. _OutputIterator
  1318. __brick_reverse_copy(_BidirectionalIterator __first, _BidirectionalIterator __last, _OutputIterator __d_first,
  1319. /*is_vector=*/std::true_type) noexcept
  1320. {
  1321. typedef typename std::iterator_traits<_BidirectionalIterator>::reference _ReferenceType1;
  1322. typedef typename std::iterator_traits<_OutputIterator>::reference _ReferenceType2;
  1323. return __unseq_backend::__simd_walk_2(std::reverse_iterator<_BidirectionalIterator>(__last), __last - __first,
  1324. __d_first, [](_ReferenceType1 __x, _ReferenceType2 __y) { __y = __x; });
  1325. }
  1326. template <class _ExecutionPolicy, class _BidirectionalIterator, class _OutputIterator, class _IsVector>
  1327. _OutputIterator
  1328. __pattern_reverse_copy(_ExecutionPolicy&&, _BidirectionalIterator __first, _BidirectionalIterator __last,
  1329. _OutputIterator __d_first, _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept
  1330. {
  1331. return __internal::__brick_reverse_copy(__first, __last, __d_first, __is_vector);
  1332. }
  1333. template <class _ExecutionPolicy, class _BidirectionalIterator, class _OutputIterator, class _IsVector>
  1334. _OutputIterator
  1335. __pattern_reverse_copy(_ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __last,
  1336. _OutputIterator __d_first, _IsVector __is_vector, /*is_parallel=*/std::true_type)
  1337. {
  1338. auto __len = __last - __first;
  1339. __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last,
  1340. [__is_vector, __first, __len, __d_first](_BidirectionalIterator __inner_first,
  1341. _BidirectionalIterator __inner_last) {
  1342. __internal::__brick_reverse_copy(__inner_first, __inner_last,
  1343. __d_first + (__len - (__inner_last - __first)),
  1344. __is_vector);
  1345. });
  1346. return __d_first + __len;
  1347. }
  1348. //------------------------------------------------------------------------
  1349. // rotate
  1350. //------------------------------------------------------------------------
  1351. template <class _ForwardIterator>
  1352. _ForwardIterator
  1353. __brick_rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last,
  1354. /*is_vector=*/std::false_type) noexcept
  1355. {
  1356. #if _PSTL_CPP11_STD_ROTATE_BROKEN
  1357. std::rotate(__first, __middle, __last);
  1358. return std::next(__first, std::distance(__middle, __last));
  1359. #else
  1360. return std::rotate(__first, __middle, __last);
  1361. #endif
  1362. }
  1363. template <class _ForwardIterator>
  1364. _ForwardIterator
  1365. __brick_rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last,
  1366. /*is_vector=*/std::true_type) noexcept
  1367. {
  1368. auto __n = __last - __first;
  1369. auto __m = __middle - __first;
  1370. const _ForwardIterator __ret = __first + (__last - __middle);
  1371. bool __is_left = (__m <= __n / 2);
  1372. if (!__is_left)
  1373. __m = __n - __m;
  1374. while (__n > 1 && __m > 0)
  1375. {
  1376. using std::iter_swap;
  1377. const auto __m_2 = __m * 2;
  1378. if (__is_left)
  1379. {
  1380. for (; __last - __first >= __m_2; __first += __m)
  1381. {
  1382. __unseq_backend::__simd_assign(__first, __m, __first + __m,
  1383. iter_swap<_ForwardIterator, _ForwardIterator>);
  1384. }
  1385. }
  1386. else
  1387. {
  1388. for (; __last - __first >= __m_2; __last -= __m)
  1389. {
  1390. __unseq_backend::__simd_assign(__last - __m, __m, __last - __m_2,
  1391. iter_swap<_ForwardIterator, _ForwardIterator>);
  1392. }
  1393. }
  1394. __is_left = !__is_left;
  1395. __m = __n % __m;
  1396. __n = __last - __first;
  1397. }
  1398. return __ret;
  1399. }
  1400. template <class _ExecutionPolicy, class _ForwardIterator, class _IsVector>
  1401. _ForwardIterator
  1402. __pattern_rotate(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last,
  1403. _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept
  1404. {
  1405. return __internal::__brick_rotate(__first, __middle, __last, __is_vector);
  1406. }
  1407. template <class _ExecutionPolicy, class _ForwardIterator, class _IsVector>
  1408. _ForwardIterator
  1409. __pattern_rotate(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __middle,
  1410. _ForwardIterator __last, _IsVector __is_vector, /*is_parallel=*/std::true_type)
  1411. {
  1412. typedef typename std::iterator_traits<_ForwardIterator>::value_type _Tp;
  1413. auto __n = __last - __first;
  1414. auto __m = __middle - __first;
  1415. if (__m <= __n / 2)
  1416. {
  1417. __par_backend::__buffer<_Tp> __buf(__n - __m);
  1418. return __internal::__except_handler([&__exec, __n, __m, __first, __middle, __last, __is_vector, &__buf]() {
  1419. _Tp* __result = __buf.get();
  1420. __par_backend::__parallel_for(
  1421. std::forward<_ExecutionPolicy>(__exec), __middle, __last,
  1422. [__middle, __result, __is_vector](_ForwardIterator __b, _ForwardIterator __e) {
  1423. __internal::__brick_uninitialized_move(__b, __e, __result + (__b - __middle), __is_vector);
  1424. });
  1425. __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __middle,
  1426. [__last, __middle, __is_vector](_ForwardIterator __b, _ForwardIterator __e) {
  1427. __internal::__brick_move(__b, __e, __b + (__last - __middle),
  1428. __is_vector);
  1429. });
  1430. __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __result, __result + (__n - __m),
  1431. [__first, __result, __is_vector](_Tp* __b, _Tp* __e) {
  1432. __internal::__brick_move(__b, __e, __first + (__b - __result),
  1433. __is_vector);
  1434. });
  1435. return __first + (__last - __middle);
  1436. });
  1437. }
  1438. else
  1439. {
  1440. __par_backend::__buffer<_Tp> __buf(__m);
  1441. return __internal::__except_handler([&__exec, __n, __m, __first, __middle, __last, __is_vector, &__buf]() {
  1442. _Tp* __result = __buf.get();
  1443. __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __middle,
  1444. [__first, __result, __is_vector](_ForwardIterator __b, _ForwardIterator __e) {
  1445. __internal::__brick_uninitialized_move(
  1446. __b, __e, __result + (__b - __first), __is_vector);
  1447. });
  1448. __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __middle, __last,
  1449. [__first, __middle, __is_vector](_ForwardIterator __b, _ForwardIterator __e) {
  1450. __internal::__brick_move(__b, __e, __first + (__b - __middle),
  1451. __is_vector);
  1452. });
  1453. __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __result, __result + __m,
  1454. [__n, __m, __first, __result, __is_vector](_Tp* __b, _Tp* __e) {
  1455. __internal::__brick_move(
  1456. __b, __e, __first + ((__n - __m) + (__b - __result)), __is_vector);
  1457. });
  1458. return __first + (__last - __middle);
  1459. });
  1460. }
  1461. }
  1462. //------------------------------------------------------------------------
  1463. // rotate_copy
  1464. //------------------------------------------------------------------------
  1465. template <class _ForwardIterator, class _OutputIterator>
  1466. _OutputIterator
  1467. __brick_rotate_copy(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last,
  1468. _OutputIterator __result, /*__is_vector=*/std::false_type) noexcept
  1469. {
  1470. return std::rotate_copy(__first, __middle, __last, __result);
  1471. }
  1472. template <class _ForwardIterator, class _OutputIterator>
  1473. _OutputIterator
  1474. __brick_rotate_copy(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last,
  1475. _OutputIterator __result, /*__is_vector=*/std::true_type) noexcept
  1476. {
  1477. _OutputIterator __res = __internal::__brick_copy(__middle, __last, __result, std::true_type());
  1478. return __internal::__brick_copy(__first, __middle, __res, std::true_type());
  1479. }
  1480. template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _IsVector>
  1481. _OutputIterator
  1482. __pattern_rotate_copy(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last,
  1483. _OutputIterator __result, _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept
  1484. {
  1485. return __internal::__brick_rotate_copy(__first, __middle, __last, __result, __is_vector);
  1486. }
  1487. template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _IsVector>
  1488. _OutputIterator
  1489. __pattern_rotate_copy(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __middle,
  1490. _ForwardIterator __last, _OutputIterator __result, _IsVector __is_vector,
  1491. /*is_parallel=*/std::true_type)
  1492. {
  1493. __par_backend::__parallel_for(
  1494. std::forward<_ExecutionPolicy>(__exec), __first, __last,
  1495. [__first, __last, __middle, __result, __is_vector](_ForwardIterator __b, _ForwardIterator __e) {
  1496. if (__b > __middle)
  1497. {
  1498. __internal::__brick_copy(__b, __e, __result + (__b - __middle), __is_vector);
  1499. }
  1500. else
  1501. {
  1502. _OutputIterator __new_result = __result + ((__last - __middle) + (__b - __first));
  1503. if (__e < __middle)
  1504. {
  1505. __internal::__brick_copy(__b, __e, __new_result, __is_vector);
  1506. }
  1507. else
  1508. {
  1509. __internal::__brick_copy(__b, __middle, __new_result, __is_vector);
  1510. __internal::__brick_copy(__middle, __e, __result, __is_vector);
  1511. }
  1512. }
  1513. });
  1514. return __result + (__last - __first);
  1515. }
  1516. //------------------------------------------------------------------------
  1517. // is_partitioned
  1518. //------------------------------------------------------------------------
  1519. template <class _ForwardIterator, class _UnaryPredicate>
  1520. bool
  1521. __brick_is_partitioned(_ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred,
  1522. /*is_vector=*/std::false_type) noexcept
  1523. {
  1524. return std::is_partitioned(__first, __last, __pred);
  1525. }
  1526. template <class _ForwardIterator, class _UnaryPredicate>
  1527. bool
  1528. __brick_is_partitioned(_ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred,
  1529. /*is_vector=*/std::true_type) noexcept
  1530. {
  1531. typedef typename std::iterator_traits<_ForwardIterator>::difference_type _SizeType;
  1532. if (__first == __last)
  1533. {
  1534. return true;
  1535. }
  1536. else
  1537. {
  1538. _ForwardIterator __result = __unseq_backend::__simd_first(
  1539. __first, _SizeType(0), __last - __first,
  1540. [&__pred](_ForwardIterator __it, _SizeType __i) { return !__pred(__it[__i]); });
  1541. if (__result == __last)
  1542. {
  1543. return true;
  1544. }
  1545. else
  1546. {
  1547. ++__result;
  1548. return !__unseq_backend::__simd_or(__result, __last - __result, __pred);
  1549. }
  1550. }
  1551. }
  1552. template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector>
  1553. bool
  1554. __pattern_is_partitioned(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred,
  1555. _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept
  1556. {
  1557. return __internal::__brick_is_partitioned(__first, __last, __pred, __is_vector);
  1558. }
  1559. template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector>
  1560. bool
  1561. __pattern_is_partitioned(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last,
  1562. _UnaryPredicate __pred, _IsVector __is_vector, /*is_parallel=*/std::true_type)
  1563. {
  1564. if (__first == __last)
  1565. {
  1566. return true;
  1567. }
  1568. else
  1569. {
  1570. return __internal::__except_handler([&]() {
  1571. // State of current range:
  1572. // broken - current range is not partitioned by pred
  1573. // all_true - all elements in current range satisfy pred
  1574. // all_false - all elements in current range don't satisfy pred
  1575. // true_false - elements satisfy pred are placed before elements that don't satisfy pred
  1576. enum _ReduceType
  1577. {
  1578. __not_init = -1,
  1579. __broken,
  1580. __all_true,
  1581. __all_false,
  1582. __true_false
  1583. };
  1584. _ReduceType __init = __not_init;
  1585. // Array with states that we'll have when state from the left branch is merged with state from the right branch.
  1586. // State is calculated by formula: new_state = table[left_state * 4 + right_state]
  1587. _ReduceType __table[] = {__broken, __broken, __broken, __broken, __broken, __all_true,
  1588. __true_false, __true_false, __broken, __broken, __all_false, __broken,
  1589. __broken, __broken, __true_false, __broken};
  1590. __init = __par_backend::__parallel_reduce(
  1591. std::forward<_ExecutionPolicy>(__exec), __first, __last, __init,
  1592. [&__pred, &__table, __is_vector](_ForwardIterator __i, _ForwardIterator __j,
  1593. _ReduceType __value) -> _ReduceType {
  1594. if (__value == __broken)
  1595. {
  1596. return __broken;
  1597. }
  1598. _ReduceType __res = __not_init;
  1599. // if first element satisfy pred
  1600. if (__pred(*__i))
  1601. {
  1602. // find first element that don't satisfy pred
  1603. _ForwardIterator __x =
  1604. __internal::__brick_find_if(__i + 1, __j, __not_pred<_UnaryPredicate>(__pred), __is_vector);
  1605. if (__x != __j)
  1606. {
  1607. // find first element after "x" that satisfy pred
  1608. _ForwardIterator __y = __internal::__brick_find_if(__x + 1, __j, __pred, __is_vector);
  1609. // if it was found then range isn't partitioned by pred
  1610. if (__y != __j)
  1611. {
  1612. return __broken;
  1613. }
  1614. else
  1615. {
  1616. __res = __true_false;
  1617. }
  1618. }
  1619. else
  1620. {
  1621. __res = __all_true;
  1622. }
  1623. }
  1624. else
  1625. { // if first element doesn't satisfy pred
  1626. // then we should find the first element that satisfy pred.
  1627. // If we found it then range isn't partitioned by pred
  1628. if (__internal::__brick_find_if(__i + 1, __j, __pred, __is_vector) != __j)
  1629. {
  1630. return __broken;
  1631. }
  1632. else
  1633. {
  1634. __res = __all_false;
  1635. }
  1636. }
  1637. // if we have value from left range then we should calculate the result
  1638. return (__value == -1) ? __res : __table[__value * 4 + __res];
  1639. },
  1640. [&__table](_ReduceType __val1, _ReduceType __val2) -> _ReduceType {
  1641. if (__val1 == __broken || __val2 == __broken)
  1642. {
  1643. return __broken;
  1644. }
  1645. // calculate the result for new big range
  1646. return __table[__val1 * 4 + __val2];
  1647. });
  1648. return __init != __broken;
  1649. });
  1650. }
  1651. }
  1652. //------------------------------------------------------------------------
  1653. // partition
  1654. //------------------------------------------------------------------------
  1655. template <class _ForwardIterator, class _UnaryPredicate>
  1656. _ForwardIterator
  1657. __brick_partition(_ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred,
  1658. /*is_vector=*/std::false_type) noexcept
  1659. {
  1660. return std::partition(__first, __last, __pred);
  1661. }
  1662. template <class _ForwardIterator, class _UnaryPredicate>
  1663. _ForwardIterator
  1664. __brick_partition(_ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred,
  1665. /*is_vector=*/std::true_type) noexcept
  1666. {
  1667. _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial");
  1668. return std::partition(__first, __last, __pred);
  1669. }
  1670. template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector>
  1671. _ForwardIterator
  1672. __pattern_partition(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred,
  1673. _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept
  1674. {
  1675. return __internal::__brick_partition(__first, __last, __pred, __is_vector);
  1676. }
  1677. template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector>
  1678. _ForwardIterator
  1679. __pattern_partition(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last,
  1680. _UnaryPredicate __pred, _IsVector __is_vector, /*is_parallel=*/std::true_type)
  1681. {
  1682. // partitioned range: elements before pivot satisfy pred (true part),
  1683. // elements after pivot don't satisfy pred (false part)
  1684. struct _PartitionRange
  1685. {
  1686. _ForwardIterator __begin;
  1687. _ForwardIterator __pivot;
  1688. _ForwardIterator __end;
  1689. };
  1690. return __internal::__except_handler([&]() {
  1691. _PartitionRange __init{__last, __last, __last};
  1692. // lambda for merging two partitioned ranges to one partitioned range
  1693. auto __reductor = [&__exec, __is_vector](_PartitionRange __val1, _PartitionRange __val2) -> _PartitionRange {
  1694. auto __size1 = __val1.__end - __val1.__pivot;
  1695. auto __size2 = __val2.__pivot - __val2.__begin;
  1696. auto __new_begin = __val2.__begin - (__val1.__end - __val1.__begin);
  1697. // if all elements in left range satisfy pred then we can move new pivot to pivot of right range
  1698. if (__val1.__end == __val1.__pivot)
  1699. {
  1700. return {__new_begin, __val2.__pivot, __val2.__end};
  1701. }
  1702. // if true part of right range greater than false part of left range
  1703. // then we should swap the false part of left range and last part of true part of right range
  1704. else if (__size2 > __size1)
  1705. {
  1706. __par_backend::__parallel_for(
  1707. std::forward<_ExecutionPolicy>(__exec), __val1.__pivot, __val1.__pivot + __size1,
  1708. [__val1, __val2, __size1, __is_vector](_ForwardIterator __i, _ForwardIterator __j) {
  1709. __internal::__brick_swap_ranges(__i, __j, (__val2.__pivot - __size1) + (__i - __val1.__pivot),
  1710. __is_vector);
  1711. });
  1712. return {__new_begin, __val2.__pivot - __size1, __val2.__end};
  1713. }
  1714. // else we should swap the first part of false part of left range and true part of right range
  1715. else
  1716. {
  1717. __par_backend::__parallel_for(
  1718. std::forward<_ExecutionPolicy>(__exec), __val1.__pivot, __val1.__pivot + __size2,
  1719. [__val1, __val2, __is_vector](_ForwardIterator __i, _ForwardIterator __j) {
  1720. __internal::__brick_swap_ranges(__i, __j, __val2.__begin + (__i - __val1.__pivot), __is_vector);
  1721. });
  1722. return {__new_begin, __val1.__pivot + __size2, __val2.__end};
  1723. }
  1724. };
  1725. _PartitionRange __result = __par_backend::__parallel_reduce(
  1726. std::forward<_ExecutionPolicy>(__exec), __first, __last, __init,
  1727. [__pred, __is_vector, __reductor](_ForwardIterator __i, _ForwardIterator __j,
  1728. _PartitionRange __value) -> _PartitionRange {
  1729. //1. serial partition
  1730. _ForwardIterator __pivot = __internal::__brick_partition(__i, __j, __pred, __is_vector);
  1731. // 2. merging of two ranges (left and right respectively)
  1732. return __reductor(__value, {__i, __pivot, __j});
  1733. },
  1734. __reductor);
  1735. return __result.__pivot;
  1736. });
  1737. }
  1738. //------------------------------------------------------------------------
  1739. // stable_partition
  1740. //------------------------------------------------------------------------
  1741. template <class _BidirectionalIterator, class _UnaryPredicate>
  1742. _BidirectionalIterator
  1743. __brick_stable_partition(_BidirectionalIterator __first, _BidirectionalIterator __last, _UnaryPredicate __pred,
  1744. /*__is_vector=*/std::false_type) noexcept
  1745. {
  1746. return std::stable_partition(__first, __last, __pred);
  1747. }
  1748. template <class _BidirectionalIterator, class _UnaryPredicate>
  1749. _BidirectionalIterator
  1750. __brick_stable_partition(_BidirectionalIterator __first, _BidirectionalIterator __last, _UnaryPredicate __pred,
  1751. /*__is_vector=*/std::true_type) noexcept
  1752. {
  1753. _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial");
  1754. return std::stable_partition(__first, __last, __pred);
  1755. }
  1756. template <class _ExecutionPolicy, class _BidirectionalIterator, class _UnaryPredicate, class _IsVector>
  1757. _BidirectionalIterator
  1758. __pattern_stable_partition(_ExecutionPolicy&&, _BidirectionalIterator __first, _BidirectionalIterator __last,
  1759. _UnaryPredicate __pred, _IsVector __is_vector,
  1760. /*is_parallelization=*/std::false_type) noexcept
  1761. {
  1762. return __internal::__brick_stable_partition(__first, __last, __pred, __is_vector);
  1763. }
  1764. template <class _ExecutionPolicy, class _BidirectionalIterator, class _UnaryPredicate, class _IsVector>
  1765. _BidirectionalIterator
  1766. __pattern_stable_partition(_ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __last,
  1767. _UnaryPredicate __pred, _IsVector __is_vector,
  1768. /*is_parallelization=*/std::true_type) noexcept
  1769. {
  1770. // partitioned range: elements before pivot satisfy pred (true part),
  1771. // elements after pivot don't satisfy pred (false part)
  1772. struct _PartitionRange
  1773. {
  1774. _BidirectionalIterator __begin;
  1775. _BidirectionalIterator __pivot;
  1776. _BidirectionalIterator __end;
  1777. };
  1778. return __internal::__except_handler([&]() {
  1779. _PartitionRange __init{__last, __last, __last};
  1780. // lambda for merging two partitioned ranges to one partitioned range
  1781. auto __reductor = [__is_vector](_PartitionRange __val1, _PartitionRange __val2) -> _PartitionRange {
  1782. auto __size1 = __val1.__end - __val1.__pivot;
  1783. auto __new_begin = __val2.__begin - (__val1.__end - __val1.__begin);
  1784. // if all elements in left range satisfy pred then we can move new pivot to pivot of right range
  1785. if (__val1.__end == __val1.__pivot)
  1786. {
  1787. return {__new_begin, __val2.__pivot, __val2.__end};
  1788. }
  1789. // if true part of right range greater than false part of left range
  1790. // then we should swap the false part of left range and last part of true part of right range
  1791. else
  1792. {
  1793. __internal::__brick_rotate(__val1.__pivot, __val2.__begin, __val2.__pivot, __is_vector);
  1794. return {__new_begin, __val2.__pivot - __size1, __val2.__end};
  1795. }
  1796. };
  1797. _PartitionRange __result = __par_backend::__parallel_reduce(
  1798. std::forward<_ExecutionPolicy>(__exec), __first, __last, __init,
  1799. [&__pred, __is_vector, __reductor](_BidirectionalIterator __i, _BidirectionalIterator __j,
  1800. _PartitionRange __value) -> _PartitionRange {
  1801. //1. serial stable_partition
  1802. _BidirectionalIterator __pivot = __internal::__brick_stable_partition(__i, __j, __pred, __is_vector);
  1803. // 2. merging of two ranges (left and right respectively)
  1804. return __reductor(__value, {__i, __pivot, __j});
  1805. },
  1806. __reductor);
  1807. return __result.__pivot;
  1808. });
  1809. }
  1810. //------------------------------------------------------------------------
  1811. // partition_copy
  1812. //------------------------------------------------------------------------
  1813. template <class _ForwardIterator, class _OutputIterator1, class _OutputIterator2, class _UnaryPredicate>
  1814. std::pair<_OutputIterator1, _OutputIterator2>
  1815. __brick_partition_copy(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator1 __out_true,
  1816. _OutputIterator2 __out_false, _UnaryPredicate __pred, /*is_vector=*/std::false_type) noexcept
  1817. {
  1818. return std::partition_copy(__first, __last, __out_true, __out_false, __pred);
  1819. }
  1820. template <class _ForwardIterator, class _OutputIterator1, class _OutputIterator2, class _UnaryPredicate>
  1821. std::pair<_OutputIterator1, _OutputIterator2>
  1822. __brick_partition_copy(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator1 __out_true,
  1823. _OutputIterator2 __out_false, _UnaryPredicate __pred, /*is_vector=*/std::true_type) noexcept
  1824. {
  1825. #if (_PSTL_MONOTONIC_PRESENT)
  1826. return __unseq_backend::__simd_partition_copy(__first, __last - __first, __out_true, __out_false, __pred);
  1827. #else
  1828. return std::partition_copy(__first, __last, __out_true, __out_false, __pred);
  1829. #endif
  1830. }
  1831. template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator1, class _OutputIterator2,
  1832. class _UnaryPredicate, class _IsVector>
  1833. std::pair<_OutputIterator1, _OutputIterator2>
  1834. __pattern_partition_copy(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last,
  1835. _OutputIterator1 __out_true, _OutputIterator2 __out_false, _UnaryPredicate __pred,
  1836. _IsVector __is_vector, /*is_parallelization=*/std::false_type) noexcept
  1837. {
  1838. return __internal::__brick_partition_copy(__first, __last, __out_true, __out_false, __pred, __is_vector);
  1839. }
  1840. template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator1, class _OutputIterator2,
  1841. class _UnaryPredicate, class _IsVector>
  1842. std::pair<_OutputIterator1, _OutputIterator2>
  1843. __pattern_partition_copy(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last,
  1844. _OutputIterator1 __out_true, _OutputIterator2 __out_false, _UnaryPredicate __pred,
  1845. _IsVector __is_vector, /*is_parallelization=*/std::true_type)
  1846. {
  1847. typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType;
  1848. typedef std::pair<_DifferenceType, _DifferenceType> _ReturnType;
  1849. const _DifferenceType __n = __last - __first;
  1850. if (_DifferenceType(1) < __n)
  1851. {
  1852. __par_backend::__buffer<bool> __mask_buf(__n);
  1853. return __internal::__except_handler([&__exec, __n, __first, __out_true, __out_false, __is_vector, __pred,
  1854. &__mask_buf]() {
  1855. bool* __mask = __mask_buf.get();
  1856. _ReturnType __m{};
  1857. __par_backend::__parallel_strict_scan(
  1858. std::forward<_ExecutionPolicy>(__exec), __n, std::make_pair(_DifferenceType(0), _DifferenceType(0)),
  1859. [=](_DifferenceType __i, _DifferenceType __len) { // Reduce
  1860. return __internal::__brick_calc_mask_1<_DifferenceType>(__first + __i, __first + (__i + __len),
  1861. __mask + __i, __pred, __is_vector);
  1862. },
  1863. [](const _ReturnType& __x, const _ReturnType& __y) -> _ReturnType {
  1864. return std::make_pair(__x.first + __y.first, __x.second + __y.second);
  1865. }, // Combine
  1866. [=](_DifferenceType __i, _DifferenceType __len, _ReturnType __initial) { // Scan
  1867. __internal::__brick_partition_by_mask(__first + __i, __first + (__i + __len),
  1868. __out_true + __initial.first, __out_false + __initial.second,
  1869. __mask + __i, __is_vector);
  1870. },
  1871. [&__m](_ReturnType __total) { __m = __total; });
  1872. return std::make_pair(__out_true + __m.first, __out_false + __m.second);
  1873. });
  1874. }
  1875. // trivial sequence - use serial algorithm
  1876. return __internal::__brick_partition_copy(__first, __last, __out_true, __out_false, __pred, __is_vector);
  1877. }
  1878. //------------------------------------------------------------------------
  1879. // sort
  1880. //------------------------------------------------------------------------
  1881. template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector,
  1882. class _IsMoveConstructible>
  1883. void
  1884. __pattern_sort(_ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp,
  1885. _IsVector /*is_vector*/, /*is_parallel=*/std::false_type, _IsMoveConstructible) noexcept
  1886. {
  1887. std::sort(__first, __last, __comp);
  1888. }
  1889. template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
  1890. void
  1891. __pattern_sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp,
  1892. _IsVector /*is_vector*/, /*is_parallel=*/std::true_type, /*is_move_constructible=*/std::true_type)
  1893. {
  1894. __internal::__except_handler([&]() {
  1895. __par_backend::__parallel_stable_sort(std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp,
  1896. [](_RandomAccessIterator __first, _RandomAccessIterator __last,
  1897. _Compare __comp) { std::sort(__first, __last, __comp); },
  1898. __last - __first);
  1899. });
  1900. }
  1901. //------------------------------------------------------------------------
  1902. // stable_sort
  1903. //------------------------------------------------------------------------
  1904. template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
  1905. void
  1906. __pattern_stable_sort(_ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp,
  1907. _IsVector /*is_vector*/, /*is_parallel=*/std::false_type) noexcept
  1908. {
  1909. std::stable_sort(__first, __last, __comp);
  1910. }
  1911. template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
  1912. void
  1913. __pattern_stable_sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last,
  1914. _Compare __comp, _IsVector /*is_vector*/, /*is_parallel=*/std::true_type)
  1915. {
  1916. __internal::__except_handler([&]() {
  1917. __par_backend::__parallel_stable_sort(std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp,
  1918. [](_RandomAccessIterator __first, _RandomAccessIterator __last,
  1919. _Compare __comp) { std::stable_sort(__first, __last, __comp); });
  1920. });
  1921. }
  1922. //------------------------------------------------------------------------
  1923. // partial_sort
  1924. //------------------------------------------------------------------------
  1925. template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
  1926. void
  1927. __pattern_partial_sort(_ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __middle,
  1928. _RandomAccessIterator __last, _Compare __comp, _IsVector,
  1929. /*is_parallel=*/std::false_type) noexcept
  1930. {
  1931. std::partial_sort(__first, __middle, __last, __comp);
  1932. }
  1933. template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
  1934. void
  1935. __pattern_partial_sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __middle,
  1936. _RandomAccessIterator __last, _Compare __comp, _IsVector, /*is_parallel=*/std::true_type)
  1937. {
  1938. const auto __n = __middle - __first;
  1939. __internal::__except_handler([&]() {
  1940. __par_backend::__parallel_stable_sort(
  1941. std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp,
  1942. [__n](_RandomAccessIterator __begin, _RandomAccessIterator __end, _Compare __comp) {
  1943. if (__n < __end - __begin)
  1944. std::partial_sort(__begin, __begin + __n, __end, __comp);
  1945. else
  1946. std::sort(__begin, __end, __comp);
  1947. },
  1948. __n);
  1949. });
  1950. }
  1951. //------------------------------------------------------------------------
  1952. // partial_sort_copy
  1953. //------------------------------------------------------------------------
  1954. template <class _ExecutionPolicy, class _ForwardIterator, class _RandomAccessIterator, class _Compare, class _IsVector>
  1955. _RandomAccessIterator
  1956. __pattern_partial_sort_copy(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last,
  1957. _RandomAccessIterator __d_first, _RandomAccessIterator __d_last, _Compare __comp, _IsVector,
  1958. /*is_parallel=*/std::false_type) noexcept
  1959. {
  1960. return std::partial_sort_copy(__first, __last, __d_first, __d_last, __comp);
  1961. }
  1962. template <class _ExecutionPolicy, class _ForwardIterator, class _RandomAccessIterator, class _Compare, class _IsVector>
  1963. _RandomAccessIterator
  1964. __pattern_partial_sort_copy(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last,
  1965. _RandomAccessIterator __d_first, _RandomAccessIterator __d_last, _Compare __comp,
  1966. _IsVector __is_vector, /*is_parallel=*/std::true_type)
  1967. {
  1968. if (__last == __first || __d_last == __d_first)
  1969. {
  1970. return __d_first;
  1971. }
  1972. auto __n1 = __last - __first;
  1973. auto __n2 = __d_last - __d_first;
  1974. return __internal::__except_handler([&]() {
  1975. if (__n2 >= __n1)
  1976. {
  1977. __par_backend::__parallel_stable_sort(
  1978. std::forward<_ExecutionPolicy>(__exec), __d_first, __d_first + __n1, __comp,
  1979. [__first, __d_first, __is_vector](_RandomAccessIterator __i, _RandomAccessIterator __j,
  1980. _Compare __comp) {
  1981. _ForwardIterator __i1 = __first + (__i - __d_first);
  1982. _ForwardIterator __j1 = __first + (__j - __d_first);
  1983. // 1. Copy elements from input to output
  1984. # if !_PSTL_ICC_18_OMP_SIMD_BROKEN
  1985. __internal::__brick_copy(__i1, __j1, __i, __is_vector);
  1986. # else
  1987. std::copy(__i1, __j1, __i);
  1988. # endif
  1989. // 2. Sort elements in output sequence
  1990. std::sort(__i, __j, __comp);
  1991. },
  1992. __n1);
  1993. return __d_first + __n1;
  1994. }
  1995. else
  1996. {
  1997. typedef typename std::iterator_traits<_ForwardIterator>::value_type _T1;
  1998. typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _T2;
  1999. __par_backend::__buffer<_T1> __buf(__n1);
  2000. _T1* __r = __buf.get();
  2001. __par_backend::__parallel_stable_sort(std::forward<_ExecutionPolicy>(__exec), __r, __r + __n1, __comp,
  2002. [__n2, __first, __r](_T1* __i, _T1* __j, _Compare __comp) {
  2003. _ForwardIterator __it = __first + (__i - __r);
  2004. // 1. Copy elements from input to raw memory
  2005. for (_T1* __k = __i; __k != __j; ++__k, ++__it)
  2006. {
  2007. ::new (__k) _T2(*__it);
  2008. }
  2009. // 2. Sort elements in temporary __buffer
  2010. if (__n2 < __j - __i)
  2011. std::partial_sort(__i, __i + __n2, __j, __comp);
  2012. else
  2013. std::sort(__i, __j, __comp);
  2014. },
  2015. __n2);
  2016. // 3. Move elements from temporary __buffer to output
  2017. __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __r, __r + __n2,
  2018. [__r, __d_first, __is_vector](_T1* __i, _T1* __j) {
  2019. __internal::__brick_move(__i, __j, __d_first + (__i - __r), __is_vector);
  2020. });
  2021. return __d_first + __n2;
  2022. }
  2023. });
  2024. }
  2025. //------------------------------------------------------------------------
  2026. // adjacent_find
  2027. //------------------------------------------------------------------------
  2028. template <class _ForwardIterator, class _BinaryPredicate>
  2029. _ForwardIterator
  2030. __brick_adjacent_find(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred,
  2031. /* IsVector = */ std::true_type, bool __or_semantic) noexcept
  2032. {
  2033. return __unseq_backend::__simd_adjacent_find(__first, __last, __pred, __or_semantic);
  2034. }
  2035. template <class _ForwardIterator, class _BinaryPredicate>
  2036. _ForwardIterator
  2037. __brick_adjacent_find(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred,
  2038. /* IsVector = */ std::false_type, bool __or_semantic) noexcept
  2039. {
  2040. return std::adjacent_find(__first, __last, __pred);
  2041. }
  2042. template <class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate, class _IsVector>
  2043. _ForwardIterator
  2044. __pattern_adjacent_find(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred,
  2045. /* is_parallel */ std::false_type, _IsVector __is_vector, bool __or_semantic) noexcept
  2046. {
  2047. return __internal::__brick_adjacent_find(__first, __last, __pred, __is_vector, __or_semantic);
  2048. }
  2049. template <class _ExecutionPolicy, class _RandomAccessIterator, class _BinaryPredicate, class _IsVector>
  2050. _RandomAccessIterator
  2051. __pattern_adjacent_find(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last,
  2052. _BinaryPredicate __pred, /* is_parallel */ std::true_type, _IsVector __is_vector,
  2053. bool __or_semantic)
  2054. {
  2055. if (__last - __first < 2)
  2056. return __last;
  2057. return __internal::__except_handler([&]() {
  2058. return __par_backend::__parallel_reduce(
  2059. std::forward<_ExecutionPolicy>(__exec), __first, __last, __last,
  2060. [__last, __pred, __is_vector, __or_semantic](_RandomAccessIterator __begin, _RandomAccessIterator __end,
  2061. _RandomAccessIterator __value) -> _RandomAccessIterator {
  2062. // TODO: investigate performance benefits from the use of shared variable for the result,
  2063. // checking (compare_and_swap idiom) its __value at __first.
  2064. if (__or_semantic && __value < __last)
  2065. { //found
  2066. __par_backend::__cancel_execution();
  2067. return __value;
  2068. }
  2069. if (__value > __begin)
  2070. {
  2071. // modify __end to check the predicate on the boundary __values;
  2072. // TODO: to use a custom range with boundaries overlapping
  2073. // TODO: investigate what if we remove "if" below and run algorithm on range [__first, __last-1)
  2074. // then check the pair [__last-1, __last)
  2075. if (__end != __last)
  2076. ++__end;
  2077. //correct the global result iterator if the "brick" returns a local "__last"
  2078. const _RandomAccessIterator __res =
  2079. __internal::__brick_adjacent_find(__begin, __end, __pred, __is_vector, __or_semantic);
  2080. if (__res < __end)
  2081. __value = __res;
  2082. }
  2083. return __value;
  2084. },
  2085. [](_RandomAccessIterator __x, _RandomAccessIterator __y) -> _RandomAccessIterator {
  2086. return __x < __y ? __x : __y;
  2087. } //reduce a __value
  2088. );
  2089. });
  2090. }
  2091. //------------------------------------------------------------------------
  2092. // nth_element
  2093. //------------------------------------------------------------------------
  2094. template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
  2095. void
  2096. __pattern_nth_element(_ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __nth,
  2097. _RandomAccessIterator __last, _Compare __comp, _IsVector,
  2098. /*is_parallel=*/std::false_type) noexcept
  2099. {
  2100. std::nth_element(__first, __nth, __last, __comp);
  2101. }
  2102. template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
  2103. void
  2104. __pattern_nth_element(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __nth,
  2105. _RandomAccessIterator __last, _Compare __comp, _IsVector __is_vector,
  2106. /*is_parallel=*/std::true_type) noexcept
  2107. {
  2108. if (__first == __last || __nth == __last)
  2109. {
  2110. return;
  2111. }
  2112. using std::iter_swap;
  2113. typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _Tp;
  2114. _RandomAccessIterator __x;
  2115. do
  2116. {
  2117. __x = __internal::__pattern_partition(std::forward<_ExecutionPolicy>(__exec), __first + 1, __last,
  2118. [&__comp, __first](const _Tp& __x) { return __comp(__x, *__first); },
  2119. __is_vector,
  2120. /*is_parallel=*/std::true_type());
  2121. --__x;
  2122. if (__x != __first)
  2123. {
  2124. iter_swap(__first, __x);
  2125. }
  2126. // if x > nth then our new range for partition is [first, x)
  2127. if (__x - __nth > 0)
  2128. {
  2129. __last = __x;
  2130. }
  2131. // if x < nth then our new range for partition is [x, last)
  2132. else if (__x - __nth < 0)
  2133. {
  2134. // if *x == *nth then we can start new partition with x+1
  2135. if (!__comp(*__nth, *__x) && !__comp(*__x, *__nth))
  2136. {
  2137. ++__x;
  2138. }
  2139. else
  2140. {
  2141. iter_swap(__nth, __x);
  2142. }
  2143. __first = __x;
  2144. }
  2145. } while (__x != __nth);
  2146. }
  2147. //------------------------------------------------------------------------
  2148. // fill, fill_n
  2149. //------------------------------------------------------------------------
  2150. template <class _ForwardIterator, class _Tp>
  2151. void
  2152. __brick_fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value,
  2153. /* __is_vector = */ std::true_type) noexcept
  2154. {
  2155. __unseq_backend::__simd_fill_n(__first, __last - __first, __value);
  2156. }
  2157. template <class _ForwardIterator, class _Tp>
  2158. void
  2159. __brick_fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value,
  2160. /* __is_vector = */ std::false_type) noexcept
  2161. {
  2162. std::fill(__first, __last, __value);
  2163. }
  2164. template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _IsVector>
  2165. void
  2166. __pattern_fill(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value,
  2167. /*is_parallel=*/std::false_type, _IsVector __is_vector) noexcept
  2168. {
  2169. __internal::__brick_fill(__first, __last, __value, __is_vector);
  2170. }
  2171. template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _IsVector>
  2172. _ForwardIterator
  2173. __pattern_fill(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value,
  2174. /*is_parallel=*/std::true_type, _IsVector __is_vector)
  2175. {
  2176. return __internal::__except_handler([&__exec, __first, __last, &__value, __is_vector]() {
  2177. __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last,
  2178. [&__value, __is_vector](_ForwardIterator __begin, _ForwardIterator __end) {
  2179. __internal::__brick_fill(__begin, __end, __value, __is_vector);
  2180. });
  2181. return __last;
  2182. });
  2183. }
  2184. template <class _OutputIterator, class _Size, class _Tp>
  2185. _OutputIterator
  2186. __brick_fill_n(_OutputIterator __first, _Size __count, const _Tp& __value, /* __is_vector = */ std::true_type) noexcept
  2187. {
  2188. return __unseq_backend::__simd_fill_n(__first, __count, __value);
  2189. }
  2190. template <class _OutputIterator, class _Size, class _Tp>
  2191. _OutputIterator
  2192. __brick_fill_n(_OutputIterator __first, _Size __count, const _Tp& __value, /* __is_vector = */ std::false_type) noexcept
  2193. {
  2194. return std::fill_n(__first, __count, __value);
  2195. }
  2196. template <class _ExecutionPolicy, class _OutputIterator, class _Size, class _Tp, class _IsVector>
  2197. _OutputIterator
  2198. __pattern_fill_n(_ExecutionPolicy&&, _OutputIterator __first, _Size __count, const _Tp& __value,
  2199. /*is_parallel=*/std::false_type, _IsVector __is_vector) noexcept
  2200. {
  2201. return __internal::__brick_fill_n(__first, __count, __value, __is_vector);
  2202. }
  2203. template <class _ExecutionPolicy, class _OutputIterator, class _Size, class _Tp, class _IsVector>
  2204. _OutputIterator
  2205. __pattern_fill_n(_ExecutionPolicy&& __exec, _OutputIterator __first, _Size __count, const _Tp& __value,
  2206. /*is_parallel=*/std::true_type, _IsVector __is_vector)
  2207. {
  2208. return __internal::__pattern_fill(std::forward<_ExecutionPolicy>(__exec), __first, __first + __count, __value,
  2209. std::true_type(), __is_vector);
  2210. }
  2211. //------------------------------------------------------------------------
  2212. // generate, generate_n
  2213. //------------------------------------------------------------------------
  2214. template <class _RandomAccessIterator, class _Generator>
  2215. void
  2216. __brick_generate(_RandomAccessIterator __first, _RandomAccessIterator __last, _Generator __g,
  2217. /* is_vector = */ std::true_type) noexcept
  2218. {
  2219. __unseq_backend::__simd_generate_n(__first, __last - __first, __g);
  2220. }
  2221. template <class _ForwardIterator, class _Generator>
  2222. void
  2223. __brick_generate(_ForwardIterator __first, _ForwardIterator __last, _Generator __g,
  2224. /* is_vector = */ std::false_type) noexcept
  2225. {
  2226. std::generate(__first, __last, __g);
  2227. }
  2228. template <class _ExecutionPolicy, class _ForwardIterator, class _Generator, class _IsVector>
  2229. void
  2230. __pattern_generate(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Generator __g,
  2231. /*is_parallel=*/std::false_type, _IsVector __is_vector) noexcept
  2232. {
  2233. __internal::__brick_generate(__first, __last, __g, __is_vector);
  2234. }
  2235. template <class _ExecutionPolicy, class _ForwardIterator, class _Generator, class _IsVector>
  2236. _ForwardIterator
  2237. __pattern_generate(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Generator __g,
  2238. /*is_parallel=*/std::true_type, _IsVector __is_vector)
  2239. {
  2240. return __internal::__except_handler([&]() {
  2241. __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last,
  2242. [__g, __is_vector](_ForwardIterator __begin, _ForwardIterator __end) {
  2243. __internal::__brick_generate(__begin, __end, __g, __is_vector);
  2244. });
  2245. return __last;
  2246. });
  2247. }
  2248. template <class OutputIterator, class Size, class _Generator>
  2249. OutputIterator
  2250. __brick_generate_n(OutputIterator __first, Size __count, _Generator __g, /* is_vector = */ std::true_type) noexcept
  2251. {
  2252. return __unseq_backend::__simd_generate_n(__first, __count, __g);
  2253. }
  2254. template <class OutputIterator, class Size, class _Generator>
  2255. OutputIterator
  2256. __brick_generate_n(OutputIterator __first, Size __count, _Generator __g, /* is_vector = */ std::false_type) noexcept
  2257. {
  2258. return std::generate_n(__first, __count, __g);
  2259. }
  2260. template <class _ExecutionPolicy, class _OutputIterator, class _Size, class _Generator, class _IsVector>
  2261. _OutputIterator
  2262. __pattern_generate_n(_ExecutionPolicy&&, _OutputIterator __first, _Size __count, _Generator __g,
  2263. /*is_parallel=*/std::false_type, _IsVector __is_vector) noexcept
  2264. {
  2265. return __internal::__brick_generate_n(__first, __count, __g, __is_vector);
  2266. }
  2267. template <class _ExecutionPolicy, class _OutputIterator, class _Size, class _Generator, class _IsVector>
  2268. _OutputIterator
  2269. __pattern_generate_n(_ExecutionPolicy&& __exec, _OutputIterator __first, _Size __count, _Generator __g,
  2270. /*is_parallel=*/std::true_type, _IsVector __is_vector)
  2271. {
  2272. static_assert(__is_random_access_iterator<_OutputIterator>::value,
  2273. "Pattern-brick error. Should be a random access iterator.");
  2274. return __internal::__pattern_generate(std::forward<_ExecutionPolicy>(__exec), __first, __first + __count, __g,
  2275. std::true_type(), __is_vector);
  2276. }
  2277. //------------------------------------------------------------------------
  2278. // remove
  2279. //------------------------------------------------------------------------
  2280. template <class _ForwardIterator, class _UnaryPredicate>
  2281. _ForwardIterator
  2282. __brick_remove_if(_ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred,
  2283. /* __is_vector = */ std::false_type) noexcept
  2284. {
  2285. return std::remove_if(__first, __last, __pred);
  2286. }
  2287. template <class _RandomAccessIterator, class _UnaryPredicate>
  2288. _RandomAccessIterator
  2289. __brick_remove_if(_RandomAccessIterator __first, _RandomAccessIterator __last, _UnaryPredicate __pred,
  2290. /* __is_vector = */ std::true_type) noexcept
  2291. {
  2292. #if _PSTL_MONOTONIC_PRESENT
  2293. return __unseq_backend::__simd_remove_if(__first, __last - __first, __pred);
  2294. #else
  2295. return std::remove_if(__first, __last, __pred);
  2296. #endif
  2297. }
  2298. template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector>
  2299. _ForwardIterator
  2300. __pattern_remove_if(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred,
  2301. _IsVector __is_vector, /*is_parallel*/ std::false_type) noexcept
  2302. {
  2303. return __internal::__brick_remove_if(__first, __last, __pred, __is_vector);
  2304. }
  2305. template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector>
  2306. _ForwardIterator
  2307. __pattern_remove_if(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last,
  2308. _UnaryPredicate __pred, _IsVector __is_vector, /*is_parallel*/ std::true_type) noexcept
  2309. {
  2310. typedef typename std::iterator_traits<_ForwardIterator>::reference _ReferenceType;
  2311. if (__first == __last || __first + 1 == __last)
  2312. {
  2313. // Trivial sequence - use serial algorithm
  2314. return __internal::__brick_remove_if(__first, __last, __pred, __is_vector);
  2315. }
  2316. return __internal::__remove_elements(
  2317. std::forward<_ExecutionPolicy>(__exec), __first, __last,
  2318. [&__pred, __is_vector](bool* __b, bool* __e, _ForwardIterator __it) {
  2319. __internal::__brick_walk2(__b, __e, __it, [&__pred](bool& __x, _ReferenceType __y) { __x = !__pred(__y); },
  2320. __is_vector);
  2321. },
  2322. __is_vector);
  2323. }
  2324. //------------------------------------------------------------------------
  2325. // merge
  2326. //------------------------------------------------------------------------
  2327. template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare>
  2328. _OutputIterator
  2329. __brick_merge(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  2330. _ForwardIterator2 __last2, _OutputIterator __d_first, _Compare __comp,
  2331. /* __is_vector = */ std::false_type) noexcept
  2332. {
  2333. return std::merge(__first1, __last1, __first2, __last2, __d_first, __comp);
  2334. }
  2335. template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare>
  2336. _OutputIterator
  2337. __brick_merge(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  2338. _ForwardIterator2 __last2, _OutputIterator __d_first, _Compare __comp,
  2339. /* __is_vector = */ std::true_type) noexcept
  2340. {
  2341. _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial");
  2342. return std::merge(__first1, __last1, __first2, __last2, __d_first, __comp);
  2343. }
  2344. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
  2345. class _Compare, class _IsVector>
  2346. _OutputIterator
  2347. __pattern_merge(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  2348. _ForwardIterator2 __last2, _OutputIterator __d_first, _Compare __comp, _IsVector __is_vector,
  2349. /* is_parallel = */ std::false_type) noexcept
  2350. {
  2351. return __internal::__brick_merge(__first1, __last1, __first2, __last2, __d_first, __comp, __is_vector);
  2352. }
  2353. template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _OutputIterator,
  2354. class _Compare, class _IsVector>
  2355. _OutputIterator
  2356. __pattern_merge(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1,
  2357. _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, _OutputIterator __d_first,
  2358. _Compare __comp, _IsVector __is_vector, /* is_parallel = */ std::true_type)
  2359. {
  2360. __par_backend::__parallel_merge(
  2361. std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __d_first, __comp,
  2362. [__is_vector](_RandomAccessIterator1 __f1, _RandomAccessIterator1 __l1, _RandomAccessIterator2 __f2,
  2363. _RandomAccessIterator2 __l2, _OutputIterator __f3, _Compare __comp) {
  2364. return __internal::__brick_merge(__f1, __l1, __f2, __l2, __f3, __comp, __is_vector);
  2365. });
  2366. return __d_first + (__last1 - __first1) + (__last2 - __first2);
  2367. }
  2368. //------------------------------------------------------------------------
  2369. // inplace_merge
  2370. //------------------------------------------------------------------------
  2371. template <class _BidirectionalIterator, class _Compare>
  2372. void
  2373. __brick_inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last,
  2374. _Compare __comp, /* __is_vector = */ std::false_type) noexcept
  2375. {
  2376. std::inplace_merge(__first, __middle, __last, __comp);
  2377. }
  2378. template <class _BidirectionalIterator, class _Compare>
  2379. void
  2380. __brick_inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last,
  2381. _Compare __comp, /* __is_vector = */ std::true_type) noexcept
  2382. {
  2383. _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial")
  2384. std::inplace_merge(__first, __middle, __last, __comp);
  2385. }
  2386. template <class _ExecutionPolicy, class _BidirectionalIterator, class _Compare, class _IsVector>
  2387. void
  2388. __pattern_inplace_merge(_ExecutionPolicy&&, _BidirectionalIterator __first, _BidirectionalIterator __middle,
  2389. _BidirectionalIterator __last, _Compare __comp, _IsVector __is_vector,
  2390. /* is_parallel = */ std::false_type) noexcept
  2391. {
  2392. __internal::__brick_inplace_merge(__first, __middle, __last, __comp, __is_vector);
  2393. }
  2394. template <class _ExecutionPolicy, class _BidirectionalIterator, class _Compare, class _IsVector>
  2395. void
  2396. __pattern_inplace_merge(_ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __middle,
  2397. _BidirectionalIterator __last, _Compare __comp, _IsVector __is_vector,
  2398. /*is_parallel=*/std::true_type)
  2399. {
  2400. if (__first == __last || __first == __middle || __middle == __last)
  2401. {
  2402. return;
  2403. }
  2404. typedef typename std::iterator_traits<_BidirectionalIterator>::value_type _Tp;
  2405. auto __n = __last - __first;
  2406. __par_backend::__buffer<_Tp> __buf(__n);
  2407. _Tp* __r = __buf.get();
  2408. __internal::__except_handler([&]() {
  2409. auto __move_values = [](_BidirectionalIterator __x, _Tp* __z) {
  2410. __internal::__invoke_if_else(std::is_trivial<_Tp>(), [&]() { *__z = std::move(*__x); },
  2411. [&]() { ::new (std::addressof(*__z)) _Tp(std::move(*__x)); });
  2412. };
  2413. auto __move_sequences = [](_BidirectionalIterator __first1, _BidirectionalIterator __last1, _Tp* __first2) {
  2414. return __internal::__brick_uninitialized_move(__first1, __last1, __first2, _IsVector());
  2415. };
  2416. __par_backend::__parallel_merge(
  2417. std::forward<_ExecutionPolicy>(__exec), __first, __middle, __middle, __last, __r, __comp,
  2418. [__n, __move_values, __move_sequences](_BidirectionalIterator __f1, _BidirectionalIterator __l1,
  2419. _BidirectionalIterator __f2, _BidirectionalIterator __l2, _Tp* __f3,
  2420. _Compare __comp) {
  2421. auto __func = __par_backend::__serial_move_merge<decltype(__move_values), decltype(__move_sequences)>(
  2422. __n, __move_values, __move_sequences);
  2423. __func(__f1, __l1, __f2, __l2, __f3, __comp);
  2424. return __f3 + (__l1 - __f1) + (__l2 - __f2);
  2425. });
  2426. __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __r, __r + __n,
  2427. [__r, __first, __is_vector](_Tp* __i, _Tp* __j) {
  2428. __internal::__brick_move(__i, __j, __first + (__i - __r), __is_vector);
  2429. });
  2430. });
  2431. }
  2432. //------------------------------------------------------------------------
  2433. // includes
  2434. //------------------------------------------------------------------------
  2435. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare, class _IsVector>
  2436. bool
  2437. __pattern_includes(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
  2438. _ForwardIterator2 __first2, _ForwardIterator2 __last2, _Compare __comp, _IsVector,
  2439. /*is_parallel=*/std::false_type) noexcept
  2440. {
  2441. return std::includes(__first1, __last1, __first2, __last2, __comp);
  2442. }
  2443. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare, class _IsVector>
  2444. bool
  2445. __pattern_includes(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
  2446. _ForwardIterator2 __first2, _ForwardIterator2 __last2, _Compare __comp, _IsVector __is_vector,
  2447. /*is_parallel=*/std::true_type)
  2448. {
  2449. if (__first2 >= __last2)
  2450. return true;
  2451. if (__first1 >= __last1 || __comp(*__first2, *__first1) || __comp(*(__last1 - 1), *(__last2 - 1)))
  2452. return false;
  2453. __first1 = std::lower_bound(__first1, __last1, *__first2, __comp);
  2454. if (__first1 == __last1)
  2455. return false;
  2456. if (__last2 - __first2 == 1)
  2457. return !__comp(*__first1, *__first2) && !__comp(*__first2, *__first1);
  2458. return __internal::__except_handler([&]() {
  2459. return !__internal::__parallel_or(
  2460. std::forward<_ExecutionPolicy>(__exec), __first2, __last2,
  2461. [__first1, __last1, __first2, __last2, &__comp](_ForwardIterator2 __i, _ForwardIterator2 __j) {
  2462. _PSTL_ASSERT(__j > __i);
  2463. //assert(__j - __i > 1);
  2464. //1. moving boundaries to "consume" subsequence of equal elements
  2465. auto __is_equal = [&__comp](_ForwardIterator2 __a, _ForwardIterator2 __b) -> bool {
  2466. return !__comp(*__a, *__b) && !__comp(*__b, *__a);
  2467. };
  2468. //1.1 left bound, case "aaa[aaaxyz...]" - searching "x"
  2469. if (__i > __first2 && __is_equal(__i, __i - 1))
  2470. {
  2471. //whole subrange continues to content equal elements - return "no op"
  2472. if (__is_equal(__i, __j - 1))
  2473. return false;
  2474. __i = std::upper_bound(__i, __last2, *__i, __comp);
  2475. }
  2476. //1.2 right bound, case "[...aaa]aaaxyz" - searching "x"
  2477. if (__j < __last2 && __is_equal(__j - 1, __j))
  2478. __j = std::upper_bound(__j, __last2, *__j, __comp);
  2479. //2. testing is __a subsequence of the second range included into the first range
  2480. auto __b = std::lower_bound(__first1, __last1, *__i, __comp);
  2481. _PSTL_ASSERT(!__comp(*(__last1 - 1), *__b));
  2482. _PSTL_ASSERT(!__comp(*(__j - 1), *__i));
  2483. return !std::includes(__b, __last1, __i, __j, __comp);
  2484. });
  2485. });
  2486. }
  2487. constexpr auto __set_algo_cut_off = 1000;
  2488. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
  2489. class _Compare, class _IsVector, class _SizeFunction, class _SetOP>
  2490. _OutputIterator
  2491. __parallel_set_op(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
  2492. _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp,
  2493. _SizeFunction __size_func, _SetOP __set_op, _IsVector __is_vector)
  2494. {
  2495. typedef typename std::iterator_traits<_ForwardIterator1>::difference_type _DifferenceType;
  2496. typedef typename std::iterator_traits<_OutputIterator>::value_type _T;
  2497. struct _SetRange
  2498. {
  2499. _DifferenceType __pos, __len, __buf_pos;
  2500. bool
  2501. empty() const
  2502. {
  2503. return __len == 0;
  2504. }
  2505. };
  2506. const _DifferenceType __n1 = __last1 - __first1;
  2507. const _DifferenceType __n2 = __last2 - __first2;
  2508. __par_backend::__buffer<_T> __buf(__size_func(__n1, __n2));
  2509. return __internal::__except_handler([&__exec, __n1, __first1, __last1, __first2, __last2, __result, __is_vector,
  2510. __comp, __size_func, __set_op, &__buf]() {
  2511. auto __buffer = __buf.get();
  2512. _DifferenceType __m{};
  2513. auto __scan = [=](_DifferenceType, _DifferenceType, const _SetRange& __s) { // Scan
  2514. if (!__s.empty())
  2515. __internal::__brick_move(__buffer + __s.__buf_pos, __buffer + (__s.__buf_pos + __s.__len),
  2516. __result + __s.__pos, __is_vector);
  2517. };
  2518. __par_backend::__parallel_strict_scan(
  2519. std::forward<_ExecutionPolicy>(__exec), __n1, _SetRange{0, 0, 0}, //-1, 0},
  2520. [=](_DifferenceType __i, _DifferenceType __len) { // Reduce
  2521. //[__b; __e) - a subrange of the first sequence, to reduce
  2522. _ForwardIterator1 __b = __first1 + __i, __e = __first1 + (__i + __len);
  2523. //try searching for the first element which not equal to *__b
  2524. if (__b != __first1)
  2525. __b = std::upper_bound(__b, __last1, *__b, __comp);
  2526. //try searching for the first element which not equal to *__e
  2527. if (__e != __last1)
  2528. __e = std::upper_bound(__e, __last1, *__e, __comp);
  2529. //check is [__b; __e) empty
  2530. if (__e - __b < 1)
  2531. {
  2532. _ForwardIterator2 __bb = __last2;
  2533. if (__b != __last1)
  2534. __bb = std::lower_bound(__first2, __last2, *__b, __comp);
  2535. const _DifferenceType __buf_pos = __size_func((__b - __first1), (__bb - __first2));
  2536. return _SetRange{0, 0, __buf_pos};
  2537. }
  2538. //try searching for "corresponding" subrange [__bb; __ee) in the second sequence
  2539. _ForwardIterator2 __bb = __first2;
  2540. if (__b != __first1)
  2541. __bb = std::lower_bound(__first2, __last2, *__b, __comp);
  2542. _ForwardIterator2 __ee = __last2;
  2543. if (__e != __last1)
  2544. __ee = std::lower_bound(__bb, __last2, *__e, __comp);
  2545. const _DifferenceType __buf_pos = __size_func((__b - __first1), (__bb - __first2));
  2546. auto __buffer_b = __buffer + __buf_pos;
  2547. auto __res = __set_op(__b, __e, __bb, __ee, __buffer_b, __comp);
  2548. return _SetRange{0, __res - __buffer_b, __buf_pos};
  2549. },
  2550. [](const _SetRange& __a, const _SetRange& __b) { // Combine
  2551. if (__b.__buf_pos > __a.__buf_pos || ((__b.__buf_pos == __a.__buf_pos) && !__b.empty()))
  2552. return _SetRange{__a.__pos + __a.__len + __b.__pos, __b.__len, __b.__buf_pos};
  2553. return _SetRange{__b.__pos + __b.__len + __a.__pos, __a.__len, __a.__buf_pos};
  2554. },
  2555. __scan, // Scan
  2556. [&__m, &__scan](const _SetRange& __total) { // Apex
  2557. //final scan
  2558. __scan(0, 0, __total);
  2559. __m = __total.__pos + __total.__len;
  2560. });
  2561. return __result + __m;
  2562. });
  2563. }
  2564. //a shared parallel pattern for '__pattern_set_union' and '__pattern_set_symmetric_difference'
  2565. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
  2566. class _Compare, class _SetUnionOp, class _IsVector>
  2567. _OutputIterator
  2568. __parallel_set_union_op(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
  2569. _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result,
  2570. _Compare __comp, _SetUnionOp __set_union_op, _IsVector __is_vector)
  2571. {
  2572. typedef typename std::iterator_traits<_ForwardIterator1>::difference_type _DifferenceType;
  2573. const auto __n1 = __last1 - __first1;
  2574. const auto __n2 = __last2 - __first2;
  2575. auto __copy_range1 = [__is_vector](_ForwardIterator1 __begin, _ForwardIterator1 __end, _OutputIterator __res) {
  2576. return __internal::__brick_copy(__begin, __end, __res, __is_vector);
  2577. };
  2578. auto __copy_range2 = [__is_vector](_ForwardIterator2 __begin, _ForwardIterator2 __end, _OutputIterator __res) {
  2579. return __internal::__brick_copy(__begin, __end, __res, __is_vector);
  2580. };
  2581. // {1} {}: parallel copying just first sequence
  2582. if (__n2 == 0)
  2583. return __internal::__pattern_walk2_brick(std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result,
  2584. __copy_range1, std::true_type());
  2585. // {} {2}: parallel copying justmake second sequence
  2586. if (__n1 == 0)
  2587. return __internal::__pattern_walk2_brick(std::forward<_ExecutionPolicy>(__exec), __first2, __last2, __result,
  2588. __copy_range2, std::true_type());
  2589. // testing whether the sequences are intersected
  2590. _ForwardIterator1 __left_bound_seq_1 = std::lower_bound(__first1, __last1, *__first2, __comp);
  2591. if (__left_bound_seq_1 == __last1)
  2592. {
  2593. //{1} < {2}: seq2 is wholly greater than seq1, so, do parallel copying seq1 and seq2
  2594. __par_backend::__parallel_invoke(
  2595. std::forward<_ExecutionPolicy>(__exec),
  2596. [=] {
  2597. __internal::__pattern_walk2_brick(std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result,
  2598. __copy_range1, std::true_type());
  2599. },
  2600. [=] {
  2601. __internal::__pattern_walk2_brick(std::forward<_ExecutionPolicy>(__exec), __first2, __last2,
  2602. __result + __n1, __copy_range2, std::true_type());
  2603. });
  2604. return __result + __n1 + __n2;
  2605. }
  2606. // testing whether the sequences are intersected
  2607. _ForwardIterator2 __left_bound_seq_2 = std::lower_bound(__first2, __last2, *__first1, __comp);
  2608. if (__left_bound_seq_2 == __last2)
  2609. {
  2610. //{2} < {1}: seq2 is wholly greater than seq1, so, do parallel copying seq1 and seq2
  2611. __par_backend::__parallel_invoke(
  2612. std::forward<_ExecutionPolicy>(__exec),
  2613. [=] {
  2614. __internal::__pattern_walk2_brick(std::forward<_ExecutionPolicy>(__exec), __first2, __last2, __result,
  2615. __copy_range2, std::true_type());
  2616. },
  2617. [=] {
  2618. __internal::__pattern_walk2_brick(std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
  2619. __result + __n2, __copy_range1, std::true_type());
  2620. });
  2621. return __result + __n1 + __n2;
  2622. }
  2623. const auto __m1 = __left_bound_seq_1 - __first1;
  2624. if (__m1 > __set_algo_cut_off)
  2625. {
  2626. auto __res_or = __result;
  2627. __result += __m1; //we know proper offset due to [first1; left_bound_seq_1) < [first2; last2)
  2628. __par_backend::__parallel_invoke(
  2629. std::forward<_ExecutionPolicy>(__exec),
  2630. //do parallel copying of [first1; left_bound_seq_1)
  2631. [=] {
  2632. __internal::__pattern_walk2_brick(std::forward<_ExecutionPolicy>(__exec), __first1, __left_bound_seq_1,
  2633. __res_or, __copy_range1, std::true_type());
  2634. },
  2635. [=, &__result] {
  2636. __result = __internal::__parallel_set_op(
  2637. std::forward<_ExecutionPolicy>(__exec), __left_bound_seq_1, __last1, __first2, __last2, __result,
  2638. __comp, [](_DifferenceType __n, _DifferenceType __m) { return __n + __m; }, __set_union_op,
  2639. __is_vector);
  2640. });
  2641. return __result;
  2642. }
  2643. const auto __m2 = __left_bound_seq_2 - __first2;
  2644. _PSTL_ASSERT(__m1 == 0 || __m2 == 0);
  2645. if (__m2 > __set_algo_cut_off)
  2646. {
  2647. auto __res_or = __result;
  2648. __result += __m2; //we know proper offset due to [first2; left_bound_seq_2) < [first1; last1)
  2649. __par_backend::__parallel_invoke(
  2650. std::forward<_ExecutionPolicy>(__exec),
  2651. //do parallel copying of [first2; left_bound_seq_2)
  2652. [=] {
  2653. __internal::__pattern_walk2_brick(std::forward<_ExecutionPolicy>(__exec), __first2, __left_bound_seq_2,
  2654. __res_or, __copy_range2, std::true_type());
  2655. },
  2656. [=, &__result] {
  2657. __result = __internal::__parallel_set_op(
  2658. std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __left_bound_seq_2, __last2, __result,
  2659. __comp, [](_DifferenceType __n, _DifferenceType __m) { return __n + __m; }, __set_union_op,
  2660. __is_vector);
  2661. });
  2662. return __result;
  2663. }
  2664. return __internal::__parallel_set_op(
  2665. std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp,
  2666. [](_DifferenceType __n, _DifferenceType __m) { return __n + __m; }, __set_union_op, __is_vector);
  2667. }
  2668. //------------------------------------------------------------------------
  2669. // set_union
  2670. //------------------------------------------------------------------------
  2671. template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare>
  2672. _OutputIterator
  2673. __brick_set_union(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  2674. _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp,
  2675. /*__is_vector=*/std::false_type) noexcept
  2676. {
  2677. return std::set_union(__first1, __last1, __first2, __last2, __result, __comp);
  2678. }
  2679. template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare>
  2680. _OutputIterator
  2681. __brick_set_union(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  2682. _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp,
  2683. /*__is_vector=*/std::true_type) noexcept
  2684. {
  2685. _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial");
  2686. return std::set_union(__first1, __last1, __first2, __last2, __result, __comp);
  2687. }
  2688. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
  2689. class _Compare, class _IsVector>
  2690. _OutputIterator
  2691. __pattern_set_union(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
  2692. _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp,
  2693. _IsVector __is_vector,
  2694. /*is_parallel=*/std::false_type) noexcept
  2695. {
  2696. return __internal::__brick_set_union(__first1, __last1, __first2, __last2, __result, __comp, __is_vector);
  2697. }
  2698. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
  2699. class _Compare, class _IsVector>
  2700. _OutputIterator
  2701. __pattern_set_union(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
  2702. _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp,
  2703. _IsVector __is_vector, /*__is_parallel=*/std::true_type)
  2704. {
  2705. const auto __n1 = __last1 - __first1;
  2706. const auto __n2 = __last2 - __first2;
  2707. // use serial algorithm
  2708. if (__n1 + __n2 <= __set_algo_cut_off)
  2709. return std::set_union(__first1, __last1, __first2, __last2, __result, __comp);
  2710. typedef typename std::iterator_traits<_OutputIterator>::value_type _T;
  2711. return __internal::__parallel_set_union_op(
  2712. std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp,
  2713. [](_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2,
  2714. _T* __result,
  2715. _Compare __comp) { return std::set_union(__first1, __last1, __first2, __last2, __result, __comp); },
  2716. __is_vector);
  2717. }
  2718. //------------------------------------------------------------------------
  2719. // set_intersection
  2720. //------------------------------------------------------------------------
  2721. template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare>
  2722. _OutputIterator
  2723. __brick_set_intersection(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  2724. _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp,
  2725. /*__is_vector=*/std::false_type) noexcept
  2726. {
  2727. return std::set_intersection(__first1, __last1, __first2, __last2, __result, __comp);
  2728. }
  2729. template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare>
  2730. _OutputIterator
  2731. __brick_set_intersection(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  2732. _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp,
  2733. /*__is_vector=*/std::true_type) noexcept
  2734. {
  2735. _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial");
  2736. return std::set_intersection(__first1, __last1, __first2, __last2, __result, __comp);
  2737. }
  2738. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
  2739. class _Compare, class _IsVector>
  2740. _OutputIterator
  2741. __pattern_set_intersection(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
  2742. _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result,
  2743. _Compare __comp, _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept
  2744. {
  2745. return __internal::__brick_set_intersection(__first1, __last1, __first2, __last2, __result, __comp, __is_vector);
  2746. }
  2747. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
  2748. class _Compare, class _IsVector>
  2749. _OutputIterator
  2750. __pattern_set_intersection(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
  2751. _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result,
  2752. _Compare __comp, _IsVector __is_vector, /*is_parallel=*/std::true_type)
  2753. {
  2754. typedef typename std::iterator_traits<_OutputIterator>::value_type _T;
  2755. typedef typename std::iterator_traits<_ForwardIterator1>::difference_type _DifferenceType;
  2756. const auto __n1 = __last1 - __first1;
  2757. const auto __n2 = __last2 - __first2;
  2758. // intersection is empty
  2759. if (__n1 == 0 || __n2 == 0)
  2760. return __result;
  2761. // testing whether the sequences are intersected
  2762. _ForwardIterator1 __left_bound_seq_1 = std::lower_bound(__first1, __last1, *__first2, __comp);
  2763. //{1} < {2}: seq 2 is wholly greater than seq 1, so, the intersection is empty
  2764. if (__left_bound_seq_1 == __last1)
  2765. return __result;
  2766. // testing whether the sequences are intersected
  2767. _ForwardIterator2 __left_bound_seq_2 = std::lower_bound(__first2, __last2, *__first1, __comp);
  2768. //{2} < {1}: seq 1 is wholly greater than seq 2, so, the intersection is empty
  2769. if (__left_bound_seq_2 == __last2)
  2770. return __result;
  2771. const auto __m1 = __last1 - __left_bound_seq_1 + __n2;
  2772. if (__m1 > __set_algo_cut_off)
  2773. {
  2774. //we know proper offset due to [first1; left_bound_seq_1) < [first2; last2)
  2775. return __internal::__parallel_set_op(
  2776. std::forward<_ExecutionPolicy>(__exec), __left_bound_seq_1, __last1, __first2, __last2, __result, __comp,
  2777. [](_DifferenceType __n, _DifferenceType __m) { return std::min(__n, __m); },
  2778. [](_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  2779. _ForwardIterator2 __last2, _T* __result, _Compare __comp) {
  2780. return std::set_intersection(__first1, __last1, __first2, __last2, __result, __comp);
  2781. },
  2782. __is_vector);
  2783. }
  2784. const auto __m2 = __last2 - __left_bound_seq_2 + __n1;
  2785. if (__m2 > __set_algo_cut_off)
  2786. {
  2787. //we know proper offset due to [first2; left_bound_seq_2) < [first1; last1)
  2788. __result = __internal::__parallel_set_op(
  2789. std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __left_bound_seq_2, __last2, __result, __comp,
  2790. [](_DifferenceType __n, _DifferenceType __m) { return std::min(__n, __m); },
  2791. [](_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  2792. _ForwardIterator2 __last2, _T* __result, _Compare __comp) {
  2793. return std::set_intersection(__first2, __last2, __first1, __last1, __result, __comp);
  2794. },
  2795. __is_vector);
  2796. return __result;
  2797. }
  2798. // [left_bound_seq_1; last1) and [left_bound_seq_2; last2) - use serial algorithm
  2799. return std::set_intersection(__left_bound_seq_1, __last1, __left_bound_seq_2, __last2, __result, __comp);
  2800. }
  2801. //------------------------------------------------------------------------
  2802. // set_difference
  2803. //------------------------------------------------------------------------
  2804. template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare>
  2805. _OutputIterator
  2806. __brick_set_difference(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  2807. _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp,
  2808. /*__is_vector=*/std::false_type) noexcept
  2809. {
  2810. return std::set_difference(__first1, __last1, __first2, __last2, __result, __comp);
  2811. }
  2812. template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare>
  2813. _OutputIterator
  2814. __brick_set_difference(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  2815. _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp,
  2816. /*__is_vector=*/std::true_type) noexcept
  2817. {
  2818. _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial");
  2819. return std::set_difference(__first1, __last1, __first2, __last2, __result, __comp);
  2820. }
  2821. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
  2822. class _Compare, class _IsVector>
  2823. _OutputIterator
  2824. __pattern_set_difference(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
  2825. _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result,
  2826. _Compare __comp, _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept
  2827. {
  2828. return __internal::__brick_set_difference(__first1, __last1, __first2, __last2, __result, __comp, __is_vector);
  2829. }
  2830. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
  2831. class _Compare, class _IsVector>
  2832. _OutputIterator
  2833. __pattern_set_difference(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
  2834. _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result,
  2835. _Compare __comp, _IsVector __is_vector, /*is_parallel=*/std::true_type)
  2836. {
  2837. typedef typename std::iterator_traits<_OutputIterator>::value_type _T;
  2838. typedef typename std::iterator_traits<_ForwardIterator1>::difference_type _DifferenceType;
  2839. const auto __n1 = __last1 - __first1;
  2840. const auto __n2 = __last2 - __first2;
  2841. // {} \ {2}: the difference is empty
  2842. if (__n1 == 0)
  2843. return __result;
  2844. // {1} \ {}: parallel copying just first sequence
  2845. if (__n2 == 0)
  2846. return __internal::__pattern_walk2_brick(
  2847. std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result,
  2848. [__is_vector](_ForwardIterator1 __begin, _ForwardIterator1 __end, _OutputIterator __res) {
  2849. return __internal::__brick_copy(__begin, __end, __res, __is_vector);
  2850. },
  2851. std::true_type());
  2852. // testing whether the sequences are intersected
  2853. _ForwardIterator1 __left_bound_seq_1 = std::lower_bound(__first1, __last1, *__first2, __comp);
  2854. //{1} < {2}: seq 2 is wholly greater than seq 1, so, parallel copying just first sequence
  2855. if (__left_bound_seq_1 == __last1)
  2856. return __internal::__pattern_walk2_brick(
  2857. std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result,
  2858. [__is_vector](_ForwardIterator1 __begin, _ForwardIterator1 __end, _OutputIterator __res) {
  2859. return __internal::__brick_copy(__begin, __end, __res, __is_vector);
  2860. },
  2861. std::true_type());
  2862. // testing whether the sequences are intersected
  2863. _ForwardIterator2 __left_bound_seq_2 = std::lower_bound(__first2, __last2, *__first1, __comp);
  2864. //{2} < {1}: seq 1 is wholly greater than seq 2, so, parallel copying just first sequence
  2865. if (__left_bound_seq_2 == __last2)
  2866. return __internal::__pattern_walk2_brick(
  2867. std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result,
  2868. [__is_vector](_ForwardIterator1 __begin, _ForwardIterator1 __end, _OutputIterator __res) {
  2869. return __internal::__brick_copy(__begin, __end, __res, __is_vector);
  2870. },
  2871. std::true_type());
  2872. if (__n1 + __n2 > __set_algo_cut_off)
  2873. return __internal::__parallel_set_op(
  2874. std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp,
  2875. [](_DifferenceType __n, _DifferenceType __m) { return __n; },
  2876. [](_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  2877. _ForwardIterator2 __last2, _T* __result,
  2878. _Compare __comp) { return std::set_difference(__first1, __last1, __first2, __last2, __result, __comp); },
  2879. __is_vector);
  2880. // use serial algorithm
  2881. return std::set_difference(__first1, __last1, __first2, __last2, __result, __comp);
  2882. }
  2883. //------------------------------------------------------------------------
  2884. // set_symmetric_difference
  2885. //------------------------------------------------------------------------
  2886. template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare>
  2887. _OutputIterator
  2888. __brick_set_symmetric_difference(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  2889. _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp,
  2890. /*__is_vector=*/std::false_type) noexcept
  2891. {
  2892. return std::set_symmetric_difference(__first1, __last1, __first2, __last2, __result, __comp);
  2893. }
  2894. template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare>
  2895. _OutputIterator
  2896. __brick_set_symmetric_difference(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  2897. _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp,
  2898. /*__is_vector=*/std::true_type) noexcept
  2899. {
  2900. _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial");
  2901. return std::set_symmetric_difference(__first1, __last1, __first2, __last2, __result, __comp);
  2902. }
  2903. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
  2904. class _Compare, class _IsVector>
  2905. _OutputIterator
  2906. __pattern_set_symmetric_difference(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
  2907. _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result,
  2908. _Compare __comp, _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept
  2909. {
  2910. return __internal::__brick_set_symmetric_difference(__first1, __last1, __first2, __last2, __result, __comp,
  2911. __is_vector);
  2912. }
  2913. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
  2914. class _Compare, class _IsVector>
  2915. _OutputIterator
  2916. __pattern_set_symmetric_difference(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
  2917. _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result,
  2918. _Compare __comp, _IsVector __is_vector, /*is_parallel=*/std::true_type)
  2919. {
  2920. const auto __n1 = __last1 - __first1;
  2921. const auto __n2 = __last2 - __first2;
  2922. // use serial algorithm
  2923. if (__n1 + __n2 <= __set_algo_cut_off)
  2924. return std::set_symmetric_difference(__first1, __last1, __first2, __last2, __result, __comp);
  2925. typedef typename std::iterator_traits<_OutputIterator>::value_type _T;
  2926. return __internal::__parallel_set_union_op(
  2927. std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp,
  2928. [](_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2,
  2929. _T* __result, _Compare __comp) {
  2930. return std::set_symmetric_difference(__first1, __last1, __first2, __last2, __result, __comp);
  2931. },
  2932. __is_vector);
  2933. }
  2934. //------------------------------------------------------------------------
  2935. // is_heap_until
  2936. //------------------------------------------------------------------------
  2937. template <class _RandomAccessIterator, class _Compare>
  2938. _RandomAccessIterator
  2939. __brick_is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp,
  2940. /* __is_vector = */ std::false_type) noexcept
  2941. {
  2942. return std::is_heap_until(__first, __last, __comp);
  2943. }
  2944. template <class _RandomAccessIterator, class _Compare>
  2945. _RandomAccessIterator
  2946. __brick_is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp,
  2947. /* __is_vector = */ std::true_type) noexcept
  2948. {
  2949. if (__last - __first < 2)
  2950. return __last;
  2951. typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _SizeType;
  2952. return __unseq_backend::__simd_first(
  2953. __first, _SizeType(0), __last - __first,
  2954. [&__comp](_RandomAccessIterator __it, _SizeType __i) { return __comp(__it[(__i - 1) / 2], __it[__i]); });
  2955. }
  2956. template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
  2957. _RandomAccessIterator
  2958. __pattern_is_heap_until(_ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last,
  2959. _Compare __comp, _IsVector __is_vector, /* is_parallel = */ std::false_type) noexcept
  2960. {
  2961. return __internal::__brick_is_heap_until(__first, __last, __comp, __is_vector);
  2962. }
  2963. template <class _RandomAccessIterator, class _DifferenceType, class _Compare>
  2964. _RandomAccessIterator
  2965. __is_heap_until_local(_RandomAccessIterator __first, _DifferenceType __begin, _DifferenceType __end, _Compare __comp,
  2966. /* __is_vector = */ std::false_type) noexcept
  2967. {
  2968. _DifferenceType __i = __begin;
  2969. for (; __i < __end; ++__i)
  2970. {
  2971. if (__comp(__first[(__i - 1) / 2], __first[__i]))
  2972. {
  2973. break;
  2974. }
  2975. }
  2976. return __first + __i;
  2977. }
  2978. template <class _RandomAccessIterator, class _DifferenceType, class _Compare>
  2979. _RandomAccessIterator
  2980. __is_heap_until_local(_RandomAccessIterator __first, _DifferenceType __begin, _DifferenceType __end, _Compare __comp,
  2981. /* __is_vector = */ std::true_type) noexcept
  2982. {
  2983. return __unseq_backend::__simd_first(
  2984. __first, __begin, __end,
  2985. [&__comp](_RandomAccessIterator __it, _DifferenceType __i) { return __comp(__it[(__i - 1) / 2], __it[__i]); });
  2986. }
  2987. template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
  2988. _RandomAccessIterator
  2989. __pattern_is_heap_until(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last,
  2990. _Compare __comp, _IsVector __is_vector, /* is_parallel = */ std::true_type) noexcept
  2991. {
  2992. if (__last - __first < 2)
  2993. return __last;
  2994. return __internal::__except_handler([&]() {
  2995. return __parallel_find(
  2996. std::forward<_ExecutionPolicy>(__exec), __first, __last,
  2997. [__first, __comp, __is_vector](_RandomAccessIterator __i, _RandomAccessIterator __j) {
  2998. return __internal::__is_heap_until_local(__first, __i - __first, __j - __first, __comp, __is_vector);
  2999. },
  3000. std::less<typename std::iterator_traits<_RandomAccessIterator>::difference_type>(), /*is_first=*/true);
  3001. });
  3002. }
  3003. //------------------------------------------------------------------------
  3004. // min_element
  3005. //------------------------------------------------------------------------
  3006. template <typename _ForwardIterator, typename _Compare>
  3007. _ForwardIterator
  3008. __brick_min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp,
  3009. /* __is_vector = */ std::false_type) noexcept
  3010. {
  3011. return std::min_element(__first, __last, __comp);
  3012. }
  3013. template <typename _ForwardIterator, typename _Compare>
  3014. _ForwardIterator
  3015. __brick_min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp,
  3016. /* __is_vector = */ std::true_type) noexcept
  3017. {
  3018. #if _PSTL_UDR_PRESENT
  3019. return __unseq_backend::__simd_min_element(__first, __last - __first, __comp);
  3020. #else
  3021. return std::min_element(__first, __last, __comp);
  3022. #endif
  3023. }
  3024. template <typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare, typename _IsVector>
  3025. _ForwardIterator
  3026. __pattern_min_element(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp,
  3027. _IsVector __is_vector, /* is_parallel = */ std::false_type) noexcept
  3028. {
  3029. return __internal::__brick_min_element(__first, __last, __comp, __is_vector);
  3030. }
  3031. template <typename _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare, typename _IsVector>
  3032. _RandomAccessIterator
  3033. __pattern_min_element(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last,
  3034. _Compare __comp, _IsVector __is_vector, /* is_parallel = */ std::true_type)
  3035. {
  3036. if (__first == __last)
  3037. return __last;
  3038. return __internal::__except_handler([&]() {
  3039. return __par_backend::__parallel_reduce(
  3040. std::forward<_ExecutionPolicy>(__exec), __first + 1, __last, __first,
  3041. [=](_RandomAccessIterator __begin, _RandomAccessIterator __end,
  3042. _RandomAccessIterator __init) -> _RandomAccessIterator {
  3043. const _RandomAccessIterator subresult =
  3044. __internal::__brick_min_element(__begin, __end, __comp, __is_vector);
  3045. return __internal::__cmp_iterators_by_values(__init, subresult, __comp);
  3046. },
  3047. [=](_RandomAccessIterator __it1, _RandomAccessIterator __it2) -> _RandomAccessIterator {
  3048. return __internal::__cmp_iterators_by_values(__it1, __it2, __comp);
  3049. });
  3050. });
  3051. }
  3052. //------------------------------------------------------------------------
  3053. // minmax_element
  3054. //------------------------------------------------------------------------
  3055. template <typename _ForwardIterator, typename _Compare>
  3056. std::pair<_ForwardIterator, _ForwardIterator>
  3057. __brick_minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp,
  3058. /* __is_vector = */ std::false_type) noexcept
  3059. {
  3060. return std::minmax_element(__first, __last, __comp);
  3061. }
  3062. template <typename _ForwardIterator, typename _Compare>
  3063. std::pair<_ForwardIterator, _ForwardIterator>
  3064. __brick_minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp,
  3065. /* __is_vector = */ std::true_type) noexcept
  3066. {
  3067. #if _PSTL_UDR_PRESENT
  3068. return __unseq_backend::__simd_minmax_element(__first, __last - __first, __comp);
  3069. #else
  3070. return std::minmax_element(__first, __last, __comp);
  3071. #endif
  3072. }
  3073. template <typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare, typename _IsVector>
  3074. std::pair<_ForwardIterator, _ForwardIterator>
  3075. __pattern_minmax_element(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp,
  3076. _IsVector __is_vector, /* is_parallel = */ std::false_type) noexcept
  3077. {
  3078. return __internal::__brick_minmax_element(__first, __last, __comp, __is_vector);
  3079. }
  3080. template <typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare, typename _IsVector>
  3081. std::pair<_ForwardIterator, _ForwardIterator>
  3082. __pattern_minmax_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp,
  3083. _IsVector __is_vector, /* is_parallel = */ std::true_type)
  3084. {
  3085. if (__first == __last)
  3086. return std::make_pair(__first, __first);
  3087. return __internal::__except_handler([&]() {
  3088. typedef std::pair<_ForwardIterator, _ForwardIterator> _Result;
  3089. return __par_backend::__parallel_reduce(
  3090. std::forward<_ExecutionPolicy>(__exec), __first + 1, __last, std::make_pair(__first, __first),
  3091. [=](_ForwardIterator __begin, _ForwardIterator __end, _Result __init) -> _Result {
  3092. const _Result __subresult = __internal::__brick_minmax_element(__begin, __end, __comp, __is_vector);
  3093. return std::make_pair(__internal::__cmp_iterators_by_values(__subresult.first, __init.first, __comp),
  3094. __internal::__cmp_iterators_by_values(__init.second, __subresult.second,
  3095. __not_pred<_Compare>(__comp)));
  3096. },
  3097. [=](_Result __p1, _Result __p2) -> _Result {
  3098. return std::make_pair(
  3099. __internal::__cmp_iterators_by_values(__p1.first, __p2.first, __comp),
  3100. __internal::__cmp_iterators_by_values(__p2.second, __p1.second, __not_pred<_Compare>(__comp)));
  3101. });
  3102. });
  3103. }
  3104. //------------------------------------------------------------------------
  3105. // mismatch
  3106. //------------------------------------------------------------------------
  3107. template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
  3108. std::pair<_ForwardIterator1, _ForwardIterator2>
  3109. __mismatch_serial(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  3110. _ForwardIterator2 __last2, _BinaryPredicate __pred)
  3111. {
  3112. #if _PSTL_CPP14_2RANGE_MISMATCH_EQUAL_PRESENT
  3113. return std::mismatch(__first1, __last1, __first2, __last2, __pred);
  3114. #else
  3115. for (; __first1 != __last1 && __first2 != __last2 && __pred(*__first1, *__first2); ++__first1, ++__first2)
  3116. {
  3117. }
  3118. return std::make_pair(__first1, __first2);
  3119. #endif
  3120. }
  3121. template <class _ForwardIterator1, class _ForwardIterator2, class _Predicate>
  3122. std::pair<_ForwardIterator1, _ForwardIterator2>
  3123. __brick_mismatch(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  3124. _ForwardIterator2 __last2, _Predicate __pred, /* __is_vector = */ std::false_type) noexcept
  3125. {
  3126. return __mismatch_serial(__first1, __last1, __first2, __last2, __pred);
  3127. }
  3128. template <class _ForwardIterator1, class _ForwardIterator2, class _Predicate>
  3129. std::pair<_ForwardIterator1, _ForwardIterator2>
  3130. __brick_mismatch(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  3131. _ForwardIterator2 __last2, _Predicate __pred, /* __is_vector = */ std::true_type) noexcept
  3132. {
  3133. auto __n = std::min(__last1 - __first1, __last2 - __first2);
  3134. return __unseq_backend::__simd_first(__first1, __n, __first2, __not_pred<_Predicate>(__pred));
  3135. }
  3136. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate, class _IsVector>
  3137. std::pair<_ForwardIterator1, _ForwardIterator2>
  3138. __pattern_mismatch(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
  3139. _ForwardIterator2 __first2, _ForwardIterator2 __last2, _Predicate __pred, _IsVector __is_vector,
  3140. /* is_parallel = */ std::false_type) noexcept
  3141. {
  3142. return __internal::__brick_mismatch(__first1, __last1, __first2, __last2, __pred, __is_vector);
  3143. }
  3144. template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _Predicate,
  3145. class _IsVector>
  3146. std::pair<_RandomAccessIterator1, _RandomAccessIterator2>
  3147. __pattern_mismatch(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1,
  3148. _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, _Predicate __pred,
  3149. _IsVector __is_vector, /* is_parallel = */ std::true_type) noexcept
  3150. {
  3151. return __internal::__except_handler([&]() {
  3152. auto __n = std::min(__last1 - __first1, __last2 - __first2);
  3153. auto __result = __internal::__parallel_find(
  3154. std::forward<_ExecutionPolicy>(__exec), __first1, __first1 + __n,
  3155. [__first1, __first2, __pred, __is_vector](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) {
  3156. return __internal::__brick_mismatch(__i, __j, __first2 + (__i - __first1), __first2 + (__j - __first1),
  3157. __pred, __is_vector)
  3158. .first;
  3159. },
  3160. std::less<typename std::iterator_traits<_RandomAccessIterator1>::difference_type>(), /*is_first=*/true);
  3161. return std::make_pair(__result, __first2 + (__result - __first1));
  3162. });
  3163. }
  3164. //------------------------------------------------------------------------
  3165. // lexicographical_compare
  3166. //------------------------------------------------------------------------
  3167. template <class _ForwardIterator1, class _ForwardIterator2, class _Compare>
  3168. bool
  3169. __brick_lexicographical_compare(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  3170. _ForwardIterator2 __last2, _Compare __comp,
  3171. /* __is_vector = */ std::false_type) noexcept
  3172. {
  3173. return std::lexicographical_compare(__first1, __last1, __first2, __last2, __comp);
  3174. }
  3175. template <class _ForwardIterator1, class _ForwardIterator2, class _Compare>
  3176. bool
  3177. __brick_lexicographical_compare(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  3178. _ForwardIterator2 __last2, _Compare __comp, /* __is_vector = */ std::true_type) noexcept
  3179. {
  3180. if (__first2 == __last2)
  3181. { // if second sequence is empty
  3182. return false;
  3183. }
  3184. else if (__first1 == __last1)
  3185. { // if first sequence is empty
  3186. return true;
  3187. }
  3188. else
  3189. {
  3190. typedef typename std::iterator_traits<_ForwardIterator1>::reference ref_type1;
  3191. typedef typename std::iterator_traits<_ForwardIterator2>::reference ref_type2;
  3192. --__last1;
  3193. --__last2;
  3194. auto __n = std::min(__last1 - __first1, __last2 - __first2);
  3195. std::pair<_ForwardIterator1, _ForwardIterator2> __result = __unseq_backend::__simd_first(
  3196. __first1, __n, __first2, [__comp](const ref_type1 __x, const ref_type2 __y) mutable {
  3197. return __comp(__x, __y) || __comp(__y, __x);
  3198. });
  3199. if (__result.first == __last1 && __result.second != __last2)
  3200. { // if first sequence shorter than second
  3201. return !__comp(*__result.second, *__result.first);
  3202. }
  3203. else
  3204. { // if second sequence shorter than first or both have the same number of elements
  3205. return __comp(*__result.first, *__result.second);
  3206. }
  3207. }
  3208. }
  3209. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare, class _IsVector>
  3210. bool
  3211. __pattern_lexicographical_compare(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
  3212. _ForwardIterator2 __first2, _ForwardIterator2 __last2, _Compare __comp,
  3213. _IsVector __is_vector, /* is_parallel = */ std::false_type) noexcept
  3214. {
  3215. return __internal::__brick_lexicographical_compare(__first1, __last1, __first2, __last2, __comp, __is_vector);
  3216. }
  3217. template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare, class _IsVector>
  3218. bool
  3219. __pattern_lexicographical_compare(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
  3220. _ForwardIterator2 __first2, _ForwardIterator2 __last2, _Compare __comp,
  3221. _IsVector __is_vector, /* is_parallel = */ std::true_type) noexcept
  3222. {
  3223. if (__first2 == __last2)
  3224. { // if second sequence is empty
  3225. return false;
  3226. }
  3227. else if (__first1 == __last1)
  3228. { // if first sequence is empty
  3229. return true;
  3230. }
  3231. else
  3232. {
  3233. typedef typename std::iterator_traits<_ForwardIterator1>::reference _RefType1;
  3234. typedef typename std::iterator_traits<_ForwardIterator2>::reference _RefType2;
  3235. --__last1;
  3236. --__last2;
  3237. auto __n = std::min(__last1 - __first1, __last2 - __first2);
  3238. auto __result = __internal::__parallel_find(
  3239. std::forward<_ExecutionPolicy>(__exec), __first1, __first1 + __n,
  3240. [__first1, __first2, &__comp, __is_vector](_ForwardIterator1 __i, _ForwardIterator1 __j) {
  3241. return __internal::__brick_mismatch(__i, __j, __first2 + (__i - __first1), __first2 + (__j - __first1),
  3242. [&__comp](const _RefType1 __x, const _RefType2 __y) {
  3243. return !__comp(__x, __y) && !__comp(__y, __x);
  3244. },
  3245. __is_vector)
  3246. .first;
  3247. },
  3248. std::less<typename std::iterator_traits<_ForwardIterator1>::difference_type>(), /*is_first=*/true);
  3249. if (__result == __last1 && __first2 + (__result - __first1) != __last2)
  3250. { // if first sequence shorter than second
  3251. return !__comp(*(__first2 + (__result - __first1)), *__result);
  3252. }
  3253. else
  3254. { // if second sequence shorter than first or both have the same number of elements
  3255. return __comp(*__result, *(__first2 + (__result - __first1)));
  3256. }
  3257. }
  3258. }
  3259. } // namespace __internal
  3260. } // namespace __pstl
  3261. #endif /* _PSTL_ALGORITHM_IMPL_H */