static_rational_power.hpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // Boost.Units - A C++ library for zero-overhead dimensional analysis and
  2. // unit/quantity manipulation and conversion
  3. //
  4. // Copyright (C) 2003-2008 Matthias Christian Schabel
  5. // Copyright (C) 2007-2008 Steven Watanabe
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See
  8. // accompanying file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. #ifndef BOOST_UNITS_DETAIL_STATIC_RATIONAL_POWER_HPP
  11. #define BOOST_UNITS_DETAIL_STATIC_RATIONAL_POWER_HPP
  12. #include <boost/config/no_tr1/cmath.hpp>
  13. #include <boost/units/detail/one.hpp>
  14. #include <boost/units/operators.hpp>
  15. namespace boost {
  16. namespace units {
  17. template<long N,long D>
  18. class static_rational;
  19. namespace detail {
  20. namespace typeof_pow_adl_barrier {
  21. using std::pow;
  22. template<class Y>
  23. struct typeof_pow
  24. {
  25. #if defined(BOOST_UNITS_HAS_BOOST_TYPEOF)
  26. BOOST_TYPEOF_NESTED_TYPEDEF_TPL(nested, pow(typeof_::make<Y>(), 0.0))
  27. typedef typename nested::type type;
  28. #elif defined(BOOST_UNITS_HAS_MWERKS_TYPEOF)
  29. typedef __typeof__(pow(typeof_::make<Y>(), 0.0)) type;
  30. #elif defined(BOOST_UNITS_HAS_GNU_TYPEOF)
  31. typedef typeof(pow(typeof_::make<Y>(), 0.0)) type;
  32. #else
  33. typedef Y type;
  34. #endif
  35. };
  36. }
  37. template<class R, class Y>
  38. struct static_rational_power_impl
  39. {
  40. typedef typename typeof_pow_adl_barrier::typeof_pow<Y>::type type;
  41. static BOOST_CONSTEXPR type call(const Y& y)
  42. {
  43. using std::pow;
  44. return(pow(y, static_cast<double>(R::Numerator) / static_cast<double>(R::Denominator)));
  45. }
  46. };
  47. template<class R>
  48. struct static_rational_power_impl<R, one>
  49. {
  50. typedef one type;
  51. static BOOST_CONSTEXPR one call(const one&)
  52. {
  53. return(one());
  54. }
  55. };
  56. template<long N>
  57. struct static_rational_power_impl<static_rational<N, 1>, one>
  58. {
  59. typedef one type;
  60. static BOOST_CONSTEXPR one call(const one&)
  61. {
  62. return(one());
  63. }
  64. };
  65. template<long N, bool = (N % 2 == 0)>
  66. struct static_int_power_impl;
  67. template<long N>
  68. struct static_int_power_impl<N, true>
  69. {
  70. template<class Y, class R>
  71. struct apply
  72. {
  73. typedef typename multiply_typeof_helper<Y, Y>::type square_type;
  74. typedef typename static_int_power_impl<(N >> 1)>::template apply<square_type, R> next;
  75. typedef typename next::type type;
  76. static BOOST_CONSTEXPR type call(const Y& y, const R& r)
  77. {
  78. return(next::call(static_cast<square_type>(y * y), r));
  79. }
  80. };
  81. };
  82. template<long N>
  83. struct static_int_power_impl<N, false>
  84. {
  85. template<class Y, class R>
  86. struct apply
  87. {
  88. typedef typename multiply_typeof_helper<Y, Y>::type square_type;
  89. typedef typename multiply_typeof_helper<Y, R>::type new_r;
  90. typedef typename static_int_power_impl<(N >> 1)>::template apply<square_type, new_r> next;
  91. typedef typename next::type type;
  92. static BOOST_CONSTEXPR type call(const Y& y, const R& r)
  93. {
  94. return(next::call(static_cast<Y>(y * y), y * r));
  95. }
  96. };
  97. };
  98. template<>
  99. struct static_int_power_impl<1, false>
  100. {
  101. template<class Y, class R>
  102. struct apply
  103. {
  104. typedef typename multiply_typeof_helper<Y, R>::type type;
  105. static BOOST_CONSTEXPR type call(const Y& y, const R& r)
  106. {
  107. return(y * r);
  108. }
  109. };
  110. };
  111. template<>
  112. struct static_int_power_impl<0, true>
  113. {
  114. template<class Y, class R>
  115. struct apply
  116. {
  117. typedef R type;
  118. static BOOST_CONSTEXPR R call(const Y&, const R& r)
  119. {
  120. return(r);
  121. }
  122. };
  123. };
  124. template<int N, bool = (N < 0)>
  125. struct static_int_power_sign_impl;
  126. template<int N>
  127. struct static_int_power_sign_impl<N, false>
  128. {
  129. template<class Y>
  130. struct apply
  131. {
  132. typedef typename static_int_power_impl<N>::template apply<Y, one> impl;
  133. typedef typename impl::type type;
  134. static BOOST_CONSTEXPR type call(const Y& y)
  135. {
  136. return(impl::call(y, one()));
  137. }
  138. };
  139. };
  140. template<int N>
  141. struct static_int_power_sign_impl<N, true>
  142. {
  143. template<class Y>
  144. struct apply
  145. {
  146. typedef typename static_int_power_impl<-N>::template apply<Y, one> impl;
  147. typedef typename divide_typeof_helper<one, typename impl::type>::type type;
  148. static BOOST_CONSTEXPR type call(const Y& y)
  149. {
  150. return(one()/impl::call(y, one()));
  151. }
  152. };
  153. };
  154. template<long N, class Y>
  155. struct static_rational_power_impl<static_rational<N, 1>, Y>
  156. {
  157. typedef typename static_int_power_sign_impl<N>::template apply<Y> impl;
  158. typedef typename impl::type type;
  159. static BOOST_CONSTEXPR type call(const Y& y)
  160. {
  161. return(impl::call(y));
  162. }
  163. };
  164. template<class R, class Y>
  165. BOOST_CONSTEXPR
  166. typename detail::static_rational_power_impl<R, Y>::type static_rational_power(const Y& y)
  167. {
  168. return(detail::static_rational_power_impl<R, Y>::call(y));
  169. }
  170. } // namespace detail
  171. } // namespace units
  172. } // namespace boost
  173. #endif