functors.hpp 16 KB

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