// 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) 2007-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) #ifndef BOOST_UNITS_CMATH_HPP #define BOOST_UNITS_CMATH_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include /// \file /// \brief Overloads of functions in \ for quantities. /// \details Only functions for which a dimensionally-correct result type /// can be determined are overloaded. /// All functions work with dimensionless quantities. // BOOST_PREVENT_MACRO_SUBSTITUTION is needed on certain compilers that define // some functions as macros; it is used for all functions even though it // isn't necessary -- I didn't want to think :) // // the form using namespace detail; return(f(x)); is used // to enable ADL for UDTs. namespace boost { namespace units { template inline BOOST_CONSTEXPR bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q) { using boost::math::isfinite; return isfinite BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()); } template inline BOOST_CONSTEXPR bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q) { using boost::math::isinf; return isinf BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()); } template inline BOOST_CONSTEXPR bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q) { using boost::math::isnan; return isnan BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()); } template inline BOOST_CONSTEXPR bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q) { using boost::math::isnormal; return isnormal BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()); } template inline BOOST_CONSTEXPR bool isgreater BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q1, const quantity& q2) { using namespace detail; return isgreater BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value()); } template inline BOOST_CONSTEXPR bool isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q1, const quantity& q2) { using namespace detail; return isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value()); } template inline BOOST_CONSTEXPR bool isless BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q1, const quantity& q2) { using namespace detail; return isless BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value()); } template inline BOOST_CONSTEXPR bool islessequal BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q1, const quantity& q2) { using namespace detail; return islessequal BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value()); } template inline BOOST_CONSTEXPR bool islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q1, const quantity& q2) { using namespace detail; return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value()); } template inline BOOST_CONSTEXPR bool isunordered BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q1, const quantity& q2) { using namespace detail; return isunordered BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value()); } template inline BOOST_CONSTEXPR quantity abs BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q) { using std::abs; typedef quantity quantity_type; return quantity_type::from_value(abs BOOST_PREVENT_MACRO_SUBSTITUTION (q.value())); } template inline BOOST_CONSTEXPR quantity ceil BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q) { using std::ceil; typedef quantity quantity_type; return quantity_type::from_value(ceil BOOST_PREVENT_MACRO_SUBSTITUTION (q.value())); } template inline BOOST_CONSTEXPR quantity copysign BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q1, const quantity& q2) { using boost::math::copysign; typedef quantity quantity_type; return quantity_type::from_value(copysign BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value())); } template inline BOOST_CONSTEXPR quantity fabs BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q) { using std::fabs; typedef quantity quantity_type; return quantity_type::from_value(fabs BOOST_PREVENT_MACRO_SUBSTITUTION (q.value())); } template inline BOOST_CONSTEXPR quantity floor BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q) { using std::floor; typedef quantity quantity_type; return quantity_type::from_value(floor BOOST_PREVENT_MACRO_SUBSTITUTION (q.value())); } template inline BOOST_CONSTEXPR quantity fdim BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q1, const quantity& q2) { using namespace detail; typedef quantity quantity_type; return quantity_type::from_value(fdim BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value())); } #if 0 template inline BOOST_CONSTEXPR typename add_typeof_helper< typename multiply_typeof_helper, quantity >::type, quantity >::type fma BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q1, const quantity& q2, const quantity& q3) { using namespace detail; typedef quantity type1; typedef quantity type2; typedef quantity type3; typedef typename multiply_typeof_helper::type prod_type; typedef typename add_typeof_helper::type quantity_type; return quantity_type::from_value(fma BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value(),q3.value())); } #endif template inline BOOST_CONSTEXPR quantity fmax BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q1, const quantity& q2) { using namespace detail; typedef quantity quantity_type; return quantity_type::from_value(fmax BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value())); } template inline BOOST_CONSTEXPR quantity fmin BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q1, const quantity& q2) { using namespace detail; typedef quantity quantity_type; return quantity_type::from_value(fmin BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value())); } template inline BOOST_CONSTEXPR int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q) { using boost::math::fpclassify; return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()); } template inline BOOST_CONSTEXPR typename root_typeof_helper< typename add_typeof_helper< typename power_typeof_helper, static_rational<2> >::type, typename power_typeof_helper, static_rational<2> >::type>::type, static_rational<2> >::type hypot BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q1,const quantity& q2) { using boost::math::hypot; typedef quantity type1; typedef typename power_typeof_helper >::type pow_type; typedef typename add_typeof_helper::type add_type; typedef typename root_typeof_helper >::type quantity_type; return quantity_type::from_value(hypot BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value())); } // does ISO C++ support long long? g++ claims not //template //inline //BOOST_CONSTEXPR //quantity //llrint BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q) //{ // using namespace detail; // // typedef quantity quantity_type; // // return quantity_type::from_value(llrint BOOST_PREVENT_MACRO_SUBSTITUTION (q.value())); //} // does ISO C++ support long long? g++ claims not //template //inline //BOOST_CONSTEXPR //quantity //llround BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q) //{ // using namespace detail; // // typedef quantity quantity_type; // // return quantity_type::from_value(llround BOOST_PREVENT_MACRO_SUBSTITUTION (q.value())); //} #if 0 template inline BOOST_CONSTEXPR quantity nearbyint BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q) { using namespace detail; typedef quantity quantity_type; return quantity_type::from_value(nearbyint BOOST_PREVENT_MACRO_SUBSTITUTION (q.value())); } #endif template inline BOOST_CONSTEXPR quantity nextafter BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q1, const quantity& q2) { using boost::math::nextafter; typedef quantity quantity_type; return quantity_type::from_value(nextafter BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value())); } template inline BOOST_CONSTEXPR quantity nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q1, const quantity& q2) { // the only difference between nextafter and nexttowards is // in the argument types. Since we are requiring identical // argument types, there is no difference. using boost::math::nextafter; typedef quantity quantity_type; return quantity_type::from_value(nextafter BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value())); } #if 0 template inline BOOST_CONSTEXPR quantity rint BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q) { using namespace detail; typedef quantity quantity_type; return quantity_type::from_value(rint BOOST_PREVENT_MACRO_SUBSTITUTION (q.value())); } #endif template inline BOOST_CONSTEXPR quantity round BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q) { using boost::math::round; typedef quantity quantity_type; return quantity_type::from_value(round BOOST_PREVENT_MACRO_SUBSTITUTION (q.value())); } template inline BOOST_CONSTEXPR int signbit BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q) { using boost::math::signbit; return signbit BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()); } template inline BOOST_CONSTEXPR quantity trunc BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q) { using namespace detail; typedef quantity quantity_type; return quantity_type::from_value(trunc BOOST_PREVENT_MACRO_SUBSTITUTION (q.value())); } template inline BOOST_CONSTEXPR quantity fmod(const quantity& q1, const quantity& q2) { using std::fmod; typedef quantity quantity_type; return quantity_type::from_value(fmod(q1.value(), q2.value())); } template inline BOOST_CONSTEXPR quantity modf(const quantity& q1, quantity* q2) { using std::modf; typedef quantity quantity_type; return quantity_type::from_value(modf(q1.value(), &quantity_cast(*q2))); } template inline BOOST_CONSTEXPR quantity frexp(const quantity& q,Int* ex) { using std::frexp; typedef quantity quantity_type; return quantity_type::from_value(frexp(q.value(),ex)); } /// For non-dimensionless quantities, integral and rational powers /// and roots can be computed by @c pow and @c root respectively. template inline BOOST_CONSTEXPR quantity pow(const quantity& q1, const quantity& q2) { using std::pow; typedef quantity quantity_type; return quantity_type::from_value(pow(q1.value(), q2.value())); } template inline BOOST_CONSTEXPR quantity exp(const quantity& q) { using std::exp; typedef quantity quantity_type; return quantity_type::from_value(exp(q.value())); } template inline BOOST_CONSTEXPR quantity ldexp(const quantity& q,const Int& ex) { using std::ldexp; typedef quantity quantity_type; return quantity_type::from_value(ldexp(q.value(), ex)); } template inline BOOST_CONSTEXPR quantity log(const quantity& q) { using std::log; typedef quantity quantity_type; return quantity_type::from_value(log(q.value())); } template inline BOOST_CONSTEXPR quantity log10(const quantity& q) { using std::log10; typedef quantity quantity_type; return quantity_type::from_value(log10(q.value())); } template inline BOOST_CONSTEXPR typename root_typeof_helper< quantity, static_rational<2> >::type sqrt(const quantity& q) { using std::sqrt; typedef typename root_typeof_helper< quantity, static_rational<2> >::type quantity_type; return quantity_type::from_value(sqrt(q.value())); } } // namespace units } // namespace boost namespace boost { namespace units { // trig functions with si argument/return types /// cos of theta in radians template BOOST_CONSTEXPR typename dimensionless_quantity::type cos(const quantity& theta) { using std::cos; return cos(theta.value()); } /// sin of theta in radians template BOOST_CONSTEXPR typename dimensionless_quantity::type sin(const quantity& theta) { using std::sin; return sin(theta.value()); } /// tan of theta in radians template BOOST_CONSTEXPR typename dimensionless_quantity::type tan(const quantity& theta) { using std::tan; return tan(theta.value()); } /// cos of theta in other angular units template BOOST_CONSTEXPR typename dimensionless_quantity::type cos(const quantity,Y>& theta) { return cos(quantity(theta)); } /// sin of theta in other angular units template BOOST_CONSTEXPR typename dimensionless_quantity::type sin(const quantity,Y>& theta) { return sin(quantity(theta)); } /// tan of theta in other angular units template BOOST_CONSTEXPR typename dimensionless_quantity::type tan(const quantity,Y>& theta) { return tan(quantity(theta)); } /// acos of dimensionless quantity returning angle in same system template BOOST_CONSTEXPR quantity >,Y> acos(const quantity >,Y>& val) { using std::acos; return quantity >,Y>(acos(val.value())*si::radians); } /// acos of dimensionless quantity returning angle in radians template BOOST_CONSTEXPR quantity acos(const quantity,Y>& val) { using std::acos; return quantity::from_value(acos(val.value())); } /// asin of dimensionless quantity returning angle in same system template BOOST_CONSTEXPR quantity >,Y> asin(const quantity >,Y>& val) { using std::asin; return quantity >,Y>(asin(val.value())*si::radians); } /// asin of dimensionless quantity returning angle in radians template BOOST_CONSTEXPR quantity asin(const quantity,Y>& val) { using std::asin; return quantity::from_value(asin(val.value())); } /// atan of dimensionless quantity returning angle in same system template BOOST_CONSTEXPR quantity >,Y> atan(const quantity >, Y>& val) { using std::atan; return quantity >,Y>(atan(val.value())*si::radians); } /// atan of dimensionless quantity returning angle in radians template BOOST_CONSTEXPR quantity atan(const quantity, Y>& val) { using std::atan; return quantity::from_value(atan(val.value())); } /// atan2 of @c value_type returning angle in radians template BOOST_CONSTEXPR quantity >, Y> atan2(const quantity >, Y>& y, const quantity >, Y>& x) { using std::atan2; return quantity >, Y>(atan2(y.value(),x.value())*si::radians); } /// atan2 of @c value_type returning angle in radians template BOOST_CONSTEXPR quantity atan2(const quantity >, Y>& y, const quantity >, Y>& x) { using std::atan2; return quantity::from_value(atan2(y.value(),x.value())); } } // namespace units } // namespace boost #endif // BOOST_UNITS_CMATH_HPP