interval_map.hpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677
  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_MAP_HPP_JOFA_100920
  9. #define BOOST_ICL_CONCEPT_INTERVAL_MAP_HPP_JOFA_100920
  10. #include <boost/icl/type_traits/element_type_of.hpp>
  11. #include <boost/icl/type_traits/segment_type_of.hpp>
  12. #include <boost/icl/type_traits/absorbs_identities.hpp>
  13. #include <boost/icl/type_traits/is_combinable.hpp>
  14. #include <boost/icl/type_traits/is_interval_splitter.hpp>
  15. #include <boost/icl/detail/set_algo.hpp>
  16. #include <boost/icl/detail/interval_map_algo.hpp>
  17. #include <boost/icl/concept/interval.hpp>
  18. #include <boost/icl/concept/joinable.hpp>
  19. namespace boost{ namespace icl
  20. {
  21. template<class Type>
  22. inline typename enable_if<is_interval_map<Type>, typename Type::segment_type>::type
  23. make_segment(const typename Type::element_type& element)
  24. {
  25. typedef typename Type::interval_type interval_type;
  26. typedef typename Type::segment_type segment_type;
  27. return segment_type(icl::singleton<interval_type>(element.key), element.data);
  28. }
  29. //==============================================================================
  30. //= Containedness<IntervalMap>
  31. //==============================================================================
  32. //------------------------------------------------------------------------------
  33. //- bool contains(c T&, c P&) T:{M} P:{b p M} fragment_types
  34. //------------------------------------------------------------------------------
  35. template<class Type>
  36. typename enable_if<is_interval_map<Type>, bool>::type
  37. contains(const Type& super, const typename Type::element_type& key_value_pair)
  38. {
  39. typedef typename Type::const_iterator const_iterator;
  40. const_iterator it_ = icl::find(super, key_value_pair.key);
  41. return it_ != super.end() && (*it_).second == key_value_pair.data;
  42. }
  43. template<class Type>
  44. typename enable_if<is_interval_map<Type>, bool>::type
  45. contains(const Type& super, const typename Type::segment_type& sub_segment)
  46. {
  47. typedef typename Type::interval_type interval_type;
  48. typedef typename Type::const_iterator const_iterator;
  49. interval_type sub_interval = sub_segment.first;
  50. if(icl::is_empty(sub_interval))
  51. return true;
  52. std::pair<const_iterator, const_iterator> exterior = super.equal_range(sub_interval);
  53. if(exterior.first == exterior.second)
  54. return false;
  55. const_iterator last_overlap = prior(exterior.second);
  56. if(!(sub_segment.second == exterior.first->second) )
  57. return false;
  58. return
  59. icl::contains(hull(exterior.first->first, last_overlap->first), sub_interval)
  60. && Interval_Map::is_joinable(super, exterior.first, last_overlap);
  61. }
  62. template<class Type, class CoType>
  63. typename enable_if<is_concept_compatible<is_interval_map, Type, CoType>, bool>::type
  64. contains(const Type& super, const CoType& sub)
  65. {
  66. return Interval_Set::within(sub, super);
  67. }
  68. //------------------------------------------------------------------------------
  69. //- bool contains(c T&, c P&) T:{M} P:{e i S} key_types : total
  70. //------------------------------------------------------------------------------
  71. template<class Type, class CoType>
  72. typename enable_if< mpl::and_< is_interval_map<Type>
  73. , is_total<Type>
  74. , is_cross_derivative<Type, CoType> >
  75. , bool>::type
  76. contains(const Type&, const CoType&)
  77. {
  78. return true;
  79. }
  80. //------------------------------------------------------------------------------
  81. //- bool contains(c T&, c P&) T:{M} P:{e i S} key_types : partial
  82. //------------------------------------------------------------------------------
  83. template<class Type>
  84. typename enable_if< mpl::and_< is_interval_map<Type>
  85. , mpl::not_<is_total<Type> > >
  86. , bool>::type
  87. contains(const Type& super, const typename Type::domain_type& key)
  88. {
  89. return icl::find(super, key) != super.end();
  90. }
  91. template<class Type>
  92. typename enable_if< mpl::and_< is_interval_map<Type>
  93. , mpl::not_<is_total<Type> > >
  94. , bool>::type
  95. contains(const Type& super, const typename Type::interval_type& sub_interval)
  96. {
  97. typedef typename Type::const_iterator const_iterator;
  98. if(icl::is_empty(sub_interval))
  99. return true;
  100. std::pair<const_iterator, const_iterator> exterior = super.equal_range(sub_interval);
  101. if(exterior.first == exterior.second)
  102. return false;
  103. const_iterator last_overlap = prior(exterior.second);
  104. return
  105. icl::contains(hull(exterior.first->first, last_overlap->first), sub_interval)
  106. && Interval_Set::is_joinable(super, exterior.first, last_overlap);
  107. }
  108. template<class Type, class KeyT>
  109. typename enable_if< mpl::and_< is_concept_combinable<is_interval_map, is_interval_set, Type, KeyT>
  110. , mpl::not_<is_total<Type> > >
  111. , bool>::type
  112. contains(const Type& super, const KeyT& sub)
  113. {
  114. return Interval_Set::within(sub, super);
  115. }
  116. //==============================================================================
  117. //= Addition<IntervalMap>
  118. //==============================================================================
  119. //------------------------------------------------------------------------------
  120. //- T& add(T&, c P&) T:{M} P:{b p} fragment_types
  121. //------------------------------------------------------------------------------
  122. template<class Type>
  123. typename enable_if<is_interval_map<Type>, Type>::type&
  124. add(Type& object, const typename Type::segment_type& operand)
  125. {
  126. return object.add(operand);
  127. }
  128. template<class Type>
  129. typename enable_if<is_interval_map<Type>, Type>::type&
  130. add(Type& object, const typename Type::element_type& operand)
  131. {
  132. return icl::add(object, make_segment<Type>(operand));
  133. }
  134. //------------------------------------------------------------------------------
  135. //- T& add(T&, J, c P&) T:{M} P:{p} segment_type
  136. //------------------------------------------------------------------------------
  137. template<class Type>
  138. typename enable_if<is_interval_map<Type>, typename Type::iterator >::type
  139. add(Type& object, typename Type::iterator prior_,
  140. const typename Type::segment_type& operand)
  141. {
  142. return object.add(prior_, operand);
  143. }
  144. //==============================================================================
  145. //= Insertion<IntervalMap>
  146. //==============================================================================
  147. //------------------------------------------------------------------------------
  148. //- T& insert(T&, c P&) T:{M} P:{b p} fragment_types
  149. //------------------------------------------------------------------------------
  150. template<class Type>
  151. typename enable_if<is_interval_map<Type>, Type>::type&
  152. insert(Type& object, const typename Type::segment_type& operand)
  153. {
  154. return object.insert(operand);
  155. }
  156. template<class Type>
  157. inline typename enable_if<is_interval_map<Type>, Type>::type&
  158. insert(Type& object, const typename Type::element_type& operand)
  159. {
  160. return icl::insert(object, make_segment<Type>(operand));
  161. }
  162. //------------------------------------------------------------------------------
  163. //- T& insert(T&, J, c P&) T:{M} P:{p} with hint
  164. //------------------------------------------------------------------------------
  165. template<class Type>
  166. typename enable_if<is_interval_map<Type>, typename Type::iterator>::type
  167. insert(Type& object, typename Type::iterator prior,
  168. const typename Type::segment_type& operand)
  169. {
  170. return object.insert(prior, operand);
  171. }
  172. //==============================================================================
  173. //= Erasure<IntervalMap>
  174. //==============================================================================
  175. //------------------------------------------------------------------------------
  176. //- T& erase(T&, c P&) T:{M} P:{e i} key_types
  177. //------------------------------------------------------------------------------
  178. template<class Type>
  179. typename enable_if<is_interval_map<Type>, Type>::type&
  180. erase(Type& object, const typename Type::interval_type& operand)
  181. {
  182. return object.erase(operand);
  183. }
  184. template<class Type>
  185. typename enable_if<is_interval_map<Type>, Type>::type&
  186. erase(Type& object, const typename Type::domain_type& operand)
  187. {
  188. typedef typename Type::interval_type interval_type;
  189. return icl::erase(object, icl::singleton<interval_type>(operand));
  190. }
  191. //------------------------------------------------------------------------------
  192. //- T& erase(T&, c P&) T:{M} P:{b p} fragment_types
  193. //------------------------------------------------------------------------------
  194. template<class Type>
  195. typename enable_if<is_interval_map<Type>, Type>::type&
  196. erase(Type& object, const typename Type::segment_type& operand)
  197. {
  198. return object.erase(operand);
  199. }
  200. template<class Type>
  201. inline typename enable_if<is_interval_map<Type>, Type>::type&
  202. erase(Type& object, const typename Type::element_type& operand)
  203. {
  204. return icl::erase(object, make_segment<Type>(operand));
  205. }
  206. //==============================================================================
  207. //= Subtraction<IntervalMap>
  208. //==============================================================================
  209. //------------------------------------------------------------------------------
  210. //- T& subtract(T&, c P&) T:{M} P:{b p} fragment_types
  211. //------------------------------------------------------------------------------
  212. template<class Type>
  213. typename enable_if<is_interval_map<Type>, Type>::type&
  214. subtract(Type& object, const typename Type::segment_type& operand)
  215. {
  216. return object.subtract(operand);
  217. }
  218. template<class Type>
  219. typename enable_if<is_interval_map<Type>, Type>::type&
  220. subtract(Type& object, const typename Type::element_type& operand)
  221. {
  222. return icl::subtract(object, make_segment<Type>(operand));
  223. }
  224. //------------------------------------------------------------------------------
  225. //- T& subtract(T&, c P&) T:{M} P:{e i} key_types
  226. //------------------------------------------------------------------------------
  227. template<class Type>
  228. typename enable_if<is_interval_map<Type>, Type>::type&
  229. subtract(Type& object, const typename Type::domain_type& operand)
  230. {
  231. return object.erase(operand);
  232. }
  233. template<class Type>
  234. typename enable_if<is_interval_map<Type>, Type>::type&
  235. subtract(Type& object, const typename Type::interval_type& operand)
  236. {
  237. return object.erase(operand);
  238. }
  239. //==============================================================================
  240. //= Selective Update<IntervalMap>
  241. //==============================================================================
  242. //------------------------------------------------------------------------------
  243. //- T& set_at(T&, c P&) T:{M} P:{e i}
  244. //------------------------------------------------------------------------------
  245. template<class Type>
  246. typename enable_if<is_interval_map<Type>, Type>::type&
  247. set_at(Type& object, const typename Type::segment_type& operand)
  248. {
  249. icl::erase(object, operand.first);
  250. return icl::insert(object, operand);
  251. }
  252. template<class Type>
  253. typename enable_if<is_interval_map<Type>, Type>::type&
  254. set_at(Type& object, const typename Type::element_type& operand)
  255. {
  256. return icl::set_at(object, make_segment<Type>(operand));
  257. }
  258. //==============================================================================
  259. //= Intersection<IntervalMap>
  260. //==============================================================================
  261. //------------------------------------------------------------------------------
  262. //- T& subtract(T&, c P&) T:{M} P:{b p} fragment_type
  263. //------------------------------------------------------------------------------
  264. template<class Type>
  265. typename enable_if<is_interval_map<Type>, void>::type
  266. add_intersection(Type& section, const Type& object,
  267. const typename Type::element_type& operand)
  268. {
  269. //CL typedef typename Type::segment_type segment_type;
  270. object.add_intersection(section, make_segment<Type>(operand));
  271. }
  272. template<class Type>
  273. typename enable_if<is_interval_map<Type>, void>::type
  274. add_intersection(Type& section, const Type& object,
  275. const typename Type::segment_type& operand)
  276. {
  277. object.add_intersection(section, operand);
  278. }
  279. //------------------------------------------------------------------------------
  280. //- T& subtract(T&, c P&) T:{M} P:{M'} map fragment_type total
  281. //------------------------------------------------------------------------------
  282. template<class Type, class MapT>
  283. typename enable_if
  284. <
  285. mpl::and_< is_total<Type>
  286. , is_concept_compatible<is_interval_map, Type, MapT> >
  287. , void
  288. >::type
  289. add_intersection(Type& section, const Type& object, const MapT& operand)
  290. {
  291. section += object;
  292. section += operand;
  293. }
  294. //------------------------------------------------------------------------------
  295. //- T& subtract(T&, c P&) T:{M} P:{M'} map fragment_type partial
  296. //------------------------------------------------------------------------------
  297. template<class Type, class MapT>
  298. typename enable_if
  299. <
  300. mpl::and_< mpl::not_<is_total<Type> >
  301. , is_concept_compatible<is_interval_map, Type, MapT> >
  302. , void
  303. >::type
  304. add_intersection(Type& section, const Type& object, const MapT& operand)
  305. {
  306. //CL typedef typename Type::segment_type segment_type;
  307. //CL typedef typename Type::interval_type interval_type;
  308. typedef typename MapT::const_iterator const_iterator;
  309. if(operand.empty())
  310. return;
  311. const_iterator common_lwb, common_upb;
  312. if(!Set::common_range(common_lwb, common_upb, operand, object))
  313. return;
  314. const_iterator it_ = common_lwb;
  315. while(it_ != common_upb)
  316. add_intersection(section, object, *it_++);
  317. }
  318. //------------------------------------------------------------------------------
  319. //- T& subtract(T&, c P&) T:{M} P:{e i S} key_type
  320. //------------------------------------------------------------------------------
  321. template<class Type>
  322. typename enable_if<is_interval_map<Type>, void>::type
  323. add_intersection(Type& section, const Type& object,
  324. const typename Type::domain_type& key_value)
  325. {
  326. typedef typename Type::interval_type interval_type;
  327. typedef typename Type::segment_type segment_type;
  328. typedef typename Type::const_iterator const_iterator;
  329. const_iterator it_ = icl::find(object, key_value);
  330. if(it_ != object.end())
  331. add(section, segment_type(interval_type(key_value),(*it_).second));
  332. }
  333. template<class Type>
  334. typename enable_if<is_interval_map<Type>, void>::type
  335. add_intersection(Type& section, const Type& object,
  336. const typename Type::interval_type& inter_val)
  337. {
  338. typedef typename Type::interval_type interval_type;
  339. typedef typename Type::value_type value_type;
  340. typedef typename Type::const_iterator const_iterator;
  341. typedef typename Type::iterator iterator;
  342. if(icl::is_empty(inter_val))
  343. return;
  344. std::pair<const_iterator, const_iterator> exterior
  345. = object.equal_range(inter_val);
  346. if(exterior.first == exterior.second)
  347. return;
  348. iterator prior_ = section.end();
  349. for(const_iterator it_=exterior.first; it_ != exterior.second; it_++)
  350. {
  351. interval_type common_interval = (*it_).first & inter_val;
  352. if(!icl::is_empty(common_interval))
  353. prior_ = add(section, prior_,
  354. value_type(common_interval, (*it_).second) );
  355. }
  356. }
  357. template<class Type, class KeySetT>
  358. typename enable_if<is_concept_combinable<is_interval_map, is_interval_set, Type, KeySetT>, void>::type
  359. add_intersection(Type& section, const Type& object, const KeySetT& key_set)
  360. {
  361. typedef typename KeySetT::const_iterator const_iterator;
  362. if(icl::is_empty(key_set))
  363. return;
  364. const_iterator common_lwb, common_upb;
  365. if(!Set::common_range(common_lwb, common_upb, key_set, object))
  366. return;
  367. const_iterator it_ = common_lwb;
  368. while(it_ != common_upb)
  369. add_intersection(section, object, *it_++);
  370. }
  371. //------------------------------------------------------------------------------
  372. //- intersects<IntervalMaps> fragment_types
  373. //------------------------------------------------------------------------------
  374. template<class Type, class OperandT>
  375. typename enable_if<mpl::and_< is_interval_map<Type>
  376. , is_total<Type>
  377. , boost::is_same< OperandT
  378. , typename segment_type_of<Type>::type> >,
  379. bool>::type
  380. intersects(const Type&, const OperandT&)
  381. {
  382. return true;
  383. }
  384. template<class Type, class OperandT>
  385. typename enable_if<mpl::and_< is_interval_map<Type>
  386. , mpl::not_<is_total<Type> >
  387. , boost::is_same<OperandT, typename segment_type_of<Type>::type> >,
  388. bool>::type
  389. intersects(const Type& object, const OperandT& operand)
  390. {
  391. Type intersection;
  392. icl::add_intersection(intersection, object, operand);
  393. return !icl::is_empty(intersection);
  394. }
  395. template<class Type, class OperandT>
  396. typename enable_if<mpl::and_< is_interval_map<Type>
  397. , boost::is_same<OperandT, typename element_type_of<Type>::type> >,
  398. bool>::type
  399. intersects(const Type& object, const OperandT& operand)
  400. {
  401. return icl::intersects(object, make_segment<Type>(operand));
  402. }
  403. //==============================================================================
  404. //= Symmetric difference<IntervalMap>
  405. //==============================================================================
  406. //------------------------------------------------------------------------------
  407. //- T& flip(T&, c P&) T:{M} P:{b p} fragment_types
  408. //------------------------------------------------------------------------------
  409. template<class Type>
  410. typename enable_if<is_interval_map<Type>, Type>::type&
  411. flip(Type& object, const typename Type::segment_type& operand)
  412. {
  413. return object.flip(operand);
  414. }
  415. template<class Type>
  416. inline typename enable_if<is_interval_map<Type>, Type>::type&
  417. flip(Type& object, const typename Type::element_type& operand)
  418. {
  419. return icl::flip(object, make_segment<Type>(operand));
  420. }
  421. //------------------------------------------------------------------------------
  422. //- T& flip(T&, c P&) T:{M} P:{M'} total absorber
  423. //------------------------------------------------------------------------------
  424. template<class Type, class OperandT>
  425. typename enable_if< mpl::and_< is_total<Type>
  426. , absorbs_identities<Type>
  427. , is_concept_compatible<is_interval_map,
  428. Type, OperandT >
  429. >
  430. , Type>::type&
  431. flip(Type& object, const OperandT&)
  432. {
  433. object.clear();
  434. return object;
  435. }
  436. //------------------------------------------------------------------------------
  437. //- T& flip(T&, c P&) T:{M} P:{M'} total enricher
  438. //------------------------------------------------------------------------------
  439. #ifdef BOOST_MSVC
  440. #pragma warning(push)
  441. #pragma warning(disable:4127) // conditional expression is constant
  442. #endif
  443. template<class Type, class OperandT>
  444. typename enable_if< mpl::and_< is_total<Type>
  445. , mpl::not_<absorbs_identities<Type> >
  446. , is_concept_compatible<is_interval_map,
  447. Type, OperandT >
  448. >
  449. , Type>::type&
  450. flip(Type& object, const OperandT& operand)
  451. {
  452. typedef typename Type::codomain_type codomain_type;
  453. object += operand;
  454. ICL_FORALL(typename Type, it_, object)
  455. (*it_).second = identity_element<codomain_type>::value();
  456. if(mpl::not_<is_interval_splitter<Type> >::value)
  457. icl::join(object);
  458. return object;
  459. }
  460. #ifdef BOOST_MSVC
  461. #pragma warning(pop)
  462. #endif
  463. //------------------------------------------------------------------------------
  464. //- T& flip(T&, c P&) T:{M} P:{M'} partial
  465. //------------------------------------------------------------------------------
  466. template<class Type, class OperandT>
  467. typename enable_if< mpl::and_< mpl::not_<is_total<Type> >
  468. , is_concept_compatible<is_interval_map,
  469. Type, OperandT >
  470. >
  471. , Type>::type&
  472. flip(Type& object, const OperandT& operand)
  473. {
  474. typedef typename OperandT::const_iterator const_iterator;
  475. //CL typedef typename Type::codomain_type codomain_type;
  476. const_iterator common_lwb, common_upb;
  477. if(!Set::common_range(common_lwb, common_upb, operand, object))
  478. return object += operand;
  479. const_iterator it_ = operand.begin();
  480. // All elements of operand left of the common range are added
  481. while(it_ != common_lwb)
  482. icl::add(object, *it_++);
  483. // All elements of operand in the common range are symmetrically subtracted
  484. while(it_ != common_upb)
  485. icl::flip(object, *it_++);
  486. // All elements of operand right of the common range are added
  487. while(it_ != operand.end())
  488. icl::add(object, *it_++);
  489. return object;
  490. }
  491. //==============================================================================
  492. //= Set selection
  493. //==============================================================================
  494. template<class Type, class SetT>
  495. typename enable_if<is_concept_combinable<is_interval_set, is_interval_map,
  496. SetT, Type>, SetT>::type&
  497. domain(SetT& result, const Type& object)
  498. {
  499. typedef typename SetT::iterator set_iterator;
  500. result.clear();
  501. set_iterator prior_ = result.end();
  502. ICL_const_FORALL(typename Type, it_, object)
  503. prior_ = icl::insert(result, prior_, (*it_).first);
  504. return result;
  505. }
  506. template<class Type, class SetT>
  507. typename enable_if<is_concept_combinable<is_interval_set, is_interval_map,
  508. SetT, Type>, SetT>::type&
  509. between(SetT& in_between, const Type& object)
  510. {
  511. typedef typename Type::const_iterator const_iterator;
  512. typedef typename SetT::iterator set_iterator;
  513. in_between.clear();
  514. const_iterator it_ = object.begin(), pred_;
  515. set_iterator prior_ = in_between.end();
  516. if(it_ != object.end())
  517. pred_ = it_++;
  518. while(it_ != object.end())
  519. prior_ = icl::insert(in_between, prior_,
  520. between((*pred_++).first, (*it_++).first));
  521. return in_between;
  522. }
  523. //==============================================================================
  524. //= Manipulation by predicates
  525. //==============================================================================
  526. template<class MapT, class Predicate>
  527. typename enable_if<is_interval_map<MapT>, MapT>::type&
  528. erase_if(const Predicate& pred, MapT& object)
  529. {
  530. typename MapT::iterator it_ = object.begin();
  531. while(it_ != object.end())
  532. if(pred(*it_))
  533. object.erase(it_++);
  534. else ++it_;
  535. return object;
  536. }
  537. template<class MapT, class Predicate>
  538. inline typename enable_if<is_interval_map<MapT>, MapT>::type&
  539. add_if(const Predicate& pred, MapT& object, const MapT& src)
  540. {
  541. typename MapT::const_iterator it_ = src.begin();
  542. while(it_ != src.end())
  543. if(pred(*it_))
  544. icl::add(object, *it_++);
  545. return object;
  546. }
  547. template<class MapT, class Predicate>
  548. inline typename enable_if<is_interval_map<MapT>, MapT>::type&
  549. assign_if(const Predicate& pred, MapT& object, const MapT& src)
  550. {
  551. icl::clear(object);
  552. return add_if(object, src, pred);
  553. }
  554. //==============================================================================
  555. //= Morphisms
  556. //==============================================================================
  557. template<class Type>
  558. typename enable_if<mpl::and_< is_interval_map<Type>
  559. , absorbs_identities<Type> >, Type>::type&
  560. absorb_identities(Type& object)
  561. {
  562. return object;
  563. }
  564. template<class Type>
  565. typename enable_if<mpl::and_< is_interval_map<Type>
  566. , mpl::not_<absorbs_identities<Type> > >, Type>::type&
  567. absorb_identities(Type& object)
  568. {
  569. typedef typename Type::segment_type segment_type;
  570. return icl::erase_if(content_is_identity_element<segment_type>(), object);
  571. }
  572. //==============================================================================
  573. //= Streaming
  574. //==============================================================================
  575. template<class CharType, class CharTraits, class Type>
  576. typename enable_if<is_interval_map<Type>,
  577. std::basic_ostream<CharType, CharTraits> >::type&
  578. operator << (std::basic_ostream<CharType, CharTraits>& stream, const Type& object)
  579. {
  580. stream << "{";
  581. ICL_const_FORALL(typename Type, it_, object)
  582. stream << "(" << (*it_).first << "->" << (*it_).second << ")";
  583. return stream << "}";
  584. }
  585. }} // namespace boost icl
  586. #endif