interval_associator.hpp 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211
  1. /*-----------------------------------------------------------------------------+
  2. Copyright (c) 2010-2010: Joachim Faulhaber
  3. +------------------------------------------------------------------------------+
  4. Distributed under the Boost Software License, Version 1.0.
  5. (See accompanying file LICENCE.txt or copy at
  6. http://www.boost.org/LICENSE_1_0.txt)
  7. +-----------------------------------------------------------------------------*/
  8. #ifndef BOOST_ICL_CONCEPT_INTERVAL_ASSOCIATOR_HPP_JOFA_100920
  9. #define BOOST_ICL_CONCEPT_INTERVAL_ASSOCIATOR_HPP_JOFA_100920
  10. #include <boost/icl/type_traits/domain_type_of.hpp>
  11. #include <boost/icl/type_traits/interval_type_of.hpp>
  12. #include <boost/icl/type_traits/is_combinable.hpp>
  13. #include <boost/icl/detail/set_algo.hpp>
  14. #include <boost/icl/detail/map_algo.hpp>
  15. #include <boost/icl/detail/interval_set_algo.hpp>
  16. #include <boost/icl/detail/interval_map_algo.hpp>
  17. #include <boost/icl/concept/interval.hpp>
  18. namespace boost{ namespace icl
  19. {
  20. //==============================================================================
  21. //= Containedness<IntervalSet|IntervalMap>
  22. //==============================================================================
  23. //------------------------------------------------------------------------------
  24. //- bool within(c T&, c P&) T={Set,Map} P={e i b p S M}
  25. //------------------------------------------------------------------------------
  26. template<class SubT, class SuperT>
  27. typename enable_if<is_interval_container<SuperT>, bool>::type
  28. within(const SubT& sub, const SuperT& super)
  29. {
  30. return icl::contains(super, sub);
  31. }
  32. //==============================================================================
  33. //= Equivalences and Orderings<IntervalSet|IntervalMap>
  34. //==============================================================================
  35. template<class Type>
  36. inline typename enable_if<is_interval_container<Type>, bool>::type
  37. operator == (const Type& left, const Type& right)
  38. {
  39. return Set::lexicographical_equal(left, right);
  40. }
  41. template<class Type>
  42. inline typename enable_if<is_interval_container<Type>, bool>::type
  43. operator < (const Type& left, const Type& right)
  44. {
  45. typedef typename Type::segment_compare segment_compare;
  46. return std::lexicographical_compare(
  47. left.begin(), left.end(), right.begin(), right.end(),
  48. segment_compare()
  49. );
  50. }
  51. /** Returns true, if \c left and \c right contain the same elements.
  52. Complexity: linear. */
  53. template<class LeftT, class RightT>
  54. typename enable_if<is_intra_combinable<LeftT, RightT>, bool>::type
  55. is_element_equal(const LeftT& left, const RightT& right)
  56. {
  57. return Interval_Set::is_element_equal(left, right);
  58. }
  59. /** Returns true, if \c left is lexicographically less than \c right.
  60. Intervals are interpreted as sequence of elements.
  61. Complexity: linear. */
  62. template<class LeftT, class RightT>
  63. typename enable_if<is_intra_combinable<LeftT, RightT>, bool>::type
  64. is_element_less(const LeftT& left, const RightT& right)
  65. {
  66. return Interval_Set::is_element_less(left, right);
  67. }
  68. /** Returns true, if \c left is lexicographically greater than \c right.
  69. Intervals are interpreted as sequence of elements.
  70. Complexity: linear. */
  71. template<class LeftT, class RightT>
  72. typename enable_if<is_intra_combinable<LeftT, RightT>, bool>::type
  73. is_element_greater(const LeftT& left, const RightT& right)
  74. {
  75. return Interval_Set::is_element_greater(left, right);
  76. }
  77. //------------------------------------------------------------------------------
  78. template<class LeftT, class RightT>
  79. typename enable_if<is_inter_combinable<LeftT, RightT>, int>::type
  80. inclusion_compare(const LeftT& left, const RightT& right)
  81. {
  82. return Interval_Set::subset_compare(left, right,
  83. left.begin(), left.end(),
  84. right.begin(), right.end());
  85. }
  86. //------------------------------------------------------------------------------
  87. template<class LeftT, class RightT>
  88. typename enable_if< is_concept_compatible<is_interval_map, LeftT, RightT>,
  89. bool >::type
  90. is_distinct_equal(const LeftT& left, const RightT& right)
  91. {
  92. return Map::lexicographical_distinct_equal(left, right);
  93. }
  94. //==============================================================================
  95. //= Size<IntervalSet|IntervalMap>
  96. //==============================================================================
  97. template<class Type>
  98. typename enable_if<is_interval_container<Type>, std::size_t>::type
  99. iterative_size(const Type& object)
  100. {
  101. return object.iterative_size();
  102. }
  103. template<class Type>
  104. typename enable_if
  105. < mpl::and_< is_interval_container<Type>
  106. , is_discrete<typename Type::domain_type> >
  107. , typename Type::size_type
  108. >::type
  109. cardinality(const Type& object)
  110. {
  111. typedef typename Type::size_type size_type;
  112. typedef typename Type::interval_type interval_type;
  113. size_type size = identity_element<size_type>::value();
  114. ICL_const_FORALL(typename Type, it, object)
  115. size += icl::cardinality(key_value<Type>(it));
  116. return size;
  117. }
  118. template<class Type>
  119. typename enable_if
  120. < mpl::and_< is_interval_container<Type>
  121. , mpl::not_<is_discrete<typename Type::domain_type> > >
  122. , typename Type::size_type
  123. >::type
  124. cardinality(const Type& object)
  125. {
  126. typedef typename Type::size_type size_type;
  127. typedef typename Type::interval_type interval_type;
  128. size_type size = identity_element<size_type>::value();
  129. size_type interval_size;
  130. ICL_const_FORALL(typename Type, it, object)
  131. {
  132. interval_size = icl::cardinality(key_value<Type>(it));
  133. if(interval_size == icl::infinity<size_type>::value())
  134. return interval_size;
  135. else
  136. size += interval_size;
  137. }
  138. return size;
  139. }
  140. template<class Type>
  141. inline typename enable_if<is_interval_container<Type>, typename Type::size_type>::type
  142. size(const Type& object)
  143. {
  144. return icl::cardinality(object);
  145. }
  146. template<class Type>
  147. typename enable_if<is_interval_container<Type>, typename Type::difference_type>::type
  148. length(const Type& object)
  149. {
  150. typedef typename Type::difference_type difference_type;
  151. typedef typename Type::const_iterator const_iterator;
  152. difference_type length = identity_element<difference_type>::value();
  153. const_iterator it_ = object.begin();
  154. while(it_ != object.end())
  155. length += icl::length(key_value<Type>(it_++));
  156. return length;
  157. }
  158. template<class Type>
  159. typename enable_if<is_interval_container<Type>, std::size_t>::type
  160. interval_count(const Type& object)
  161. {
  162. return icl::iterative_size(object);
  163. }
  164. template<class Type>
  165. typename enable_if< is_interval_container<Type>
  166. , typename Type::difference_type >::type
  167. distance(const Type& object)
  168. {
  169. typedef typename Type::difference_type DiffT;
  170. typedef typename Type::const_iterator const_iterator;
  171. const_iterator it_ = object.begin(), pred_;
  172. DiffT dist = identity_element<DiffT>::value();
  173. if(it_ != object.end())
  174. pred_ = it_++;
  175. while(it_ != object.end())
  176. dist += icl::distance(key_value<Type>(pred_++), key_value<Type>(it_++));
  177. return dist;
  178. }
  179. //==============================================================================
  180. //= Range<IntervalSet|IntervalMap>
  181. //==============================================================================
  182. template<class Type>
  183. typename enable_if<is_interval_container<Type>,
  184. typename Type::interval_type>::type
  185. hull(const Type& object)
  186. {
  187. return
  188. icl::is_empty(object)
  189. ? identity_element<typename Type::interval_type>::value()
  190. : icl::hull( key_value<Type>(object.begin()),
  191. key_value<Type>(object.rbegin()) );
  192. }
  193. template<class Type>
  194. typename enable_if<is_interval_container<Type>,
  195. typename domain_type_of<Type>::type>::type
  196. lower(const Type& object)
  197. {
  198. typedef typename domain_type_of<Type>::type DomainT;
  199. return
  200. icl::is_empty(object)
  201. ? unit_element<DomainT>::value()
  202. : icl::lower( key_value<Type>(object.begin()) );
  203. }
  204. template<class Type>
  205. typename enable_if<is_interval_container<Type>,
  206. typename domain_type_of<Type>::type>::type
  207. upper(const Type& object)
  208. {
  209. typedef typename domain_type_of<Type>::type DomainT;
  210. return
  211. icl::is_empty(object)
  212. ? identity_element<DomainT>::value()
  213. : icl::upper( key_value<Type>(object.rbegin()) );
  214. }
  215. //------------------------------------------------------------------------------
  216. template<class Type>
  217. typename enable_if
  218. < mpl::and_< is_interval_container<Type>
  219. , is_discrete<typename domain_type_of<Type>::type> >
  220. , typename domain_type_of<Type>::type>::type
  221. first(const Type& object)
  222. {
  223. typedef typename domain_type_of<Type>::type DomainT;
  224. return
  225. icl::is_empty(object)
  226. ? unit_element<DomainT>::value()
  227. : icl::first( key_value<Type>(object.begin()) );
  228. }
  229. template<class Type>
  230. typename enable_if
  231. < mpl::and_< is_interval_container<Type>
  232. , is_discrete<typename domain_type_of<Type>::type> >
  233. , typename domain_type_of<Type>::type>::type
  234. last(const Type& object)
  235. {
  236. typedef typename domain_type_of<Type>::type DomainT;
  237. return
  238. icl::is_empty(object)
  239. ? identity_element<DomainT>::value()
  240. : icl::last( key_value<Type>(object.rbegin()) );
  241. }
  242. //==============================================================================
  243. //= Addition<IntervalSet|IntervalMap>
  244. //==============================================================================
  245. //------------------------------------------------------------------------------
  246. //- T& op +=(T&, c P&) T:{S}|{M} P:{e i}|{b p}
  247. //------------------------------------------------------------------------------
  248. /* \par \b Requires: \c OperandT is an addable derivative type of \c Type.
  249. \b Effects: \c operand is added to \c object.
  250. \par \b Returns: A reference to \c object.
  251. \b Complexity:
  252. \code
  253. \ OperandT:
  254. \ element segment
  255. Type:
  256. interval container O(log n) O(n)
  257. interval_set amortized
  258. spearate_interval_set O(log n)
  259. n = object.interval_count()
  260. \endcode
  261. For the addition of \b elements or \b segments
  262. complexity is \b logarithmic or \b linear respectively.
  263. For \c interval_sets and \c separate_interval_sets addition of segments
  264. is \b amortized \b logarithmic.
  265. */
  266. template<class Type, class OperandT>
  267. typename enable_if<is_intra_derivative<Type, OperandT>, Type>::type&
  268. operator += (Type& object, const OperandT& operand)
  269. {
  270. return icl::add(object, operand);
  271. }
  272. //------------------------------------------------------------------------------
  273. //- T& op +=(T&, c P&) T:{S}|{M} P:{S'}|{M'}
  274. //------------------------------------------------------------------------------
  275. /** \par \b Requires: \c OperandT is an interval container addable to \c Type.
  276. \b Effects: \c operand is added to \c object.
  277. \par \b Returns: A reference to \c object.
  278. \b Complexity: loglinear */
  279. template<class Type, class OperandT>
  280. typename enable_if<is_intra_combinable<Type, OperandT>, Type>::type&
  281. operator += (Type& object, const OperandT& operand)
  282. {
  283. typename Type::iterator prior_ = object.end();
  284. ICL_const_FORALL(typename OperandT, elem_, operand)
  285. prior_ = icl::add(object, prior_, *elem_);
  286. return object;
  287. }
  288. #ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  289. //------------------------------------------------------------------------------
  290. //- T op + (T, c P&) T:{S}|{M} P:{e i S}|{b p M}
  291. //------------------------------------------------------------------------------
  292. /** \par \b Requires: \c object and \c operand are addable.
  293. \b Effects: \c operand is added to \c object.
  294. \par \b Efficieny: There is one additional copy of
  295. \c Type \c object compared to inplace \c operator \c += */
  296. template<class Type, class OperandT>
  297. typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
  298. operator + (Type object, const OperandT& operand)
  299. {
  300. return object += operand;
  301. }
  302. #else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  303. template<class Type, class OperandT>
  304. typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
  305. operator + (const Type& object, const OperandT& operand)
  306. {
  307. Type temp = object;
  308. return boost::move(temp += operand);
  309. }
  310. template<class Type, class OperandT>
  311. typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
  312. operator + (Type&& object, const OperandT& operand)
  313. {
  314. return boost::move(object += operand);
  315. }
  316. #endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  317. #ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  318. //------------------------------------------------------------------------------
  319. //- T op + (c P&, T) T:{S}|{M} P:{e i S'}|{b p M'}
  320. //------------------------------------------------------------------------------
  321. /** \par \b Requires: \c object and \c operand are addable.
  322. \b Effects: \c operand is added to \c object.
  323. \par \b Efficieny: There is one additional copy of
  324. \c Type \c object compared to inplace \c operator \c += */
  325. template<class Type, class OperandT>
  326. typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
  327. operator + (const OperandT& operand, Type object)
  328. {
  329. return object += operand;
  330. }
  331. #else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  332. template<class Type, class OperandT>
  333. typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
  334. operator + (const OperandT& operand, const Type& object)
  335. {
  336. Type temp = object;
  337. return boost::move(temp += operand);
  338. }
  339. template<class Type, class OperandT>
  340. typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
  341. operator + (const OperandT& operand, Type&& object)
  342. {
  343. return boost::move(object += operand);
  344. }
  345. #endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  346. #ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  347. //------------------------------------------------------------------------------
  348. //- T op + (T, c P&) T:{S}|{M} P:{S}|{M}
  349. //------------------------------------------------------------------------------
  350. /** \par \b Requires: \c object and \c operand are addable.
  351. \b Effects: \c operand is added to \c object.
  352. \par \b Efficieny: There is one additional copy of
  353. \c Type \c object compared to inplace \c operator \c += */
  354. template<class Type>
  355. typename enable_if<is_interval_container<Type>, Type>::type
  356. operator + (Type object, const Type& operand)
  357. {
  358. return object += operand;
  359. }
  360. #else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  361. template<class Type>
  362. typename enable_if<is_interval_container<Type>, Type>::type
  363. operator + (const Type& object, const Type& operand)
  364. {
  365. Type temp = object;
  366. return boost::move(temp += operand);
  367. }
  368. template<class Type>
  369. typename enable_if<is_interval_container<Type>, Type>::type
  370. operator + (Type&& object, const Type& operand)
  371. {
  372. return boost::move(object += operand);
  373. }
  374. template<class Type>
  375. typename enable_if<is_interval_container<Type>, Type>::type
  376. operator + (const Type& operand, Type&& object)
  377. {
  378. return boost::move(object += operand);
  379. }
  380. template<class Type>
  381. typename enable_if<is_interval_container<Type>, Type>::type
  382. operator + (Type&& object, Type&& operand)
  383. {
  384. return boost::move(object += operand);
  385. }
  386. #endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  387. //------------------------------------------------------------------------------
  388. //- Addition |=, |
  389. //------------------------------------------------------------------------------
  390. //------------------------------------------------------------------------------
  391. //- T& op |=(c P&) T:{S}|{M} P:{e i}|{b p}
  392. //------------------------------------------------------------------------------
  393. /** \par \b Requires: Types \c Type and \c OperandT are addable.
  394. \par \b Effects: \c operand is added to \c object.
  395. \par \b Returns: A reference to \c object.
  396. \b Complexity:
  397. \code
  398. \ OperandT: interval
  399. \ element segment container
  400. Type:
  401. interval container O(log n) O(n) O(m log(n+m))
  402. interval_set amortized
  403. spearate_interval_set O(log n)
  404. n = object.interval_count()
  405. m = operand.interval_count()
  406. \endcode
  407. For the addition of \b elements, \b segments and \b interval \b containers
  408. complexity is \b logarithmic, \b linear and \b loglinear respectively.
  409. For \c interval_sets and \c separate_interval_sets addition of segments
  410. is \b amortized \b logarithmic.
  411. */
  412. template<class Type, class OperandT>
  413. typename enable_if<is_right_intra_combinable<Type, OperandT>, Type>::type&
  414. operator |= (Type& object, const OperandT& operand)
  415. {
  416. return object += operand;
  417. }
  418. #ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  419. //------------------------------------------------------------------------------
  420. //- T op | (T, c P&) T:{S}|{M} P:{e i S}|{b p M}
  421. //------------------------------------------------------------------------------
  422. /** \par \b Requires: \c object and \c operand are addable.
  423. \b Effects: \c operand is added to \c object.
  424. \par \b Efficieny: There is one additional copy of
  425. \c Type \c object compared to inplace \c operator \c |= */
  426. template<class Type, class OperandT>
  427. typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
  428. operator | (Type object, const OperandT& operand)
  429. {
  430. return object += operand;
  431. }
  432. #else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  433. template<class Type, class OperandT>
  434. typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
  435. operator | (const Type& object, const OperandT& operand)
  436. {
  437. Type temp = object;
  438. return boost::move(temp += operand);
  439. }
  440. template<class Type, class OperandT>
  441. typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
  442. operator | (Type&& object, const OperandT& operand)
  443. {
  444. return boost::move(object += operand);
  445. }
  446. #endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  447. #ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  448. //------------------------------------------------------------------------------
  449. //- T op | (T, c P&) T:{S}|{M} P:{S}|{M}
  450. //------------------------------------------------------------------------------
  451. /** \par \b Requires: \c object and \c operand are addable.
  452. \b Effects: \c operand is added to \c object.
  453. \par \b Efficieny: There is one additional copy of
  454. \c Type \c object compared to inplace \c operator \c |= */
  455. template<class Type, class OperandT>
  456. typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
  457. operator | (const OperandT& operand, Type object)
  458. {
  459. return object += operand;
  460. }
  461. #else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  462. template<class Type, class OperandT>
  463. typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
  464. operator | (const OperandT& operand, const Type& object)
  465. {
  466. Type temp = object;
  467. return boost::move(temp += operand);
  468. }
  469. template<class Type, class OperandT>
  470. typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
  471. operator | (const OperandT& operand, Type&& object)
  472. {
  473. return boost::move(object += operand);
  474. }
  475. #endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  476. #ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  477. //------------------------------------------------------------------------------
  478. //- T op | (T, c P&) T:{S}|{M} P:{S}|{M}
  479. //------------------------------------------------------------------------------
  480. /** \par \b Requires: \c object and \c operand are addable.
  481. \b Effects: \c operand is added to \c object.
  482. \par \b Efficieny: There is one additional copy of
  483. \c Type \c object compared to inplace \c operator \c |= */
  484. template<class Type>
  485. typename enable_if<is_interval_container<Type>, Type>::type
  486. operator | (Type object, const Type& operand)
  487. {
  488. return object += operand;
  489. }
  490. #else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  491. template<class Type>
  492. typename enable_if<is_interval_container<Type>, Type>::type
  493. operator | (const Type& object, const Type& operand)
  494. {
  495. Type temp = object;
  496. return boost::move(temp += operand);
  497. }
  498. template<class Type>
  499. typename enable_if<is_interval_container<Type>, Type>::type
  500. operator | (Type&& object, const Type& operand)
  501. {
  502. return boost::move(object += operand);
  503. }
  504. template<class Type>
  505. typename enable_if<is_interval_container<Type>, Type>::type
  506. operator | (const Type& operand, Type&& object)
  507. {
  508. return boost::move(object += operand);
  509. }
  510. template<class Type>
  511. typename enable_if<is_interval_container<Type>, Type>::type
  512. operator | (Type&& object, Type&& operand)
  513. {
  514. return boost::move(object += operand);
  515. }
  516. #endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  517. //==============================================================================
  518. //= Insertion<IntervalSet|IntervalSet>
  519. //==============================================================================
  520. //------------------------------------------------------------------------------
  521. //- T& insert(T&, c P&) T:{S}|{M} P:{S'}|{M'}
  522. //------------------------------------------------------------------------------
  523. template<class Type, class OperandT>
  524. typename enable_if<is_intra_combinable<Type, OperandT>, Type>::type&
  525. insert(Type& object, const OperandT& operand)
  526. {
  527. typename Type::iterator prior_ = object.end();
  528. ICL_const_FORALL(typename OperandT, elem_, operand)
  529. insert(object, prior_, *elem_);
  530. return object;
  531. }
  532. //==============================================================================
  533. //= Erasure<IntervalSet|IntervalSet>
  534. //==============================================================================
  535. //------------------------------------------------------------------------------
  536. //- T& erase(T&, c P&) T:{S}|{M} P:{S'}|{S' M'}
  537. //------------------------------------------------------------------------------
  538. template<class Type, class OperandT>
  539. typename enable_if<combines_right_to_interval_container<Type, OperandT>,
  540. Type>::type&
  541. erase(Type& object, const OperandT& operand)
  542. {
  543. typedef typename OperandT::const_iterator const_iterator;
  544. if(icl::is_empty(operand))
  545. return object;
  546. const_iterator common_lwb, common_upb;
  547. if(!Set::common_range(common_lwb, common_upb, operand, object))
  548. return object;
  549. const_iterator it_ = common_lwb;
  550. while(it_ != common_upb)
  551. icl::erase(object, *it_++);
  552. return object;
  553. }
  554. //==============================================================================
  555. //= Subtraction<IntervalSet|IntervalSet>
  556. //==============================================================================
  557. //------------------------------------------------------------------------------
  558. //- T& op -= (c P&) T:{M} P:{M'}
  559. //------------------------------------------------------------------------------
  560. /** \par \b Requires: Types \c Type and \c OperandT are subtractable.
  561. \par \b Effects: \c operand is subtracted from \c object.
  562. \par \b Returns: A reference to \c object.
  563. \b Complexity:
  564. \code
  565. \ OperandT: interval
  566. \ element segment container
  567. Type:
  568. interval container O(log n) O(n) O(m log(n+m))
  569. amortized
  570. interval_sets O(log n)
  571. n = object.interval_count()
  572. m = operand.interval_count()
  573. \endcode
  574. For the subtraction of \em elements, \b segments and \b interval \b containers
  575. complexity is \b logarithmic, \b linear and \b loglinear respectively.
  576. For interval sets subtraction of segments
  577. is \b amortized \b logarithmic.
  578. */
  579. template<class Type, class OperandT>
  580. typename enable_if<is_concept_compatible<is_interval_map, Type, OperandT>,
  581. Type>::type&
  582. operator -=(Type& object, const OperandT& operand)
  583. {
  584. ICL_const_FORALL(typename OperandT, elem_, operand)
  585. icl::subtract(object, *elem_);
  586. return object;
  587. }
  588. //------------------------------------------------------------------------------
  589. //- T& op -= (c P&) T:{S}|{M} P:{e i}|{b p}
  590. //------------------------------------------------------------------------------
  591. template<class Type, class OperandT>
  592. typename enable_if<is_intra_derivative<Type, OperandT>, Type>::type&
  593. operator -= (Type& object, const OperandT& operand)
  594. {
  595. return icl::subtract(object, operand);
  596. }
  597. //------------------------------------------------------------------------------
  598. //- T& op -= (c P&) T:{M} P:{e i}
  599. //------------------------------------------------------------------------------
  600. template<class Type, class OperandT>
  601. typename enable_if<is_cross_derivative<Type, OperandT>, Type>::type&
  602. operator -= (Type& object, const OperandT& operand)
  603. {
  604. return icl::erase(object, operand);
  605. }
  606. //------------------------------------------------------------------------------
  607. //- T& op -= (c P&) T:{S M} P:{S'}
  608. //------------------------------------------------------------------------------
  609. template<class Type, class IntervalSetT>
  610. typename enable_if<combines_right_to_interval_set<Type, IntervalSetT>,
  611. Type>::type&
  612. operator -= (Type& object, const IntervalSetT& operand)
  613. {
  614. return erase(object, operand);
  615. }
  616. #ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  617. //------------------------------------------------------------------------------
  618. //- T op - (T, c P&) T:{S}|{M} P:{e i S'}|{e i b p S' M'}
  619. //------------------------------------------------------------------------------
  620. template<class Type, class OperandT>
  621. typename enable_if<is_right_inter_combinable<Type, OperandT>, Type>::type
  622. operator - (Type object, const OperandT& operand)
  623. {
  624. return object -= operand;
  625. }
  626. #else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  627. template<class Type, class OperandT>
  628. typename enable_if<is_right_inter_combinable<Type, OperandT>, Type>::type
  629. operator - (const Type& object, const OperandT& operand)
  630. {
  631. Type temp = object;
  632. return boost::move(temp -= operand);
  633. }
  634. template<class Type, class OperandT>
  635. typename enable_if<is_right_inter_combinable<Type, OperandT>, Type>::type
  636. operator - (Type&& object, const OperandT& operand)
  637. {
  638. return boost::move(object -= operand);
  639. }
  640. #endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  641. //==============================================================================
  642. //= Intersection<IntervalSet|IntervalSet>
  643. //==============================================================================
  644. //------------------------------------------------------------------------------
  645. //- void add_intersection(T&, c T&, c P&) T:{S M} P:{S'}
  646. //------------------------------------------------------------------------------
  647. template<class Type, class OperandT>
  648. typename enable_if<mpl::and_<is_interval_set<Type>,
  649. combines_right_to_interval_set<Type, OperandT> >,
  650. void>::type
  651. add_intersection(Type& section, const Type& object, const OperandT& operand)
  652. {
  653. typedef typename OperandT::const_iterator const_iterator;
  654. if(operand.empty())
  655. return;
  656. const_iterator common_lwb, common_upb;
  657. if(!Set::common_range(common_lwb, common_upb, operand, object))
  658. return;
  659. const_iterator it_ = common_lwb;
  660. while(it_ != common_upb)
  661. icl::add_intersection(section, object, key_value<OperandT>(it_++));
  662. }
  663. //------------------------------------------------------------------------------
  664. //- T& op &=(T&, c P&) T:{S}|{M} P:{e i S'}|{e i b p S' M'}
  665. //------------------------------------------------------------------------------
  666. template<class Type, class OperandT>
  667. typename enable_if<is_right_inter_combinable<Type, OperandT>, Type>::type&
  668. operator &= (Type& object, const OperandT& operand)
  669. {
  670. Type intersection;
  671. add_intersection(intersection, object, operand);
  672. object.swap(intersection);
  673. return object;
  674. }
  675. #ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  676. //------------------------------------------------------------------------------
  677. //- T op & (T, c P&) T:{S}|{M} P:{e i S'}|{e i b p S' M'} S<S' M<M' <:coarser
  678. //------------------------------------------------------------------------------
  679. template<class Type, class OperandT>
  680. typename enable_if<is_binary_inter_combinable<Type, OperandT>, Type>::type
  681. operator & (Type object, const OperandT& operand)
  682. {
  683. return object &= operand;
  684. }
  685. #else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  686. template<class Type, class OperandT>
  687. typename enable_if<is_binary_inter_combinable<Type, OperandT>, Type>::type
  688. operator & (const Type& object, const OperandT& operand)
  689. {
  690. Type temp = object;
  691. return boost::move(temp &= operand);
  692. }
  693. template<class Type, class OperandT>
  694. typename enable_if<is_binary_inter_combinable<Type, OperandT>, Type>::type
  695. operator & (Type&& object, const OperandT& operand)
  696. {
  697. return boost::move(object &= operand);
  698. }
  699. #endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  700. #ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  701. //------------------------------------------------------------------------------
  702. //- T op & (c P&, T) T:{S}|{M} P:{e i S'}|{e i b p S' M'} S<S' M<M' <:coarser
  703. //------------------------------------------------------------------------------
  704. template<class Type, class OperandT>
  705. typename enable_if<is_binary_inter_combinable<Type, OperandT>, Type>::type
  706. operator & (const OperandT& operand, Type object)
  707. {
  708. return object &= operand;
  709. }
  710. #else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  711. template<class Type, class OperandT>
  712. typename enable_if<is_binary_inter_combinable<Type, OperandT>, Type>::type
  713. operator & (const OperandT& operand, const Type& object)
  714. {
  715. Type temp = object;
  716. return boost::move(temp &= operand);
  717. }
  718. template<class Type, class OperandT>
  719. typename enable_if<is_binary_inter_combinable<Type, OperandT>, Type>::type
  720. operator & (const OperandT& operand, Type&& object)
  721. {
  722. return boost::move(object &= operand);
  723. }
  724. #endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  725. #ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  726. //------------------------------------------------------------------------------
  727. //- T op & (T, c T&) T:{S M}
  728. //------------------------------------------------------------------------------
  729. template<class Type>
  730. typename enable_if<is_interval_container<Type>, Type>::type
  731. operator & (Type object, const Type& operand)
  732. {
  733. return object &= operand;
  734. }
  735. #else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  736. template<class Type>
  737. typename enable_if<is_interval_container<Type>, Type>::type
  738. operator & (const Type& object, const Type& operand)
  739. {
  740. Type temp = object;
  741. return boost::move(temp &= operand);
  742. }
  743. template<class Type>
  744. typename enable_if<is_interval_container<Type>, Type>::type
  745. operator & (Type&& object, const Type& operand)
  746. {
  747. return boost::move(object &= operand);
  748. }
  749. template<class Type>
  750. typename enable_if<is_interval_container<Type>, Type>::type
  751. operator & (const Type& operand, Type&& object)
  752. {
  753. return boost::move(object &= operand);
  754. }
  755. template<class Type>
  756. typename enable_if<is_interval_container<Type>, Type>::type
  757. operator & (Type&& object, Type&& operand)
  758. {
  759. return boost::move(object &= operand);
  760. }
  761. #endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  762. //------------------------------------------------------------------------------
  763. //- intersects<IntervalSet|IntervalMap>
  764. //------------------------------------------------------------------------------
  765. //------------------------------------------------------------------------------
  766. //- bool intersects(c T&, c P&) T:{S}|{M} P:{e i}
  767. //------------------------------------------------------------------------------
  768. template<class Type, class CoType>
  769. typename enable_if<mpl::and_< is_interval_container<Type>
  770. , boost::is_same<CoType, typename domain_type_of<Type>::type> >,
  771. bool>::type
  772. intersects(const Type& left, const CoType& right)
  773. {
  774. return icl::contains(left, right);
  775. }
  776. template<class Type, class CoType>
  777. typename enable_if<mpl::and_< is_interval_container<Type>
  778. , boost::is_same<CoType, typename interval_type_of<Type>::type> >,
  779. bool>::type
  780. intersects(const Type& left, const CoType& right)
  781. {
  782. return icl::find(left, right) != left.end();
  783. }
  784. template<class LeftT, class RightT>
  785. typename enable_if< mpl::and_< is_intra_combinable<LeftT, RightT>
  786. , mpl::or_<is_total<LeftT>, is_total<RightT> > >
  787. , bool>::type
  788. intersects(const LeftT&, const RightT&)
  789. {
  790. return true;
  791. }
  792. template<class LeftT, class RightT>
  793. typename enable_if< mpl::and_< is_intra_combinable<LeftT, RightT>
  794. , mpl::not_<mpl::or_< is_total<LeftT>
  795. , is_total<RightT> > > >
  796. , bool>::type
  797. intersects(const LeftT& left, const RightT& right)
  798. {
  799. typedef typename RightT::const_iterator const_iterator;
  800. LeftT intersection;
  801. const_iterator right_common_lower_, right_common_upper_;
  802. if(!Set::common_range(right_common_lower_, right_common_upper_, right, left))
  803. return false;
  804. const_iterator it_ = right_common_lower_;
  805. while(it_ != right_common_upper_)
  806. {
  807. icl::add_intersection(intersection, left, *it_++);
  808. if(!icl::is_empty(intersection))
  809. return true;
  810. }
  811. return false;
  812. }
  813. template<class LeftT, class RightT>
  814. typename enable_if<is_cross_combinable<LeftT, RightT>, bool>::type
  815. intersects(const LeftT& left, const RightT& right)
  816. {
  817. typedef typename RightT::const_iterator const_iterator;
  818. LeftT intersection;
  819. if(icl::is_empty(left) || icl::is_empty(right))
  820. return false;
  821. const_iterator right_common_lower_, right_common_upper_;
  822. if(!Set::common_range(right_common_lower_, right_common_upper_, right, left))
  823. return false;
  824. typename RightT::const_iterator it_ = right_common_lower_;
  825. while(it_ != right_common_upper_)
  826. {
  827. icl::add_intersection(intersection, left, key_value<RightT>(it_++));
  828. if(!icl::is_empty(intersection))
  829. return true;
  830. }
  831. return false;
  832. }
  833. /** \b Returns true, if \c left and \c right have no common elements.
  834. Intervals are interpreted as sequence of elements.
  835. \b Complexity: loglinear, if \c left and \c right are interval containers. */
  836. template<class LeftT, class RightT>
  837. typename enable_if<is_inter_combinable<LeftT, RightT>, bool>::type
  838. disjoint(const LeftT& left, const RightT& right)
  839. {
  840. return !intersects(left, right);
  841. }
  842. /** \b Returns true, if \c left and \c right have no common elements.
  843. Intervals are interpreted as sequence of elements.
  844. \b Complexity: logarithmic, if \c AssociateT is an element type \c Type::element_type.
  845. linear, if \c AssociateT is a segment type \c Type::segment_type. */
  846. template<class Type, class AssociateT>
  847. typename enable_if<is_inter_derivative<Type, AssociateT>, bool>::type
  848. disjoint(const Type& left, const AssociateT& right)
  849. {
  850. return !intersects(left,right);
  851. }
  852. //==============================================================================
  853. //= Symmetric difference<IntervalSet|IntervalSet>
  854. //==============================================================================
  855. //------------------------------------------------------------------------------
  856. //- Symmetric difference ^=, ^
  857. //------------------------------------------------------------------------------
  858. //------------------------------------------------------------------------------
  859. //- T& op ^=(T&, c P&) T:{S}|{M} P:{S'}|{M'}
  860. //------------------------------------------------------------------------------
  861. template<class Type, class OperandT>
  862. typename enable_if<is_intra_combinable<Type, OperandT>, Type>::type&
  863. operator ^= (Type& object, const OperandT& operand)
  864. {
  865. return icl::flip(object, operand);
  866. }
  867. //------------------------------------------------------------------------------
  868. //- T& op ^=(T&, c P&) T:{S}|{M} P:{e i}|{b p}
  869. //------------------------------------------------------------------------------
  870. template<class Type, class OperandT>
  871. typename enable_if<is_intra_derivative<Type, OperandT>, Type>::type&
  872. operator ^= (Type& object, const OperandT& operand)
  873. {
  874. return icl::flip(object, operand);
  875. }
  876. #ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  877. //------------------------------------------------------------------------------
  878. //- T op ^ (T, c P&) T:{S}|{M} P:{e i S'}|{b p M'} S<S' M<M' <:coarser
  879. //------------------------------------------------------------------------------
  880. template<class Type, class OperandT>
  881. typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
  882. operator ^ (Type object, const OperandT& operand)
  883. {
  884. return object ^= operand;
  885. }
  886. #else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  887. template<class Type, class OperandT>
  888. typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
  889. operator ^ (const Type& object, const OperandT& operand)
  890. {
  891. Type temp = object;
  892. return boost::move(temp ^= operand);
  893. }
  894. template<class Type, class OperandT>
  895. typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
  896. operator ^ (Type&& object, const OperandT& operand)
  897. {
  898. return boost::move(object ^= operand);
  899. }
  900. #endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  901. #ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  902. //------------------------------------------------------------------------------
  903. //- T op ^ (c P&, T) T:{S}|{M} P:{e i S'}|{b p M'} S<S' M<M' <:coarser
  904. //------------------------------------------------------------------------------
  905. template<class Type, class OperandT>
  906. typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
  907. operator ^ (const OperandT& operand, Type object)
  908. {
  909. return object ^= operand;
  910. }
  911. #else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  912. template<class Type, class OperandT>
  913. typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
  914. operator ^ (const OperandT& operand, const Type& object)
  915. {
  916. Type temp = object;
  917. return boost::move(temp ^= operand);
  918. }
  919. template<class Type, class OperandT>
  920. typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
  921. operator ^ (const OperandT& operand, Type&& object)
  922. {
  923. return boost::move(object ^= operand);
  924. }
  925. #endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  926. #ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  927. //------------------------------------------------------------------------------
  928. //- T op ^ (T, c T&) T:{S M}
  929. //------------------------------------------------------------------------------
  930. template<class Type>
  931. typename enable_if<is_interval_container<Type>, Type>::type
  932. operator ^ (typename Type::overloadable_type object, const Type& operand)
  933. {
  934. return object ^= operand;
  935. }
  936. #else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  937. template<class Type>
  938. typename enable_if<is_interval_container<Type>, Type>::type
  939. operator ^ (const Type& object, const Type& operand)
  940. {
  941. Type temp = object;
  942. return boost::move(temp ^= operand);
  943. }
  944. template<class Type>
  945. typename enable_if<is_interval_container<Type>, Type>::type
  946. operator ^ (Type&& object, const Type& operand)
  947. {
  948. return boost::move(object ^= operand);
  949. }
  950. template<class Type>
  951. typename enable_if<is_interval_container<Type>, Type>::type
  952. operator ^ (const Type& operand, Type&& object)
  953. {
  954. return boost::move(object ^= operand);
  955. }
  956. template<class Type>
  957. typename enable_if<is_interval_container<Type>, Type>::type
  958. operator ^ (Type&& object, Type&& operand)
  959. {
  960. return boost::move(object ^= operand);
  961. }
  962. #endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
  963. //==========================================================================
  964. //= Element Iteration <IntervalSet|IntervalMap>
  965. //==========================================================================
  966. //--------------------------------------------------------------------------
  967. //- Forward
  968. //--------------------------------------------------------------------------
  969. template<class Type>
  970. typename enable_if
  971. <mpl::and_< is_interval_container<Type>
  972. , mpl::not_<is_continuous_interval<typename Type::interval_type> > >,
  973. typename Type::element_iterator>::type
  974. elements_begin(Type& object)
  975. {
  976. return typename Type::element_iterator(object.begin());
  977. }
  978. template<class Type>
  979. typename enable_if
  980. <mpl::and_< is_interval_container<Type>
  981. , mpl::not_<is_continuous_interval<typename Type::interval_type> > >,
  982. typename Type::element_iterator>::type
  983. elements_end(Type& object)
  984. {
  985. return typename Type::element_iterator(object.end());
  986. }
  987. template<class Type>
  988. typename enable_if
  989. <mpl::and_< is_interval_container<Type>
  990. , mpl::not_<is_continuous_interval<typename Type::interval_type> > >,
  991. typename Type::element_const_iterator>::type
  992. elements_begin(const Type& object)
  993. {
  994. return typename Type::element_const_iterator(object.begin());
  995. }
  996. template<class Type>
  997. typename enable_if
  998. <mpl::and_< is_interval_container<Type>
  999. , mpl::not_<is_continuous_interval<typename Type::interval_type> > >,
  1000. typename Type::element_const_iterator>::type
  1001. elements_end(const Type& object)
  1002. {
  1003. return typename Type::element_const_iterator(object.end());
  1004. }
  1005. //--------------------------------------------------------------------------
  1006. //- Reverse
  1007. //--------------------------------------------------------------------------
  1008. template<class Type>
  1009. typename enable_if
  1010. <mpl::and_< is_interval_container<Type>
  1011. , mpl::not_<is_continuous_interval<typename Type::interval_type> > >,
  1012. typename Type::element_reverse_iterator>::type
  1013. elements_rbegin(Type& object)
  1014. {
  1015. return typename Type::element_reverse_iterator(object.rbegin());
  1016. }
  1017. template<class Type>
  1018. typename enable_if
  1019. <mpl::and_< is_interval_container<Type>
  1020. , mpl::not_<is_continuous_interval<typename Type::interval_type> > >,
  1021. typename Type::element_reverse_iterator>::type
  1022. elements_rend(Type& object)
  1023. {
  1024. return typename Type::element_reverse_iterator(object.rend());
  1025. }
  1026. template<class Type>
  1027. typename enable_if
  1028. <mpl::and_< is_interval_container<Type>
  1029. , mpl::not_<is_continuous_interval<typename Type::interval_type> > >,
  1030. typename Type::element_const_reverse_iterator>::type
  1031. elements_rbegin(const Type& object)
  1032. {
  1033. return typename Type::element_const_reverse_iterator(object.rbegin());
  1034. }
  1035. template<class Type>
  1036. typename enable_if
  1037. <mpl::and_< is_interval_container<Type>
  1038. , mpl::not_<is_continuous_interval<typename Type::interval_type> > >,
  1039. typename Type::element_const_reverse_iterator>::type
  1040. elements_rend(const Type& object)
  1041. {
  1042. return typename Type::element_const_reverse_iterator(object.rend());
  1043. }
  1044. }} // namespace boost icl
  1045. #endif