common_factor_ct.hpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // Boost common_factor_ct.hpp header file ----------------------------------//
  2. // (C) Copyright Daryle Walker and Stephen Cleary 2001-2002.
  3. // Distributed under the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. // See http://www.boost.org for updates, documentation, and revision history.
  7. #ifndef BOOST_MATH_COMMON_FACTOR_CT_HPP
  8. #define BOOST_MATH_COMMON_FACTOR_CT_HPP
  9. #include <boost/math_fwd.hpp> // self include
  10. #include <boost/config.hpp> // for BOOST_STATIC_CONSTANT, etc.
  11. #include <boost/mpl/integral_c.hpp>
  12. namespace boost
  13. {
  14. namespace math
  15. {
  16. // Implementation details --------------------------------------------------//
  17. namespace detail
  18. {
  19. #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  20. // Build GCD with Euclid's recursive algorithm
  21. template < static_gcd_type Value1, static_gcd_type Value2 >
  22. struct static_gcd_helper_t
  23. {
  24. private:
  25. BOOST_STATIC_CONSTANT( static_gcd_type, new_value1 = Value2 );
  26. BOOST_STATIC_CONSTANT( static_gcd_type, new_value2 = Value1 % Value2 );
  27. #ifndef __BORLANDC__
  28. #define BOOST_DETAIL_GCD_HELPER_VAL(Value) static_cast<static_gcd_type>(Value)
  29. #else
  30. typedef static_gcd_helper_t self_type;
  31. #define BOOST_DETAIL_GCD_HELPER_VAL(Value) (self_type:: Value )
  32. #endif
  33. typedef static_gcd_helper_t< BOOST_DETAIL_GCD_HELPER_VAL(new_value1),
  34. BOOST_DETAIL_GCD_HELPER_VAL(new_value2) > next_step_type;
  35. #undef BOOST_DETAIL_GCD_HELPER_VAL
  36. public:
  37. BOOST_STATIC_CONSTANT( static_gcd_type, value = next_step_type::value );
  38. };
  39. // Non-recursive case
  40. template < static_gcd_type Value1 >
  41. struct static_gcd_helper_t< Value1, 0UL >
  42. {
  43. BOOST_STATIC_CONSTANT( static_gcd_type, value = Value1 );
  44. };
  45. #else
  46. // Use inner class template workaround from Peter Dimov
  47. template < static_gcd_type Value1 >
  48. struct static_gcd_helper2_t
  49. {
  50. template < static_gcd_type Value2 >
  51. struct helper
  52. {
  53. BOOST_STATIC_CONSTANT( static_gcd_type, value
  54. = static_gcd_helper2_t<Value2>::BOOST_NESTED_TEMPLATE
  55. helper<Value1 % Value2>::value );
  56. };
  57. template < >
  58. struct helper< 0UL >
  59. {
  60. BOOST_STATIC_CONSTANT( static_gcd_type, value = Value1 );
  61. };
  62. };
  63. // Special case
  64. template < >
  65. struct static_gcd_helper2_t< 0UL >
  66. {
  67. template < static_gcd_type Value2 >
  68. struct helper
  69. {
  70. BOOST_STATIC_CONSTANT( static_gcd_type, value = Value2 );
  71. };
  72. };
  73. // Build the GCD from the above template(s)
  74. template < static_gcd_type Value1, static_gcd_type Value2 >
  75. struct static_gcd_helper_t
  76. {
  77. BOOST_STATIC_CONSTANT( static_gcd_type, value
  78. = static_gcd_helper2_t<Value1>::BOOST_NESTED_TEMPLATE
  79. helper<Value2>::value );
  80. };
  81. #endif
  82. #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  83. // Build the LCM from the GCD
  84. template < static_gcd_type Value1, static_gcd_type Value2 >
  85. struct static_lcm_helper_t
  86. {
  87. typedef static_gcd_helper_t<Value1, Value2> gcd_type;
  88. BOOST_STATIC_CONSTANT( static_gcd_type, value = Value1 / gcd_type::value
  89. * Value2 );
  90. };
  91. // Special case for zero-GCD values
  92. template < >
  93. struct static_lcm_helper_t< 0UL, 0UL >
  94. {
  95. BOOST_STATIC_CONSTANT( static_gcd_type, value = 0UL );
  96. };
  97. #else
  98. // Adapt GCD's inner class template workaround for LCM
  99. template < static_gcd_type Value1 >
  100. struct static_lcm_helper2_t
  101. {
  102. template < static_gcd_type Value2 >
  103. struct helper
  104. {
  105. typedef static_gcd_helper_t<Value1, Value2> gcd_type;
  106. BOOST_STATIC_CONSTANT( static_gcd_type, value = Value1
  107. / gcd_type::value * Value2 );
  108. };
  109. template < >
  110. struct helper< 0UL >
  111. {
  112. BOOST_STATIC_CONSTANT( static_gcd_type, value = 0UL );
  113. };
  114. };
  115. // Special case
  116. template < >
  117. struct static_lcm_helper2_t< 0UL >
  118. {
  119. template < static_gcd_type Value2 >
  120. struct helper
  121. {
  122. BOOST_STATIC_CONSTANT( static_gcd_type, value = 0UL );
  123. };
  124. };
  125. // Build the LCM from the above template(s)
  126. template < static_gcd_type Value1, static_gcd_type Value2 >
  127. struct static_lcm_helper_t
  128. {
  129. BOOST_STATIC_CONSTANT( static_gcd_type, value
  130. = static_lcm_helper2_t<Value1>::BOOST_NESTED_TEMPLATE
  131. helper<Value2>::value );
  132. };
  133. #endif
  134. } // namespace detail
  135. // Compile-time greatest common divisor evaluator class declaration --------//
  136. template < static_gcd_type Value1, static_gcd_type Value2 >
  137. struct static_gcd : public mpl::integral_c<static_gcd_type, (detail::static_gcd_helper_t<Value1, Value2>::value) >
  138. {
  139. }; // boost::math::static_gcd
  140. // Compile-time least common multiple evaluator class declaration ----------//
  141. template < static_gcd_type Value1, static_gcd_type Value2 >
  142. struct static_lcm : public mpl::integral_c<static_gcd_type, (detail::static_lcm_helper_t<Value1, Value2>::value) >
  143. {
  144. }; // boost::math::static_lcm
  145. } // namespace math
  146. } // namespace boost
  147. #endif // BOOST_MATH_COMMON_FACTOR_CT_HPP