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