algorithm_impl.h 170 KB

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