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 11 #include <functional> 12 #include <boost/type_traits.hpp> 13 #include <boost/mpl/if.hpp> 14 #include <boost/icl/type_traits/identity_element.hpp> 15 #include <boost/icl/type_traits/unit_element.hpp> 16 #include <boost/icl/type_traits/is_set.hpp> 17 #include <boost/icl/type_traits/has_set_semantics.hpp> 18 19 namespace boost{namespace icl 20 { 21 // ------------------------------------------------------------------------ 22 template <typename Type> struct identity_based_inplace_combine 23 : public std::binary_function<Type&, const Type&, void> 24 { identity_elementboost::icl::identity_based_inplace_combine25 inline static Type identity_element() { return boost::icl::identity_element<Type>::value(); } 26 }; 27 28 // ------------------------------------------------------------------------ 29 template <typename Type> struct unit_element_based_inplace_combine 30 : public std::binary_function<Type&, const Type&, void> 31 { identity_elementboost::icl::unit_element_based_inplace_combine32 inline static Type identity_element() { return boost::icl::unit_element<Type>::value(); } 33 }; 34 35 // ------------------------------------------------------------------------ 36 template <typename Type> struct inplace_identity 37 : public identity_based_inplace_combine<Type> 38 { 39 typedef inplace_identity<Type> type; operator ()boost::icl::inplace_identity40 void operator()(Type&, const Type&)const{} 41 }; 42 43 template<> apply()44 inline std::string unary_template_to_string<inplace_identity>::apply() 45 { return "i="; } 46 47 // ------------------------------------------------------------------------ 48 template <typename Type> struct inplace_erasure 49 : public identity_based_inplace_combine<Type> 50 { 51 typedef inplace_erasure<Type> type; 52 typedef identity_based_inplace_combine<Type> base_type; 53 operator ()boost::icl::inplace_erasure54 void operator()(Type& object, const Type& operand)const 55 { 56 if(object == operand) 57 //identity_element(); //JODO Old gcc-3.4.4 does not compile this 58 object = base_type::identity_element(); //<-- but this. 59 } 60 }; 61 62 template<> apply()63 inline std::string unary_template_to_string<inplace_erasure>::apply() 64 { return "0="; } 65 66 // ------------------------------------------------------------------------ 67 template <typename Type> struct inplace_plus 68 : public identity_based_inplace_combine<Type> 69 { 70 typedef inplace_plus<Type> type; 71 operator ()boost::icl::inplace_plus72 void operator()(Type& object, const Type& operand)const 73 { object += operand; } 74 versionboost::icl::inplace_plus75 static void version(Type&){} 76 }; 77 78 template<> apply()79 inline std::string unary_template_to_string<inplace_plus>::apply() { return "+="; } 80 81 // ------------------------------------------------------------------------ 82 template <typename Type> struct inplace_minus 83 : public identity_based_inplace_combine<Type> 84 { 85 typedef inplace_minus<Type> type; 86 operator ()boost::icl::inplace_minus87 void operator()(Type& object, const Type& operand)const 88 { object -= operand; } 89 }; 90 91 template<> apply()92 inline std::string unary_template_to_string<inplace_minus>::apply() { return "-="; } 93 94 // ------------------------------------------------------------------------ 95 template <typename Type> struct inplace_bit_add 96 : public identity_based_inplace_combine<Type> 97 { 98 typedef inplace_bit_add<Type> type; 99 operator ()boost::icl::inplace_bit_add100 void operator()(Type& object, const Type& operand)const 101 { object |= operand; } 102 versionboost::icl::inplace_bit_add103 static void version(Type&){} 104 }; 105 106 template<> apply()107 inline std::string unary_template_to_string<inplace_bit_add>::apply() { return "b|="; } 108 109 // ------------------------------------------------------------------------ 110 template <typename Type> struct inplace_bit_subtract 111 : public identity_based_inplace_combine<Type> 112 { 113 typedef inplace_bit_subtract<Type> type; 114 operator ()boost::icl::inplace_bit_subtract115 void operator()(Type& object, const Type& operand)const 116 { object &= ~operand; } 117 }; 118 119 template<> apply()120 inline std::string unary_template_to_string<inplace_bit_subtract>::apply() { return "b-="; } 121 122 // ------------------------------------------------------------------------ 123 template <typename Type> struct inplace_bit_and 124 : public identity_based_inplace_combine<Type> 125 { 126 typedef inplace_bit_and<Type> type; 127 operator ()boost::icl::inplace_bit_and128 void operator()(Type& object, const Type& operand)const 129 { object &= operand; } 130 }; 131 132 template<> apply()133 inline std::string unary_template_to_string<inplace_bit_and>::apply() { return "b&="; } 134 135 // ------------------------------------------------------------------------ 136 template <typename Type> struct inplace_bit_xor 137 : public identity_based_inplace_combine<Type> 138 { 139 typedef inplace_bit_xor<Type> type; 140 operator ()boost::icl::inplace_bit_xor141 void operator()(Type& object, const Type& operand)const 142 { object ^= operand; } 143 }; 144 145 // ------------------------------------------------------------------------ 146 template <typename Type> struct inplace_et 147 : public identity_based_inplace_combine<Type> 148 { 149 typedef inplace_et<Type> type; 150 operator ()boost::icl::inplace_et151 void operator()(Type& object, const Type& operand)const 152 { object &= operand; } 153 }; 154 155 template<> apply()156 inline std::string unary_template_to_string<inplace_et>::apply() { return "&="; } 157 158 // ------------------------------------------------------------------------ 159 template <typename Type> struct inplace_caret 160 : public identity_based_inplace_combine<Type> 161 { 162 typedef inplace_caret<Type> type; 163 operator ()boost::icl::inplace_caret164 void operator()(Type& object, const Type& operand)const 165 { object ^= operand; } 166 }; 167 168 template<> apply()169 inline std::string unary_template_to_string<inplace_caret>::apply() { return "^="; } 170 171 // ------------------------------------------------------------------------ 172 template <typename Type> struct inplace_insert 173 : public identity_based_inplace_combine<Type> 174 { 175 typedef inplace_insert<Type> type; 176 operator ()boost::icl::inplace_insert177 void operator()(Type& object, const Type& operand)const 178 { insert(object,operand); } 179 }; 180 181 template<> apply()182 inline std::string unary_template_to_string<inplace_insert>::apply() { return "ins="; } 183 184 // ------------------------------------------------------------------------ 185 template <typename Type> struct inplace_erase 186 : public identity_based_inplace_combine<Type> 187 { 188 typedef inplace_erase<Type> type; 189 operator ()boost::icl::inplace_erase190 void operator()(Type& object, const Type& operand)const 191 { erase(object,operand); } 192 }; 193 194 template<> apply()195 inline std::string unary_template_to_string<inplace_erase>::apply() { return "ers="; } 196 197 // ------------------------------------------------------------------------ 198 template <typename Type> struct inplace_star 199 : public identity_based_inplace_combine<Type> //JODO unit_element_ 200 { 201 typedef inplace_star<Type> type; 202 operator ()boost::icl::inplace_star203 void operator()(Type& object, const Type& operand)const 204 { object *= operand; } 205 }; 206 207 template<> apply()208 inline std::string unary_template_to_string<inplace_star>::apply() { return "*="; } 209 210 // ------------------------------------------------------------------------ 211 template <typename Type> struct inplace_slash 212 : public identity_based_inplace_combine<Type> //JODO unit_element_ 213 { 214 typedef inplace_slash<Type> type; 215 operator ()boost::icl::inplace_slash216 void operator()(Type& object, const Type& operand)const 217 { object /= operand; } 218 }; 219 220 template<> apply()221 inline std::string unary_template_to_string<inplace_slash>::apply() { return "/="; } 222 223 // ------------------------------------------------------------------------ 224 template <typename Type> struct inplace_max 225 : public identity_based_inplace_combine<Type> 226 { 227 typedef inplace_max<Type> type; 228 operator ()boost::icl::inplace_max229 void operator()(Type& object, const Type& operand)const 230 { 231 if(object < operand) 232 object = operand; 233 } 234 }; 235 236 template<> apply()237 inline std::string unary_template_to_string<inplace_max>::apply() { return "max="; } 238 239 // ------------------------------------------------------------------------ 240 template <typename Type> struct inplace_min 241 : public identity_based_inplace_combine<Type> 242 { 243 typedef inplace_min<Type> type; 244 operator ()boost::icl::inplace_min245 void operator()(Type& object, const Type& operand)const 246 { 247 if(object > operand) 248 object = operand; 249 } 250 }; 251 252 template<> apply()253 inline std::string unary_template_to_string<inplace_min>::apply() { return "min="; } 254 255 //-------------------------------------------------------------------------- 256 // Inter_section functor 257 //-------------------------------------------------------------------------- 258 template<class Type> struct inter_section 259 : public identity_based_inplace_combine<Type> 260 { 261 typedef typename boost::mpl:: 262 if_<has_set_semantics<Type>, 263 icl::inplace_et<Type>, 264 icl::inplace_plus<Type> 265 >::type 266 type; 267 operator ()boost::icl::inter_section268 void operator()(Type& object, const Type& operand)const 269 { 270 type()(object, operand); 271 } 272 }; 273 274 //-------------------------------------------------------------------------- 275 // Inverse functor 276 //-------------------------------------------------------------------------- 277 template<class Functor> struct inverse; 278 279 template<class Type> 280 struct inverse<icl::inplace_plus<Type> > 281 { typedef icl::inplace_minus<Type> type; }; 282 283 template<class Type> 284 struct inverse<icl::inplace_minus<Type> > 285 { typedef icl::inplace_plus<Type> type; }; 286 287 template<class Type> 288 struct inverse<icl::inplace_bit_add<Type> > 289 { typedef icl::inplace_bit_subtract<Type> type; }; 290 291 template<class Type> 292 struct inverse<icl::inplace_bit_subtract<Type> > 293 { typedef icl::inplace_bit_add<Type> type; }; 294 295 template<class Type> 296 struct inverse<icl::inplace_et<Type> > 297 { typedef icl::inplace_caret<Type> type; }; 298 299 template<class Type> 300 struct inverse<icl::inplace_caret<Type> > 301 { typedef icl::inplace_et<Type> type; }; 302 303 template<class Type> 304 struct inverse<icl::inplace_bit_and<Type> > 305 { typedef icl::inplace_bit_xor<Type> type; }; 306 307 template<class Type> 308 struct inverse<icl::inplace_bit_xor<Type> > 309 { typedef icl::inplace_bit_and<Type> type; }; 310 311 template<class Type> 312 struct inverse<icl::inplace_star<Type> > 313 { typedef icl::inplace_slash<Type> type; }; 314 315 template<class Type> 316 struct inverse<icl::inplace_slash<Type> > 317 { typedef icl::inplace_star<Type> type; }; 318 319 template<class Type> 320 struct inverse<icl::inplace_max<Type> > 321 { typedef icl::inplace_min<Type> type; }; 322 323 template<class Type> 324 struct inverse<icl::inplace_min<Type> > 325 { typedef icl::inplace_max<Type> type; }; 326 327 template<class Type> 328 struct inverse<icl::inplace_identity<Type> > 329 { typedef icl::inplace_erasure<Type> type; }; 330 331 // If a Functor 332 template<class Functor> 333 struct inverse 334 { 335 typedef typename 336 remove_reference<typename Functor::first_argument_type>::type argument_type; 337 typedef icl::inplace_erasure<argument_type> type; 338 }; 339 340 341 //-------------------------------------------------------------------------- 342 // Inverse inter_section functor 343 //-------------------------------------------------------------------------- 344 template<class Type> 345 struct inverse<icl::inter_section<Type> > 346 : public identity_based_inplace_combine<Type> 347 { 348 typedef typename boost::mpl:: 349 if_<has_set_semantics<Type>, 350 icl::inplace_caret<Type>, 351 icl::inplace_minus<Type> 352 >::type 353 type; 354 operator ()boost::icl::inverse355 void operator()(Type& object, const Type& operand)const 356 { 357 type()(object, operand); 358 } 359 }; 360 361 362 //-------------------------------------------------------------------------- 363 // Positive or negative functor trait 364 //-------------------------------------------------------------------------- 365 366 // A binary operation - is negative (or inverting) with respect to the 367 // neutral element iff it yields the inverse element if it is applied to the 368 // identity element: 369 // 0 - x = -x 370 // For a functor that wraps the inplace of op-assign version this is 371 // equivalent to 372 // 373 // T x = ..., y; 374 // y = Functor::identity_element(); 375 // Functor()(y, x); // y == inverse_of(x) 376 377 template<class Functor> struct is_negative; 378 379 template<class Functor> 380 struct is_negative 381 { 382 typedef is_negative<Functor> type; 383 BOOST_STATIC_CONSTANT(bool, value = false); 384 }; 385 386 template<class Type> 387 struct is_negative<icl::inplace_minus<Type> > 388 { 389 typedef is_negative type; 390 BOOST_STATIC_CONSTANT(bool, value = true); 391 }; 392 393 template<class Type> 394 struct is_negative<icl::inplace_bit_subtract<Type> > 395 { 396 typedef is_negative type; 397 BOOST_STATIC_CONSTANT(bool, value = true); 398 }; 399 400 //-------------------------------------------------------------------------- 401 // Pro- or in-version functor 402 //-------------------------------------------------------------------------- 403 template<class Combiner> struct conversion; 404 405 template<class Combiner> 406 struct conversion 407 { 408 typedef conversion<Combiner> type; 409 typedef typename 410 remove_const< 411 typename remove_reference<typename Combiner::first_argument_type 412 >::type 413 >::type 414 argument_type; 415 // The proversion of an op-assign functor o= lets the value unchanged 416 // (0 o= x) == x; 417 // Example += : (0 += x) == x proversionboost::icl::conversion418 static argument_type proversion(const argument_type& value) 419 { 420 return value; 421 } 422 423 // The inversion of an op-assign functor o= inverts the value x 424 // to it's inverse element -x 425 // (0 o= x) == -x; 426 // Example -= : (0 -= x) == -x inversionboost::icl::conversion427 static argument_type inversion(const argument_type& value) 428 { 429 argument_type inverse = Combiner::identity_element(); 430 Combiner()(inverse, value); 431 return inverse; 432 } 433 }; 434 435 template<class Combiner> struct version : public conversion<Combiner> 436 { 437 typedef version<Combiner> type; 438 typedef conversion<Combiner> base_type; 439 typedef typename base_type::argument_type argument_type; 440 operator ()boost::icl::version441 argument_type operator()(const argument_type& value) 442 { return base_type::proversion(value); } 443 }; 444 operator ()boost::icl::version445 template<>struct version<icl::inplace_minus<short > >{short operator()(short val){return -val;}}; operator ()boost::icl::version446 template<>struct version<icl::inplace_minus<int > >{int operator()(int val){return -val;}}; operator ()boost::icl::version447 template<>struct version<icl::inplace_minus<long > >{long operator()(long val){return -val;}}; operator ()boost::icl::version448 template<>struct version<icl::inplace_minus<long long > >{long long operator()(long long val){return -val;}}; operator ()boost::icl::version449 template<>struct version<icl::inplace_minus<float > >{float operator()(float val){return -val;}}; operator ()boost::icl::version450 template<>struct version<icl::inplace_minus<double > >{double operator()(double val){return -val;}}; operator ()boost::icl::version451 template<>struct version<icl::inplace_minus<long double> >{long double operator()(long double val){return -val;}}; 452 453 template<class Type> 454 struct version<icl::inplace_minus<Type> > : public conversion<icl::inplace_minus<Type> > 455 { 456 typedef version<icl::inplace_minus<Type> > type; 457 typedef conversion<icl::inplace_minus<Type> > base_type; 458 typedef typename base_type::argument_type argument_type; 459 operator ()boost::icl::version460 Type operator()(const Type& value) 461 { 462 return base_type::inversion(value); 463 } 464 }; 465 466 }} // namespace icl boost 467 468 #endif 469 470 471