summaryrefslogtreecommitdiff
path: root/boost/units/detail/static_rational_power.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/units/detail/static_rational_power.hpp')
-rw-r--r--boost/units/detail/static_rational_power.hpp206
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 0000000..9c71f55
--- /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