PageRenderTime 70ms CodeModel.GetById 10ms app.highlight 54ms RepoModel.GetById 2ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/accumulators/numeric/functional.hpp

http://hadesmem.googlecode.com/
C++ Header | 490 lines | 394 code | 62 blank | 34 comment | 2 complexity | 9c728dcd0cdf902362cc4a0863d40913 MD5 | raw file
  1///////////////////////////////////////////////////////////////////////////////
  2/// \file functional.hpp
  3///
  4//  Copyright 2005 Eric Niebler. Distributed under the Boost
  5//  Software License, Version 1.0. (See accompanying file
  6//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7
  8#ifndef BOOST_NUMERIC_FUNCTIONAL_HPP_EAN_08_12_2005
  9#define BOOST_NUMERIC_FUNCTIONAL_HPP_EAN_08_12_2005
 10
 11#include <limits>
 12#include <functional>
 13#include <boost/mpl/if.hpp>
 14#include <boost/mpl/and.hpp>
 15#include <boost/type_traits/remove_const.hpp>
 16#include <boost/type_traits/add_reference.hpp>
 17#include <boost/type_traits/is_empty.hpp>
 18#include <boost/type_traits/is_integral.hpp>
 19#include <boost/type_traits/is_floating_point.hpp>
 20#include <boost/utility/enable_if.hpp>
 21#include <boost/typeof/typeof.hpp>
 22#include <boost/accumulators/numeric/functional_fwd.hpp>
 23#include <boost/accumulators/numeric/detail/function1.hpp>
 24#include <boost/accumulators/numeric/detail/function2.hpp>
 25#include <boost/accumulators/numeric/detail/pod_singleton.hpp>
 26
 27#ifdef BOOST_NUMERIC_FUNCTIONAL_STD_VECTOR_SUPPORT
 28# include <boost/accumulators/numeric/functional/vector.hpp>
 29#endif
 30
 31#ifdef BOOST_NUMERIC_FUNCTIONAL_STD_VALARRAY_SUPPORT
 32# include <boost/accumulators/numeric/functional/valarray.hpp>
 33#endif
 34
 35#ifdef BOOST_NUMERIC_FUNCTIONAL_STD_COMPLEX_SUPPORT
 36# include <boost/accumulators/numeric/functional/complex.hpp>
 37#endif
 38
 39/// INTERNAL ONLY
 40///
 41#define BOOST_NUMERIC_FUNCTIONAL_HPP_INCLUDED
 42
 43#ifdef BOOST_NUMERIC_FUNCTIONAL_DOXYGEN_INVOKED
 44// Hack to make Doxygen show the inheritance relationships
 45/// INTERNAL ONLY
 46///
 47namespace std
 48{
 49    /// INTERNAL ONLY
 50    ///
 51    template<class Arg, class Ret> struct unary_function {};
 52    /// INTERNAL ONLY
 53    ///
 54    template<class Left, class Right, class Ret> struct binary_function {};
 55}
 56#endif
 57
 58namespace boost { namespace numeric
 59{
 60    namespace functional
 61    {
 62        /// INTERNAL ONLY
 63        ///
 64        template<typename A0, typename A1>
 65        struct are_integral
 66          : mpl::and_<is_integral<A0>, is_integral<A1> >
 67        {};
 68
 69        template<typename Left, typename Right>
 70        struct left_ref
 71        {
 72            typedef Left &type;
 73        };
 74
 75        namespace detail
 76        {
 77            template<typename T>
 78            T &lvalue_of();
 79        }
 80    }
 81
 82    // TODO: handle complex weight, valarray, MTL vectors
 83
 84    /// INTERNAL ONLY
 85    ///
 86#define BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(Name, Op)                                      \
 87    namespace functional                                                                        \
 88    {                                                                                           \
 89        template<typename Arg>                                                                  \
 90        struct result_of_ ## Name                                                               \
 91        {                                                                                       \
 92            BOOST_TYPEOF_NESTED_TYPEDEF_TPL(                                                    \
 93                nested                                                                          \
 94              , Op boost::numeric::functional::detail::lvalue_of<Arg>()                         \
 95            )                                                                                   \
 96            typedef typename nested::type type;                                                 \
 97        };                                                                                      \
 98        template<typename Arg, typename EnableIf>                                               \
 99        struct Name ## _base                                                                    \
100          : std::unary_function<                                                                \
101                typename remove_const<Arg>::type                                                \
102              , typename result_of_ ## Name<Arg>::type                                          \
103            >                                                                                   \
104        {                                                                                       \
105            typename result_of_ ## Name<Arg>::type operator ()(Arg &arg) const                  \
106            {                                                                                   \
107                return Op arg;                                                                  \
108            }                                                                                   \
109        };                                                                                      \
110        template<typename Arg, typename ArgTag>                                                 \
111        struct Name                                                                             \
112          : Name ## _base<Arg, void>                                                            \
113        {};                                                                                     \
114    }                                                                                           \
115    namespace op                                                                                \
116    {                                                                                           \
117        struct Name                                                                             \
118          : boost::detail::function1<functional::Name<_, functional::tag<_> > >                 \
119        {};                                                                                     \
120    }                                                                                           \
121    namespace                                                                                   \
122    {                                                                                           \
123        op::Name const &Name = boost::detail::pod_singleton<op::Name>::instance;                \
124    }                                                                                           \
125    /**/
126
127    /// INTERNAL ONLY
128    ///
129#define BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(Name, Op, RetType)                            \
130    namespace functional                                                                        \
131    {                                                                                           \
132        template<typename Left, typename Right, typename EnableIf>                              \
133        struct result_of_ ## Name                                                               \
134        {                                                                                       \
135            RetType(Left, Op, Right)                                                            \
136        };                                                                                      \
137        template<typename Left, typename Right, typename EnableIf>                              \
138        struct Name ## _base                                                                    \
139          : std::binary_function<                                                               \
140                typename remove_const<Left>::type                                               \
141              , typename remove_const<Right>::type                                              \
142              , typename result_of_ ## Name<Left, Right>::type                                  \
143            >                                                                                   \
144        {                                                                                       \
145            typename result_of_ ## Name<Left, Right>::type                                      \
146            operator ()(Left &left, Right &right) const                                         \
147            {                                                                                   \
148                return left Op right;                                                           \
149            }                                                                                   \
150        };                                                                                      \
151        template<typename Left, typename Right, typename LeftTag, typename RightTag>            \
152        struct Name                                                                             \
153          : Name ## _base<Left, Right, void>                                                    \
154        {};                                                                                     \
155    }                                                                                           \
156    namespace op                                                                                \
157    {                                                                                           \
158        struct Name                                                                             \
159          : boost::detail::function2<                                                           \
160                functional::Name<_1, _2, functional::tag<_1>, functional::tag<_2> >             \
161            >                                                                                   \
162        {};                                                                                     \
163    }                                                                                           \
164    namespace                                                                                   \
165    {                                                                                           \
166        op::Name const &Name = boost::detail::pod_singleton<op::Name>::instance;                \
167    }                                                                                           \
168    /**/
169
170    /// INTERNAL ONLY
171    ///
172#define BOOST_NUMERIC_FUNCTIONAL_DEDUCED(Left, Op, Right)                                       \
173    BOOST_TYPEOF_NESTED_TYPEDEF_TPL(                                                            \
174        nested                                                                                  \
175      , boost::numeric::functional::detail::lvalue_of<Left>() Op                                \
176        boost::numeric::functional::detail::lvalue_of<Right>()                                  \
177    )                                                                                           \
178    typedef typename nested::type type;                                                         \
179    /**/
180
181    /// INTERNAL ONLY
182    ///
183#define BOOST_NUMERIC_FUNCTIONAL_LEFT(Left, Op, Right)                                          \
184    typedef Left &type;                                                                         \
185    /**/
186
187    BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(plus, +, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
188    BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(minus, -, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
189    BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(multiplies, *, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
190    BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(divides, /, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
191    BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(modulus, %, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
192    BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(greater, >, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
193    BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(greater_equal, >=, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
194    BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(less, <, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
195    BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(less_equal, <=, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
196    BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(equal_to, ==, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
197    BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(not_equal_to, !=, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
198
199    BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(assign, =, BOOST_NUMERIC_FUNCTIONAL_LEFT)
200    BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(plus_assign, +=, BOOST_NUMERIC_FUNCTIONAL_LEFT)
201    BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(minus_assign, -=, BOOST_NUMERIC_FUNCTIONAL_LEFT)
202    BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(multiplies_assign, *=, BOOST_NUMERIC_FUNCTIONAL_LEFT)
203    BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(divides_assign, /=, BOOST_NUMERIC_FUNCTIONAL_LEFT)
204    BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(modulus_assign, %=, BOOST_NUMERIC_FUNCTIONAL_LEFT)
205
206    BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(unary_plus, +)
207    BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(unary_minus, -)
208    BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(complement, ~)
209    BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(logical_not, !)
210
211#undef BOOST_NUMERIC_FUNCTIONAL_LEFT
212#undef BOOST_NUMERIC_FUNCTIONAL_DEDUCED
213#undef BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP
214#undef BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP
215
216    namespace functional
217    {
218        template<typename Left, typename Right, typename EnableIf>
219        struct min_assign_base
220          : std::binary_function<Left, Right, void>
221        {
222            void operator ()(Left &left, Right &right) const
223            {
224                if(numeric::less(right, left))
225                {
226                    left = right;
227                }
228            }
229        };
230
231        template<typename Left, typename Right, typename EnableIf>
232        struct max_assign_base
233          : std::binary_function<Left, Right, void>
234        {
235            void operator ()(Left &left, Right &right) const
236            {
237                if(numeric::greater(right, left))
238                {
239                    left = right;
240                }
241            }
242        };
243
244        template<typename Left, typename Right, typename EnableIf>
245        struct average_base
246          : functional::divides<Left, Right>
247        {};
248
249        // partial specialization that promotes the arguments to double for
250        // integral division.
251        template<typename Left, typename Right>
252        struct average_base<Left, Right, typename enable_if<are_integral<Left, Right> >::type>
253          : functional::divides<double const, double const>
254        {};
255
256        template<typename To, typename From, typename EnableIf>
257        struct promote_base
258          : std::unary_function<From, To>
259        {
260            To operator ()(From &from) const
261            {
262                return from;
263            }
264        };
265
266        template<typename ToFrom>
267        struct promote_base<ToFrom, ToFrom, void>
268          : std::unary_function<ToFrom, ToFrom>
269        {
270            ToFrom &operator ()(ToFrom &tofrom)
271            {
272                return tofrom;
273            }
274        };
275
276        template<typename Arg, typename EnableIf>
277        struct as_min_base
278          : std::unary_function<Arg, typename remove_const<Arg>::type>
279        {
280            typename remove_const<Arg>::type operator ()(Arg &) const
281            {
282                return (std::numeric_limits<typename remove_const<Arg>::type>::min)();
283            }
284        };
285
286        template<typename Arg>
287        struct as_min_base<Arg, typename enable_if<is_floating_point<Arg> >::type>
288          : std::unary_function<Arg, typename remove_const<Arg>::type>
289        {
290            typename remove_const<Arg>::type operator ()(Arg &) const
291            {
292                return -(std::numeric_limits<typename remove_const<Arg>::type>::max)();
293            }
294        };
295
296        template<typename Arg, typename EnableIf>
297        struct as_max_base
298          : std::unary_function<Arg, typename remove_const<Arg>::type>
299        {
300            typename remove_const<Arg>::type operator ()(Arg &) const
301            {
302                return (std::numeric_limits<typename remove_const<Arg>::type>::max)();
303            }
304        };
305
306        template<typename Arg, typename EnableIf>
307        struct as_zero_base
308          : std::unary_function<Arg, typename remove_const<Arg>::type>
309        {
310            typename remove_const<Arg>::type operator ()(Arg &) const
311            {
312                return numeric::zero<typename remove_const<Arg>::type>::value;
313            }
314        };
315
316        template<typename Arg, typename EnableIf>
317        struct as_one_base
318          : std::unary_function<Arg, typename remove_const<Arg>::type>
319        {
320            typename remove_const<Arg>::type operator ()(Arg &) const
321            {
322                return numeric::one<typename remove_const<Arg>::type>::value;
323            }
324        };
325
326        template<typename To, typename From, typename ToTag, typename FromTag>
327        struct promote
328          : promote_base<To, From, void>
329        {};
330
331        template<typename Left, typename Right, typename LeftTag, typename RightTag>
332        struct min_assign
333          : min_assign_base<Left, Right, void>
334        {};
335
336        template<typename Left, typename Right, typename LeftTag, typename RightTag>
337        struct max_assign
338          : max_assign_base<Left, Right, void>
339        {};
340
341        template<typename Left, typename Right, typename LeftTag, typename RightTag>
342        struct average
343          : average_base<Left, Right, void>
344        {};
345
346        template<typename Arg, typename Tag>
347        struct as_min
348          : as_min_base<Arg, void>
349        {};
350
351        template<typename Arg, typename Tag>
352        struct as_max
353          : as_max_base<Arg, void>
354        {};
355
356        template<typename Arg, typename Tag>
357        struct as_zero
358          : as_zero_base<Arg, void>
359        {};
360
361        template<typename Arg, typename Tag>
362        struct as_one
363          : as_one_base<Arg, void>
364        {};
365    }
366
367    namespace op
368    {
369        template<typename To>
370        struct promote
371          : boost::detail::function1<functional::promote<To, _, typename functional::tag<To>::type, functional::tag<_> > >
372        {};
373
374        struct min_assign
375          : boost::detail::function2<functional::min_assign<_1, _2, functional::tag<_1>, functional::tag<_2> > >
376        {};
377
378        struct max_assign
379          : boost::detail::function2<functional::max_assign<_1, _2, functional::tag<_1>, functional::tag<_2> > >
380        {};
381
382        struct average
383          : boost::detail::function2<functional::average<_1, _2, functional::tag<_1>, functional::tag<_2> > >
384        {};
385
386        struct as_min
387          : boost::detail::function1<functional::as_min<_, functional::tag<_> > >
388        {};
389
390        struct as_max
391          : boost::detail::function1<functional::as_max<_, functional::tag<_> > >
392        {};
393
394        struct as_zero
395          : boost::detail::function1<functional::as_zero<_, functional::tag<_> > >
396        {};
397
398        struct as_one
399          : boost::detail::function1<functional::as_one<_, functional::tag<_> > >
400        {};
401    }
402
403    namespace
404    {
405        op::min_assign const &min_assign = boost::detail::pod_singleton<op::min_assign>::instance;
406        op::max_assign const &max_assign = boost::detail::pod_singleton<op::max_assign>::instance;
407        op::average const &average = boost::detail::pod_singleton<op::average>::instance;
408        op::as_min const &as_min = boost::detail::pod_singleton<op::as_min>::instance;
409        op::as_max const &as_max = boost::detail::pod_singleton<op::as_max>::instance;
410        op::as_zero const &as_zero = boost::detail::pod_singleton<op::as_zero>::instance;
411        op::as_one const &as_one = boost::detail::pod_singleton<op::as_one>::instance;
412    }
413
414    ///////////////////////////////////////////////////////////////////////////////
415    // promote
416    template<typename To, typename From>
417    typename lazy_disable_if<is_const<From>, mpl::if_<is_same<To, From>, To &, To> >::type
418    promote(From &from)
419    {
420        return functional::promote<To, From>()(from);
421    }
422
423    template<typename To, typename From>
424    typename mpl::if_<is_same<To const, From const>, To const &, To const>::type
425    promote(From const &from)
426    {
427        return functional::promote<To const, From const>()(from);
428    }
429
430    template<typename T>
431    struct default_
432    {
433        typedef default_ type;
434        typedef T value_type;
435        static T const value;
436
437        operator T const & () const
438        {
439            return default_::value;
440        }
441    };
442
443    template<typename T>
444    T const default_<T>::value = T();
445
446    template<typename T>
447    struct one
448    {
449        typedef one type;
450        typedef T value_type;
451        static T const value;
452
453        operator T const & () const
454        {
455            return one::value;
456        }
457    };
458
459    template<typename T>
460    T const one<T>::value = T(1);
461
462    template<typename T>
463    struct zero
464    {
465        typedef zero type;
466        typedef T value_type;
467        static T const value;
468
469        operator T const & () const
470        {
471            return zero::value;
472        }
473    };
474
475    template<typename T>
476    T const zero<T>::value = T();
477
478    template<typename T>
479    struct one_or_default
480      : mpl::if_<is_empty<T>, default_<T>, one<T> >::type
481    {};
482
483    template<typename T>
484    struct zero_or_default
485      : mpl::if_<is_empty<T>, default_<T>, zero<T> >::type
486    {};
487
488}} // namespace boost::numeric
489
490#endif