functors.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. /*-----------------------------------------------------------------------------+
  2. Copyright (c) 2007-2009: 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_FUNCTORS_HPP_JOFA_080315
  9. #define BOOST_ICL_FUNCTORS_HPP_JOFA_080315
  10. #include <functional>
  11. #include <boost/type_traits.hpp>
  12. #include <boost/mpl/if.hpp>
  13. #include <boost/icl/type_traits/identity_element.hpp>
  14. #include <boost/icl/type_traits/unit_element.hpp>
  15. #include <boost/icl/type_traits/is_set.hpp>
  16. #include <boost/icl/type_traits/has_set_semantics.hpp>
  17. namespace boost{namespace icl
  18. {
  19. // ------------------------------------------------------------------------
  20. template <typename Type> struct identity_based_inplace_combine
  21. : public std::binary_function<Type&, const Type&, void>
  22. {
  23. inline static Type identity_element() { return boost::icl::identity_element<Type>::value(); }
  24. };
  25. // ------------------------------------------------------------------------
  26. template <typename Type> struct unit_element_based_inplace_combine
  27. : public std::binary_function<Type&, const Type&, void>
  28. {
  29. inline static Type identity_element() { return boost::icl::unit_element<Type>::value(); }
  30. };
  31. // ------------------------------------------------------------------------
  32. template <typename Type> struct inplace_identity
  33. : public identity_based_inplace_combine<Type>
  34. {
  35. typedef inplace_identity<Type> type;
  36. void operator()(Type&, const Type&)const{}
  37. };
  38. template<>
  39. inline std::string unary_template_to_string<inplace_identity>::apply()
  40. { return "i="; }
  41. // ------------------------------------------------------------------------
  42. template <typename Type> struct inplace_erasure
  43. : public identity_based_inplace_combine<Type>
  44. {
  45. typedef inplace_erasure<Type> type;
  46. typedef identity_based_inplace_combine<Type> base_type;
  47. void operator()(Type& object, const Type& operand)const
  48. {
  49. if(object == operand)
  50. //identity_element(); //JODO Old gcc-3.4.4 does not compile this
  51. object = base_type::identity_element(); //<-- but this.
  52. }
  53. };
  54. template<>
  55. inline std::string unary_template_to_string<inplace_erasure>::apply()
  56. { return "0="; }
  57. // ------------------------------------------------------------------------
  58. template <typename Type> struct inplace_plus
  59. : public identity_based_inplace_combine<Type>
  60. {
  61. typedef inplace_plus<Type> type;
  62. void operator()(Type& object, const Type& operand)const
  63. { object += operand; }
  64. static void version(Type&){}
  65. };
  66. template<>
  67. inline std::string unary_template_to_string<inplace_plus>::apply() { return "+="; }
  68. // ------------------------------------------------------------------------
  69. template <typename Type> struct inplace_minus
  70. : public identity_based_inplace_combine<Type>
  71. {
  72. typedef inplace_minus<Type> type;
  73. void operator()(Type& object, const Type& operand)const
  74. { object -= operand; }
  75. };
  76. template<>
  77. inline std::string unary_template_to_string<inplace_minus>::apply() { return "-="; }
  78. // ------------------------------------------------------------------------
  79. template <typename Type> struct inplace_bit_add
  80. : public identity_based_inplace_combine<Type>
  81. {
  82. typedef inplace_bit_add<Type> type;
  83. void operator()(Type& object, const Type& operand)const
  84. { object |= operand; }
  85. static void version(Type&){}
  86. };
  87. template<>
  88. inline std::string unary_template_to_string<inplace_bit_add>::apply() { return "b|="; }
  89. // ------------------------------------------------------------------------
  90. template <typename Type> struct inplace_bit_subtract
  91. : public identity_based_inplace_combine<Type>
  92. {
  93. typedef inplace_bit_subtract<Type> type;
  94. void operator()(Type& object, const Type& operand)const
  95. { object &= ~operand; }
  96. };
  97. template<>
  98. inline std::string unary_template_to_string<inplace_bit_subtract>::apply() { return "b-="; }
  99. // ------------------------------------------------------------------------
  100. template <typename Type> struct inplace_bit_and
  101. : public identity_based_inplace_combine<Type>
  102. {
  103. typedef inplace_bit_and<Type> type;
  104. void operator()(Type& object, const Type& operand)const
  105. { object &= operand; }
  106. };
  107. template<>
  108. inline std::string unary_template_to_string<inplace_bit_and>::apply() { return "b&="; }
  109. // ------------------------------------------------------------------------
  110. template <typename Type> struct inplace_bit_xor
  111. : public identity_based_inplace_combine<Type>
  112. {
  113. typedef inplace_bit_xor<Type> type;
  114. void operator()(Type& object, const Type& operand)const
  115. { object ^= operand; }
  116. };
  117. // ------------------------------------------------------------------------
  118. template <typename Type> struct inplace_et
  119. : public identity_based_inplace_combine<Type>
  120. {
  121. typedef inplace_et<Type> type;
  122. void operator()(Type& object, const Type& operand)const
  123. { object &= operand; }
  124. };
  125. template<>
  126. inline std::string unary_template_to_string<inplace_et>::apply() { return "&="; }
  127. // ------------------------------------------------------------------------
  128. template <typename Type> struct inplace_caret
  129. : public identity_based_inplace_combine<Type>
  130. {
  131. typedef inplace_caret<Type> type;
  132. void operator()(Type& object, const Type& operand)const
  133. { object ^= operand; }
  134. };
  135. template<>
  136. inline std::string unary_template_to_string<inplace_caret>::apply() { return "^="; }
  137. // ------------------------------------------------------------------------
  138. template <typename Type> struct inplace_insert
  139. : public identity_based_inplace_combine<Type>
  140. {
  141. typedef inplace_insert<Type> type;
  142. void operator()(Type& object, const Type& operand)const
  143. { insert(object,operand); }
  144. };
  145. template<>
  146. inline std::string unary_template_to_string<inplace_insert>::apply() { return "ins="; }
  147. // ------------------------------------------------------------------------
  148. template <typename Type> struct inplace_erase
  149. : public identity_based_inplace_combine<Type>
  150. {
  151. typedef inplace_erase<Type> type;
  152. void operator()(Type& object, const Type& operand)const
  153. { erase(object,operand); }
  154. };
  155. template<>
  156. inline std::string unary_template_to_string<inplace_erase>::apply() { return "ers="; }
  157. // ------------------------------------------------------------------------
  158. template <typename Type> struct inplace_star
  159. : public identity_based_inplace_combine<Type> //JODO unit_element_
  160. {
  161. typedef inplace_star<Type> type;
  162. void operator()(Type& object, const Type& operand)const
  163. { object *= operand; }
  164. };
  165. template<>
  166. inline std::string unary_template_to_string<inplace_star>::apply() { return "*="; }
  167. // ------------------------------------------------------------------------
  168. template <typename Type> struct inplace_slash
  169. : public identity_based_inplace_combine<Type> //JODO unit_element_
  170. {
  171. typedef inplace_slash<Type> type;
  172. void operator()(Type& object, const Type& operand)const
  173. { object /= operand; }
  174. };
  175. template<>
  176. inline std::string unary_template_to_string<inplace_slash>::apply() { return "/="; }
  177. // ------------------------------------------------------------------------
  178. template <typename Type> struct inplace_max
  179. : public identity_based_inplace_combine<Type>
  180. {
  181. typedef inplace_max<Type> type;
  182. void operator()(Type& object, const Type& operand)const
  183. {
  184. if(object < operand)
  185. object = operand;
  186. }
  187. };
  188. template<>
  189. inline std::string unary_template_to_string<inplace_max>::apply() { return "max="; }
  190. // ------------------------------------------------------------------------
  191. template <typename Type> struct inplace_min
  192. : public identity_based_inplace_combine<Type>
  193. {
  194. typedef inplace_min<Type> type;
  195. void operator()(Type& object, const Type& operand)const
  196. {
  197. if(object > operand)
  198. object = operand;
  199. }
  200. };
  201. template<>
  202. inline std::string unary_template_to_string<inplace_min>::apply() { return "min="; }
  203. //--------------------------------------------------------------------------
  204. // Inter_section functor
  205. //--------------------------------------------------------------------------
  206. template<class Type> struct inter_section
  207. : public identity_based_inplace_combine<Type>
  208. {
  209. typedef typename boost::mpl::
  210. if_<has_set_semantics<Type>,
  211. icl::inplace_et<Type>,
  212. icl::inplace_plus<Type>
  213. >::type
  214. type;
  215. void operator()(Type& object, const Type& operand)const
  216. {
  217. type()(object, operand);
  218. }
  219. };
  220. //--------------------------------------------------------------------------
  221. // Inverse functor
  222. //--------------------------------------------------------------------------
  223. template<class Functor> struct inverse;
  224. template<class Type>
  225. struct inverse<icl::inplace_plus<Type> >
  226. { typedef icl::inplace_minus<Type> type; };
  227. template<class Type>
  228. struct inverse<icl::inplace_minus<Type> >
  229. { typedef icl::inplace_plus<Type> type; };
  230. template<class Type>
  231. struct inverse<icl::inplace_bit_add<Type> >
  232. { typedef icl::inplace_bit_subtract<Type> type; };
  233. template<class Type>
  234. struct inverse<icl::inplace_bit_subtract<Type> >
  235. { typedef icl::inplace_bit_add<Type> type; };
  236. template<class Type>
  237. struct inverse<icl::inplace_et<Type> >
  238. { typedef icl::inplace_caret<Type> type; };
  239. template<class Type>
  240. struct inverse<icl::inplace_caret<Type> >
  241. { typedef icl::inplace_et<Type> type; };
  242. template<class Type>
  243. struct inverse<icl::inplace_bit_and<Type> >
  244. { typedef icl::inplace_bit_xor<Type> type; };
  245. template<class Type>
  246. struct inverse<icl::inplace_bit_xor<Type> >
  247. { typedef icl::inplace_bit_and<Type> type; };
  248. template<class Type>
  249. struct inverse<icl::inplace_star<Type> >
  250. { typedef icl::inplace_slash<Type> type; };
  251. template<class Type>
  252. struct inverse<icl::inplace_slash<Type> >
  253. { typedef icl::inplace_star<Type> type; };
  254. template<class Type>
  255. struct inverse<icl::inplace_max<Type> >
  256. { typedef icl::inplace_min<Type> type; };
  257. template<class Type>
  258. struct inverse<icl::inplace_min<Type> >
  259. { typedef icl::inplace_max<Type> type; };
  260. template<class Type>
  261. struct inverse<icl::inplace_identity<Type> >
  262. { typedef icl::inplace_erasure<Type> type; };
  263. // If a Functor
  264. template<class Functor>
  265. struct inverse
  266. {
  267. typedef typename
  268. remove_reference<typename Functor::first_argument_type>::type argument_type;
  269. typedef icl::inplace_erasure<argument_type> type;
  270. };
  271. //--------------------------------------------------------------------------
  272. // Inverse inter_section functor
  273. //--------------------------------------------------------------------------
  274. template<class Type>
  275. struct inverse<icl::inter_section<Type> >
  276. : public identity_based_inplace_combine<Type>
  277. {
  278. typedef typename boost::mpl::
  279. if_<has_set_semantics<Type>,
  280. icl::inplace_caret<Type>,
  281. icl::inplace_minus<Type>
  282. >::type
  283. type;
  284. void operator()(Type& object, const Type& operand)const
  285. {
  286. type()(object, operand);
  287. }
  288. };
  289. //--------------------------------------------------------------------------
  290. // Positive or negative functor trait
  291. //--------------------------------------------------------------------------
  292. // A binary operation - is negative (or inverting) with respect to the
  293. // neutral element iff it yields the inverse element if it is applied to the
  294. // identity element:
  295. // 0 - x = -x
  296. // For a functor that wraps the inplace of op-assign version this is
  297. // equivalent to
  298. //
  299. // T x = ..., y;
  300. // y = Functor::identity_element();
  301. // Functor()(y, x); // y == inverse_of(x)
  302. template<class Functor> struct is_negative;
  303. template<class Functor>
  304. struct is_negative
  305. {
  306. typedef is_negative<Functor> type;
  307. BOOST_STATIC_CONSTANT(bool, value = false);
  308. };
  309. template<class Type>
  310. struct is_negative<icl::inplace_minus<Type> >
  311. {
  312. typedef is_negative type;
  313. BOOST_STATIC_CONSTANT(bool, value = true);
  314. };
  315. template<class Type>
  316. struct is_negative<icl::inplace_bit_subtract<Type> >
  317. {
  318. typedef is_negative type;
  319. BOOST_STATIC_CONSTANT(bool, value = true);
  320. };
  321. //--------------------------------------------------------------------------
  322. // Pro- or in-version functor
  323. //--------------------------------------------------------------------------
  324. template<class Combiner> struct conversion;
  325. template<class Combiner>
  326. struct conversion
  327. {
  328. typedef conversion<Combiner> type;
  329. typedef typename
  330. remove_const<
  331. typename remove_reference<typename Combiner::first_argument_type
  332. >::type
  333. >::type
  334. argument_type;
  335. // The proversion of an op-assign functor o= lets the value unchanged
  336. // (0 o= x) == x;
  337. // Example += : (0 += x) == x
  338. static argument_type proversion(const argument_type& value)
  339. {
  340. return value;
  341. }
  342. // The inversion of an op-assign functor o= inverts the value x
  343. // to it's inverse element -x
  344. // (0 o= x) == -x;
  345. // Example -= : (0 -= x) == -x
  346. static argument_type inversion(const argument_type& value)
  347. {
  348. argument_type inverse = Combiner::identity_element();
  349. Combiner()(inverse, value);
  350. return inverse;
  351. }
  352. };
  353. template<class Combiner> struct version : public conversion<Combiner>
  354. {
  355. typedef version<Combiner> type;
  356. typedef conversion<Combiner> base_type;
  357. typedef typename base_type::argument_type argument_type;
  358. argument_type operator()(const argument_type& value)
  359. { return base_type::proversion(value); }
  360. };
  361. template<>struct version<icl::inplace_minus<short > >{short operator()(short val){return -val;}};
  362. template<>struct version<icl::inplace_minus<int > >{int operator()(int val){return -val;}};
  363. template<>struct version<icl::inplace_minus<long > >{long operator()(long val){return -val;}};
  364. template<>struct version<icl::inplace_minus<long long > >{long long operator()(long long val){return -val;}};
  365. template<>struct version<icl::inplace_minus<float > >{float operator()(float val){return -val;}};
  366. template<>struct version<icl::inplace_minus<double > >{double operator()(double val){return -val;}};
  367. template<>struct version<icl::inplace_minus<long double> >{long double operator()(long double val){return -val;}};
  368. template<class Type>
  369. struct version<icl::inplace_minus<Type> > : public conversion<icl::inplace_minus<Type> >
  370. {
  371. typedef version<icl::inplace_minus<Type> > type;
  372. typedef conversion<icl::inplace_minus<Type> > base_type;
  373. typedef typename base_type::argument_type argument_type;
  374. Type operator()(const Type& value)
  375. {
  376. return base_type::inversion(value);
  377. }
  378. };
  379. }} // namespace icl boost
  380. #endif