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