// 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 #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 typename root_typeof_helper< quantity, static_rational<3> >::type cbrt(const quantity& q) { using boost::math::cbrt; typedef typename root_typeof_helper< quantity, static_rational<3> >::type quantity_type; return quantity_type::from_value(cbrt(q.value())); } template inline quantity max BOOST_PREVENT_MACRO_SUBSTITUTION ( const quantity& q1, const quantity& q2 ) { using std::max; typedef quantity result_type; return result_type::from_value(max BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value())); } template inline quantity min BOOST_PREVENT_MACRO_SUBSTITUTION ( const quantity& q1, const quantity& q2 ) { using std::min; typedef quantity quantity_type; return quantity_type::from_value(min BOOST_PREVENT_MACRO_SUBSTITUTION (q1.value(),q2.value())); } template inline bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q) { using boost::math::isfinite; return isfinite BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()); } template inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q) { using boost::math::isinf; return isinf BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()); } template inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q) { using boost::math::isnan; return isnan BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()); } template inline bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q) { using boost::math::isnormal; return isnormal BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()); } template inline 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q) { using boost::math::fpclassify; return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()); } template inline 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 //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 //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 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 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 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 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 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 int signbit BOOST_PREVENT_MACRO_SUBSTITUTION (const quantity& q) { using boost::math::signbit; return signbit BOOST_PREVENT_MACRO_SUBSTITUTION (q.value()); } template inline 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 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 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 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 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 quantity exp(const quantity& q) { using std::exp; typedef quantity quantity_type; return quantity_type::from_value(exp(q.value())); } template inline 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 quantity log(const quantity& q) { using std::log; typedef quantity quantity_type; return quantity_type::from_value(log(q.value())); } template inline quantity log10(const quantity& q) { using std::log10; typedef quantity quantity_type; return quantity_type::from_value(log10(q.value())); } template inline 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 typename dimensionless_quantity::type cos(const quantity& theta) { using std::cos; return cos(theta.value()); } /// sin of theta in radians template typename dimensionless_quantity::type sin(const quantity& theta) { using std::sin; return sin(theta.value()); } /// tan of theta in radians template typename dimensionless_quantity::type tan(const quantity& theta) { using std::tan; return tan(theta.value()); } /// cos of theta in other angular units template typename dimensionless_quantity::type cos(const quantity,Y>& theta) { return cos(quantity(theta)); } /// sin of theta in other angular units template typename dimensionless_quantity::type sin(const quantity,Y>& theta) { return sin(quantity(theta)); } /// tan of theta in other angular units template typename dimensionless_quantity::type tan(const quantity,Y>& theta) { return tan(quantity(theta)); } /// acos of dimensionless quantity returning angle in same system template 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 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 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 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 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 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 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 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