// Boost.Units - A C++ library for zero-overhead dimensional analysis and // unit/quantity manipulation and conversion // // Copyright (C) 2003-2008 Matthias Christian Schabel // Copyright (C) 2008 Steven Watanabe // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // $Id: math_functional.hpp 30 2008-06-20 13:29:58Z maehne $ //////////////////////////////////////////////////////////////////////// /// /// \file math_functional.hpp /// /// \brief Definitions of functor wrappers for the mathematical /// functions defined in \ and \ to /// facilitate their use in functors created with the /// Boost.Lambda library. /// /// \author Torsten Maehne /// \date 2008-06-19 /// /// The definition of functor wrappers for the overloaded functions in /// \ and and \ facilitate the usage of /// mathematical functions in functors created with Boost.Lambda. The /// functors include a \c sig template or \c result_type typedef, /// which allows Boost::Lambda's bind to choose the correct overloaded /// function depending on the types passed through the lambda /// placeholders. If overloaded functions are passed directly, to /// Boost::Lamdba's bind, a tedious static_cast needs be applied to /// specify explicitely the signature of the function to be /// chosen. The cmath function calls are not prefixed by a namespace /// qualifier thus allowing argument dependent lookup (ADL, /// a.k.a. Koenig lookup). All functor wrappers have a '_t' prefix to /// avoid interference with the ADL. The functor wrappers for /// functions from \ are defined in namespace /// boost::math::functional (to anticipate a generalization of this /// header). Functor wrappers for Boost.Units specific functions are /// defined in boost::units::functional. /// /// /// \todo Functor wrapper for fma (boost::units::fma unfinished in /// trunk). /// /// \todo Functor wrapper for nearbyint (boost::units::nearbyint /// unfinished in trunk). /// /// \todo Functor wrapper for rint (boost::units::rint unfinished in /// trunk). /// /// \todo Remove limitation of functor wrapper nexttoward to only /// boost::units::nexttoward, which is currently implemented in /// terms of boost::math::nextafter because /// boost::math::nexttoward is not yet available. /// //////////////////////////////////////////////////////////////////////// #ifndef BOOST_UNITS_MATH_FUNCTIONAL_HPP #define BOOST_UNITS_MATH_FUNCTIONAL_HPP #include #include #include #include #include namespace boost { namespace math { /// Namespace for all the functor wrappers for the cmath functions. namespace functional { BOOST_MATH_STD_USING // Pull in some replacements for C99 functions from Boost.Math or Boost.Units using boost::units::detail::isgreater; using boost::units::detail::isgreaterequal; using boost::units::detail::isless; using boost::units::detail::islessequal; using boost::units::detail::islessgreater; using boost::units::detail::isunordered; /// Internal namespace with placeholder function for Boost.Typeof /// /// Origin: namespace typeof_ { /// Function template to be used as placeholder in expressions passed /// to Boost.Typeof. This avoids the need for a default constructor /// and eliminates divide by zero errors. template T make(); } // namespace typeof_ /// \brief Functor wrapper for isfinite. struct isfinite_t { typedef bool result_type; template bool operator()(const T& arg) const { return isfinite(arg); } }; /// \brief Functor wrapper for isinf. struct isinf_t { typedef bool result_type; template bool operator()(const T& arg) const { return isinf(arg); } }; /// \brief Functor wrapper for isnan. struct isnan_t { typedef bool result_type; template bool operator()(const T& arg) const { return isnan(arg); } }; /// \brief Functor wrapper for isgreater. struct isgreater_t { typedef bool result_type; template bool operator()(const T& arg1, const T& arg2) const { return isgreater(arg1, arg2); } }; /// \brief Functor wrapper for isgreater. struct isgreaterequal_t { typedef bool result_type; template bool operator()(const T& arg1, const T& arg2) const { return isgreaterequal(arg1, arg2); } }; /// \brief Functor wrapper for isless. struct isless_t { typedef bool result_type; template bool operator()(const T& arg1, const T& arg2) const { return isless(arg1, arg2); } }; /// \brief Functor wrapper for islessequal. struct islessequal_t { typedef bool result_type; template bool operator()(const T& arg1, const T& arg2) const { return islessequal(arg1, arg2); } }; /// \brief Functor wrapper for islessgreater. struct islessgreater_t { typedef bool result_type; template bool operator()(const T& arg1, const T& arg2) const { return islessgreater(arg1, arg2); } }; /// \brief Functor wrapper for isunordered. struct isunordered_t { typedef bool result_type; template bool operator()(const T& arg1, const T& arg2) const { return isunordered(arg1, arg2); } }; /// \brief Functor wrapper for abs. struct abs_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (abs(typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& arg) const { return abs(arg); } }; /// \brief Functor wrapper for ceil. struct ceil_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (ceil(typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& arg) const { return ceil(arg); } }; /// \brief Functor wrapper for copysign. struct copysign_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; typedef typename boost::tuples::element<2, Args>::type arg2_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (copysign(typeof_::make(), typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& arg1, const T& arg2) const { return copysign(arg1, arg2); } }; /// \brief Functor wrapper for fabs. struct fabs_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (fabs(typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& arg) const { return fabs(arg); } }; /// \brief Functor wrapper for floor. struct floor_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (floor(typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& arg) const { return floor(arg); } }; /// \brief Functor wrapper for fdim. struct fdim_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; typedef typename boost::tuples::element<2, Args>::type arg2_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (fdim(typeof_::make(), typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& x, const T& y) const { return fdim(x, y); } }; /// \brief Functor wrapper for fma. struct fma_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; typedef typename boost::tuples::element<2, Args>::type arg2_type; typedef typename boost::tuples::element<3, Args>::type arg3_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (fma(typeof_::make(), typeof_::make(), typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T1& x, const T2& y, const T3& z) const { return fma(x, y, z); } }; /// \brief Functor wrapper for fmax. struct fmax_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; typedef typename boost::tuples::element<2, Args>::type arg2_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (fmax(typeof_::make(), typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& x, const T& y) const { return fmax(x, y); } }; /// \brief Functor wrapper for fmin. struct fmin_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; typedef typename boost::tuples::element<2, Args>::type arg2_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (fmin(typeof_::make(), typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& x, const T& y) const { return fmin(x, y); } }; /// \brief Functor wrapper for fpclassify struct fpclassify_t { typedef int result_type; template int operator()(const T& arg) const { return fpclassify(arg); } }; /// Functor wrapper for hypot. struct hypot_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; typedef typename boost::tuples::element<2, Args>::type arg2_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (hypot(typeof_::make(), typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& x, const T& y) const { return hypot(x, y); } }; /// \brief Functor wrapper for nearbyint. struct nearbyint_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (nearbyint(typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& arg) const { return nearbyint(arg); } }; /// \brief Functor wrapper for nextafter struct nextafter_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; typedef typename boost::tuples::element<2, Args>::type arg2_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (nextafter(typeof_::make(), typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& x, const T& y) const { return nextafter(x, y); } }; /// \brief Functor wrapper for nexttoward. struct nexttoward_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; typedef typename boost::tuples::element<2, Args>::type arg2_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (nexttoward(typeof_::make(), typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T1& x, const T2& y) const { return nexttoward(x, y); } }; /// \brief Functor wrapper for rint. struct rint_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (rint(typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& arg) const { return rint(arg); } }; /// \brief Functor wrapper for round. struct round_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (round(typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& arg) const { return round(arg); } }; /// \brief Functor wrapper for signbit. struct signbit_t { typedef int result_type; template int operator()(const T& arg) const { return signbit(arg); } }; /// \brief Functor wrapper for trunc. struct trunc_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (trunc(typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& arg) const { return trunc(arg); } }; /// \brief Functor wrapper for fmod. struct fmod_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; typedef typename boost::tuples::element<2, Args>::type arg2_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (fmod(typeof_::make(), typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& x, const T& y) const { return fmod(x, y); } }; /// \brief Functor wrapper for modf. struct modf_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; typedef typename boost::tuples::element<2, Args>::type arg2_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (modf(typeof_::make(), typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& x, T* iptr) const { return modf(x, iptr); } }; /// \brief Functor wrapper for frexp. struct frexp_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; typedef typename boost::tuples::element<2, Args>::type arg2_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (frexp(typeof_::make(), typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& x, Int* exp) const { return frexp(x, exp); } }; /// \brief Functor wrapper for pow. struct pow_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; typedef typename boost::tuples::element<2, Args>::type arg2_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (pow(typeof_::make(), typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& x, const T& y) const { return pow(x, y); } }; /// \brief Functor wrapper for exp. struct exp_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (exp(typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& arg) const { return exp(arg); } }; /// \brief Functor wrapper for ldexp. struct ldexp_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; typedef typename boost::tuples::element<2, Args>::type arg2_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (ldexp(typeof_::make(), typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& x, const Int& exp) const { return ldexp(x, exp); } }; /// \brief Functor wrapper for log. struct log_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (log(typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& arg) const { return log(arg); } }; /// \brief Functor wrapper for log10. struct log10_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (log10(typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& arg) const { return log10(arg); } }; /// \brief Functor wrapper for sqrt. struct sqrt_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (sqrt(typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& arg) const { return sqrt(arg); } }; /// \brief Functor wrapper for cos. struct cos_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (cos(typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& arg) const { return cos(arg); } }; /// \brief Functor wrapper for sin. struct sin_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (sin(typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& arg) const { return sin(arg); } }; /// \brief Functor wrapper for tan. struct tan_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (tan(typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& arg) const { return tan(arg); } }; /// \brief Functor wrapper for acos. struct acos_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (acos(typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& arg) const { return acos(arg); } }; /// \brief Functor wrapper for asin. struct asin_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (asin(typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& arg) const { return asin(arg); } }; /// \brief Functor wrapper for atan. struct atan_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (atan(typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& arg) const { return atan(arg); } }; /// \brief Functor wrapper for atan2. struct atan2_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; typedef typename boost::tuples::element<2, Args>::type arg2_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (atan2(typeof_::make(), typeof_::make()))) public: typedef typename nested::type type; }; template typename sig >::type operator()(const T& y, const T& x) const { return atan2(y, x); } }; } // namespace functional } // namespace math namespace units { /// Boost.Units specific functor wrappers for functions defined /// exclusively in \. namespace functional { /// \brief Functor wrapper for boost::units::pow. template struct static_rational_pow_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (pow(boost::units::typeof_::make()))) public: typedef typename nested::type type; }; template typename sig, Y> >::type operator()(const Y& arg) const { return pow(arg); } }; /// \brief Functor wrapper for boost::units::pow. template struct static_integer_pow_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (pow(boost::units::typeof_::make()))) public: typedef typename nested::type type; }; template typename sig, Y> >::type operator()(const Y& arg) const { return pow(arg); } }; /// \brief Templatized functor wrapper for boost::units::root. template struct static_rational_root_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (root(boost::units::typeof_::make()))) public: typedef typename nested::type type; }; template typename sig, Y> >::type operator()(const Y& arg) const { return root(arg); } }; /// \brief Templatized functor wrapper for boost::units::root. template struct static_integer_root_t { template class sig { private: typedef typename boost::tuples::element<1, Args>::type arg1_type; BOOST_TYPEOF_NESTED_TYPEDEF(nested, (root(boost::units::typeof_::make()))) public: typedef typename nested::type type; }; template typename sig, Y> >::type operator()(const Y& arg) const { return root(arg); } }; } // namespace functional } // namespace units } // namespace boost #endif // BOOST_UNITS_MATH_FUNCTIONAL_HPP