diff options
Diffstat (limited to 'boost/units/detail/static_rational_power.hpp')
-rw-r--r-- | boost/units/detail/static_rational_power.hpp | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/boost/units/detail/static_rational_power.hpp b/boost/units/detail/static_rational_power.hpp new file mode 100644 index 0000000000..9c71f55ab7 --- /dev/null +++ b/boost/units/detail/static_rational_power.hpp @@ -0,0 +1,206 @@ +// 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 |