static_rational_power.hpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  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 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 one call(const one&)
  52. {
  53. one result;
  54. return(result);
  55. }
  56. };
  57. template<long N>
  58. struct static_rational_power_impl<static_rational<N, 1>, one>
  59. {
  60. typedef one type;
  61. static one call(const one&)
  62. {
  63. one result;
  64. return(result);
  65. }
  66. };
  67. template<long N, bool = (N % 2 == 0)>
  68. struct static_int_power_impl;
  69. template<long N>
  70. struct static_int_power_impl<N, true>
  71. {
  72. template<class Y, class R>
  73. struct apply
  74. {
  75. typedef typename multiply_typeof_helper<Y, Y>::type square_type;
  76. typedef typename static_int_power_impl<(N >> 1)>::template apply<square_type, R> next;
  77. typedef typename next::type type;
  78. static type call(const Y& y, const R& r)
  79. {
  80. const square_type square = y * y;
  81. return(next::call(square, r));
  82. }
  83. };
  84. };
  85. template<long N>
  86. struct static_int_power_impl<N, false>
  87. {
  88. template<class Y, class R>
  89. struct apply
  90. {
  91. typedef typename multiply_typeof_helper<Y, Y>::type square_type;
  92. typedef typename multiply_typeof_helper<Y, R>::type new_r;
  93. typedef typename static_int_power_impl<(N >> 1)>::template apply<square_type, new_r> next;
  94. typedef typename next::type type;
  95. static type call(const Y& y, const R& r)
  96. {
  97. const Y square = y * y;
  98. return(next::call(square, y * r));
  99. }
  100. };
  101. };
  102. template<>
  103. struct static_int_power_impl<1, false>
  104. {
  105. template<class Y, class R>
  106. struct apply
  107. {
  108. typedef typename multiply_typeof_helper<Y, R>::type type;
  109. static type call(const Y& y, const R& r)
  110. {
  111. return(y * r);
  112. }
  113. };
  114. };
  115. template<>
  116. struct static_int_power_impl<0, true>
  117. {
  118. template<class Y, class R>
  119. struct apply
  120. {
  121. typedef R type;
  122. static R call(const Y&, const R& r)
  123. {
  124. return(r);
  125. }
  126. };
  127. };
  128. template<int N, bool = (N < 0)>
  129. struct static_int_power_sign_impl;
  130. template<int N>
  131. struct static_int_power_sign_impl<N, false>
  132. {
  133. template<class Y>
  134. struct apply
  135. {
  136. typedef typename static_int_power_impl<N>::template apply<Y, one> impl;
  137. typedef typename impl::type type;
  138. static type call(const Y& y)
  139. {
  140. one result;
  141. return(impl::call(y, result));
  142. }
  143. };
  144. };
  145. template<int N>
  146. struct static_int_power_sign_impl<N, true>
  147. {
  148. template<class Y>
  149. struct apply
  150. {
  151. typedef typename static_int_power_impl<-N>::template apply<Y, one> impl;
  152. typedef typename divide_typeof_helper<one, typename impl::type>::type type;
  153. static type call(const Y& y)
  154. {
  155. one result;
  156. return(result/impl::call(y, result));
  157. }
  158. };
  159. };
  160. template<long N, class Y>
  161. struct static_rational_power_impl<static_rational<N, 1>, Y>
  162. {
  163. typedef typename static_int_power_sign_impl<N>::template apply<Y> impl;
  164. typedef typename impl::type type;
  165. static type call(const Y& y)
  166. {
  167. return(impl::call(y));
  168. }
  169. };
  170. template<class R, class Y>
  171. typename detail::static_rational_power_impl<R, Y>::type static_rational_power(const Y& y)
  172. {
  173. return(detail::static_rational_power_impl<R, Y>::call(y));
  174. }
  175. } // namespace detail
  176. } // namespace units
  177. } // namespace boost
  178. #endif