Chris@16: // Copyright John Maddock 2007. 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_NTL_RR_HPP Chris@16: #define BOOST_MATH_NTL_RR_HPP 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: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost{ namespace math{ Chris@16: Chris@16: namespace ntl Chris@16: { Chris@16: Chris@16: class RR; Chris@16: Chris@16: RR ldexp(RR r, int exp); Chris@16: RR frexp(RR r, int* exp); Chris@16: Chris@16: class RR Chris@16: { Chris@16: public: Chris@16: // Constructors: Chris@16: RR() {} Chris@16: RR(const ::NTL::RR& c) : m_value(c){} Chris@16: RR(char c) Chris@16: { Chris@16: m_value = c; Chris@16: } Chris@16: #ifndef BOOST_NO_INTRINSIC_WCHAR_T Chris@16: RR(wchar_t c) Chris@16: { Chris@16: m_value = c; Chris@16: } Chris@16: #endif Chris@16: RR(unsigned char c) Chris@16: { Chris@16: m_value = c; Chris@16: } Chris@16: RR(signed char c) Chris@16: { Chris@16: m_value = c; Chris@16: } Chris@16: RR(unsigned short c) Chris@16: { Chris@16: m_value = c; Chris@16: } Chris@16: RR(short c) Chris@16: { Chris@16: m_value = c; Chris@16: } Chris@16: RR(unsigned int c) Chris@16: { Chris@16: assign_large_int(c); Chris@16: } Chris@16: RR(int c) Chris@16: { Chris@16: assign_large_int(c); Chris@16: } Chris@16: RR(unsigned long c) Chris@16: { Chris@16: assign_large_int(c); Chris@16: } Chris@16: RR(long c) Chris@16: { Chris@16: assign_large_int(c); Chris@16: } Chris@16: #ifdef BOOST_HAS_LONG_LONG Chris@16: RR(boost::ulong_long_type c) Chris@16: { Chris@16: assign_large_int(c); Chris@16: } Chris@16: RR(boost::long_long_type c) Chris@16: { Chris@16: assign_large_int(c); Chris@16: } Chris@16: #endif Chris@16: RR(float c) Chris@16: { Chris@16: m_value = c; Chris@16: } Chris@16: RR(double c) Chris@16: { Chris@16: m_value = c; Chris@16: } Chris@16: RR(long double c) Chris@16: { Chris@16: assign_large_real(c); Chris@16: } Chris@16: Chris@16: // Assignment: Chris@16: RR& operator=(char c) { m_value = c; return *this; } Chris@16: RR& operator=(unsigned char c) { m_value = c; return *this; } Chris@16: RR& operator=(signed char c) { m_value = c; return *this; } Chris@16: #ifndef BOOST_NO_INTRINSIC_WCHAR_T Chris@16: RR& operator=(wchar_t c) { m_value = c; return *this; } Chris@16: #endif Chris@16: RR& operator=(short c) { m_value = c; return *this; } Chris@16: RR& operator=(unsigned short c) { m_value = c; return *this; } Chris@16: RR& operator=(int c) { assign_large_int(c); return *this; } Chris@16: RR& operator=(unsigned int c) { assign_large_int(c); return *this; } Chris@16: RR& operator=(long c) { assign_large_int(c); return *this; } Chris@16: RR& operator=(unsigned long c) { assign_large_int(c); return *this; } Chris@16: #ifdef BOOST_HAS_LONG_LONG Chris@16: RR& operator=(boost::long_long_type c) { assign_large_int(c); return *this; } Chris@16: RR& operator=(boost::ulong_long_type c) { assign_large_int(c); return *this; } Chris@16: #endif Chris@16: RR& operator=(float c) { m_value = c; return *this; } Chris@16: RR& operator=(double c) { m_value = c; return *this; } Chris@16: RR& operator=(long double c) { assign_large_real(c); return *this; } Chris@16: Chris@16: // Access: Chris@16: NTL::RR& value(){ return m_value; } Chris@16: NTL::RR const& value()const{ return m_value; } Chris@16: Chris@16: // Member arithmetic: Chris@16: RR& operator+=(const RR& other) Chris@16: { m_value += other.value(); return *this; } Chris@16: RR& operator-=(const RR& other) Chris@16: { m_value -= other.value(); return *this; } Chris@16: RR& operator*=(const RR& other) Chris@16: { m_value *= other.value(); return *this; } Chris@16: RR& operator/=(const RR& other) Chris@16: { m_value /= other.value(); return *this; } Chris@16: RR operator-()const Chris@16: { return -m_value; } Chris@16: RR const& operator+()const Chris@16: { return *this; } Chris@16: Chris@16: // RR compatibity: Chris@16: const ::NTL::ZZ& mantissa() const Chris@16: { return m_value.mantissa(); } Chris@16: long exponent() const Chris@16: { return m_value.exponent(); } Chris@16: Chris@16: static void SetPrecision(long p) Chris@16: { ::NTL::RR::SetPrecision(p); } Chris@16: Chris@16: static long precision() Chris@16: { return ::NTL::RR::precision(); } Chris@16: Chris@16: static void SetOutputPrecision(long p) Chris@16: { ::NTL::RR::SetOutputPrecision(p); } Chris@16: static long OutputPrecision() Chris@16: { return ::NTL::RR::OutputPrecision(); } Chris@16: Chris@16: Chris@16: private: Chris@16: ::NTL::RR m_value; Chris@16: Chris@16: template Chris@16: void assign_large_real(const V& a) Chris@16: { Chris@16: using std::frexp; Chris@16: using std::ldexp; Chris@16: using std::floor; Chris@16: if (a == 0) { Chris@16: clear(m_value); Chris@16: return; Chris@16: } Chris@16: Chris@16: if (a == 1) { Chris@16: NTL::set(m_value); Chris@16: return; Chris@16: } Chris@16: Chris@16: if (!(boost::math::isfinite)(a)) Chris@16: { Chris@16: throw std::overflow_error("Cannot construct an instance of NTL::RR with an infinite value."); Chris@16: } Chris@16: Chris@16: int e; Chris@16: long double f, term; Chris@16: ::NTL::RR t; Chris@16: clear(m_value); Chris@16: Chris@16: f = frexp(a, &e); Chris@16: Chris@16: while(f) Chris@16: { Chris@16: // extract 30 bits from f: Chris@16: f = ldexp(f, 30); Chris@16: term = floor(f); Chris@16: e -= 30; Chris@16: conv(t.x, (int)term); Chris@16: t.e = e; Chris@16: m_value += t; Chris@16: f -= term; Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: void assign_large_int(V a) Chris@16: { Chris@16: #ifdef BOOST_MSVC Chris@16: #pragma warning(push) Chris@16: #pragma warning(disable:4146) Chris@16: #endif Chris@16: clear(m_value); Chris@16: int exp = 0; Chris@16: NTL::RR t; Chris@16: bool neg = a < V(0) ? true : false; Chris@16: if(neg) Chris@16: a = -a; Chris@16: while(a) Chris@16: { Chris@16: t = static_cast(a & 0xffff); Chris@16: m_value += ldexp(RR(t), exp).value(); Chris@16: a >>= 16; Chris@16: exp += 16; Chris@16: } Chris@16: if(neg) Chris@16: m_value = -m_value; Chris@16: #ifdef BOOST_MSVC Chris@16: #pragma warning(pop) Chris@16: #endif Chris@16: } Chris@16: }; Chris@16: Chris@16: // Non-member arithmetic: Chris@16: inline RR operator+(const RR& a, const RR& b) Chris@16: { Chris@16: RR result(a); Chris@16: result += b; Chris@16: return result; Chris@16: } Chris@16: inline RR operator-(const RR& a, const RR& b) Chris@16: { Chris@16: RR result(a); Chris@16: result -= b; Chris@16: return result; Chris@16: } Chris@16: inline RR operator*(const RR& a, const RR& b) Chris@16: { Chris@16: RR result(a); Chris@16: result *= b; Chris@16: return result; Chris@16: } Chris@16: inline RR operator/(const RR& a, const RR& b) Chris@16: { Chris@16: RR result(a); Chris@16: result /= b; Chris@16: return result; Chris@16: } Chris@16: Chris@16: // Comparison: Chris@16: inline bool operator == (const RR& a, const RR& b) Chris@16: { return a.value() == b.value() ? true : false; } Chris@16: inline bool operator != (const RR& a, const RR& b) Chris@16: { return a.value() != b.value() ? true : false;} Chris@16: inline bool operator < (const RR& a, const RR& b) Chris@16: { return a.value() < b.value() ? true : false; } Chris@16: inline bool operator <= (const RR& a, const RR& b) Chris@16: { return a.value() <= b.value() ? true : false; } Chris@16: inline bool operator > (const RR& a, const RR& b) Chris@16: { return a.value() > b.value() ? true : false; } Chris@16: inline bool operator >= (const RR& a, const RR& b) Chris@16: { return a.value() >= b.value() ? true : false; } Chris@16: Chris@16: #if 0 Chris@16: // Non-member mixed compare: Chris@16: template Chris@16: inline bool operator == (const T& a, const RR& b) Chris@16: { Chris@16: return a == b.value(); Chris@16: } Chris@16: template Chris@16: inline bool operator != (const T& a, const RR& b) Chris@16: { Chris@16: return a != b.value(); Chris@16: } Chris@16: template Chris@16: inline bool operator < (const T& a, const RR& b) Chris@16: { Chris@16: return a < b.value(); Chris@16: } Chris@16: template Chris@16: inline bool operator > (const T& a, const RR& b) Chris@16: { Chris@16: return a > b.value(); Chris@16: } Chris@16: template Chris@16: inline bool operator <= (const T& a, const RR& b) Chris@16: { Chris@16: return a <= b.value(); Chris@16: } Chris@16: template Chris@16: inline bool operator >= (const T& a, const RR& b) Chris@16: { Chris@16: return a >= b.value(); Chris@16: } Chris@16: #endif // Non-member mixed compare: Chris@16: Chris@16: // Non-member functions: Chris@16: /* Chris@16: inline RR acos(RR a) Chris@16: { return ::NTL::acos(a.value()); } Chris@16: */ Chris@16: inline RR cos(RR a) Chris@16: { return ::NTL::cos(a.value()); } Chris@16: /* Chris@16: inline RR asin(RR a) Chris@16: { return ::NTL::asin(a.value()); } Chris@16: inline RR atan(RR a) Chris@16: { return ::NTL::atan(a.value()); } Chris@16: inline RR atan2(RR a, RR b) Chris@16: { return ::NTL::atan2(a.value(), b.value()); } Chris@16: */ Chris@16: inline RR ceil(RR a) Chris@16: { return ::NTL::ceil(a.value()); } Chris@16: /* Chris@16: inline RR fmod(RR a, RR b) Chris@16: { return ::NTL::fmod(a.value(), b.value()); } Chris@16: inline RR cosh(RR a) Chris@16: { return ::NTL::cosh(a.value()); } Chris@16: */ Chris@16: inline RR exp(RR a) Chris@16: { return ::NTL::exp(a.value()); } Chris@16: inline RR fabs(RR a) Chris@16: { return ::NTL::fabs(a.value()); } Chris@16: inline RR abs(RR a) Chris@16: { return ::NTL::abs(a.value()); } Chris@16: inline RR floor(RR a) Chris@16: { return ::NTL::floor(a.value()); } Chris@16: /* Chris@16: inline RR modf(RR a, RR* ipart) Chris@16: { Chris@16: ::NTL::RR ip; Chris@16: RR result = modf(a.value(), &ip); Chris@16: *ipart = ip; Chris@16: return result; Chris@16: } Chris@16: inline RR frexp(RR a, int* expon) Chris@16: { return ::NTL::frexp(a.value(), expon); } Chris@16: inline RR ldexp(RR a, int expon) Chris@16: { return ::NTL::ldexp(a.value(), expon); } Chris@16: */ Chris@16: inline RR log(RR a) Chris@16: { return ::NTL::log(a.value()); } Chris@16: inline RR log10(RR a) Chris@16: { return ::NTL::log10(a.value()); } Chris@16: /* Chris@16: inline RR tan(RR a) Chris@16: { return ::NTL::tan(a.value()); } Chris@16: */ Chris@16: inline RR pow(RR a, RR b) Chris@16: { return ::NTL::pow(a.value(), b.value()); } Chris@16: inline RR pow(RR a, int b) Chris@16: { return ::NTL::power(a.value(), b); } Chris@16: inline RR sin(RR a) Chris@16: { return ::NTL::sin(a.value()); } Chris@16: /* Chris@16: inline RR sinh(RR a) Chris@16: { return ::NTL::sinh(a.value()); } Chris@16: */ Chris@16: inline RR sqrt(RR a) Chris@16: { return ::NTL::sqrt(a.value()); } Chris@16: /* Chris@16: inline RR tanh(RR a) Chris@16: { return ::NTL::tanh(a.value()); } Chris@16: */ Chris@16: inline RR pow(const RR& r, long l) Chris@16: { Chris@16: return ::NTL::power(r.value(), l); Chris@16: } Chris@16: inline RR tan(const RR& a) Chris@16: { Chris@16: return sin(a)/cos(a); Chris@16: } Chris@16: inline RR frexp(RR r, int* exp) Chris@16: { Chris@16: *exp = r.value().e; Chris@16: r.value().e = 0; Chris@16: while(r >= 1) Chris@16: { Chris@16: *exp += 1; Chris@16: r.value().e -= 1; Chris@16: } Chris@16: while(r < 0.5) Chris@16: { Chris@16: *exp -= 1; Chris@16: r.value().e += 1; Chris@16: } Chris@16: BOOST_ASSERT(r < 1); Chris@16: BOOST_ASSERT(r >= 0.5); Chris@16: return r; Chris@16: } Chris@16: inline RR ldexp(RR r, int exp) Chris@16: { Chris@16: r.value().e += exp; Chris@16: return r; Chris@16: } Chris@16: Chris@16: // Streaming: Chris@16: template Chris@16: inline std::basic_ostream& operator<<(std::basic_ostream& os, const RR& a) Chris@16: { Chris@16: return os << a.value(); Chris@16: } Chris@16: template Chris@16: inline std::basic_istream& operator>>(std::basic_istream& is, RR& a) Chris@16: { Chris@16: ::NTL::RR v; Chris@16: is >> v; Chris@16: a = v; Chris@16: return is; Chris@16: } Chris@16: Chris@16: } // namespace ntl Chris@16: Chris@16: namespace lanczos{ Chris@16: Chris@16: struct ntl_lanczos Chris@16: { Chris@16: static ntl::RR lanczos_sum(const ntl::RR& z) Chris@16: { Chris@16: unsigned long p = ntl::RR::precision(); Chris@16: if(p <= 72) Chris@16: return lanczos13UDT::lanczos_sum(z); Chris@16: else if(p <= 120) Chris@16: return lanczos22UDT::lanczos_sum(z); Chris@16: else if(p <= 170) Chris@16: return lanczos31UDT::lanczos_sum(z); Chris@16: else //if(p <= 370) approx 100 digit precision: Chris@16: return lanczos61UDT::lanczos_sum(z); Chris@16: } Chris@16: static ntl::RR lanczos_sum_expG_scaled(const ntl::RR& z) Chris@16: { Chris@16: unsigned long p = ntl::RR::precision(); Chris@16: if(p <= 72) Chris@16: return lanczos13UDT::lanczos_sum_expG_scaled(z); Chris@16: else if(p <= 120) Chris@16: return lanczos22UDT::lanczos_sum_expG_scaled(z); Chris@16: else if(p <= 170) Chris@16: return lanczos31UDT::lanczos_sum_expG_scaled(z); Chris@16: else //if(p <= 370) approx 100 digit precision: Chris@16: return lanczos61UDT::lanczos_sum_expG_scaled(z); Chris@16: } Chris@16: static ntl::RR lanczos_sum_near_1(const ntl::RR& z) Chris@16: { Chris@16: unsigned long p = ntl::RR::precision(); Chris@16: if(p <= 72) Chris@16: return lanczos13UDT::lanczos_sum_near_1(z); Chris@16: else if(p <= 120) Chris@16: return lanczos22UDT::lanczos_sum_near_1(z); Chris@16: else if(p <= 170) Chris@16: return lanczos31UDT::lanczos_sum_near_1(z); Chris@16: else //if(p <= 370) approx 100 digit precision: Chris@16: return lanczos61UDT::lanczos_sum_near_1(z); Chris@16: } Chris@16: static ntl::RR lanczos_sum_near_2(const ntl::RR& z) Chris@16: { Chris@16: unsigned long p = ntl::RR::precision(); Chris@16: if(p <= 72) Chris@16: return lanczos13UDT::lanczos_sum_near_2(z); Chris@16: else if(p <= 120) Chris@16: return lanczos22UDT::lanczos_sum_near_2(z); Chris@16: else if(p <= 170) Chris@16: return lanczos31UDT::lanczos_sum_near_2(z); Chris@16: else //if(p <= 370) approx 100 digit precision: Chris@16: return lanczos61UDT::lanczos_sum_near_2(z); Chris@16: } Chris@16: static ntl::RR g() Chris@16: { Chris@16: unsigned long p = ntl::RR::precision(); Chris@16: if(p <= 72) Chris@16: return lanczos13UDT::g(); Chris@16: else if(p <= 120) Chris@16: return lanczos22UDT::g(); Chris@16: else if(p <= 170) Chris@16: return lanczos31UDT::g(); Chris@16: else //if(p <= 370) approx 100 digit precision: Chris@16: return lanczos61UDT::g(); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct lanczos Chris@16: { Chris@16: typedef ntl_lanczos type; Chris@16: }; Chris@16: Chris@16: } // namespace lanczos Chris@16: Chris@16: namespace tools Chris@16: { Chris@16: Chris@16: template<> Chris@16: inline int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR)) Chris@16: { Chris@16: return ::NTL::RR::precision(); Chris@16: } Chris@16: Chris@16: template <> Chris@16: inline float real_cast(boost::math::ntl::RR t) Chris@16: { Chris@16: double r; Chris@16: conv(r, t.value()); Chris@16: return static_cast(r); Chris@16: } Chris@16: template <> Chris@16: inline double real_cast(boost::math::ntl::RR t) Chris@16: { Chris@16: double r; Chris@16: conv(r, t.value()); Chris@16: return r; Chris@16: } Chris@16: Chris@16: namespace detail{ Chris@16: Chris@16: template Chris@16: void convert_to_long_result(NTL::RR const& r, I& result) Chris@16: { Chris@16: result = 0; Chris@16: I last_result(0); Chris@16: NTL::RR t(r); Chris@16: double term; Chris@16: do Chris@16: { Chris@16: conv(term, t); Chris@16: last_result = result; Chris@16: result += static_cast(term); Chris@16: t -= term; Chris@16: }while(result != last_result); Chris@16: } Chris@16: Chris@16: } Chris@16: Chris@16: template <> Chris@16: inline long double real_cast(boost::math::ntl::RR t) Chris@16: { Chris@16: long double result(0); Chris@16: detail::convert_to_long_result(t.value(), result); Chris@16: return result; Chris@16: } Chris@16: template <> Chris@16: inline boost::math::ntl::RR real_cast(boost::math::ntl::RR t) Chris@16: { Chris@16: return t; Chris@16: } Chris@16: template <> Chris@16: inline unsigned real_cast(boost::math::ntl::RR t) Chris@16: { Chris@16: unsigned result; Chris@16: detail::convert_to_long_result(t.value(), result); Chris@16: return result; Chris@16: } Chris@16: template <> Chris@16: inline int real_cast(boost::math::ntl::RR t) Chris@16: { Chris@16: int result; Chris@16: detail::convert_to_long_result(t.value(), result); Chris@16: return result; Chris@16: } Chris@16: template <> Chris@16: inline long real_cast(boost::math::ntl::RR t) Chris@16: { Chris@16: long result; Chris@16: detail::convert_to_long_result(t.value(), result); Chris@16: return result; Chris@16: } Chris@16: template <> Chris@16: inline long long real_cast(boost::math::ntl::RR t) Chris@16: { Chris@16: long long result; Chris@16: detail::convert_to_long_result(t.value(), result); Chris@16: return result; Chris@16: } Chris@16: Chris@16: template <> Chris@16: inline boost::math::ntl::RR max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR)) Chris@16: { Chris@16: static bool has_init = false; Chris@16: static NTL::RR val; Chris@16: if(!has_init) Chris@16: { Chris@16: val = 1; Chris@16: val.e = NTL_OVFBND-20; Chris@16: has_init = true; Chris@16: } Chris@16: return val; Chris@16: } Chris@16: Chris@16: template <> Chris@16: inline boost::math::ntl::RR min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR)) Chris@16: { Chris@16: static bool has_init = false; Chris@16: static NTL::RR val; Chris@16: if(!has_init) Chris@16: { Chris@16: val = 1; Chris@16: val.e = -NTL_OVFBND+20; Chris@16: has_init = true; Chris@16: } Chris@16: return val; Chris@16: } Chris@16: Chris@16: template <> Chris@16: inline boost::math::ntl::RR log_max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR)) Chris@16: { Chris@16: static bool has_init = false; Chris@16: static NTL::RR val; Chris@16: if(!has_init) Chris@16: { Chris@16: val = 1; Chris@16: val.e = NTL_OVFBND-20; Chris@16: val = log(val); Chris@16: has_init = true; Chris@16: } Chris@16: return val; Chris@16: } Chris@16: Chris@16: template <> Chris@16: inline boost::math::ntl::RR log_min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR)) Chris@16: { Chris@16: static bool has_init = false; Chris@16: static NTL::RR val; Chris@16: if(!has_init) Chris@16: { Chris@16: val = 1; Chris@16: val.e = -NTL_OVFBND+20; Chris@16: val = log(val); Chris@16: has_init = true; Chris@16: } Chris@16: return val; Chris@16: } Chris@16: Chris@16: template <> Chris@16: inline boost::math::ntl::RR epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR)) Chris@16: { Chris@16: return ldexp(boost::math::ntl::RR(1), 1-boost::math::policies::digits >()); Chris@16: } Chris@16: Chris@16: } // namespace tools Chris@16: Chris@16: // Chris@16: // The number of digits precision in RR can vary with each call Chris@16: // so we need to recalculate these with each call: Chris@16: // Chris@16: namespace constants{ Chris@16: Chris@16: template<> inline boost::math::ntl::RR pi(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR)) Chris@16: { Chris@16: NTL::RR result; Chris@16: ComputePi(result); Chris@16: return result; Chris@16: } Chris@16: template<> inline boost::math::ntl::RR e(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR)) Chris@16: { Chris@16: NTL::RR result; Chris@16: result = 1; Chris@16: return exp(result); Chris@16: } Chris@16: Chris@16: } // namespace constants Chris@16: Chris@16: namespace ntl{ Chris@16: // Chris@16: // These are some fairly brain-dead versions of the math Chris@16: // functions that NTL fails to provide. Chris@16: // Chris@16: Chris@16: Chris@16: // Chris@16: // Inverse trig functions: Chris@16: // Chris@16: struct asin_root Chris@16: { Chris@16: asin_root(RR const& target) : t(target){} Chris@16: Chris@16: boost::math::tuple operator()(RR const& p) Chris@16: { Chris@16: RR f0 = sin(p); Chris@16: RR f1 = cos(p); Chris@16: RR f2 = -f0; Chris@16: f0 -= t; Chris@16: return boost::math::make_tuple(f0, f1, f2); Chris@16: } Chris@16: private: Chris@16: RR t; Chris@16: }; Chris@16: Chris@16: inline RR asin(RR z) Chris@16: { Chris@16: double r; Chris@16: conv(r, z.value()); Chris@16: return boost::math::tools::halley_iterate( Chris@16: asin_root(z), Chris@16: RR(std::asin(r)), Chris@16: RR(-boost::math::constants::pi()/2), Chris@16: RR(boost::math::constants::pi()/2), Chris@16: NTL::RR::precision()); Chris@16: } Chris@16: Chris@16: struct acos_root Chris@16: { Chris@16: acos_root(RR const& target) : t(target){} Chris@16: Chris@16: boost::math::tuple operator()(RR const& p) Chris@16: { Chris@16: RR f0 = cos(p); Chris@16: RR f1 = -sin(p); Chris@16: RR f2 = -f0; Chris@16: f0 -= t; Chris@16: return boost::math::make_tuple(f0, f1, f2); Chris@16: } Chris@16: private: Chris@16: RR t; Chris@16: }; Chris@16: Chris@16: inline RR acos(RR z) Chris@16: { Chris@16: double r; Chris@16: conv(r, z.value()); Chris@16: return boost::math::tools::halley_iterate( Chris@16: acos_root(z), Chris@16: RR(std::acos(r)), Chris@16: RR(-boost::math::constants::pi()/2), Chris@16: RR(boost::math::constants::pi()/2), Chris@16: NTL::RR::precision()); Chris@16: } Chris@16: Chris@16: struct atan_root Chris@16: { Chris@16: atan_root(RR const& target) : t(target){} Chris@16: Chris@16: boost::math::tuple operator()(RR const& p) Chris@16: { Chris@16: RR c = cos(p); Chris@16: RR ta = tan(p); Chris@16: RR f0 = ta - t; Chris@16: RR f1 = 1 / (c * c); Chris@16: RR f2 = 2 * ta / (c * c); Chris@16: return boost::math::make_tuple(f0, f1, f2); Chris@16: } Chris@16: private: Chris@16: RR t; Chris@16: }; Chris@16: Chris@16: inline RR atan(RR z) Chris@16: { Chris@16: double r; Chris@16: conv(r, z.value()); Chris@16: return boost::math::tools::halley_iterate( Chris@16: atan_root(z), Chris@16: RR(std::atan(r)), Chris@16: -boost::math::constants::pi()/2, Chris@16: boost::math::constants::pi()/2, Chris@16: NTL::RR::precision()); Chris@16: } Chris@16: Chris@16: inline RR atan2(RR y, RR x) Chris@16: { Chris@16: if(x > 0) Chris@16: return atan(y / x); Chris@16: if(x < 0) Chris@16: { Chris@16: return y < 0 ? atan(y / x) - boost::math::constants::pi() : atan(y / x) + boost::math::constants::pi(); Chris@16: } Chris@16: return y < 0 ? -boost::math::constants::half_pi() : boost::math::constants::half_pi() ; Chris@16: } Chris@16: Chris@16: inline RR sinh(RR z) Chris@16: { Chris@16: return (expm1(z.value()) - expm1(-z.value())) / 2; Chris@16: } Chris@16: Chris@16: inline RR cosh(RR z) Chris@16: { Chris@16: return (exp(z) + exp(-z)) / 2; Chris@16: } Chris@16: Chris@16: inline RR tanh(RR z) Chris@16: { Chris@16: return sinh(z) / cosh(z); Chris@16: } Chris@16: Chris@16: inline RR fmod(RR x, RR y) Chris@16: { Chris@16: // This is a really crummy version of fmod, we rely on lots Chris@16: // of digits to get us out of trouble... Chris@16: RR factor = floor(x/y); Chris@16: return x - factor * y; Chris@16: } Chris@16: Chris@16: template Chris@16: inline int iround(RR const& x, const Policy& pol) Chris@16: { Chris@16: return tools::real_cast(round(x, pol)); Chris@16: } Chris@16: Chris@16: template Chris@16: inline long lround(RR const& x, const Policy& pol) Chris@16: { Chris@16: return tools::real_cast(round(x, pol)); Chris@16: } Chris@16: Chris@16: template Chris@16: inline long long llround(RR const& x, const Policy& pol) Chris@16: { Chris@16: return tools::real_cast(round(x, pol)); Chris@16: } Chris@16: Chris@16: template Chris@16: inline int itrunc(RR const& x, const Policy& pol) Chris@16: { Chris@16: return tools::real_cast(trunc(x, pol)); Chris@16: } Chris@16: Chris@16: template Chris@16: inline long ltrunc(RR const& x, const Policy& pol) Chris@16: { Chris@16: return tools::real_cast(trunc(x, pol)); Chris@16: } Chris@16: Chris@16: template Chris@16: inline long long lltrunc(RR const& x, const Policy& pol) Chris@16: { Chris@16: return tools::real_cast(trunc(x, pol)); Chris@16: } Chris@16: Chris@16: } // namespace ntl Chris@16: Chris@16: namespace detail{ Chris@16: Chris@16: template Chris@16: ntl::RR digamma_imp(ntl::RR x, const mpl::int_<0>* , const Policy& pol) Chris@16: { Chris@16: // Chris@16: // This handles reflection of negative arguments, and all our Chris@16: // error handling, then forwards to the T-specific approximation. Chris@16: // Chris@16: BOOST_MATH_STD_USING // ADL of std functions. Chris@16: Chris@16: ntl::RR result = 0; Chris@16: // Chris@16: // Check for negative arguments and use reflection: Chris@16: // Chris@16: if(x < 0) Chris@16: { Chris@16: // Reflect: Chris@16: x = 1 - x; Chris@16: // Argument reduction for tan: Chris@16: ntl::RR remainder = x - floor(x); Chris@16: // Shift to negative if > 0.5: Chris@16: if(remainder > 0.5) Chris@16: { Chris@16: remainder -= 1; Chris@16: } Chris@16: // Chris@16: // check for evaluation at a negative pole: Chris@16: // Chris@16: if(remainder == 0) Chris@16: { Chris@16: return policies::raise_pole_error("boost::math::digamma<%1%>(%1%)", 0, (1-x), pol); Chris@16: } Chris@16: result = constants::pi() / tan(constants::pi() * remainder); Chris@16: } Chris@16: result += big_digamma(x); Chris@16: return result; Chris@16: } Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: } // namespace math Chris@16: } // namespace boost Chris@16: Chris@16: #endif // BOOST_MATH_REAL_CONCEPT_HPP Chris@16: Chris@16: