Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: /// \file functional.hpp Chris@16: /// Chris@16: // Copyright 2005 Eric Niebler. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_NUMERIC_FUNCTIONAL_HPP_EAN_08_12_2005 Chris@16: #define BOOST_NUMERIC_FUNCTIONAL_HPP_EAN_08_12_2005 Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #ifdef BOOST_NUMERIC_FUNCTIONAL_STD_VECTOR_SUPPORT Chris@16: # include Chris@16: #endif Chris@16: Chris@16: #ifdef BOOST_NUMERIC_FUNCTIONAL_STD_VALARRAY_SUPPORT Chris@16: # include Chris@16: #endif Chris@16: Chris@16: #ifdef BOOST_NUMERIC_FUNCTIONAL_STD_COMPLEX_SUPPORT Chris@16: # include Chris@16: #endif Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: #define BOOST_NUMERIC_FUNCTIONAL_HPP_INCLUDED Chris@16: Chris@16: #ifdef BOOST_NUMERIC_FUNCTIONAL_DOXYGEN_INVOKED Chris@16: // Hack to make Doxygen show the inheritance relationships Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: namespace std Chris@16: { Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: template struct unary_function {}; Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: template struct binary_function {}; Chris@16: } Chris@16: #endif Chris@16: Chris@16: namespace boost { namespace numeric Chris@16: { Chris@16: namespace functional Chris@16: { Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: template Chris@16: struct are_integral Chris@16: : mpl::and_, is_integral > Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct left_ref Chris@16: { Chris@16: typedef Left &type; Chris@16: }; Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: template Chris@16: T &lvalue_of(); Chris@16: } Chris@16: } Chris@16: Chris@16: // TODO: handle complex weight, valarray, MTL vectors Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: #define BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(Name, Op) \ Chris@16: namespace functional \ Chris@16: { \ Chris@16: template \ Chris@16: struct result_of_ ## Name \ Chris@16: { \ Chris@16: BOOST_TYPEOF_NESTED_TYPEDEF_TPL( \ Chris@16: nested \ Chris@16: , Op boost::numeric::functional::detail::lvalue_of() \ Chris@16: ) \ Chris@16: typedef typename nested::type type; \ Chris@16: }; \ Chris@16: template \ Chris@16: struct Name ## _base \ Chris@16: : std::unary_function< \ Chris@16: typename remove_const::type \ Chris@16: , typename result_of_ ## Name::type \ Chris@16: > \ Chris@16: { \ Chris@16: typename result_of_ ## Name::type operator ()(Arg &arg) const \ Chris@16: { \ Chris@16: return Op arg; \ Chris@16: } \ Chris@16: }; \ Chris@16: template \ Chris@16: struct Name \ Chris@16: : Name ## _base \ Chris@16: {}; \ Chris@16: } \ Chris@16: namespace op \ Chris@16: { \ Chris@16: struct Name \ Chris@16: : boost::detail::function1 > > \ Chris@16: {}; \ Chris@16: } \ Chris@16: namespace \ Chris@16: { \ Chris@16: op::Name const &Name = boost::detail::pod_singleton::instance; \ Chris@16: } \ Chris@16: /**/ Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: #define BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(Name, Op, RetType) \ Chris@16: namespace functional \ Chris@16: { \ Chris@16: template \ Chris@16: struct result_of_ ## Name \ Chris@16: { \ Chris@16: RetType(Left, Op, Right) \ Chris@16: }; \ Chris@16: template \ Chris@16: struct Name ## _base \ Chris@16: : std::binary_function< \ Chris@16: typename remove_const::type \ Chris@16: , typename remove_const::type \ Chris@16: , typename result_of_ ## Name::type \ Chris@16: > \ Chris@16: { \ Chris@16: typename result_of_ ## Name::type \ Chris@16: operator ()(Left &left, Right &right) const \ Chris@16: { \ Chris@16: return left Op right; \ Chris@16: } \ Chris@16: }; \ Chris@16: template \ Chris@16: struct Name \ Chris@16: : Name ## _base \ Chris@16: {}; \ Chris@16: } \ Chris@16: namespace op \ Chris@16: { \ Chris@16: struct Name \ Chris@16: : boost::detail::function2< \ Chris@16: functional::Name<_1, _2, functional::tag<_1>, functional::tag<_2> > \ Chris@16: > \ Chris@16: {}; \ Chris@16: } \ Chris@16: namespace \ Chris@16: { \ Chris@16: op::Name const &Name = boost::detail::pod_singleton::instance; \ Chris@16: } \ Chris@16: BOOST_ACCUMULATORS_IGNORE_GLOBAL(Name) \ Chris@16: /**/ Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: #define BOOST_NUMERIC_FUNCTIONAL_DEDUCED(Left, Op, Right) \ Chris@16: BOOST_TYPEOF_NESTED_TYPEDEF_TPL( \ Chris@16: nested \ Chris@16: , boost::numeric::functional::detail::lvalue_of() Op \ Chris@16: boost::numeric::functional::detail::lvalue_of() \ Chris@16: ) \ Chris@16: typedef typename nested::type type; \ Chris@16: /**/ Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: #define BOOST_NUMERIC_FUNCTIONAL_LEFT(Left, Op, Right) \ Chris@16: typedef Left &type; \ Chris@16: /**/ Chris@16: Chris@16: BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(plus, +, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) Chris@16: BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(minus, -, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) Chris@16: BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(multiplies, *, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) Chris@16: BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(divides, /, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) Chris@16: BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(modulus, %, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) Chris@16: BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(greater, >, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) Chris@16: BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(greater_equal, >=, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) Chris@16: BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(less, <, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) Chris@16: BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(less_equal, <=, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) Chris@16: BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(equal_to, ==, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) Chris@16: BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(not_equal_to, !=, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) Chris@16: Chris@16: BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(assign, =, BOOST_NUMERIC_FUNCTIONAL_LEFT) Chris@16: BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(plus_assign, +=, BOOST_NUMERIC_FUNCTIONAL_LEFT) Chris@16: BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(minus_assign, -=, BOOST_NUMERIC_FUNCTIONAL_LEFT) Chris@16: BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(multiplies_assign, *=, BOOST_NUMERIC_FUNCTIONAL_LEFT) Chris@16: BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(divides_assign, /=, BOOST_NUMERIC_FUNCTIONAL_LEFT) Chris@16: BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(modulus_assign, %=, BOOST_NUMERIC_FUNCTIONAL_LEFT) Chris@16: Chris@16: BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(unary_plus, +) Chris@16: BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(unary_minus, -) Chris@16: BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(complement, ~) Chris@16: BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(logical_not, !) Chris@16: Chris@16: #undef BOOST_NUMERIC_FUNCTIONAL_LEFT Chris@16: #undef BOOST_NUMERIC_FUNCTIONAL_DEDUCED Chris@16: #undef BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP Chris@16: #undef BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP Chris@16: Chris@16: namespace functional Chris@16: { Chris@16: template Chris@16: struct min_assign_base Chris@16: : std::binary_function Chris@16: { Chris@16: void operator ()(Left &left, Right &right) const Chris@16: { Chris@16: if(numeric::less(right, left)) Chris@16: { Chris@16: left = right; Chris@16: } Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct max_assign_base Chris@16: : std::binary_function Chris@16: { Chris@16: void operator ()(Left &left, Right &right) const Chris@16: { Chris@16: if(numeric::greater(right, left)) Chris@16: { Chris@16: left = right; Chris@16: } Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct fdiv_base Chris@16: : functional::divides Chris@16: {}; Chris@16: Chris@16: // partial specialization that promotes the arguments to double for Chris@16: // integral division. Chris@16: template Chris@16: struct fdiv_base >::type> Chris@16: : functional::divides Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct promote_base Chris@16: : std::unary_function Chris@16: { Chris@16: To operator ()(From &from) const Chris@16: { Chris@16: return from; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct promote_base Chris@16: : std::unary_function Chris@16: { Chris@16: ToFrom &operator ()(ToFrom &tofrom) Chris@16: { Chris@16: return tofrom; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct as_min_base Chris@16: : std::unary_function::type> Chris@16: { Chris@16: BOOST_STATIC_ASSERT(std::numeric_limits::type>::is_specialized); Chris@16: Chris@16: typename remove_const::type operator ()(Arg &) const Chris@16: { Chris@16: return (std::numeric_limits::type>::min)(); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct as_min_base >::type> Chris@16: : std::unary_function::type> Chris@16: { Chris@16: BOOST_STATIC_ASSERT(std::numeric_limits::type>::is_specialized); Chris@16: Chris@16: typename remove_const::type operator ()(Arg &) const Chris@16: { Chris@16: return -(std::numeric_limits::type>::max)(); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct as_max_base Chris@16: : std::unary_function::type> Chris@16: { Chris@16: BOOST_STATIC_ASSERT(std::numeric_limits::type>::is_specialized); Chris@16: Chris@16: typename remove_const::type operator ()(Arg &) const Chris@16: { Chris@16: return (std::numeric_limits::type>::max)(); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct as_zero_base Chris@16: : std::unary_function::type> Chris@16: { Chris@16: typename remove_const::type operator ()(Arg &) const Chris@16: { Chris@16: return numeric::zero::type>::value; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct as_one_base Chris@16: : std::unary_function::type> Chris@16: { Chris@16: typename remove_const::type operator ()(Arg &) const Chris@16: { Chris@16: return numeric::one::type>::value; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct promote Chris@16: : promote_base Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct min_assign Chris@16: : min_assign_base Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct max_assign Chris@16: : max_assign_base Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct fdiv Chris@16: : fdiv_base Chris@16: {}; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: /// For back-compat only. Use fdiv. Chris@16: template Chris@16: struct average Chris@16: : fdiv Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct as_min Chris@16: : as_min_base Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct as_max Chris@16: : as_max_base Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct as_zero Chris@16: : as_zero_base Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct as_one Chris@16: : as_one_base Chris@16: {}; Chris@16: } Chris@16: Chris@16: namespace op Chris@16: { Chris@16: template Chris@16: struct promote Chris@16: : boost::detail::function1::type, functional::tag<_> > > Chris@16: {}; Chris@16: Chris@16: struct min_assign Chris@16: : boost::detail::function2, functional::tag<_2> > > Chris@16: {}; Chris@16: Chris@16: struct max_assign Chris@16: : boost::detail::function2, functional::tag<_2> > > Chris@16: {}; Chris@16: Chris@16: struct fdiv Chris@16: : boost::detail::function2, functional::tag<_2> > > Chris@16: {}; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: struct average Chris@16: : boost::detail::function2, functional::tag<_2> > > Chris@16: {}; Chris@16: Chris@16: struct as_min Chris@16: : boost::detail::function1 > > Chris@16: {}; Chris@16: Chris@16: struct as_max Chris@16: : boost::detail::function1 > > Chris@16: {}; Chris@16: Chris@16: struct as_zero Chris@16: : boost::detail::function1 > > Chris@16: {}; Chris@16: Chris@16: struct as_one Chris@16: : boost::detail::function1 > > Chris@16: {}; Chris@16: } Chris@16: Chris@16: namespace Chris@16: { Chris@16: op::min_assign const &min_assign = boost::detail::pod_singleton::instance; Chris@16: op::max_assign const &max_assign = boost::detail::pod_singleton::instance; Chris@16: op::fdiv const &fdiv = boost::detail::pod_singleton::instance; Chris@16: op::fdiv const &average = boost::detail::pod_singleton::instance; ///< INTERNAL ONLY Chris@16: op::as_min const &as_min = boost::detail::pod_singleton::instance; Chris@16: op::as_max const &as_max = boost::detail::pod_singleton::instance; Chris@16: op::as_zero const &as_zero = boost::detail::pod_singleton::instance; Chris@16: op::as_one const &as_one = boost::detail::pod_singleton::instance; Chris@16: Chris@16: BOOST_ACCUMULATORS_IGNORE_GLOBAL(min_assign) Chris@16: BOOST_ACCUMULATORS_IGNORE_GLOBAL(max_assign) Chris@16: BOOST_ACCUMULATORS_IGNORE_GLOBAL(fdiv) Chris@16: BOOST_ACCUMULATORS_IGNORE_GLOBAL(average) Chris@16: BOOST_ACCUMULATORS_IGNORE_GLOBAL(as_min) Chris@16: BOOST_ACCUMULATORS_IGNORE_GLOBAL(as_max) Chris@16: BOOST_ACCUMULATORS_IGNORE_GLOBAL(as_zero) Chris@16: BOOST_ACCUMULATORS_IGNORE_GLOBAL(as_one) Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // promote Chris@16: template Chris@16: typename lazy_disable_if, mpl::if_, To &, To> >::type Chris@16: promote(From &from) Chris@16: { Chris@16: return functional::promote()(from); Chris@16: } Chris@16: Chris@16: template Chris@16: typename mpl::if_, To const &, To const>::type Chris@16: promote(From const &from) Chris@16: { Chris@16: return functional::promote()(from); Chris@16: } Chris@16: Chris@16: template Chris@16: struct default_ Chris@16: { Chris@16: typedef default_ type; Chris@16: typedef T value_type; Chris@16: static T const value; Chris@16: Chris@16: operator T const & () const Chris@16: { Chris@16: return default_::value; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: T const default_::value = T(); Chris@16: Chris@16: template Chris@16: struct one Chris@16: { Chris@16: typedef one type; Chris@16: typedef T value_type; Chris@16: static T const value; Chris@16: Chris@16: operator T const & () const Chris@16: { Chris@16: return one::value; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: T const one::value = T(1); Chris@16: Chris@16: template Chris@16: struct zero Chris@16: { Chris@16: typedef zero type; Chris@16: typedef T value_type; Chris@16: static T const value; Chris@16: Chris@16: operator T const & () const Chris@16: { Chris@16: return zero::value; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: T const zero::value = T(); Chris@16: Chris@16: template Chris@16: struct one_or_default Chris@16: : mpl::if_, default_, one >::type Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct zero_or_default Chris@16: : mpl::if_, default_, zero >::type Chris@16: {}; Chris@16: Chris@16: }} // namespace boost::numeric Chris@16: Chris@16: #endif