algorithm.hpp 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186
  1. /* Copyright 2016-2020 Joaquin M Lopez Munoz.
  2. * Distributed under the Boost Software License, Version 1.0.
  3. * (See accompanying file LICENSE_1_0.txt or copy at
  4. * http://www.boost.org/LICENSE_1_0.txt)
  5. *
  6. * See http://www.boost.org/libs/poly_collection for library home page.
  7. */
  8. #ifndef BOOST_POLY_COLLECTION_ALGORITHM_HPP
  9. #define BOOST_POLY_COLLECTION_ALGORITHM_HPP
  10. #if defined(_MSC_VER)
  11. #pragma once
  12. #endif
  13. #include <algorithm>
  14. #include <boost/poly_collection/detail/auto_iterator.hpp>
  15. #include <boost/poly_collection/detail/functional.hpp>
  16. #include <boost/poly_collection/detail/iterator_traits.hpp>
  17. #include <boost/poly_collection/detail/segment_split.hpp>
  18. #include <boost/poly_collection/detail/type_restitution.hpp>
  19. #include <iterator>
  20. #include <random>
  21. #include <type_traits>
  22. #include <utility>
  23. /* Improved performance versions of std algorithms over poly_collection.
  24. * poly_collection::alg is expected to be faster than the homonym std::alg
  25. * because the latter does a traversal over a segmented structured, where
  26. * incrementing requires checking for segment change, whereas the former
  27. * for-loops over flat segments.
  28. * Additionally, poly_collection::alg<Ti...>(...,f) *restitutes* Ti when
  29. * passing elements to f, i.e. if the concrete type of the element is Ti
  30. * then f is invoked with a [const] Ti&, which can dramatically improve
  31. * performance when f has specific overloads for Ti (like, for instance,
  32. * generic lambdas) as static optimization can kick in (devirtualization
  33. * being a particular example).
  34. */
  35. namespace boost{
  36. namespace poly_collection{
  37. namespace detail{
  38. namespace algorithm{
  39. template<typename Iterator>
  40. using enable_if_poly_collection_iterator=typename std::enable_if<
  41. !std::is_void<typename poly_collection_of<Iterator>::type>::value
  42. >::type*;
  43. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_all_of,std::all_of)
  44. template<
  45. typename... Ts,typename Iterator,typename Predicate,
  46. enable_if_poly_collection_iterator<Iterator> =nullptr
  47. >
  48. bool all_of(const Iterator& first,const Iterator& last,Predicate pred)
  49. {
  50. auto alg=restitute_range<Ts...>(std_all_of{},pred);
  51. for(auto i:detail::segment_split(first,last))if(!alg(i))return false;
  52. return true;
  53. }
  54. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_any_of,std::any_of)
  55. template<
  56. typename... Ts,typename Iterator,typename Predicate,
  57. enable_if_poly_collection_iterator<Iterator> =nullptr
  58. >
  59. bool any_of(const Iterator& first,const Iterator& last,Predicate pred)
  60. {
  61. auto alg=restitute_range<Ts...>(std_any_of{},pred);
  62. for(auto i:detail::segment_split(first,last))if(alg(i))return true;
  63. return false;
  64. }
  65. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_none_of,std::none_of)
  66. template<
  67. typename... Ts,typename Iterator,typename Predicate,
  68. enable_if_poly_collection_iterator<Iterator> =nullptr
  69. >
  70. bool none_of(const Iterator& first,const Iterator& last,Predicate pred)
  71. {
  72. auto alg=restitute_range<Ts...>(std_none_of{},pred);
  73. for(auto i:detail::segment_split(first,last))if(!alg(i))return false;
  74. return true;
  75. }
  76. struct for_each_alg
  77. {
  78. template<typename InputIterator,typename Function>
  79. void operator()(
  80. InputIterator first,InputIterator last,Function& f)const /* note the & */
  81. {
  82. for(;first!=last;++first)f(*first);
  83. }
  84. };
  85. template<
  86. typename... Ts,typename Iterator,typename Function,
  87. enable_if_poly_collection_iterator<Iterator> =nullptr
  88. >
  89. Function for_each(const Iterator& first,const Iterator& last,Function f)
  90. {
  91. for_each_segment(first,last,restitute_range<Ts...>(for_each_alg{},f));
  92. return f;
  93. }
  94. struct for_each_n_alg
  95. {
  96. template<
  97. typename InputIterator,typename Size,typename Function
  98. >
  99. InputIterator operator()(
  100. InputIterator first,Size n,Function& f)const /* note the & */
  101. {
  102. for(;n>0;++first,(void)--n)f(*first);
  103. return first;
  104. }
  105. };
  106. template<
  107. typename... Ts,typename Iterator,typename Size,typename Function,
  108. enable_if_poly_collection_iterator<Iterator> =nullptr
  109. >
  110. Iterator for_each_n(const Iterator& first,Size n,Function f)
  111. {
  112. using traits=iterator_traits<Iterator>;
  113. using local_base_iterator=typename traits::local_base_iterator;
  114. if(n<=0)return first;
  115. auto alg=restitute_iterator<Ts...>(
  116. cast_return<local_base_iterator>(for_each_n_alg{}));
  117. auto lbit=traits::local_base_iterator_from(first);
  118. auto sit=traits::base_segment_info_iterator_from(first);
  119. for(;;){
  120. auto m=sit->end()-lbit;
  121. if(n<=m){
  122. auto it=alg(sit->type_info(),lbit,n,f);
  123. return traits::iterator_from(
  124. it,traits::end_base_segment_info_iterator_from(first));
  125. }
  126. else{
  127. alg(sit->type_info(),lbit,m,f);
  128. n-=m;
  129. }
  130. ++sit;
  131. lbit=sit->begin();
  132. }
  133. }
  134. template<
  135. typename Algorithm,typename... Ts,
  136. typename Iterator,typename... Args,
  137. enable_if_poly_collection_iterator<Iterator> =nullptr
  138. >
  139. Iterator generic_find(
  140. const Iterator& first,const Iterator& last,Args&&... args)
  141. {
  142. using traits=iterator_traits<Iterator>;
  143. using local_base_iterator=typename traits::local_base_iterator;
  144. auto alg=restitute_range<Ts...>(
  145. cast_return<local_base_iterator>(Algorithm{}),
  146. std::forward<Args>(args)...);
  147. for(auto i:detail::segment_split(first,last)){
  148. auto it=alg(i);
  149. if(it!=i.end())
  150. return traits::iterator_from(
  151. it,traits::end_base_segment_info_iterator_from(last));
  152. }
  153. return last;
  154. }
  155. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_find,std::find)
  156. template<
  157. typename... Ts,typename Iterator,typename T,
  158. enable_if_poly_collection_iterator<Iterator> =nullptr
  159. >
  160. Iterator find(const Iterator& first,const Iterator& last,const T& x)
  161. {
  162. return generic_find<std_find,Ts...>(first,last,x);
  163. }
  164. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_find_if,std::find_if)
  165. template<
  166. typename... Ts,typename Iterator,typename Predicate,
  167. enable_if_poly_collection_iterator<Iterator> =nullptr
  168. >
  169. Iterator find_if(const Iterator& first,const Iterator& last,Predicate pred)
  170. {
  171. return generic_find<std_find_if,Ts...>(first,last,pred);
  172. }
  173. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_find_if_not,std::find_if_not)
  174. template<
  175. typename... Ts,typename Iterator,typename Predicate,
  176. enable_if_poly_collection_iterator<Iterator> =nullptr
  177. >
  178. Iterator find_if_not(const Iterator& first,const Iterator& last,Predicate pred)
  179. {
  180. return generic_find<std_find_if_not,Ts...>(first,last,pred);
  181. }
  182. /* find_end defined after search below */
  183. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_find_first_of,std::find_first_of)
  184. template<
  185. typename... Ts,typename Iterator,typename ForwardIterator,
  186. enable_if_poly_collection_iterator<Iterator> =nullptr
  187. >
  188. Iterator find_first_of(
  189. const Iterator& first1,const Iterator& last1,
  190. ForwardIterator first2,ForwardIterator last2)
  191. {
  192. return generic_find<std_find_first_of,Ts...>(first1,last1,first2,last2);
  193. }
  194. template<
  195. typename... Ts,typename Iterator,
  196. typename ForwardIterator,typename BinaryPredicate,
  197. enable_if_poly_collection_iterator<Iterator> =nullptr
  198. >
  199. Iterator find_first_of(
  200. const Iterator& first1,const Iterator& last1,
  201. ForwardIterator first2,ForwardIterator last2,BinaryPredicate pred)
  202. {
  203. return generic_find<std_find_first_of,Ts...>(first1,last1,first2,last2,pred);
  204. }
  205. template<typename... Ts>
  206. struct adjacent_find_alg
  207. {
  208. template<
  209. typename LocalIterator,typename BinaryPredicate,typename LocalBaseIterator
  210. >
  211. LocalBaseIterator operator()(
  212. LocalIterator first,LocalIterator last,BinaryPredicate pred,
  213. bool& carry,const std::type_info* prev_info, /* note the &s */
  214. LocalBaseIterator& prev)const
  215. {
  216. if(first==last)return LocalBaseIterator{last};
  217. if(carry){
  218. auto p=restitute_iterator<Ts...>(deref_to(pred));
  219. if(p(*prev_info,prev,first))return prev;
  220. }
  221. auto res=std::adjacent_find(first,last,pred);
  222. if(res==last){
  223. carry=true;
  224. prev_info=&typeid(
  225. typename std::iterator_traits<LocalIterator>::value_type);
  226. prev=LocalBaseIterator{last-1};
  227. }
  228. else carry=false;
  229. return LocalBaseIterator{res};
  230. }
  231. };
  232. template<
  233. typename... Ts,typename Iterator,typename BinaryPredicate,
  234. enable_if_poly_collection_iterator<Iterator> =nullptr
  235. >
  236. Iterator adjacent_find(
  237. const Iterator& first,const Iterator& last,BinaryPredicate pred)
  238. {
  239. using traits=iterator_traits<Iterator>;
  240. using local_base_iterator=typename traits::local_base_iterator;
  241. bool carry=false;
  242. const std::type_info* prev_info{&typeid(void)};
  243. local_base_iterator prev;
  244. return generic_find<adjacent_find_alg<Ts...>,Ts...>(
  245. first,last,pred,carry,prev_info,prev);
  246. }
  247. template<
  248. typename... Ts,typename Iterator,
  249. enable_if_poly_collection_iterator<Iterator> =nullptr
  250. >
  251. Iterator adjacent_find(const Iterator& first,const Iterator& last)
  252. {
  253. return algorithm::adjacent_find<Ts...>(first,last,transparent_equal_to{});
  254. }
  255. template<
  256. typename Algorithm,typename... Ts,
  257. typename Iterator,typename... Args,
  258. enable_if_poly_collection_iterator<Iterator> =nullptr
  259. >
  260. std::ptrdiff_t generic_count(
  261. const Iterator& first,const Iterator& last,Args&&... args)
  262. {
  263. auto alg=restitute_range<Ts...>(Algorithm{},std::forward<Args>(args)...);
  264. std::ptrdiff_t res=0;
  265. for(auto i:detail::segment_split(first,last))res+=alg(i);
  266. return res;
  267. }
  268. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_count,std::count)
  269. template<
  270. typename... Ts,typename Iterator,typename T,
  271. enable_if_poly_collection_iterator<Iterator> =nullptr
  272. >
  273. std::ptrdiff_t count(const Iterator& first,const Iterator& last,const T& x)
  274. {
  275. return generic_count<std_count,Ts...>(first,last,x);
  276. }
  277. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_count_if,std::count_if)
  278. template<
  279. typename... Ts,typename Iterator,typename Predicate,
  280. enable_if_poly_collection_iterator<Iterator> =nullptr
  281. >
  282. std::ptrdiff_t count_if(
  283. const Iterator& first,const Iterator& last,Predicate pred)
  284. {
  285. return generic_count<std_count_if,Ts...>(first,last,pred);
  286. }
  287. struct mismatch_alg
  288. {
  289. template<
  290. typename InputIterator1,
  291. typename InputIterator2,typename BinaryPredicate
  292. >
  293. InputIterator1 operator()(
  294. InputIterator1 first1,InputIterator1 last1,
  295. InputIterator2& first2,BinaryPredicate pred)const /* note the & */
  296. {
  297. while(first1!=last1&&pred(*first1,*first2)){
  298. ++first1;
  299. ++first2;
  300. }
  301. return first1;
  302. }
  303. template<
  304. typename InputIterator1,
  305. typename InputIterator2,typename BinaryPredicate
  306. >
  307. InputIterator1 operator()(
  308. InputIterator1 first1,InputIterator1 last1,
  309. InputIterator2& first2,InputIterator2 last2, /* note the & */
  310. BinaryPredicate pred)const
  311. {
  312. while(first1!=last1&&first2!=last2&&pred(*first1,*first2)){
  313. ++first1;
  314. ++first2;
  315. }
  316. return first1;
  317. }
  318. };
  319. template<
  320. typename... Ts,typename Iterator,
  321. typename InputIterator,typename BinaryPredicate,
  322. enable_if_poly_collection_iterator<Iterator> =nullptr
  323. >
  324. std::pair<Iterator,InputIterator> mismatch(
  325. const Iterator& first1,const Iterator& last1,
  326. InputIterator first2,BinaryPredicate pred)
  327. {
  328. auto it=generic_find<mismatch_alg,Ts...>(first1,last1,first2,pred);
  329. return {it,first2};
  330. }
  331. template<
  332. typename... Ts,typename Iterator,typename InputIterator,
  333. enable_if_poly_collection_iterator<Iterator> =nullptr
  334. >
  335. std::pair<Iterator,InputIterator> mismatch(
  336. const Iterator& first1,const Iterator& last1,InputIterator first2)
  337. {
  338. return algorithm::mismatch<Ts...>(
  339. first1,last1,first2,transparent_equal_to{});
  340. }
  341. template<
  342. typename... Ts,typename Iterator,
  343. typename InputIterator,typename BinaryPredicate,
  344. enable_if_poly_collection_iterator<Iterator> =nullptr
  345. >
  346. std::pair<Iterator,InputIterator> mismatch(
  347. const Iterator& first1,const Iterator& last1,
  348. InputIterator first2,InputIterator last2,BinaryPredicate pred)
  349. {
  350. auto it=generic_find<mismatch_alg,Ts...>(first1,last1,first2,last2,pred);
  351. return {it,first2};
  352. }
  353. template<
  354. typename... Ts,typename Iterator,typename InputIterator,
  355. enable_if_poly_collection_iterator<Iterator> =nullptr
  356. >
  357. std::pair<Iterator,InputIterator> mismatch(
  358. const Iterator& first1,const Iterator& last1,
  359. InputIterator first2,InputIterator last2)
  360. {
  361. return algorithm::mismatch<Ts...>(
  362. first1,last1,first2,last2,transparent_equal_to{});
  363. }
  364. struct equal_alg
  365. {
  366. template<
  367. typename InputIterator1,
  368. typename InputIterator2,typename BinaryPredicate
  369. >
  370. bool operator()(
  371. InputIterator1 first1,InputIterator1 last1,
  372. InputIterator2& first2,BinaryPredicate pred)const /* note the & */
  373. {
  374. for(;first1!=last1;++first1,++first2){
  375. if(!pred(*first1,*first2))return false;
  376. }
  377. return true;
  378. }
  379. template<
  380. typename InputIterator1,
  381. typename InputIterator2,typename BinaryPredicate
  382. >
  383. bool operator()(
  384. InputIterator1 first1,InputIterator1 last1,
  385. InputIterator2& first2,InputIterator2 last2, /* note the & */
  386. BinaryPredicate pred)const
  387. {
  388. for(;first1!=last1&&first2!=last2;++first1,++first2){
  389. if(!pred(*first1,*first2))return false;
  390. }
  391. return first1==last1; /* don't check first2==last2 as op is partial */
  392. }
  393. };
  394. template<
  395. typename... Ts,typename Iterator,
  396. typename InputIterator,typename BinaryPredicate,
  397. enable_if_poly_collection_iterator<Iterator> =nullptr
  398. >
  399. bool equal(
  400. const Iterator& first1,const Iterator& last1,
  401. InputIterator first2,BinaryPredicate pred)
  402. {
  403. auto alg=restitute_range<Ts...>(equal_alg{},first2,pred);
  404. for(auto i:detail::segment_split(first1,last1))if(!alg(i))return false;
  405. return true;
  406. }
  407. template<
  408. typename... Ts,typename Iterator,typename InputIterator,
  409. enable_if_poly_collection_iterator<Iterator> =nullptr
  410. >
  411. bool equal(
  412. const Iterator& first1,const Iterator& last1,InputIterator first2)
  413. {
  414. return algorithm::equal<Ts...>(first1,last1,first2,transparent_equal_to{});
  415. }
  416. template<
  417. typename... Ts,typename Iterator,
  418. typename InputIterator,typename BinaryPredicate,
  419. enable_if_poly_collection_iterator<Iterator> =nullptr
  420. >
  421. bool equal(
  422. const Iterator& first1,const Iterator& last1,
  423. InputIterator first2,InputIterator last2,BinaryPredicate pred)
  424. {
  425. auto alg=restitute_range<Ts...>(equal_alg{},first2,last2,pred);
  426. for(auto i:detail::segment_split(first1,last1))if(!alg(i))return false;
  427. return first2==last2;
  428. }
  429. template<
  430. typename... Ts,typename Iterator,typename InputIterator,
  431. enable_if_poly_collection_iterator<Iterator> =nullptr
  432. >
  433. bool equal(
  434. const Iterator& first1,const Iterator& last1,
  435. InputIterator first2,InputIterator last2)
  436. {
  437. return algorithm::equal<Ts...>(
  438. first1,last1,first2,last2,transparent_equal_to{});
  439. }
  440. template<
  441. typename Iterator,
  442. enable_if_poly_collection_iterator<Iterator> =nullptr
  443. >
  444. std::ptrdiff_t fast_distance(const Iterator& first,const Iterator& last)
  445. {
  446. using traits=iterator_traits<Iterator>;
  447. if(first==last)return 0;
  448. auto sfirst=traits::base_segment_info_iterator_from(first),
  449. slast=traits::base_segment_info_iterator_from(last);
  450. if(sfirst==slast){
  451. return std::distance(
  452. traits::local_base_iterator_from(first),
  453. traits::local_base_iterator_from(last));
  454. }
  455. else{
  456. std::ptrdiff_t m=std::distance(
  457. traits::local_base_iterator_from(first),sfirst->end());
  458. while(++sfirst!=slast)m+=std::distance(sfirst->begin(),sfirst->end());
  459. if(slast!=traits::end_base_segment_info_iterator_from(last)){
  460. m+=std::distance(
  461. slast->begin(),traits::local_base_iterator_from(last));
  462. }
  463. return m;
  464. }
  465. }
  466. template<
  467. typename... Ts,typename Iterator,
  468. typename ForwardIterator,typename BinaryPredicate,
  469. enable_if_poly_collection_iterator<Iterator> =nullptr
  470. >
  471. bool is_permutation_suffix(
  472. const Iterator& first1,const Iterator& last1,
  473. ForwardIterator first2,ForwardIterator last2,BinaryPredicate pred)
  474. {
  475. using traits=iterator_traits<Iterator>;
  476. auto send=traits::end_base_segment_info_iterator_from(last1);
  477. for(auto i:detail::segment_split(first1,last1)){
  478. for(auto lbscan=i.begin();lbscan!=i.end();++lbscan){
  479. auto& info=i.type_info();
  480. auto p=head_closure(
  481. restitute_iterator<Ts...>(deref_1st_to(pred)),info,lbscan);
  482. auto scan=traits::iterator_from(lbscan,send);
  483. if(algorithm::find_if<Ts...>(first1,scan,p)!=scan)continue;
  484. std::ptrdiff_t matches=std::count_if(first2,last2,p);
  485. if(matches==0||
  486. matches!=algorithm::count_if<Ts...>(scan,last1,p))return false;
  487. }
  488. }
  489. return true;
  490. }
  491. template<
  492. typename... Ts,typename Iterator,
  493. typename ForwardIterator,typename BinaryPredicate,
  494. enable_if_poly_collection_iterator<Iterator> =nullptr
  495. >
  496. bool is_permutation(
  497. Iterator first1,Iterator last1,ForwardIterator first2,BinaryPredicate pred)
  498. {
  499. std::tie(first1,first2)=algorithm::mismatch<Ts...>(first1,last1,first2,pred);
  500. auto last2=std::next(first2,algorithm::fast_distance(first1,last1));
  501. return is_permutation_suffix<Ts...>(first1,last1,first2,last2,pred);
  502. }
  503. template<
  504. typename... Ts,typename Iterator,typename ForwardIterator,
  505. enable_if_poly_collection_iterator<Iterator> =nullptr
  506. >
  507. bool is_permutation(
  508. const Iterator& first1,const Iterator& last1,ForwardIterator first2)
  509. {
  510. return algorithm::is_permutation<Ts...>(
  511. first1,last1,first2,transparent_equal_to{});
  512. }
  513. template<
  514. typename... Ts,typename Iterator,
  515. typename ForwardIterator,typename BinaryPredicate,
  516. enable_if_poly_collection_iterator<Iterator> =nullptr
  517. >
  518. bool is_permutation(
  519. Iterator first1,Iterator last1,
  520. ForwardIterator first2,ForwardIterator last2,BinaryPredicate pred)
  521. {
  522. std::tie(first1,first2)=algorithm::mismatch<Ts...>(
  523. first1,last1,first2,last2,pred);
  524. if(algorithm::fast_distance(first1,last1)!=std::distance(first2,last2))
  525. return false;
  526. else return is_permutation_suffix<Ts...>(first1,last1,first2,last2,pred);
  527. }
  528. template<
  529. typename... Ts,typename Iterator,typename ForwardIterator,
  530. enable_if_poly_collection_iterator<Iterator> =nullptr
  531. >
  532. bool is_permutation(
  533. const Iterator& first1,const Iterator& last1,
  534. ForwardIterator first2,ForwardIterator last2)
  535. {
  536. return algorithm::is_permutation<Ts...>(
  537. first1,last1,first2,last2,transparent_equal_to{});
  538. }
  539. template<
  540. typename... Ts,typename Iterator,
  541. typename ForwardIterator,typename BinaryPredicate,
  542. enable_if_poly_collection_iterator<Iterator> =nullptr
  543. >
  544. Iterator search(
  545. const Iterator& first1,const Iterator& last1,
  546. ForwardIterator first2,ForwardIterator last2,BinaryPredicate pred)
  547. {
  548. using traits=iterator_traits<Iterator>;
  549. auto send=traits::end_base_segment_info_iterator_from(last1);
  550. for(auto i:detail::segment_split(first1,last1)){
  551. for(auto lbit=i.begin(),lbend=i.end();lbit!=lbend;++lbit){
  552. Iterator it=traits::iterator_from(lbit,send);
  553. if(algorithm::mismatch<Ts...>(it,last1,first2,last2,pred).second==last2)
  554. return it;
  555. }
  556. }
  557. return last1;
  558. }
  559. template<
  560. typename... Ts,typename Iterator,typename ForwardIterator,
  561. enable_if_poly_collection_iterator<Iterator> =nullptr
  562. >
  563. Iterator search(
  564. const Iterator& first1,const Iterator& last1,
  565. ForwardIterator first2,ForwardIterator last2)
  566. {
  567. return algorithm::search<Ts...>(
  568. first1,last1,first2,last2,transparent_equal_to{});
  569. }
  570. template<
  571. typename... Ts,typename Iterator,
  572. typename ForwardIterator,typename BinaryPredicate,
  573. enable_if_poly_collection_iterator<Iterator> =nullptr
  574. >
  575. Iterator find_end(
  576. Iterator first1,Iterator last1,
  577. ForwardIterator first2,ForwardIterator last2,BinaryPredicate pred)
  578. {
  579. if(first2==last2)return last1;
  580. for(Iterator res=last1;;){
  581. Iterator res1=algorithm::search<Ts...>(first1,last1,first2,last2,pred);
  582. if(res1==last1)return res;
  583. else{
  584. first1=res=res1;
  585. ++first1;
  586. }
  587. }
  588. }
  589. template<
  590. typename... Ts,typename Iterator,typename ForwardIterator,
  591. enable_if_poly_collection_iterator<Iterator> =nullptr
  592. >
  593. Iterator find_end(
  594. const Iterator& first1,const Iterator& last1,
  595. ForwardIterator first2,ForwardIterator last2)
  596. {
  597. return algorithm::find_end<Ts...>(
  598. first1,last1,first2,last2,transparent_equal_to{});
  599. }
  600. struct search_n_alg
  601. {
  602. template<
  603. typename ForwardIterator,typename Size,
  604. typename T,typename BinaryPredicate
  605. >
  606. ForwardIterator operator()(
  607. ForwardIterator first,ForwardIterator last,
  608. Size count,bool& carry,Size& remain,const T& x, /* note the &s */
  609. BinaryPredicate pred)const
  610. {
  611. for(;first!=last;++first){
  612. if(!pred(*first,x)){carry=false;remain=count;continue;}
  613. auto res=first;
  614. for(;;){
  615. if(--remain==0||++first==last)return res;
  616. if(!pred(*first,x)){carry=false;remain=count;break;}
  617. }
  618. }
  619. return last;
  620. }
  621. };
  622. template<
  623. typename... Ts,typename Iterator,
  624. typename Size,typename T,typename BinaryPredicate,
  625. enable_if_poly_collection_iterator<Iterator> =nullptr
  626. >
  627. Iterator search_n(
  628. const Iterator& first,const Iterator& last,
  629. Size count,const T& x,BinaryPredicate pred)
  630. {
  631. using traits=iterator_traits<Iterator>;
  632. using local_base_iterator=typename traits::local_base_iterator;
  633. if(count<=0)return first;
  634. bool carry=false;
  635. auto remain=count;
  636. auto alg=restitute_range<Ts...>(
  637. cast_return<local_base_iterator>(search_n_alg{}),
  638. count,carry,remain,x,pred);
  639. local_base_iterator prev;
  640. for(auto i:detail::segment_split(first,last)){
  641. auto it=alg(i);
  642. if(it!=i.end()){
  643. if(remain==0)
  644. return traits::iterator_from(
  645. carry?prev:it,
  646. traits::end_base_segment_info_iterator_from(last));
  647. else if(!carry){prev=it;carry=true;}
  648. }
  649. }
  650. return last;
  651. }
  652. template<
  653. typename... Ts,typename Iterator,
  654. typename Size,typename T,
  655. enable_if_poly_collection_iterator<Iterator> =nullptr
  656. >
  657. Iterator search_n(
  658. const Iterator& first,const Iterator& last,Size count,const T& x)
  659. {
  660. return algorithm::search_n<Ts...>(
  661. first,last,count,x,transparent_equal_to{});
  662. }
  663. template<
  664. typename Algorithm,typename... Ts,
  665. typename Iterator,typename OutputIterator,typename... Args,
  666. enable_if_poly_collection_iterator<Iterator> =nullptr
  667. >
  668. OutputIterator generic_copy(
  669. const Iterator& first,const Iterator& last,OutputIterator res,Args&&... args)
  670. {
  671. for(auto i:detail::segment_split(first,last)){
  672. auto alg=restitute_range<Ts...>(
  673. Algorithm{},res,std::forward<Args>(args)...);
  674. res=alg(i);
  675. }
  676. return res;
  677. }
  678. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_copy,std::copy)
  679. template<
  680. typename... Ts,typename Iterator,typename OutputIterator,
  681. enable_if_poly_collection_iterator<Iterator> =nullptr
  682. >
  683. OutputIterator copy(
  684. const Iterator& first,const Iterator& last,OutputIterator res)
  685. {
  686. return generic_copy<std_copy,Ts...>(first,last,res);
  687. }
  688. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_copy_n,std::copy_n)
  689. template<
  690. typename... Ts,typename Iterator,typename Size,typename OutputIterator,
  691. enable_if_poly_collection_iterator<Iterator> =nullptr
  692. >
  693. OutputIterator copy_n(const Iterator& first,Size count,OutputIterator res)
  694. {
  695. using traits=iterator_traits<Iterator>;
  696. if(count<=0)return res;
  697. auto lbit=traits::local_base_iterator_from(first);
  698. auto sit=traits::base_segment_info_iterator_from(first);
  699. for(;;){
  700. auto n=(std::min)(count,sit->end()-lbit);
  701. auto alg=restitute_iterator<Ts...>(std_copy_n{},n,res);
  702. res=alg(sit->type_info(),lbit);
  703. if((count-=n)==0)break;
  704. ++sit;
  705. lbit=sit->begin();
  706. }
  707. return res;
  708. }
  709. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_copy_if,std::copy_if)
  710. template<
  711. typename... Ts,typename Iterator,typename OutputIterator,typename Predicate,
  712. enable_if_poly_collection_iterator<Iterator> =nullptr
  713. >
  714. OutputIterator copy_if(
  715. const Iterator& first,const Iterator& last,OutputIterator res,Predicate pred)
  716. {
  717. return generic_copy<std_copy_if,Ts...>(first,last,res,pred);
  718. }
  719. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_move,std::move)
  720. template<
  721. typename... Ts,typename Iterator,typename OutputIterator,
  722. enable_if_poly_collection_iterator<Iterator> =nullptr
  723. >
  724. OutputIterator move(
  725. const Iterator& first,const Iterator& last,OutputIterator res)
  726. {
  727. return generic_copy<std_move,Ts...>(first,last,res);
  728. }
  729. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_transform,std::transform)
  730. template<
  731. typename... Ts,typename Iterator,
  732. typename OutputIterator,typename UnaryOperation,
  733. enable_if_poly_collection_iterator<Iterator> =nullptr
  734. >
  735. OutputIterator transform(
  736. const Iterator& first,const Iterator& last,
  737. OutputIterator res,UnaryOperation op)
  738. {
  739. return generic_copy<std_transform,Ts...>(first,last,res,op);
  740. }
  741. struct transform2_alg
  742. {
  743. template<
  744. typename InputIterator1,typename InputIterator2,
  745. typename OutputIterator,typename BinaryOperation
  746. >
  747. OutputIterator operator()(
  748. InputIterator1 first1,InputIterator1 last1,
  749. OutputIterator res, /* third place for compatibility with generic_copy */
  750. InputIterator2& first2, BinaryOperation op)const /* note the & */
  751. {
  752. while(first1!=last1)*res++=op(*first1++,*first2++);
  753. return res;
  754. }
  755. };
  756. template<
  757. typename... Ts,typename Iterator,typename InputIterator,
  758. typename OutputIterator,typename BinaryOperation,
  759. enable_if_poly_collection_iterator<Iterator> =nullptr
  760. >
  761. OutputIterator transform(
  762. const Iterator& first1,const Iterator& last1,InputIterator first2,
  763. OutputIterator res,BinaryOperation op)
  764. {
  765. return generic_copy<transform2_alg,Ts...>(first1,last1,res,first2,op);
  766. }
  767. struct replace_copy_alg
  768. {
  769. /* std::replace_copy broken in VS2015, internal ticket VSO#279818
  770. * "<algorithm>: replace_copy() and replace_copy_if() shouldn't use the
  771. * conditional operator".
  772. */
  773. template<typename InputIterator,typename OutputIterator,typename T>
  774. OutputIterator operator()(
  775. InputIterator first,InputIterator last,OutputIterator res,
  776. const T& old_x,const T& new_x)
  777. {
  778. for(;first!=last;++first,++res){
  779. if(*first==old_x)*res=new_x;
  780. else *res=*first;
  781. }
  782. return res;
  783. }
  784. };
  785. template<
  786. typename... Ts,typename Iterator,typename OutputIterator,typename T,
  787. enable_if_poly_collection_iterator<Iterator> =nullptr
  788. >
  789. OutputIterator replace_copy(
  790. const Iterator& first,const Iterator& last,OutputIterator res,
  791. const T& old_x,const T& new_x)
  792. {
  793. return generic_copy<replace_copy_alg,Ts...>(first,last,res,old_x,new_x);
  794. }
  795. struct replace_copy_if_alg
  796. {
  797. /* std::replace_copy_if broken in VS2015, internal ticket VSO#279818
  798. * "<algorithm>: replace_copy() and replace_copy_if() shouldn't use the
  799. * conditional operator".
  800. */
  801. template<
  802. typename InputIterator,typename OutputIterator,
  803. typename Predicate,typename T
  804. >
  805. OutputIterator operator()(
  806. InputIterator first,InputIterator last,OutputIterator res,
  807. Predicate pred,const T& new_x)
  808. {
  809. for(;first!=last;++first,++res){
  810. if(pred(*first))*res=new_x;
  811. else *res=*first;
  812. }
  813. return res;
  814. }
  815. };
  816. template<
  817. typename... Ts,typename Iterator,typename OutputIterator,
  818. typename Predicate,typename T,
  819. enable_if_poly_collection_iterator<Iterator> =nullptr
  820. >
  821. OutputIterator replace_copy_if(
  822. const Iterator& first,const Iterator& last,OutputIterator res,
  823. Predicate pred,const T& new_x)
  824. {
  825. return generic_copy<replace_copy_if_alg,Ts...>(first,last,res,pred,new_x);
  826. }
  827. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(std_remove_copy,std::remove_copy)
  828. template<
  829. typename... Ts,typename Iterator,typename OutputIterator,typename T,
  830. enable_if_poly_collection_iterator<Iterator> =nullptr
  831. >
  832. OutputIterator remove_copy(
  833. const Iterator& first,const Iterator& last,OutputIterator res,const T& x)
  834. {
  835. return generic_copy<std_remove_copy,Ts...>(first,last,res,x);
  836. }
  837. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(
  838. std_remove_copy_if,std::remove_copy_if)
  839. template<
  840. typename... Ts,typename Iterator,typename OutputIterator,typename Predicate,
  841. enable_if_poly_collection_iterator<Iterator> =nullptr
  842. >
  843. OutputIterator remove_copy_if(
  844. const Iterator& first,const Iterator& last,OutputIterator res,Predicate pred)
  845. {
  846. return generic_copy<std_remove_copy_if,Ts...>(first,last,res,pred);
  847. }
  848. template<typename... Ts>
  849. struct unique_copy_alg
  850. {
  851. template<
  852. typename LocalIterator,typename OutputIterator,
  853. typename BinaryPredicate,typename LocalBaseIterator
  854. >
  855. OutputIterator operator()(
  856. LocalIterator first,LocalIterator last,
  857. OutputIterator res, BinaryPredicate pred,
  858. bool& carry,const std::type_info* prev_info, /* note the &s */
  859. LocalBaseIterator& prev)const
  860. {
  861. if(carry){
  862. auto p=restitute_iterator<Ts...>(deref_to(pred));
  863. for(;first!=last;++first)if(!p(*prev_info,prev,first))break;
  864. }
  865. if(first==last)return res;
  866. res=std::unique_copy(first,last,res,pred);
  867. carry=true;
  868. prev_info=&typeid(
  869. typename std::iterator_traits<LocalIterator>::value_type);
  870. prev=LocalBaseIterator{last-1};
  871. return res;
  872. }
  873. };
  874. template<
  875. typename... Ts,typename Iterator,
  876. typename OutputIterator,typename BinaryPredicate,
  877. enable_if_poly_collection_iterator<Iterator> =nullptr
  878. >
  879. OutputIterator unique_copy(
  880. const Iterator& first,const Iterator& last,
  881. OutputIterator res,BinaryPredicate pred)
  882. {
  883. using traits=iterator_traits<Iterator>;
  884. using local_base_iterator=typename traits::local_base_iterator;
  885. bool carry=false;
  886. const std::type_info* prev_info{&typeid(void)};
  887. local_base_iterator prev;
  888. return generic_copy<unique_copy_alg<Ts...>,Ts...>(
  889. first,last,res,pred,carry,prev_info,prev);
  890. }
  891. template<
  892. typename... Ts,typename Iterator,typename OutputIterator,
  893. enable_if_poly_collection_iterator<Iterator> =nullptr
  894. >
  895. OutputIterator unique_copy(
  896. const Iterator& first,const Iterator& last,OutputIterator res)
  897. {
  898. return algorithm::unique_copy<Ts...>(first,last,res,transparent_equal_to{});
  899. }
  900. template<
  901. typename... Ts,typename Iterator,typename OutputIterator,
  902. enable_if_poly_collection_iterator<Iterator> =nullptr
  903. >
  904. OutputIterator rotate_copy(
  905. const Iterator& first,const Iterator& middle,const Iterator& last,
  906. OutputIterator res)
  907. {
  908. res=algorithm::copy<Ts...>(middle,last,res);
  909. return algorithm::copy<Ts...>(first,middle,res);
  910. }
  911. struct sample_alg
  912. {
  913. template<
  914. typename InputIterator,typename OutputIterator,
  915. typename Distance,typename UniformRandomBitGenerator
  916. >
  917. OutputIterator operator()(
  918. InputIterator first,InputIterator last,
  919. OutputIterator res,Distance& n,Distance& m, /* note the &s */
  920. UniformRandomBitGenerator& g)const
  921. {
  922. for(;first!=last&&n!=0;++first){
  923. auto r=std::uniform_int_distribution<Distance>(0,--m)(g);
  924. if (r<n){
  925. *res++=*first;
  926. --n;
  927. }
  928. }
  929. return res;
  930. }
  931. };
  932. template<
  933. typename... Ts,typename Iterator,typename OutputIterator,
  934. typename Distance,typename UniformRandomBitGenerator,
  935. enable_if_poly_collection_iterator<Iterator> =nullptr
  936. >
  937. OutputIterator sample(
  938. const Iterator& first,const Iterator& last,
  939. OutputIterator res,Distance n,UniformRandomBitGenerator&& g)
  940. {
  941. Distance m=algorithm::fast_distance(first,last);
  942. n=(std::min)(n,m);
  943. for(auto i:detail::segment_split(first,last)){
  944. auto alg=restitute_range<Ts...>(sample_alg{},res,n,m,g);
  945. res=alg(i);
  946. if(n==0)return res;
  947. }
  948. return res; /* never reached */
  949. }
  950. template<
  951. typename... Ts,typename Iterator,typename Predicate,
  952. enable_if_poly_collection_iterator<Iterator> =nullptr
  953. >
  954. bool is_partitioned(const Iterator& first,const Iterator& last,Predicate pred)
  955. {
  956. auto it=algorithm::find_if_not<Ts...>(first,last,pred);
  957. if(it==last)return true;
  958. return algorithm::none_of<Ts...>(++it,last,pred);
  959. }
  960. BOOST_POLY_COLLECTION_DEFINE_OVERLOAD_SET(
  961. std_partition_copy,std::partition_copy)
  962. template<
  963. typename... Ts,typename Iterator,
  964. typename OutputIterator1,typename OutputIterator2,typename Predicate,
  965. enable_if_poly_collection_iterator<Iterator> =nullptr
  966. >
  967. std::pair<OutputIterator1,OutputIterator2> partition_copy(
  968. const Iterator& first,const Iterator& last,
  969. OutputIterator1 rest,OutputIterator2 resf,Predicate pred)
  970. {
  971. for(auto i:detail::segment_split(first,last)){
  972. auto alg=restitute_range<Ts...>(std_partition_copy{},rest,resf,pred);
  973. std::tie(rest,resf)=alg(i);
  974. }
  975. return {rest,resf};
  976. }
  977. template<typename Predicate,typename... Ts>
  978. struct partition_point_pred
  979. {
  980. partition_point_pred(const Predicate& pred):pred(pred){}
  981. template<typename Iterator>
  982. bool operator()(const Iterator& it)const
  983. {
  984. using traits=iterator_traits<Iterator>;
  985. auto p=restitute_iterator<Ts...>(deref_to(pred));
  986. return p(
  987. traits::base_segment_info_iterator_from(it)->type_info(),
  988. traits::local_base_iterator_from(it));
  989. }
  990. Predicate pred;
  991. };
  992. template<
  993. typename... Ts,typename Iterator,typename Predicate,
  994. enable_if_poly_collection_iterator<Iterator> =nullptr
  995. >
  996. Iterator partition_point(
  997. const Iterator& first,const Iterator& last,Predicate pred)
  998. {
  999. auto_iterator<Iterator> afirst{first},alast{last};
  1000. partition_point_pred<Predicate,Ts...> p{pred};
  1001. return *std::partition_point(afirst,alast,p);
  1002. }
  1003. } /* namespace poly_collection::detail::algorithm */
  1004. } /* namespace poly_collection::detail */
  1005. /* non-modifying sequence operations */
  1006. using detail::algorithm::all_of;
  1007. using detail::algorithm::any_of;
  1008. using detail::algorithm::none_of;
  1009. using detail::algorithm::for_each;
  1010. using detail::algorithm::for_each_n;
  1011. using detail::algorithm::find;
  1012. using detail::algorithm::find_if;
  1013. using detail::algorithm::find_if_not;
  1014. using detail::algorithm::find_end;
  1015. using detail::algorithm::find_first_of;
  1016. using detail::algorithm::adjacent_find;
  1017. using detail::algorithm::count;
  1018. using detail::algorithm::count_if;
  1019. using detail::algorithm::mismatch;
  1020. using detail::algorithm::equal;
  1021. using detail::algorithm::is_permutation;
  1022. using detail::algorithm::search;
  1023. using detail::algorithm::search_n;
  1024. /* modifying sequence operations */
  1025. using detail::algorithm::copy;
  1026. using detail::algorithm::copy_n;
  1027. using detail::algorithm::copy_if;
  1028. /* copy_backward requires BidirectionalIterator */
  1029. using detail::algorithm::move;
  1030. /* move_backward requires BidirectionalIterator */
  1031. /* swap_ranges requires Swappable */
  1032. /* iter_swap requires Swappable */
  1033. using detail::algorithm::transform;
  1034. /* replace requires Assignable */
  1035. /* replace_if requires Assignable */
  1036. using detail::algorithm::replace_copy;
  1037. using detail::algorithm::replace_copy_if;
  1038. /* fill requires Assignable */
  1039. /* fill_n requires Assignable */
  1040. /* generate requires Assignable */
  1041. /* generate_n requires Assignable */
  1042. /* remove requires MoveAssignable */
  1043. /* remove_if requires MoveAssignable */
  1044. using detail::algorithm::remove_copy;
  1045. using detail::algorithm::remove_copy_if;
  1046. /* unique requires MoveAssignable */
  1047. using detail::algorithm::unique_copy;
  1048. /* reverse requires BidirectionalIterator */
  1049. /* reverse_copy requires BidirectionalIterator */
  1050. /* rotate requires MoveAssignable */
  1051. using detail::algorithm::rotate_copy;
  1052. using detail::algorithm::sample;
  1053. /* shuffle requires RandomAccessIterator */
  1054. using detail::algorithm::is_partitioned;
  1055. /* partition requires Swappable */
  1056. /* stable_partition requires Swappable */
  1057. using detail::algorithm::partition_copy;
  1058. using detail::algorithm::partition_point;
  1059. /* sorting and related operations not provided */
  1060. } /* namespace poly_collection */
  1061. } /* namespace boost */
  1062. #endif