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