Chris@16: // (C) Copyright John Maddock 2006. Chris@16: // Use, modification and distribution are subject to the Chris@16: // Boost Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_MATH_TOOLS_RATIONAL_HPP Chris@16: #define BOOST_MATH_TOOLS_RATIONAL_HPP Chris@16: Chris@16: #ifdef _MSC_VER Chris@16: #pragma once Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #if BOOST_MATH_POLY_METHOD == 1 Chris@16: # define BOOST_HEADER() Chris@16: # include BOOST_HEADER() Chris@16: # undef BOOST_HEADER Chris@16: #elif BOOST_MATH_POLY_METHOD == 2 Chris@16: # define BOOST_HEADER() Chris@16: # include BOOST_HEADER() Chris@16: # undef BOOST_HEADER Chris@16: #elif BOOST_MATH_POLY_METHOD == 3 Chris@16: # define BOOST_HEADER() Chris@16: # include BOOST_HEADER() Chris@16: # undef BOOST_HEADER Chris@16: #endif Chris@16: #if BOOST_MATH_RATIONAL_METHOD == 1 Chris@16: # define BOOST_HEADER() Chris@16: # include BOOST_HEADER() Chris@16: # undef BOOST_HEADER Chris@16: #elif BOOST_MATH_RATIONAL_METHOD == 2 Chris@16: # define BOOST_HEADER() Chris@16: # include BOOST_HEADER() Chris@16: # undef BOOST_HEADER Chris@16: #elif BOOST_MATH_RATIONAL_METHOD == 3 Chris@16: # define BOOST_HEADER() Chris@16: # include BOOST_HEADER() Chris@16: # undef BOOST_HEADER Chris@16: #endif Chris@16: Chris@16: #if 0 Chris@16: // Chris@16: // This just allows dependency trackers to find the headers Chris@16: // used in the above PP-magic. Chris@16: // Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #endif Chris@16: Chris@16: namespace boost{ namespace math{ namespace tools{ Chris@16: Chris@16: // Chris@16: // Forward declaration to keep two phase lookup happy: Chris@16: // Chris@16: template Chris@16: U evaluate_polynomial(const T* poly, U const& z, std::size_t count); Chris@16: Chris@16: namespace detail{ Chris@16: Chris@16: template Chris@16: inline V evaluate_polynomial_c_imp(const T* a, const V& val, const Tag*) Chris@16: { Chris@16: return evaluate_polynomial(a, val, Tag::value); Chris@16: } Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: // Chris@16: // Polynomial evaluation with runtime size. Chris@16: // This requires a for-loop which may be more expensive than Chris@16: // the loop expanded versions above: Chris@16: // Chris@16: template Chris@16: inline U evaluate_polynomial(const T* poly, U const& z, std::size_t count) Chris@16: { Chris@16: BOOST_ASSERT(count > 0); Chris@16: U sum = static_cast(poly[count - 1]); Chris@16: for(int i = static_cast(count) - 2; i >= 0; --i) Chris@16: { Chris@16: sum *= z; Chris@16: sum += static_cast(poly[i]); Chris@16: } Chris@16: return sum; Chris@16: } Chris@16: // Chris@16: // Compile time sized polynomials, just inline forwarders to the Chris@16: // implementations above: Chris@16: // Chris@16: template Chris@16: inline V evaluate_polynomial(const T(&a)[N], const V& val) Chris@16: { Chris@16: typedef mpl::int_ tag_type; Chris@16: return detail::evaluate_polynomial_c_imp(static_cast(a), val, static_cast(0)); Chris@16: } Chris@16: Chris@16: template Chris@16: inline V evaluate_polynomial(const boost::array& a, const V& val) Chris@16: { Chris@16: typedef mpl::int_ tag_type; Chris@16: return detail::evaluate_polynomial_c_imp(static_cast(a.data()), val, static_cast(0)); Chris@16: } Chris@16: // Chris@16: // Even polynomials are trivial: just square the argument! Chris@16: // Chris@16: template Chris@16: inline U evaluate_even_polynomial(const T* poly, U z, std::size_t count) Chris@16: { Chris@16: return evaluate_polynomial(poly, U(z*z), count); Chris@16: } Chris@16: Chris@16: template Chris@16: inline V evaluate_even_polynomial(const T(&a)[N], const V& z) Chris@16: { Chris@16: return evaluate_polynomial(a, V(z*z)); Chris@16: } Chris@16: Chris@16: template Chris@16: inline V evaluate_even_polynomial(const boost::array& a, const V& z) Chris@16: { Chris@16: return evaluate_polynomial(a, V(z*z)); Chris@16: } Chris@16: // Chris@16: // Odd polynomials come next: Chris@16: // Chris@16: template Chris@16: inline U evaluate_odd_polynomial(const T* poly, U z, std::size_t count) Chris@16: { Chris@16: return poly[0] + z * evaluate_polynomial(poly+1, U(z*z), count-1); Chris@16: } Chris@16: Chris@16: template Chris@16: inline V evaluate_odd_polynomial(const T(&a)[N], const V& z) Chris@16: { Chris@16: typedef mpl::int_ tag_type; Chris@16: return a[0] + z * detail::evaluate_polynomial_c_imp(static_cast(a) + 1, V(z*z), static_cast(0)); Chris@16: } Chris@16: Chris@16: template Chris@16: inline V evaluate_odd_polynomial(const boost::array& a, const V& z) Chris@16: { Chris@16: typedef mpl::int_ tag_type; Chris@16: return a[0] + z * detail::evaluate_polynomial_c_imp(static_cast(a.data()) + 1, V(z*z), static_cast(0)); Chris@16: } Chris@16: Chris@16: template Chris@16: V evaluate_rational(const T* num, const U* denom, const V& z_, std::size_t count); Chris@16: Chris@16: namespace detail{ Chris@16: Chris@16: template Chris@16: inline V evaluate_rational_c_imp(const T* num, const U* denom, const V& z, const Tag*) Chris@16: { Chris@16: return boost::math::tools::evaluate_rational(num, denom, z, Tag::value); Chris@16: } Chris@16: Chris@16: } Chris@16: // Chris@16: // Rational functions: numerator and denominator must be Chris@16: // equal in size. These always have a for-loop and so may be less Chris@16: // efficient than evaluating a pair of polynomials. However, there Chris@16: // are some tricks we can use to prevent overflow that might otherwise Chris@16: // occur in polynomial evaluation, if z is large. This is important Chris@16: // in our Lanczos code for example. Chris@16: // Chris@16: template Chris@16: V evaluate_rational(const T* num, const U* denom, const V& z_, std::size_t count) Chris@16: { Chris@16: V z(z_); Chris@16: V s1, s2; Chris@16: if(z <= 1) Chris@16: { Chris@16: s1 = static_cast(num[count-1]); Chris@16: s2 = static_cast(denom[count-1]); Chris@16: for(int i = (int)count - 2; i >= 0; --i) Chris@16: { Chris@16: s1 *= z; Chris@16: s2 *= z; Chris@16: s1 += num[i]; Chris@16: s2 += denom[i]; Chris@16: } Chris@16: } Chris@16: else Chris@16: { Chris@16: z = 1 / z; Chris@16: s1 = static_cast(num[0]); Chris@16: s2 = static_cast(denom[0]); Chris@16: for(unsigned i = 1; i < count; ++i) Chris@16: { Chris@16: s1 *= z; Chris@16: s2 *= z; Chris@16: s1 += num[i]; Chris@16: s2 += denom[i]; Chris@16: } Chris@16: } Chris@16: return s1 / s2; Chris@16: } Chris@16: Chris@16: template Chris@16: inline V evaluate_rational(const T(&a)[N], const U(&b)[N], const V& z) Chris@16: { Chris@16: return detail::evaluate_rational_c_imp(a, b, z, static_cast*>(0)); Chris@16: } Chris@16: Chris@16: template Chris@16: inline V evaluate_rational(const boost::array& a, const boost::array& b, const V& z) Chris@16: { Chris@16: return detail::evaluate_rational_c_imp(a.data(), b.data(), z, static_cast*>(0)); Chris@16: } Chris@16: Chris@16: } // namespace tools Chris@16: } // namespace math Chris@16: } // namespace boost Chris@16: Chris@16: #endif // BOOST_MATH_TOOLS_RATIONAL_HPP Chris@16: Chris@16: Chris@16: Chris@16: