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