Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:42:43

0001 ///////////////////////////////////////////////////////////////////////////////
0002 /// \file functional.hpp
0003 ///
0004 //  Copyright 2005 Eric Niebler. Distributed under the Boost
0005 //  Software License, Version 1.0. (See accompanying file
0006 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 
0008 #ifndef BOOST_NUMERIC_FUNCTIONAL_HPP_EAN_08_12_2005
0009 #define BOOST_NUMERIC_FUNCTIONAL_HPP_EAN_08_12_2005
0010 
0011 #include <limits>
0012 #include <functional>
0013 #include <boost/static_assert.hpp>
0014 #include <boost/mpl/if.hpp>
0015 #include <boost/mpl/and.hpp>
0016 #include <boost/type_traits/remove_const.hpp>
0017 #include <boost/type_traits/add_reference.hpp>
0018 #include <boost/type_traits/is_empty.hpp>
0019 #include <boost/type_traits/is_integral.hpp>
0020 #include <boost/type_traits/is_floating_point.hpp>
0021 #include <boost/utility/enable_if.hpp>
0022 #include <boost/typeof/typeof.hpp>
0023 #include <boost/accumulators/accumulators_fwd.hpp>
0024 #include <boost/accumulators/numeric/functional_fwd.hpp>
0025 #include <boost/accumulators/numeric/detail/function1.hpp>
0026 #include <boost/accumulators/numeric/detail/function2.hpp>
0027 #include <boost/accumulators/numeric/detail/pod_singleton.hpp>
0028 
0029 #ifdef BOOST_NUMERIC_FUNCTIONAL_STD_VECTOR_SUPPORT
0030 # include <boost/accumulators/numeric/functional/vector.hpp>
0031 #endif
0032 
0033 #ifdef BOOST_NUMERIC_FUNCTIONAL_STD_VALARRAY_SUPPORT
0034 # include <boost/accumulators/numeric/functional/valarray.hpp>
0035 #endif
0036 
0037 #ifdef BOOST_NUMERIC_FUNCTIONAL_STD_COMPLEX_SUPPORT
0038 # include <boost/accumulators/numeric/functional/complex.hpp>
0039 #endif
0040 
0041 /// INTERNAL ONLY
0042 ///
0043 #define BOOST_NUMERIC_FUNCTIONAL_HPP_INCLUDED
0044 
0045 #ifdef BOOST_NUMERIC_FUNCTIONAL_DOXYGEN_INVOKED
0046 // Hack to make Doxygen show the inheritance relationships
0047 /// INTERNAL ONLY
0048 ///
0049 namespace std
0050 {
0051     /// INTERNAL ONLY
0052     ///
0053     template<class Arg, class Ret> struct unary_function {};
0054     /// INTERNAL ONLY
0055     ///
0056     template<class Left, class Right, class Ret> struct binary_function {};
0057 }
0058 #endif
0059 
0060 namespace boost { namespace numeric
0061 {
0062     namespace functional
0063     {
0064         /// INTERNAL ONLY
0065         ///
0066         template<typename A0, typename A1>
0067         struct are_integral
0068           : mpl::and_<is_integral<A0>, is_integral<A1> >
0069         {};
0070 
0071         template<typename Left, typename Right>
0072         struct left_ref
0073         {
0074             typedef Left &type;
0075         };
0076 
0077         namespace detail
0078         {
0079             template<typename T>
0080             T &lvalue_of();
0081         }
0082     }
0083 
0084     // TODO: handle complex weight, valarray, MTL vectors
0085 
0086     /// INTERNAL ONLY
0087     ///
0088 #define BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(Name, Op)                                      \
0089     namespace functional                                                                        \
0090     {                                                                                           \
0091         template<typename Arg>                                                                  \
0092         struct result_of_ ## Name                                                               \
0093         {                                                                                       \
0094             BOOST_TYPEOF_NESTED_TYPEDEF_TPL(                                                    \
0095                 nested                                                                          \
0096               , Op boost::numeric::functional::detail::lvalue_of<Arg>()                         \
0097             )                                                                                   \
0098             typedef typename nested::type type;                                                 \
0099         };                                                                                      \
0100         template<typename Arg, typename EnableIf>                                               \
0101         struct Name ## _base                                                                    \
0102         {                                                                                       \
0103             typedef typename remove_const<Arg>::type argument_type;                             \
0104             typedef typename result_of_ ## Name<Arg>::type result_type;                         \
0105             typename result_of_ ## Name<Arg>::type operator ()(Arg &arg) const                  \
0106             {                                                                                   \
0107                 return Op arg;                                                                  \
0108             }                                                                                   \
0109         };                                                                                      \
0110         template<typename Arg, typename ArgTag>                                                 \
0111         struct Name                                                                             \
0112           : Name ## _base<Arg, void>                                                            \
0113         {};                                                                                     \
0114     }                                                                                           \
0115     namespace op                                                                                \
0116     {                                                                                           \
0117         struct Name                                                                             \
0118           : boost::detail::function1<functional::Name<_, functional::tag<_> > >                 \
0119         {};                                                                                     \
0120     }                                                                                           \
0121     namespace                                                                                   \
0122     {                                                                                           \
0123         op::Name const &Name = boost::detail::pod_singleton<op::Name>::instance;                \
0124     }                                                                                           \
0125     /**/
0126 
0127     /// INTERNAL ONLY
0128     ///
0129 #define BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(Name, Op, RetType)                            \
0130     namespace functional                                                                        \
0131     {                                                                                           \
0132         template<typename Left, typename Right, typename EnableIf>                              \
0133         struct result_of_ ## Name                                                               \
0134         {                                                                                       \
0135             RetType(Left, Op, Right)                                                            \
0136         };                                                                                      \
0137         template<typename Left, typename Right, typename EnableIf>                              \
0138         struct Name ## _base                                                                    \
0139         {                                                                                       \
0140             typedef typename remove_const<Left>::type first_argument_type;                      \
0141             typedef typename remove_const<Right>::type second_argument_type;                    \
0142             typedef typename result_of_ ## Name<Left, Right>::type result_type;                 \
0143             typename result_of_ ## Name<Left, Right>::type                                      \
0144             operator ()(Left &left, Right &right) const                                         \
0145             {                                                                                   \
0146                 return left Op right;                                                           \
0147             }                                                                                   \
0148         };                                                                                      \
0149         template<typename Left, typename Right, typename LeftTag, typename RightTag>            \
0150         struct Name                                                                             \
0151           : Name ## _base<Left, Right, void>                                                    \
0152         {};                                                                                     \
0153     }                                                                                           \
0154     namespace op                                                                                \
0155     {                                                                                           \
0156         struct Name                                                                             \
0157           : boost::detail::function2<                                                           \
0158                 functional::Name<_1, _2, functional::tag<_1>, functional::tag<_2> >             \
0159             >                                                                                   \
0160         {};                                                                                     \
0161     }                                                                                           \
0162     namespace                                                                                   \
0163     {                                                                                           \
0164         op::Name const &Name = boost::detail::pod_singleton<op::Name>::instance;                \
0165     }                                                                                           \
0166     BOOST_ACCUMULATORS_IGNORE_GLOBAL(Name)                                                      \
0167     /**/
0168 
0169     /// INTERNAL ONLY
0170     ///
0171 #define BOOST_NUMERIC_FUNCTIONAL_DEDUCED(Left, Op, Right)                                       \
0172     BOOST_TYPEOF_NESTED_TYPEDEF_TPL(                                                            \
0173         nested                                                                                  \
0174       , boost::numeric::functional::detail::lvalue_of<Left>() Op                                \
0175         boost::numeric::functional::detail::lvalue_of<Right>()                                  \
0176     )                                                                                           \
0177     typedef typename nested::type type;                                                         \
0178     /**/
0179 
0180     /// INTERNAL ONLY
0181     ///
0182 #define BOOST_NUMERIC_FUNCTIONAL_LEFT(Left, Op, Right)                                          \
0183     typedef Left &type;                                                                         \
0184     /**/
0185 
0186     BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(plus, +, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
0187     BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(minus, -, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
0188     BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(multiplies, *, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
0189     BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(divides, /, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
0190     BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(modulus, %, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
0191     BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(greater, >, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
0192     BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(greater_equal, >=, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
0193     BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(less, <, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
0194     BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(less_equal, <=, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
0195     BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(equal_to, ==, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
0196     BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(not_equal_to, !=, BOOST_NUMERIC_FUNCTIONAL_DEDUCED)
0197 
0198     BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(assign, =, BOOST_NUMERIC_FUNCTIONAL_LEFT)
0199     BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(plus_assign, +=, BOOST_NUMERIC_FUNCTIONAL_LEFT)
0200     BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(minus_assign, -=, BOOST_NUMERIC_FUNCTIONAL_LEFT)
0201     BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(multiplies_assign, *=, BOOST_NUMERIC_FUNCTIONAL_LEFT)
0202     BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(divides_assign, /=, BOOST_NUMERIC_FUNCTIONAL_LEFT)
0203     BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(modulus_assign, %=, BOOST_NUMERIC_FUNCTIONAL_LEFT)
0204 
0205     BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(unary_plus, +)
0206     BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(unary_minus, -)
0207     BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(complement, ~)
0208     BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(logical_not, !)
0209 
0210 #undef BOOST_NUMERIC_FUNCTIONAL_LEFT
0211 #undef BOOST_NUMERIC_FUNCTIONAL_DEDUCED
0212 #undef BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP
0213 #undef BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP
0214 
0215     namespace functional
0216     {
0217         template<typename Left, typename Right, typename EnableIf>
0218         struct min_assign_base
0219         {
0220             typedef Left first_argument_type;
0221             typedef Right second_argument_type;
0222             typedef void result_type;
0223 
0224             void operator ()(Left &left, Right &right) const
0225             {
0226                 if(numeric::less(right, left))
0227                 {
0228                     left = right;
0229                 }
0230             }
0231         };
0232 
0233         template<typename Left, typename Right, typename EnableIf>
0234         struct max_assign_base
0235         {
0236             typedef Left first_argument_type;
0237             typedef Right second_argument_type;
0238             typedef void result_type;
0239 
0240             void operator ()(Left &left, Right &right) const
0241             {
0242                 if(numeric::greater(right, left))
0243                 {
0244                     left = right;
0245                 }
0246             }
0247         };
0248 
0249         template<typename Left, typename Right, typename EnableIf>
0250         struct fdiv_base
0251           : functional::divides<Left, Right>
0252         {};
0253 
0254         // partial specialization that promotes the arguments to double for
0255         // integral division.
0256         template<typename Left, typename Right>
0257         struct fdiv_base<Left, Right, typename enable_if<are_integral<Left, Right> >::type>
0258           : functional::divides<double const, double const>
0259         {};
0260 
0261         template<typename To, typename From, typename EnableIf>
0262         struct promote_base
0263         {
0264             typedef From argument_type;
0265             typedef To result_type;
0266 
0267             To operator ()(From &from) const
0268             {
0269                 return from;
0270             }
0271         };
0272 
0273         template<typename ToFrom>
0274         struct promote_base<ToFrom, ToFrom, void>
0275         {
0276             typedef ToFrom argument_type;
0277             typedef ToFrom result_type;
0278 
0279             ToFrom &operator ()(ToFrom &tofrom)
0280             {
0281                 return tofrom;
0282             }
0283         };
0284 
0285         template<typename Arg, typename EnableIf>
0286         struct as_min_base
0287         {
0288             BOOST_STATIC_ASSERT(std::numeric_limits<typename remove_const<Arg>::type>::is_specialized);
0289 
0290             typedef Arg argument_type;
0291             typedef typename remove_const<Arg>::type result_type;
0292 
0293             typename remove_const<Arg>::type operator ()(Arg &) const
0294             {
0295                 return (std::numeric_limits<typename remove_const<Arg>::type>::min)();
0296             }
0297         };
0298 
0299         template<typename Arg>
0300         struct as_min_base<Arg, typename enable_if<is_floating_point<Arg> >::type>
0301         {
0302             BOOST_STATIC_ASSERT(std::numeric_limits<typename remove_const<Arg>::type>::is_specialized);
0303 
0304             typedef Arg argument_type;
0305             typedef typename remove_const<Arg>::type result_type;
0306 
0307             typename remove_const<Arg>::type operator ()(Arg &) const
0308             {
0309                 return -(std::numeric_limits<typename remove_const<Arg>::type>::max)();
0310             }
0311         };
0312 
0313         template<typename Arg, typename EnableIf>
0314         struct as_max_base
0315         {
0316             BOOST_STATIC_ASSERT(std::numeric_limits<typename remove_const<Arg>::type>::is_specialized);
0317 
0318             typedef Arg argument_type;
0319             typedef typename remove_const<Arg>::type result_type;
0320 
0321             typename remove_const<Arg>::type operator ()(Arg &) const
0322             {
0323                 return (std::numeric_limits<typename remove_const<Arg>::type>::max)();
0324             }
0325         };
0326 
0327         template<typename Arg, typename EnableIf>
0328         struct as_zero_base
0329         {
0330             typedef Arg argument_type;
0331             typedef typename remove_const<Arg>::type result_type;
0332 
0333             typename remove_const<Arg>::type operator ()(Arg &) const
0334             {
0335                 return numeric::zero<typename remove_const<Arg>::type>::value;
0336             }
0337         };
0338 
0339         template<typename Arg, typename EnableIf>
0340         struct as_one_base
0341         {
0342             typedef Arg argument_type;
0343             typedef typename remove_const<Arg>::type result_type;
0344 
0345             typename remove_const<Arg>::type operator ()(Arg &) const
0346             {
0347                 return numeric::one<typename remove_const<Arg>::type>::value;
0348             }
0349         };
0350 
0351         template<typename To, typename From, typename ToTag, typename FromTag>
0352         struct promote
0353           : promote_base<To, From, void>
0354         {};
0355 
0356         template<typename Left, typename Right, typename LeftTag, typename RightTag>
0357         struct min_assign
0358           : min_assign_base<Left, Right, void>
0359         {};
0360 
0361         template<typename Left, typename Right, typename LeftTag, typename RightTag>
0362         struct max_assign
0363           : max_assign_base<Left, Right, void>
0364         {};
0365 
0366         template<typename Left, typename Right, typename LeftTag, typename RightTag>
0367         struct fdiv
0368           : fdiv_base<Left, Right, void>
0369         {};
0370 
0371         /// INTERNAL ONLY 
0372         /// For back-compat only. Use fdiv.
0373         template<typename Left, typename Right, typename LeftTag, typename RightTag>
0374         struct average
0375           : fdiv<Left, Right, LeftTag, RightTag>
0376         {};
0377 
0378         template<typename Arg, typename Tag>
0379         struct as_min
0380           : as_min_base<Arg, void>
0381         {};
0382 
0383         template<typename Arg, typename Tag>
0384         struct as_max
0385           : as_max_base<Arg, void>
0386         {};
0387 
0388         template<typename Arg, typename Tag>
0389         struct as_zero
0390           : as_zero_base<Arg, void>
0391         {};
0392 
0393         template<typename Arg, typename Tag>
0394         struct as_one
0395           : as_one_base<Arg, void>
0396         {};
0397     }
0398 
0399     namespace op
0400     {
0401         template<typename To>
0402         struct promote
0403           : boost::detail::function1<functional::promote<To, _, typename functional::tag<To>::type, functional::tag<_> > >
0404         {};
0405 
0406         struct min_assign
0407           : boost::detail::function2<functional::min_assign<_1, _2, functional::tag<_1>, functional::tag<_2> > >
0408         {};
0409 
0410         struct max_assign
0411           : boost::detail::function2<functional::max_assign<_1, _2, functional::tag<_1>, functional::tag<_2> > >
0412         {};
0413 
0414         struct fdiv
0415           : boost::detail::function2<functional::fdiv<_1, _2, functional::tag<_1>, functional::tag<_2> > >
0416         {};
0417 
0418         /// INTERNAL ONLY
0419         struct average
0420           : boost::detail::function2<functional::fdiv<_1, _2, functional::tag<_1>, functional::tag<_2> > >
0421         {};
0422 
0423         struct as_min
0424           : boost::detail::function1<functional::as_min<_, functional::tag<_> > >
0425         {};
0426 
0427         struct as_max
0428           : boost::detail::function1<functional::as_max<_, functional::tag<_> > >
0429         {};
0430 
0431         struct as_zero
0432           : boost::detail::function1<functional::as_zero<_, functional::tag<_> > >
0433         {};
0434 
0435         struct as_one
0436           : boost::detail::function1<functional::as_one<_, functional::tag<_> > >
0437         {};
0438     }
0439 
0440     namespace
0441     {
0442         op::min_assign const &min_assign = boost::detail::pod_singleton<op::min_assign>::instance;
0443         op::max_assign const &max_assign = boost::detail::pod_singleton<op::max_assign>::instance;
0444         op::fdiv const &fdiv = boost::detail::pod_singleton<op::fdiv>::instance;
0445         op::fdiv const &average = boost::detail::pod_singleton<op::fdiv>::instance; ///< INTERNAL ONLY
0446         op::as_min const &as_min = boost::detail::pod_singleton<op::as_min>::instance;
0447         op::as_max const &as_max = boost::detail::pod_singleton<op::as_max>::instance;
0448         op::as_zero const &as_zero = boost::detail::pod_singleton<op::as_zero>::instance;
0449         op::as_one const &as_one = boost::detail::pod_singleton<op::as_one>::instance;
0450 
0451         BOOST_ACCUMULATORS_IGNORE_GLOBAL(min_assign)
0452         BOOST_ACCUMULATORS_IGNORE_GLOBAL(max_assign)
0453         BOOST_ACCUMULATORS_IGNORE_GLOBAL(fdiv)
0454         BOOST_ACCUMULATORS_IGNORE_GLOBAL(average)
0455         BOOST_ACCUMULATORS_IGNORE_GLOBAL(as_min)
0456         BOOST_ACCUMULATORS_IGNORE_GLOBAL(as_max)
0457         BOOST_ACCUMULATORS_IGNORE_GLOBAL(as_zero)
0458         BOOST_ACCUMULATORS_IGNORE_GLOBAL(as_one)
0459     }
0460 
0461     ///////////////////////////////////////////////////////////////////////////////
0462     // promote
0463     template<typename To, typename From>
0464     typename lazy_disable_if<is_const<From>, mpl::if_<is_same<To, From>, To &, To> >::type
0465     promote(From &from)
0466     {
0467         return functional::promote<To, From>()(from);
0468     }
0469 
0470     template<typename To, typename From>
0471     typename mpl::if_<is_same<To const, From const>, To const &, To const>::type
0472     promote(From const &from)
0473     {
0474         return functional::promote<To const, From const>()(from);
0475     }
0476 
0477     template<typename T>
0478     struct default_
0479     {
0480         typedef default_ type;
0481         typedef T value_type;
0482         static T const value;
0483 
0484         operator T const & () const
0485         {
0486             return default_::value;
0487         }
0488     };
0489 
0490     template<typename T>
0491     T const default_<T>::value = T();
0492 
0493     template<typename T>
0494     struct one
0495     {
0496         typedef one type;
0497         typedef T value_type;
0498         static T const value;
0499 
0500         operator T const & () const
0501         {
0502             return one::value;
0503         }
0504     };
0505 
0506     template<typename T>
0507     T const one<T>::value = T(1);
0508 
0509     template<typename T>
0510     struct zero
0511     {
0512         typedef zero type;
0513         typedef T value_type;
0514         static T const value;
0515 
0516         operator T const & () const
0517         {
0518             return zero::value;
0519         }
0520     };
0521 
0522     template<typename T>
0523     T const zero<T>::value = T();
0524 
0525     template<typename T>
0526     struct one_or_default
0527       : mpl::if_<is_empty<T>, default_<T>, one<T> >::type
0528     {};
0529 
0530     template<typename T>
0531     struct zero_or_default
0532       : mpl::if_<is_empty<T>, default_<T>, zero<T> >::type
0533     {};
0534 
0535 }} // namespace boost::numeric
0536 
0537 #endif