| // 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_DETAIL_STATIC_RATIONAL_POWER_HPP |
| #define BOOST_UNITS_DETAIL_STATIC_RATIONAL_POWER_HPP |
| |
| #include <boost/config/no_tr1/cmath.hpp> |
| |
| #include <boost/units/detail/one.hpp> |
| #include <boost/units/operators.hpp> |
| |
| namespace boost { |
| |
| namespace units { |
| |
| template<long N,long D> |
| class static_rational; |
| |
| namespace detail { |
| |
| namespace typeof_pow_adl_barrier { |
| |
| using std::pow; |
| |
| template<class Y> |
| struct typeof_pow |
| { |
| #if defined(BOOST_UNITS_HAS_BOOST_TYPEOF) |
| BOOST_TYPEOF_NESTED_TYPEDEF_TPL(nested, pow(typeof_::make<Y>(), 0.0)) |
| typedef typename nested::type type; |
| #elif defined(BOOST_UNITS_HAS_MWERKS_TYPEOF) |
| typedef __typeof__(pow(typeof_::make<Y>(), 0.0)) type; |
| #elif defined(BOOST_UNITS_HAS_GNU_TYPEOF) |
| typedef typeof(pow(typeof_::make<Y>(), 0.0)) type; |
| #else |
| typedef Y type; |
| #endif |
| }; |
| |
| } |
| |
| template<class R, class Y> |
| struct static_rational_power_impl |
| { |
| typedef typename typeof_pow_adl_barrier::typeof_pow<Y>::type type; |
| static type call(const Y& y) |
| { |
| using std::pow; |
| return(pow(y, static_cast<double>(R::Numerator) / static_cast<double>(R::Denominator))); |
| } |
| }; |
| |
| template<class R> |
| struct static_rational_power_impl<R, one> |
| { |
| typedef one type; |
| static one call(const one&) |
| { |
| one result; |
| return(result); |
| } |
| }; |
| |
| template<long N> |
| struct static_rational_power_impl<static_rational<N, 1>, one> |
| { |
| typedef one type; |
| static one call(const one&) |
| { |
| one result; |
| return(result); |
| } |
| }; |
| |
| template<long N, bool = (N % 2 == 0)> |
| struct static_int_power_impl; |
| |
| template<long N> |
| struct static_int_power_impl<N, true> |
| { |
| template<class Y, class R> |
| struct apply |
| { |
| typedef typename multiply_typeof_helper<Y, Y>::type square_type; |
| typedef typename static_int_power_impl<(N >> 1)>::template apply<square_type, R> next; |
| typedef typename next::type type; |
| static type call(const Y& y, const R& r) |
| { |
| const Y square = y * y; |
| return(next::call(square, r)); |
| } |
| }; |
| }; |
| |
| template<long N> |
| struct static_int_power_impl<N, false> |
| { |
| template<class Y, class R> |
| struct apply |
| { |
| typedef typename multiply_typeof_helper<Y, Y>::type square_type; |
| typedef typename multiply_typeof_helper<Y, R>::type new_r; |
| typedef typename static_int_power_impl<(N >> 1)>::template apply<square_type, new_r> next; |
| typedef typename next::type type; |
| static type call(const Y& y, const R& r) |
| { |
| const Y square = y * y; |
| return(next::call(square, y * r)); |
| } |
| }; |
| }; |
| |
| template<> |
| struct static_int_power_impl<1, false> |
| { |
| template<class Y, class R> |
| struct apply |
| { |
| typedef typename multiply_typeof_helper<Y, R>::type type; |
| static type call(const Y& y, const R& r) |
| { |
| return(y * r); |
| } |
| }; |
| }; |
| |
| template<> |
| struct static_int_power_impl<0, true> |
| { |
| template<class Y, class R> |
| struct apply |
| { |
| typedef R type; |
| static R call(const Y&, const R& r) |
| { |
| return(r); |
| } |
| }; |
| }; |
| |
| template<int N, bool = (N < 0)> |
| struct static_int_power_sign_impl; |
| |
| template<int N> |
| struct static_int_power_sign_impl<N, false> |
| { |
| template<class Y> |
| struct apply |
| { |
| typedef typename static_int_power_impl<N>::template apply<Y, one> impl; |
| typedef typename impl::type type; |
| static type call(const Y& y) |
| { |
| one result; |
| return(impl::call(y, result)); |
| } |
| }; |
| }; |
| |
| template<int N> |
| struct static_int_power_sign_impl<N, true> |
| { |
| template<class Y> |
| struct apply |
| { |
| typedef typename static_int_power_impl<-N>::template apply<Y, one> impl; |
| typedef typename divide_typeof_helper<one, typename impl::type>::type type; |
| static type call(const Y& y) |
| { |
| one result; |
| return(result/impl::call(y, result)); |
| } |
| }; |
| }; |
| |
| template<long N, class Y> |
| struct static_rational_power_impl<static_rational<N, 1>, Y> |
| { |
| typedef typename static_int_power_sign_impl<N>::template apply<Y> impl; |
| typedef typename impl::type type; |
| static Y call(const Y& y) |
| { |
| return(impl::call(y)); |
| } |
| }; |
| |
| template<class R, class Y> |
| typename detail::static_rational_power_impl<R, Y>::type static_rational_power(const Y& y) |
| { |
| return(detail::static_rational_power_impl<R, Y>::call(y)); |
| } |
| |
| } // namespace detail |
| |
| } // namespace units |
| |
| } // namespace boost |
| |
| #endif |