interval.hpp 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509
  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_HPP_JOFA_100323
  9. #define BOOST_ICL_CONCEPT_INTERVAL_HPP_JOFA_100323
  10. #include <boost/assert.hpp>
  11. #include <boost/core/ignore_unused.hpp>
  12. #include <boost/utility/enable_if.hpp>
  13. #include <boost/mpl/and.hpp>
  14. #include <boost/mpl/or.hpp>
  15. #include <boost/mpl/not.hpp>
  16. #include <boost/icl/detail/design_config.hpp>
  17. #include <boost/icl/type_traits/unit_element.hpp>
  18. #include <boost/icl/type_traits/identity_element.hpp>
  19. #include <boost/icl/type_traits/infinity.hpp>
  20. #include <boost/icl/type_traits/succ_pred.hpp>
  21. #include <boost/icl/type_traits/is_numeric.hpp>
  22. #include <boost/icl/type_traits/is_discrete.hpp>
  23. #include <boost/icl/type_traits/is_continuous.hpp>
  24. #include <boost/icl/type_traits/is_asymmetric_interval.hpp>
  25. #include <boost/icl/type_traits/is_discrete_interval.hpp>
  26. #include <boost/icl/type_traits/is_continuous_interval.hpp>
  27. #include <boost/icl/concept/interval_bounds.hpp>
  28. #include <boost/icl/interval_traits.hpp>
  29. #include <boost/icl/dynamic_interval_traits.hpp>
  30. #include <algorithm>
  31. namespace boost{namespace icl
  32. {
  33. //==============================================================================
  34. //= Ordering
  35. //==============================================================================
  36. template<class Type>
  37. inline typename enable_if<is_interval<Type>, bool>::type
  38. domain_less(const typename interval_traits<Type>::domain_type& left,
  39. const typename interval_traits<Type>::domain_type& right)
  40. {
  41. return typename interval_traits<Type>::domain_compare()(left, right);
  42. }
  43. template<class Type>
  44. inline typename enable_if<is_interval<Type>, bool>::type
  45. domain_less_equal(const typename interval_traits<Type>::domain_type& left,
  46. const typename interval_traits<Type>::domain_type& right)
  47. {
  48. return !(typename interval_traits<Type>::domain_compare()(right, left));
  49. }
  50. template<class Type>
  51. inline typename enable_if<is_interval<Type>, bool>::type
  52. domain_equal(const typename interval_traits<Type>::domain_type& left,
  53. const typename interval_traits<Type>::domain_type& right)
  54. {
  55. typedef typename interval_traits<Type>::domain_compare domain_compare;
  56. return !(domain_compare()(left, right)) && !(domain_compare()(right, left));
  57. }
  58. template<class Type>
  59. inline typename enable_if< is_interval<Type>
  60. , typename interval_traits<Type>::domain_type>::type
  61. domain_next(const typename interval_traits<Type>::domain_type value)
  62. {
  63. typedef typename interval_traits<Type>::domain_type domain_type;
  64. typedef typename interval_traits<Type>::domain_compare domain_compare;
  65. return icl::successor<domain_type,domain_compare>::apply(value);
  66. }
  67. template<class Type>
  68. inline typename enable_if< is_interval<Type>
  69. , typename interval_traits<Type>::domain_type>::type
  70. domain_prior(const typename interval_traits<Type>::domain_type value)
  71. {
  72. typedef typename interval_traits<Type>::domain_type domain_type;
  73. typedef typename interval_traits<Type>::domain_compare domain_compare;
  74. return icl::predecessor<domain_type,domain_compare>::apply(value);
  75. }
  76. //==============================================================================
  77. //= Construct<Interval> singleton
  78. //==============================================================================
  79. template<class Type>
  80. typename enable_if
  81. <
  82. mpl::and_< is_static_right_open<Type>
  83. , is_discrete<typename interval_traits<Type>::domain_type> >
  84. , Type
  85. >::type
  86. singleton(const typename interval_traits<Type>::domain_type& value)
  87. {
  88. //ASSERT: This always creates an interval with exactly one element
  89. return interval_traits<Type>::construct(value, domain_next<Type>(value));
  90. }
  91. template<class Type>
  92. typename enable_if
  93. <
  94. mpl::and_< is_static_left_open<Type>
  95. , is_discrete<typename interval_traits<Type>::domain_type> >
  96. , Type
  97. >::type
  98. singleton(const typename interval_traits<Type>::domain_type& value)
  99. {
  100. //ASSERT: This always creates an interval with exactly one element
  101. typedef typename interval_traits<Type>::domain_type domain_type;
  102. typedef typename interval_traits<Type>::domain_compare domain_compare;
  103. BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
  104. ::is_less_than(value) ));
  105. boost::ignore_unused<domain_type, domain_compare>();
  106. return interval_traits<Type>::construct(domain_prior<Type>(value), value);
  107. }
  108. template<class Type>
  109. typename enable_if<is_discrete_static_open<Type>, Type>::type
  110. singleton(const typename interval_traits<Type>::domain_type& value)
  111. {
  112. //ASSERT: This always creates an interval with exactly one element
  113. typedef typename interval_traits<Type>::domain_type domain_type;
  114. typedef typename interval_traits<Type>::domain_compare domain_compare;
  115. BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
  116. ::is_less_than(value)));
  117. boost::ignore_unused<domain_type, domain_compare>();
  118. return interval_traits<Type>::construct( domain_prior<Type>(value)
  119. , domain_next<Type>(value));
  120. }
  121. template<class Type>
  122. typename enable_if<is_discrete_static_closed<Type>, Type>::type
  123. singleton(const typename interval_traits<Type>::domain_type& value)
  124. {
  125. //ASSERT: This always creates an interval with exactly one element
  126. return interval_traits<Type>::construct(value, value);
  127. }
  128. template<class Type>
  129. typename enable_if<has_dynamic_bounds<Type>, Type>::type
  130. singleton(const typename interval_traits<Type>::domain_type& value)
  131. {
  132. return dynamic_interval_traits<Type>::construct(value, value, interval_bounds::closed());
  133. }
  134. namespace detail
  135. {
  136. //==============================================================================
  137. //= Construct<Interval> unit_trail == generalized singleton
  138. // The smallest interval on an incrementable (and decrementable) type that can
  139. // be constructed using ++ and -- and such that it contains a given value.
  140. // If 'Type' is discrete, 'unit_trail' and 'singleton' are identical. So we
  141. // can view 'unit_trail' as a generalized singleton for static intervals of
  142. // continuous types.
  143. //==============================================================================
  144. template<class Type>
  145. typename enable_if
  146. <
  147. mpl::and_< is_static_right_open<Type>
  148. , boost::detail::is_incrementable<typename interval_traits<Type>::domain_type> >
  149. , Type
  150. >::type
  151. unit_trail(const typename interval_traits<Type>::domain_type& value)
  152. {
  153. return interval_traits<Type>::construct(value, domain_next<Type>(value));
  154. }
  155. template<class Type>
  156. typename enable_if
  157. <
  158. mpl::and_< is_static_left_open<Type>
  159. , boost::detail::is_incrementable<typename interval_traits<Type>::domain_type> >
  160. , Type
  161. >::type
  162. unit_trail(const typename interval_traits<Type>::domain_type& value)
  163. {
  164. typedef typename interval_traits<Type>::domain_type domain_type;
  165. typedef typename interval_traits<Type>::domain_compare domain_compare;
  166. BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
  167. ::is_less_than(value) ));
  168. boost::ignore_unused<domain_type, domain_compare>();
  169. return interval_traits<Type>::construct(domain_prior<Type>(value), value);
  170. }
  171. template<class Type>
  172. typename enable_if
  173. <
  174. mpl::and_< is_static_open<Type>
  175. , is_discrete<typename interval_traits<Type>::domain_type> >
  176. , Type
  177. >::type
  178. unit_trail(const typename interval_traits<Type>::domain_type& value)
  179. {
  180. typedef typename interval_traits<Type>::domain_type domain_type;
  181. typedef typename interval_traits<Type>::domain_compare domain_compare;
  182. BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
  183. ::is_less_than(value)));
  184. boost::ignore_unused<domain_type, domain_compare>();
  185. return interval_traits<Type>::construct( domain_prior<Type>(value)
  186. , domain_next<Type>(value));
  187. }
  188. template<class Type>
  189. typename enable_if
  190. <
  191. mpl::and_< is_static_closed<Type>
  192. , is_discrete<typename interval_traits<Type>::domain_type> >
  193. , Type
  194. >::type
  195. unit_trail(const typename interval_traits<Type>::domain_type& value)
  196. {
  197. return interval_traits<Type>::construct(value, value);
  198. }
  199. //NOTE: statically bounded closed or open intervals of continuous domain types
  200. // are NOT supported by ICL. They can not be used with interval containers
  201. // consistently.
  202. template<class Type>
  203. typename enable_if<has_dynamic_bounds<Type>, Type>::type
  204. unit_trail(const typename interval_traits<Type>::domain_type& value)
  205. {
  206. return dynamic_interval_traits<Type>::construct(value, value, interval_bounds::closed());
  207. }
  208. } //namespace detail
  209. //==============================================================================
  210. //= Construct<Interval> multon
  211. //==============================================================================
  212. template<class Type>
  213. typename enable_if<has_static_bounds<Type>, Type>::type
  214. construct(const typename interval_traits<Type>::domain_type& low,
  215. const typename interval_traits<Type>::domain_type& up )
  216. {
  217. return interval_traits<Type>::construct(low, up);
  218. }
  219. template<class Type>
  220. typename enable_if<has_dynamic_bounds<Type>, Type>::type
  221. construct(const typename interval_traits<Type>::domain_type& low,
  222. const typename interval_traits<Type>::domain_type& up,
  223. interval_bounds bounds = interval_bounds::right_open())
  224. {
  225. return dynamic_interval_traits<Type>::construct(low, up, bounds);
  226. }
  227. //- construct form bounded values ----------------------------------------------
  228. template<class Type>
  229. typename enable_if<has_dynamic_bounds<Type>, Type>::type
  230. construct(const typename Type::bounded_domain_type& low,
  231. const typename Type::bounded_domain_type& up)
  232. {
  233. return dynamic_interval_traits<Type>::construct_bounded(low, up);
  234. }
  235. template<class Type>
  236. typename enable_if<is_interval<Type>, Type>::type
  237. span(const typename interval_traits<Type>::domain_type& left,
  238. const typename interval_traits<Type>::domain_type& right)
  239. {
  240. typedef typename interval_traits<Type>::domain_compare domain_compare;
  241. if(domain_compare()(left,right))
  242. return construct<Type>(left, right);
  243. else
  244. return construct<Type>(right, left);
  245. }
  246. //==============================================================================
  247. template<class Type>
  248. typename enable_if<is_static_right_open<Type>, Type>::type
  249. hull(const typename interval_traits<Type>::domain_type& left,
  250. const typename interval_traits<Type>::domain_type& right)
  251. {
  252. typedef typename interval_traits<Type>::domain_compare domain_compare;
  253. if(domain_compare()(left,right))
  254. return construct<Type>(left, domain_next<Type>(right));
  255. else
  256. return construct<Type>(right, domain_next<Type>(left));
  257. }
  258. template<class Type>
  259. typename enable_if<is_static_left_open<Type>, Type>::type
  260. hull(const typename interval_traits<Type>::domain_type& left,
  261. const typename interval_traits<Type>::domain_type& right)
  262. {
  263. typedef typename interval_traits<Type>::domain_type domain_type;
  264. typedef typename interval_traits<Type>::domain_compare domain_compare;
  265. boost::ignore_unused<domain_type>();
  266. if(domain_compare()(left,right))
  267. {
  268. BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
  269. ::is_less_than(left) ));
  270. return construct<Type>(domain_prior<Type>(left), right);
  271. }
  272. else
  273. {
  274. BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
  275. ::is_less_than(right) ));
  276. return construct<Type>(domain_prior<Type>(right), left);
  277. }
  278. }
  279. template<class Type>
  280. typename enable_if<is_static_closed<Type>, Type>::type
  281. hull(const typename interval_traits<Type>::domain_type& left,
  282. const typename interval_traits<Type>::domain_type& right)
  283. {
  284. typedef typename interval_traits<Type>::domain_compare domain_compare;
  285. if(domain_compare()(left,right))
  286. return construct<Type>(left, right);
  287. else
  288. return construct<Type>(right, left);
  289. }
  290. template<class Type>
  291. typename enable_if<is_static_open<Type>, Type>::type
  292. hull(const typename interval_traits<Type>::domain_type& left,
  293. const typename interval_traits<Type>::domain_type& right)
  294. {
  295. typedef typename interval_traits<Type>::domain_type domain_type;
  296. typedef typename interval_traits<Type>::domain_compare domain_compare;
  297. boost::ignore_unused<domain_type>();
  298. if(domain_compare()(left,right))
  299. {
  300. BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
  301. ::is_less_than(left) ));
  302. return construct<Type>( domain_prior<Type>(left)
  303. , domain_next<Type>(right));
  304. }
  305. else
  306. {
  307. BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
  308. ::is_less_than(right) ));
  309. return construct<Type>( domain_prior<Type>(right)
  310. , domain_next<Type>(left));
  311. }
  312. }
  313. template<class Type>
  314. typename enable_if<has_dynamic_bounds<Type>, Type>::type
  315. hull(const typename interval_traits<Type>::domain_type& left,
  316. const typename interval_traits<Type>::domain_type& right)
  317. {
  318. typedef typename interval_traits<Type>::domain_compare domain_compare;
  319. if(domain_compare()(left,right))
  320. return construct<Type>(left, right, interval_bounds::closed());
  321. else
  322. return construct<Type>(right, left, interval_bounds::closed());
  323. }
  324. //==============================================================================
  325. //= Selection
  326. //==============================================================================
  327. template<class Type>
  328. inline typename enable_if<is_interval<Type>,
  329. typename interval_traits<Type>::domain_type>::type
  330. lower(const Type& object)
  331. {
  332. return interval_traits<Type>::lower(object);
  333. }
  334. template<class Type>
  335. inline typename enable_if<is_interval<Type>,
  336. typename interval_traits<Type>::domain_type>::type
  337. upper(const Type& object)
  338. {
  339. return interval_traits<Type>::upper(object);
  340. }
  341. //- first ----------------------------------------------------------------------
  342. template<class Type>
  343. inline typename
  344. enable_if< mpl::or_<is_static_right_open<Type>, is_static_closed<Type> >
  345. , typename interval_traits<Type>::domain_type>::type
  346. first(const Type& object)
  347. {
  348. return lower(object);
  349. }
  350. template<class Type>
  351. inline typename
  352. enable_if< mpl::and_< mpl::or_<is_static_left_open<Type>, is_static_open<Type> >
  353. , is_discrete<typename interval_traits<Type>::domain_type> >
  354. , typename interval_traits<Type>::domain_type>::type
  355. first(const Type& object)
  356. {
  357. return domain_next<Type>(lower(object));
  358. }
  359. template<class Type>
  360. inline typename enable_if<is_discrete_interval<Type>,
  361. typename interval_traits<Type>::domain_type>::type
  362. first(const Type& object)
  363. {
  364. return is_left_closed(object.bounds()) ?
  365. lower(object) :
  366. domain_next<Type>(lower(object));
  367. }
  368. //- last -----------------------------------------------------------------------
  369. template<class Type>
  370. inline typename
  371. enable_if< mpl::or_<is_static_left_open<Type>, is_static_closed<Type> >
  372. , typename interval_traits<Type>::domain_type>::type
  373. last(const Type& object)
  374. {
  375. return upper(object);
  376. }
  377. template<class Type>
  378. inline typename
  379. enable_if< mpl::and_< mpl::or_<is_static_right_open<Type>, is_static_open<Type> >
  380. , is_discrete<typename interval_traits<Type>::domain_type> >
  381. , typename interval_traits<Type>::domain_type>::type
  382. last(const Type& object)
  383. {
  384. typedef typename interval_traits<Type>::domain_type domain_type;
  385. typedef typename interval_traits<Type>::domain_compare domain_compare;
  386. BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
  387. ::is_less_than(upper(object)) ));
  388. boost::ignore_unused<domain_type, domain_compare>();
  389. return domain_prior<Type>(upper(object));
  390. }
  391. template<class Type>
  392. inline typename enable_if<is_discrete_interval<Type>,
  393. typename interval_traits<Type>::domain_type>::type
  394. last(const Type& object)
  395. {
  396. typedef typename interval_traits<Type>::domain_type domain_type;
  397. typedef typename interval_traits<Type>::domain_compare domain_compare;
  398. BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
  399. ::is_less_than_or(upper(object), is_right_closed(object.bounds())) ));
  400. boost::ignore_unused<domain_type, domain_compare>();
  401. return is_right_closed(object.bounds()) ?
  402. upper(object) :
  403. domain_prior<Type>(upper(object));
  404. }
  405. //- last_next ------------------------------------------------------------------
  406. template<class Type>
  407. inline typename
  408. enable_if< mpl::and_< mpl::or_<is_static_left_open<Type>, is_static_closed<Type> >
  409. , is_discrete<typename interval_traits<Type>::domain_type> >
  410. , typename interval_traits<Type>::domain_type>::type
  411. last_next(const Type& object)
  412. {
  413. return domain_next<Type>(upper(object));
  414. }
  415. template<class Type>
  416. inline typename
  417. enable_if< mpl::and_< mpl::or_<is_static_right_open<Type>, is_static_open<Type> >
  418. , is_discrete<typename interval_traits<Type>::domain_type> >
  419. , typename interval_traits<Type>::domain_type>::type
  420. last_next(const Type& object)
  421. {
  422. //CL typedef typename interval_traits<Type>::domain_type domain_type;
  423. return upper(object); // NOTE: last_next is implemented to avoid calling pred(object)
  424. } // For unsigned integral types this may cause underflow.
  425. template<class Type>
  426. inline typename enable_if<is_discrete_interval<Type>,
  427. typename interval_traits<Type>::domain_type>::type
  428. last_next(const Type& object)
  429. {
  430. return is_right_closed(object.bounds()) ?
  431. domain_next<Type>(upper(object)):
  432. upper(object) ;
  433. }
  434. //------------------------------------------------------------------------------
  435. template<class Type>
  436. typename enable_if<has_dynamic_bounds<Type>,
  437. typename Type::bounded_domain_type>::type
  438. bounded_lower(const Type& object)
  439. {
  440. return typename
  441. Type::bounded_domain_type(lower(object), object.bounds().left());
  442. }
  443. template<class Type>
  444. typename enable_if<has_dynamic_bounds<Type>,
  445. typename Type::bounded_domain_type>::type
  446. reverse_bounded_lower(const Type& object)
  447. {
  448. return typename
  449. Type::bounded_domain_type(lower(object),
  450. object.bounds().reverse_left());
  451. }
  452. template<class Type>
  453. typename enable_if<has_dynamic_bounds<Type>,
  454. typename Type::bounded_domain_type>::type
  455. bounded_upper(const Type& object)
  456. {
  457. return typename
  458. Type::bounded_domain_type(upper(object),
  459. object.bounds().right());
  460. }
  461. template<class Type>
  462. typename enable_if<has_dynamic_bounds<Type>,
  463. typename Type::bounded_domain_type>::type
  464. reverse_bounded_upper(const Type& object)
  465. {
  466. return typename
  467. Type::bounded_domain_type(upper(object),
  468. object.bounds().reverse_right());
  469. }
  470. //- bounds ---------------------------------------------------------------------
  471. template<class Type>
  472. inline typename enable_if<has_dynamic_bounds<Type>, interval_bounds>::type
  473. bounds(const Type& object)
  474. {
  475. return object.bounds();
  476. }
  477. template<class Type>
  478. inline typename enable_if<has_static_bounds<Type>, interval_bounds>::type
  479. bounds(const Type&)
  480. {
  481. return interval_bounds(interval_bound_type<Type>::value);
  482. }
  483. //==============================================================================
  484. //= Emptieness
  485. //==============================================================================
  486. /** Is the interval empty? */
  487. template<class Type>
  488. typename boost::enable_if<is_asymmetric_interval<Type>, bool>::type
  489. is_empty(const Type& object)
  490. {
  491. return domain_less_equal<Type>(upper(object), lower(object));
  492. }
  493. template<class Type>
  494. typename boost::enable_if<is_static_closed<Type>, bool>::type
  495. is_empty(const Type& object)
  496. {
  497. return domain_less<Type>(upper(object), lower(object));
  498. }
  499. template<class Type>
  500. typename boost::enable_if<is_static_open<Type>, bool>::type
  501. is_empty(const Type& object)
  502. {
  503. return domain_less_equal<Type>(upper(object), lower(object) )
  504. || domain_less_equal<Type>(upper(object), domain_next<Type>(lower(object)));
  505. }
  506. template<class Type>
  507. typename boost::enable_if<is_discrete_interval<Type>, bool>::type
  508. is_empty(const Type& object)
  509. {
  510. if(object.bounds() == interval_bounds::closed())
  511. return domain_less<Type>(upper(object), lower(object));
  512. else if(object.bounds() == interval_bounds::open())
  513. return domain_less_equal<Type>(upper(object), lower(object) )
  514. || domain_less_equal<Type>(upper(object), domain_next<Type>(lower(object)));
  515. else
  516. return domain_less_equal<Type>(upper(object), lower(object));
  517. }
  518. template<class Type>
  519. typename boost::enable_if<is_continuous_interval<Type>, bool>::type
  520. is_empty(const Type& object)
  521. {
  522. return domain_less<Type>(upper(object), lower(object))
  523. || ( domain_equal<Type>(upper(object), lower(object))
  524. && object.bounds() != interval_bounds::closed() );
  525. }
  526. //==============================================================================
  527. //= Equivalences and Orderings
  528. //==============================================================================
  529. //- exclusive_less -------------------------------------------------------------
  530. /** Maximal element of <tt>left</tt> is less than the minimal element of
  531. <tt>right</tt> */
  532. template<class Type>
  533. inline typename boost::enable_if<is_asymmetric_interval<Type>, bool>::type
  534. exclusive_less(const Type& left, const Type& right)
  535. {
  536. return icl::is_empty(left) || icl::is_empty(right)
  537. || domain_less_equal<Type>(upper(left), lower(right));
  538. }
  539. template<class Type>
  540. inline typename boost::enable_if<is_discrete_interval<Type>, bool>::type
  541. exclusive_less(const Type& left, const Type& right)
  542. {
  543. return icl::is_empty(left) || icl::is_empty(right)
  544. || domain_less<Type>(last(left), first(right));
  545. }
  546. template<class Type>
  547. inline typename boost::
  548. enable_if<has_symmetric_bounds<Type>, bool>::type
  549. exclusive_less(const Type& left, const Type& right)
  550. {
  551. return icl::is_empty(left) || icl::is_empty(right)
  552. || domain_less<Type>(last(left), first(right));
  553. }
  554. template<class Type>
  555. inline typename boost::enable_if<is_continuous_interval<Type>, bool>::type
  556. exclusive_less(const Type& left, const Type& right)
  557. {
  558. return icl::is_empty(left) || icl::is_empty(right)
  559. || domain_less<Type>(upper(left), lower(right))
  560. || ( domain_equal<Type>(upper(left), lower(right))
  561. && inner_bounds(left,right) != interval_bounds::open() );
  562. }
  563. //------------------------------------------------------------------------------
  564. template<class Type>
  565. typename boost::enable_if<has_static_bounds<Type>, bool>::type
  566. lower_less(const Type& left, const Type& right)
  567. {
  568. return domain_less<Type>(lower(left), lower(right));
  569. }
  570. template<class Type>
  571. typename boost::enable_if<is_discrete_interval<Type>, bool>::type
  572. lower_less(const Type& left, const Type& right)
  573. {
  574. return domain_less<Type>(first(left), first(right));
  575. }
  576. template<class Type>
  577. typename boost::enable_if<is_continuous_interval<Type>, bool>::type
  578. lower_less(const Type& left, const Type& right)
  579. {
  580. if(left_bounds(left,right) == interval_bounds::right_open()) //'[(' == 10
  581. return domain_less_equal<Type>(lower(left), lower(right));
  582. else
  583. return domain_less<Type>(lower(left), lower(right));
  584. }
  585. //------------------------------------------------------------------------------
  586. template<class Type>
  587. typename boost::enable_if<has_static_bounds<Type>, bool>::type
  588. upper_less(const Type& left, const Type& right)
  589. {
  590. return domain_less<Type>(upper(left), upper(right));
  591. }
  592. template<class Type>
  593. typename boost::enable_if<is_discrete_interval<Type>, bool>::type
  594. upper_less(const Type& left, const Type& right)
  595. {
  596. return domain_less<Type>(last(left), last(right));
  597. }
  598. template<class Type>
  599. typename boost::enable_if<is_continuous_interval<Type>, bool>::type
  600. upper_less(const Type& left, const Type& right)
  601. {
  602. if(right_bounds(left,right) == interval_bounds::left_open())
  603. return domain_less_equal<Type>(upper(left), upper(right));
  604. else
  605. return domain_less<Type>(upper(left), upper(right));
  606. }
  607. //------------------------------------------------------------------------------
  608. template<class Type>
  609. typename boost::enable_if<has_dynamic_bounds<Type>,
  610. typename Type::bounded_domain_type >::type
  611. lower_min(const Type& left, const Type& right)
  612. {
  613. return lower_less(left, right) ? bounded_lower(left) : bounded_lower(right);
  614. }
  615. //------------------------------------------------------------------------------
  616. template<class Type>
  617. typename boost::enable_if<has_dynamic_bounds<Type>,
  618. typename Type::bounded_domain_type >::type
  619. lower_max(const Type& left, const Type& right)
  620. {
  621. return lower_less(left, right) ? bounded_lower(right) : bounded_lower(left);
  622. }
  623. //------------------------------------------------------------------------------
  624. template<class Type>
  625. typename boost::enable_if<has_dynamic_bounds<Type>,
  626. typename Type::bounded_domain_type >::type
  627. upper_max(const Type& left, const Type& right)
  628. {
  629. return upper_less(left, right) ? bounded_upper(right) : bounded_upper(left);
  630. }
  631. //------------------------------------------------------------------------------
  632. template<class Type>
  633. typename boost::enable_if<has_dynamic_bounds<Type>,
  634. typename Type::bounded_domain_type >::type
  635. upper_min(const Type& left, const Type& right)
  636. {
  637. return upper_less(left, right) ? bounded_upper(left) : bounded_upper(right);
  638. }
  639. //------------------------------------------------------------------------------
  640. template<class Type>
  641. typename boost::enable_if<is_asymmetric_interval<Type>, bool>::type
  642. lower_equal(const Type& left, const Type& right)
  643. {
  644. return domain_equal<Type>(lower(left), lower(right));
  645. }
  646. template<class Type>
  647. typename boost::enable_if<has_symmetric_bounds<Type>, bool>::type
  648. lower_equal(const Type& left, const Type& right)
  649. {
  650. return domain_equal<Type>(first(left), first(right));
  651. }
  652. template<class Type>
  653. typename boost::enable_if<is_discrete_interval<Type>, bool>::type
  654. lower_equal(const Type& left, const Type& right)
  655. {
  656. return domain_equal<Type>(first(left), first(right));
  657. }
  658. template<class Type>
  659. typename boost::enable_if<is_continuous_interval<Type>, bool>::type
  660. lower_equal(const Type& left, const Type& right)
  661. {
  662. return (left.bounds().left()==right.bounds().left())
  663. && domain_equal<Type>(lower(left), lower(right));
  664. }
  665. //------------------------------------------------------------------------------
  666. template<class Type>
  667. typename boost::enable_if<is_asymmetric_interval<Type>, bool>::type
  668. upper_equal(const Type& left, const Type& right)
  669. {
  670. return domain_equal<Type>(upper(left), upper(right));
  671. }
  672. template<class Type>
  673. typename boost::enable_if<has_symmetric_bounds<Type>, bool>::type
  674. upper_equal(const Type& left, const Type& right)
  675. {
  676. return domain_equal<Type>(last(left), last(right));
  677. }
  678. template<class Type>
  679. typename boost::enable_if<is_discrete_interval<Type>, bool>::type
  680. upper_equal(const Type& left, const Type& right)
  681. {
  682. return domain_equal<Type>(last(left), last(right));
  683. }
  684. template<class Type>
  685. typename boost::enable_if<is_continuous_interval<Type>, bool>::type
  686. upper_equal(const Type& left, const Type& right)
  687. {
  688. return (left.bounds().right()==right.bounds().right())
  689. && domain_equal<Type>(upper(left), upper(right));
  690. }
  691. //------------------------------------------------------------------------------
  692. template<class Type>
  693. typename boost::enable_if<is_interval<Type>, bool>::type
  694. lower_less_equal(const Type& left, const Type& right)
  695. {
  696. return lower_less(left,right) || lower_equal(left,right);
  697. }
  698. template<class Type>
  699. typename boost::enable_if<is_interval<Type>, bool>::type
  700. upper_less_equal(const Type& left, const Type& right)
  701. {
  702. return upper_less(left,right) || upper_equal(left,right);
  703. }
  704. //==============================================================================
  705. //= Orderings, containedness (non empty)
  706. //==============================================================================
  707. namespace non_empty
  708. {
  709. template<class Type>
  710. inline typename boost::enable_if<is_asymmetric_interval<Type>, bool>::type
  711. exclusive_less(const Type& left, const Type& right)
  712. {
  713. BOOST_ASSERT(!(icl::is_empty(left) || icl::is_empty(right)));
  714. return domain_less_equal<Type>(upper(left), lower(right));
  715. }
  716. template<class Type>
  717. inline typename boost::enable_if<is_discrete_interval<Type>, bool>::type
  718. exclusive_less(const Type& left, const Type& right)
  719. {
  720. BOOST_ASSERT(!(icl::is_empty(left) || icl::is_empty(right)));
  721. return domain_less<Type>(last(left), first(right));
  722. }
  723. template<class Type>
  724. inline typename boost::
  725. enable_if<has_symmetric_bounds<Type>, bool>::type
  726. exclusive_less(const Type& left, const Type& right)
  727. {
  728. BOOST_ASSERT(!(icl::is_empty(left) || icl::is_empty(right)));
  729. return domain_less<Type>(last(left), first(right));
  730. }
  731. template<class Type>
  732. inline typename boost::enable_if<is_continuous_interval<Type>, bool>::type
  733. exclusive_less(const Type& left, const Type& right)
  734. {
  735. BOOST_ASSERT(!(icl::is_empty(left) || icl::is_empty(right)));
  736. return domain_less <Type>(upper(left), lower(right))
  737. || ( domain_equal<Type>(upper(left), lower(right))
  738. && inner_bounds(left,right) != interval_bounds::open() );
  739. }
  740. template<class Type>
  741. inline typename boost::enable_if<is_interval<Type>, bool>::type
  742. contains(const Type& super, const Type& sub)
  743. {
  744. return lower_less_equal(super,sub) && upper_less_equal(sub,super);
  745. }
  746. } //namespace non_empty
  747. //- contains -------------------------------------------------------------------
  748. template<class Type>
  749. inline typename boost::enable_if<is_interval<Type>, bool>::type
  750. contains(const Type& super, const Type& sub)
  751. {
  752. return icl::is_empty(sub) || non_empty::contains(super, sub);
  753. }
  754. template<class Type>
  755. typename boost::enable_if<is_discrete_static<Type>, bool>::type
  756. contains(const Type& super, const typename interval_traits<Type>::domain_type& element)
  757. {
  758. return domain_less_equal<Type>(icl::first(super), element )
  759. && domain_less_equal<Type>( element, icl::last(super));
  760. }
  761. template<class Type>
  762. typename boost::enable_if<is_continuous_left_open<Type>, bool>::type
  763. contains(const Type& super, const typename interval_traits<Type>::domain_type& element)
  764. {
  765. return domain_less <Type>(icl::lower(super), element )
  766. && domain_less_equal<Type>( element, icl::upper(super));
  767. }
  768. template<class Type>
  769. typename boost::enable_if<is_continuous_right_open<Type>, bool>::type
  770. contains(const Type& super, const typename interval_traits<Type>::domain_type& element)
  771. {
  772. return domain_less_equal<Type>(icl::lower(super), element )
  773. && domain_less <Type>( element, icl::upper(super));
  774. }
  775. template<class Type>
  776. typename boost::enable_if<has_dynamic_bounds<Type>, bool>::type
  777. contains(const Type& super, const typename interval_traits<Type>::domain_type& element)
  778. {
  779. return
  780. (is_left_closed(super.bounds())
  781. ? domain_less_equal<Type>(lower(super), element)
  782. : domain_less<Type>(lower(super), element))
  783. &&
  784. (is_right_closed(super.bounds())
  785. ? domain_less_equal<Type>(element, upper(super))
  786. : domain_less<Type>(element, upper(super)));
  787. }
  788. //- within ---------------------------------------------------------------------
  789. template<class Type>
  790. inline typename boost::enable_if<is_interval<Type>, bool>::type
  791. within(const Type& sub, const Type& super)
  792. {
  793. return contains(super,sub);
  794. }
  795. //- operator == ----------------------------------------------------------------
  796. template<class Type>
  797. typename boost::enable_if<is_interval<Type>, bool>::type
  798. operator == (const Type& left, const Type& right)
  799. {
  800. return (icl::is_empty(left) && icl::is_empty(right))
  801. || (lower_equal(left,right) && upper_equal(left,right));
  802. }
  803. template<class Type>
  804. typename boost::enable_if<is_interval<Type>, bool>::type
  805. operator != (const Type& left, const Type& right)
  806. {
  807. return !(left == right);
  808. }
  809. //- operator < -----------------------------------------------------------------
  810. template<class Type>
  811. typename boost::enable_if<is_interval<Type>, bool>::type
  812. operator < (const Type& left, const Type& right)
  813. {
  814. return (!icl::is_empty(left) && !icl::is_empty(right))
  815. && ( lower_less(left,right)
  816. || (lower_equal(left,right) && upper_less(left,right)) );
  817. }
  818. template<class Type>
  819. inline typename boost::enable_if<is_interval<Type>, bool>::type
  820. operator > (const Type& left, const Type& right)
  821. {
  822. return right < left;
  823. }
  824. //- operator <= ----------------------------------------------------------------
  825. template<class Type>
  826. inline typename boost::enable_if<is_interval<Type>, bool>::type
  827. operator <= (const Type& left, const Type& right)
  828. {
  829. if(icl::is_empty(left) || icl::is_empty(right))
  830. return false;
  831. return !(left > right);
  832. }
  833. template<class Type>
  834. inline typename boost::enable_if<is_interval<Type>, bool>::type
  835. operator >= (const Type& left, const Type& right)
  836. {
  837. if(icl::is_empty(left) || icl::is_empty(right))
  838. return false;
  839. return !(left < right);
  840. }
  841. //------------------------------------------------------------------------------
  842. template<class Type>
  843. typename boost::enable_if<is_asymmetric_interval<Type>, bool>::type
  844. touches(const Type& left, const Type& right)
  845. {
  846. return domain_equal<Type>(upper(left), lower(right));
  847. }
  848. template<class Type>
  849. typename boost::enable_if<has_symmetric_bounds<Type>, bool>::type
  850. touches(const Type& left, const Type& right)
  851. {
  852. return domain_equal<Type>(last_next(left), first(right));
  853. }
  854. template<class Type>
  855. typename boost::enable_if<is_discrete_interval<Type>, bool>::type
  856. touches(const Type& left, const Type& right)
  857. {
  858. return domain_equal<Type>(domain_next<Type>(last(left)), first(right));
  859. }
  860. template<class Type>
  861. typename boost::enable_if<is_continuous_interval<Type>, bool>::type
  862. touches(const Type& left, const Type& right)
  863. {
  864. return is_complementary(inner_bounds(left,right))
  865. && domain_equal<Type>(upper(left), lower(right));
  866. }
  867. //==============================================================================
  868. //= Size
  869. //==============================================================================
  870. //- cardinality ----------------------------------------------------------------
  871. template<class Type>
  872. typename boost::enable_if<is_continuous_interval<Type>,
  873. typename size_type_of<interval_traits<Type> >::type>::type
  874. cardinality(const Type& object)
  875. {
  876. typedef typename size_type_of<interval_traits<Type> >::type SizeT;
  877. if(icl::is_empty(object))
  878. return icl::identity_element<SizeT>::value();
  879. else if( object.bounds() == interval_bounds::closed()
  880. && domain_equal<Type>(lower(object), upper(object)))
  881. return icl::unit_element<SizeT>::value();
  882. else
  883. return icl::infinity<SizeT>::value();
  884. }
  885. template<class Type>
  886. typename boost::enable_if<is_discrete_interval<Type>,
  887. typename size_type_of<interval_traits<Type> >::type>::type
  888. cardinality(const Type& object)
  889. {
  890. typedef typename size_type_of<interval_traits<Type> >::type SizeT;
  891. return icl::is_empty(object) ? identity_element<SizeT>::value()
  892. : static_cast<SizeT>(last_next(object) - first(object));
  893. }
  894. template<class Type>
  895. typename boost::enable_if<is_continuous_asymmetric<Type>,
  896. typename size_type_of<interval_traits<Type> >::type>::type
  897. cardinality(const Type& object)
  898. {
  899. typedef typename size_type_of<interval_traits<Type> >::type SizeT;
  900. if(icl::is_empty(object))
  901. return icl::identity_element<SizeT>::value();
  902. else
  903. return icl::infinity<SizeT>::value();
  904. }
  905. template<class Type>
  906. typename boost::enable_if<is_discrete_asymmetric<Type>,
  907. typename size_type_of<interval_traits<Type> >::type>::type
  908. cardinality(const Type& object)
  909. {
  910. typedef typename size_type_of<interval_traits<Type> >::type SizeT;
  911. return icl::is_empty(object) ? identity_element<SizeT>::value()
  912. : static_cast<SizeT>(last_next(object) - first(object));
  913. }
  914. template<class Type>
  915. typename boost::enable_if<has_symmetric_bounds<Type>,
  916. typename size_type_of<interval_traits<Type> >::type>::type
  917. cardinality(const Type& object)
  918. {
  919. typedef typename size_type_of<interval_traits<Type> >::type SizeT;
  920. return icl::is_empty(object) ? identity_element<SizeT>::value()
  921. : static_cast<SizeT>(last_next(object) - first(object));
  922. }
  923. //- size -----------------------------------------------------------------------
  924. template<class Type>
  925. inline typename enable_if<is_interval<Type>,
  926. typename size_type_of<interval_traits<Type> >::type>::type
  927. size(const Type& object)
  928. {
  929. return cardinality(object);
  930. }
  931. //- length ---------------------------------------------------------------------
  932. template<class Type>
  933. inline typename boost::enable_if<is_continuous_interval<Type>,
  934. typename difference_type_of<interval_traits<Type> >::type>::type
  935. length(const Type& object)
  936. {
  937. typedef typename difference_type_of<interval_traits<Type> >::type DiffT;
  938. return icl::is_empty(object) ? identity_element<DiffT>::value()
  939. : upper(object) - lower(object);
  940. }
  941. template<class Type>
  942. inline typename boost::enable_if<is_discrete_interval<Type>,
  943. typename difference_type_of<interval_traits<Type> >::type>::type
  944. length(const Type& object)
  945. {
  946. typedef typename difference_type_of<interval_traits<Type> >::type DiffT;
  947. return icl::is_empty(object) ? identity_element<DiffT>::value()
  948. : last_next(object) - first(object);
  949. }
  950. template<class Type>
  951. typename boost::enable_if<is_continuous_asymmetric<Type>,
  952. typename difference_type_of<interval_traits<Type> >::type>::type
  953. length(const Type& object)
  954. {
  955. typedef typename difference_type_of<interval_traits<Type> >::type DiffT;
  956. return icl::is_empty(object) ? identity_element<DiffT>::value()
  957. : upper(object) - lower(object);
  958. }
  959. template<class Type>
  960. inline typename boost::enable_if<is_discrete_static<Type>,
  961. typename difference_type_of<interval_traits<Type> >::type>::type
  962. length(const Type& object)
  963. {
  964. typedef typename difference_type_of<interval_traits<Type> >::type DiffT;
  965. return icl::is_empty(object) ? identity_element<DiffT>::value()
  966. : last_next(object) - first(object);
  967. }
  968. //- iterative_size -------------------------------------------------------------
  969. template<class Type>
  970. inline typename enable_if<is_interval<Type>,
  971. typename size_type_of<interval_traits<Type> >::type>::type
  972. iterative_size(const Type&)
  973. {
  974. return 2;
  975. }
  976. //==============================================================================
  977. //= Addition
  978. //==============================================================================
  979. //- hull -----------------------------------------------------------------------
  980. /** \c hull returns the smallest interval containing \c left and \c right. */
  981. template<class Type>
  982. typename boost::enable_if<has_static_bounds<Type>, Type>::type
  983. hull(Type left, const Type& right)
  984. {
  985. typedef typename interval_traits<Type>::domain_compare domain_compare;
  986. if(icl::is_empty(right))
  987. return left;
  988. else if(icl::is_empty(left))
  989. return right;
  990. return
  991. construct<Type>
  992. (
  993. (std::min)(lower(left), lower(right), domain_compare()),
  994. (std::max)(upper(left), upper(right), domain_compare())
  995. );
  996. }
  997. template<class Type>
  998. typename boost::enable_if<has_dynamic_bounds<Type>, Type>::type
  999. hull(Type left, const Type& right)
  1000. {
  1001. if(icl::is_empty(right))
  1002. return left;
  1003. else if(icl::is_empty(left))
  1004. return right;
  1005. return dynamic_interval_traits<Type>::construct_bounded
  1006. (
  1007. lower_min(left, right),
  1008. upper_max(left, right)
  1009. );
  1010. }
  1011. //==============================================================================
  1012. //= Subtraction
  1013. //==============================================================================
  1014. //- left_subtract --------------------------------------------------------------
  1015. /** subtract \c left_minuend from the \c right interval on it's left side.
  1016. Return the difference: The part of \c right right of \c left_minuend.
  1017. \code
  1018. right_over = right - left_minuend; //on the left.
  1019. ... d) : right
  1020. ... c) : left_minuend
  1021. [c d) : right_over
  1022. \endcode
  1023. */
  1024. template<class Type>
  1025. typename boost::enable_if<is_asymmetric_interval<Type>, Type>::type
  1026. left_subtract(Type right, const Type& left_minuend)
  1027. {
  1028. if(exclusive_less(left_minuend, right))
  1029. return right;
  1030. return construct<Type>(upper(left_minuend), upper(right));
  1031. }
  1032. template<class Type>
  1033. typename boost::enable_if<is_static_closed<Type>, Type>::type
  1034. left_subtract(Type right, const Type& left_minuend)
  1035. {
  1036. if(exclusive_less(left_minuend, right))
  1037. return right;
  1038. else if(upper_less_equal(right, left_minuend))
  1039. return identity_element<Type>::value();
  1040. return construct<Type>(domain_next<Type>(upper(left_minuend)), upper(right));
  1041. }
  1042. template<class Type>
  1043. typename boost::enable_if<is_static_open<Type>, Type>::type
  1044. left_subtract(Type right, const Type& left_minuend)
  1045. {
  1046. if(exclusive_less(left_minuend, right))
  1047. return right;
  1048. return construct<Type>(domain_prior<Type>(upper(left_minuend)), upper(right));
  1049. }
  1050. template<class Type>
  1051. typename boost::enable_if<has_dynamic_bounds<Type>, Type>::type
  1052. left_subtract(Type right, const Type& left_minuend)
  1053. {
  1054. if(exclusive_less(left_minuend, right))
  1055. return right;
  1056. return dynamic_interval_traits<Type>::construct_bounded
  1057. ( reverse_bounded_upper(left_minuend), bounded_upper(right) );
  1058. }
  1059. //- right_subtract -------------------------------------------------------------
  1060. /** subtract \c right_minuend from the \c left interval on it's right side.
  1061. Return the difference: The part of \c left left of \c right_minuend.
  1062. \code
  1063. left_over = left - right_minuend; //on the right side.
  1064. [a ... : left
  1065. [b ... : right_minuend
  1066. [a b) : left_over
  1067. \endcode
  1068. */
  1069. template<class Type>
  1070. typename boost::enable_if<is_asymmetric_interval<Type>, Type>::type
  1071. right_subtract(Type left, const Type& right_minuend)
  1072. {
  1073. if(exclusive_less(left, right_minuend))
  1074. return left;
  1075. return construct<Type>(lower(left), lower(right_minuend));
  1076. }
  1077. template<class Type>
  1078. typename boost::enable_if<is_static_closed<Type>, Type>::type
  1079. right_subtract(Type left, const Type& right_minuend)
  1080. {
  1081. if(exclusive_less(left, right_minuend))
  1082. return left;
  1083. else if(lower_less_equal(right_minuend, left))
  1084. return identity_element<Type>::value();
  1085. return construct<Type>(lower(left), domain_prior<Type>(lower(right_minuend)));
  1086. }
  1087. template<class Type>
  1088. typename boost::enable_if<is_static_open<Type>, Type>::type
  1089. right_subtract(Type left, const Type& right_minuend)
  1090. {
  1091. if(exclusive_less(left, right_minuend))
  1092. return left;
  1093. return construct<Type>(lower(left), domain_next<Type>(lower(right_minuend)));
  1094. }
  1095. template<class Type>
  1096. typename boost::enable_if<has_dynamic_bounds<Type>, Type>::type
  1097. right_subtract(Type left, const Type& right_minuend)
  1098. {
  1099. if(exclusive_less(left, right_minuend))
  1100. return left;
  1101. return dynamic_interval_traits<Type>::construct_bounded
  1102. ( bounded_lower(left), reverse_bounded_lower(right_minuend) );
  1103. }
  1104. //==============================================================================
  1105. //= Intersection
  1106. //==============================================================================
  1107. //- operator & -----------------------------------------------------------------
  1108. /** Returns the intersection of \c left and \c right interval. */
  1109. template<class Type>
  1110. typename boost::enable_if<is_asymmetric_interval<Type>, Type>::type
  1111. operator & (Type left, const Type& right)
  1112. {
  1113. typedef typename interval_traits<Type>::domain_compare domain_compare;
  1114. if(icl::is_empty(left) || icl::is_empty(right))
  1115. return identity_element<Type>::value();
  1116. else
  1117. return
  1118. construct<Type>
  1119. (
  1120. (std::max)(icl::lower(left), icl::lower(right), domain_compare()),
  1121. (std::min)(icl::upper(left), icl::upper(right), domain_compare())
  1122. );
  1123. }
  1124. template<class Type>
  1125. typename boost::enable_if<has_symmetric_bounds<Type>, Type>::type
  1126. operator & (Type left, const Type& right)
  1127. {
  1128. typedef typename interval_traits<Type>::domain_compare domain_compare;
  1129. if(icl::is_empty(left) || icl::is_empty(right))
  1130. return identity_element<Type>::value();
  1131. else
  1132. return
  1133. construct<Type>
  1134. (
  1135. (std::max)(icl::lower(left), icl::lower(right), domain_compare()),
  1136. (std::min)(icl::upper(left), icl::upper(right), domain_compare())
  1137. );
  1138. }
  1139. template<class Type>
  1140. typename boost::enable_if<has_dynamic_bounds<Type>, Type>::type
  1141. operator & (Type left, const Type& right)
  1142. {
  1143. if(icl::is_empty(left) || icl::is_empty(right))
  1144. return identity_element<Type>::value();
  1145. else
  1146. return dynamic_interval_traits<Type>::construct_bounded
  1147. (
  1148. lower_max(left, right),
  1149. upper_min(left, right)
  1150. );
  1151. }
  1152. //- intersects -----------------------------------------------------------------
  1153. template<class Type>
  1154. typename boost::enable_if<is_interval<Type>, bool>::type
  1155. intersects(const Type& left, const Type& right)
  1156. {
  1157. return !( icl::is_empty(left) || icl::is_empty(right)
  1158. || exclusive_less(left,right) || exclusive_less(right,left));
  1159. }
  1160. //- disjoint -------------------------------------------------------------------
  1161. template<class Type>
  1162. typename boost::enable_if<is_interval<Type>, bool>::type
  1163. disjoint(const Type& left, const Type& right)
  1164. {
  1165. return icl::is_empty(left) || icl::is_empty(right)
  1166. || exclusive_less(left,right) || exclusive_less(right,left);
  1167. }
  1168. //==============================================================================
  1169. //= Complement
  1170. //==============================================================================
  1171. template<class Type>
  1172. typename boost::enable_if<is_asymmetric_interval<Type>, Type>::type
  1173. inner_complement(const Type& left, const Type& right)
  1174. {
  1175. if(icl::is_empty(left) || icl::is_empty(right))
  1176. return identity_element<Type>::value();
  1177. else if(exclusive_less(left, right))
  1178. return construct<Type>(upper(left), lower(right));
  1179. else if(exclusive_less(right, left))
  1180. return construct<Type>(upper(right), lower(left));
  1181. else
  1182. return identity_element<Type>::value();
  1183. }
  1184. template<class Type>
  1185. typename boost::enable_if<is_discrete_static_closed<Type>, Type>::type
  1186. inner_complement(const Type& left, const Type& right)
  1187. {
  1188. if(icl::is_empty(left) || icl::is_empty(right))
  1189. return identity_element<Type>::value();
  1190. else if(exclusive_less(left, right))
  1191. return construct<Type>(domain_next<Type>(upper(left)), domain_prior<Type>(lower(right)));
  1192. else if(exclusive_less(right, left))
  1193. return construct<Type>(domain_next<Type>(upper(right)), domain_prior<Type>(lower(left)));
  1194. else
  1195. return identity_element<Type>::value();
  1196. }
  1197. template<class Type>
  1198. typename boost::enable_if<is_discrete_static_open<Type>, Type>::type
  1199. inner_complement(const Type& left, const Type& right)
  1200. {
  1201. if(icl::is_empty(left) || icl::is_empty(right))
  1202. return identity_element<Type>::value();
  1203. else if(exclusive_less(left, right))
  1204. return construct<Type>(last(left), first(right));
  1205. else if(exclusive_less(right, left))
  1206. return construct<Type>(last(right), first(left));
  1207. else
  1208. return identity_element<Type>::value();
  1209. }
  1210. template<class Type>
  1211. typename boost::enable_if<has_dynamic_bounds<Type>, Type>::type
  1212. inner_complement(const Type& left, const Type& right)
  1213. {
  1214. if(icl::is_empty(left) || icl::is_empty(right))
  1215. return identity_element<Type>::value();
  1216. else if(exclusive_less(left, right))
  1217. return right_subtract(left_subtract(hull(left, right), left), right);
  1218. else if(exclusive_less(right, left))
  1219. return right_subtract(left_subtract(hull(right, left), right), left);
  1220. else
  1221. return identity_element<Type>::value();
  1222. }
  1223. template<class Type>
  1224. inline typename boost::enable_if<is_interval<Type>, Type>::type
  1225. between(const Type& left, const Type& right)
  1226. {
  1227. return inner_complement(left, right);
  1228. }
  1229. //==============================================================================
  1230. //= Distance
  1231. //==============================================================================
  1232. template<class Type>
  1233. typename boost::
  1234. enable_if< mpl::and_< is_interval<Type>
  1235. , has_difference<typename interval_traits<Type>::domain_type>
  1236. , is_discrete<typename interval_traits<Type>::domain_type>
  1237. >
  1238. , typename difference_type_of<interval_traits<Type> >::type>::type
  1239. distance(const Type& x1, const Type& x2)
  1240. {
  1241. typedef typename difference_type_of<interval_traits<Type> >::type difference_type;
  1242. if(icl::is_empty(x1) || icl::is_empty(x2))
  1243. return icl::identity_element<difference_type>::value();
  1244. else if(domain_less<Type>(last(x1), first(x2)))
  1245. return static_cast<difference_type>(icl::pred(first(x2) - last(x1)));
  1246. else if(domain_less<Type>(last(x2), first(x1)))
  1247. return static_cast<difference_type>(icl::pred(first(x1) - last(x2)));
  1248. else
  1249. return icl::identity_element<difference_type>::value();
  1250. }
  1251. template<class Type>
  1252. typename boost::
  1253. enable_if< mpl::and_< is_interval<Type>
  1254. , has_difference<typename interval_traits<Type>::domain_type>
  1255. , is_continuous<typename interval_traits<Type>::domain_type>
  1256. >
  1257. , typename difference_type_of<interval_traits<Type> >::type>::type
  1258. distance(const Type& x1, const Type& x2)
  1259. {
  1260. typedef typename difference_type_of<interval_traits<Type> >::type DiffT;
  1261. if(icl::is_empty(x1) || icl::is_empty(x2))
  1262. return icl::identity_element<DiffT>::value();
  1263. else if(domain_less<Type>(upper(x1), lower(x2)))
  1264. return lower(x2) - upper(x1);
  1265. else if(domain_less<Type>(upper(x2), lower(x1)))
  1266. return lower(x1) - upper(x2);
  1267. else
  1268. return icl::identity_element<DiffT>::value();
  1269. }
  1270. //==============================================================================
  1271. //= Streaming, representation
  1272. //==============================================================================
  1273. template<class Type>
  1274. typename boost::
  1275. enable_if< mpl::or_< is_static_left_open<Type>
  1276. , is_static_open<Type> >, std::string>::type
  1277. left_bracket(const Type&) { return "("; }
  1278. template<class Type>
  1279. typename boost::
  1280. enable_if< mpl::or_< is_static_right_open<Type>
  1281. , is_static_closed<Type> >, std::string>::type
  1282. left_bracket(const Type&) { return "["; }
  1283. template<class Type>
  1284. typename boost::enable_if<has_dynamic_bounds<Type>, std::string>::type
  1285. left_bracket(const Type& object)
  1286. {
  1287. return left_bracket(object.bounds());
  1288. }
  1289. //------------------------------------------------------------------------------
  1290. template<class Type>
  1291. typename boost::
  1292. enable_if< mpl::or_< is_static_right_open<Type>
  1293. , is_static_open<Type> >, std::string>::type
  1294. right_bracket(const Type&) { return ")"; }
  1295. template<class Type>
  1296. typename boost::
  1297. enable_if< mpl::or_< is_static_left_open<Type>
  1298. , is_static_closed<Type> >, std::string>::type
  1299. right_bracket(const Type&) { return "]"; }
  1300. template<class Type>
  1301. typename boost::enable_if<has_dynamic_bounds<Type>, std::string>::type
  1302. right_bracket(const Type& object)
  1303. {
  1304. return right_bracket(object.bounds());
  1305. }
  1306. //------------------------------------------------------------------------------
  1307. template<class CharType, class CharTraits, class Type>
  1308. typename boost::enable_if<is_interval<Type>,
  1309. std::basic_ostream<CharType, CharTraits> >::type&
  1310. operator << (std::basic_ostream<CharType, CharTraits> &stream, Type const& object)
  1311. {
  1312. if(boost::icl::is_empty(object))
  1313. return stream << left_bracket<Type>(object) << right_bracket<Type>(object);
  1314. else
  1315. return stream << left_bracket<Type>(object)
  1316. << interval_traits<Type>::lower(object)
  1317. << ","
  1318. << interval_traits<Type>::upper(object)
  1319. << right_bracket<Type>(object) ;
  1320. }
  1321. }} // namespace icl boost
  1322. #endif