File indexing completed on 2025-01-18 09:39:31
0001
0002
0003
0004
0005
0006 #ifndef BOOST_MATH_NTL_RR_HPP
0007 #define BOOST_MATH_NTL_RR_HPP
0008
0009 #include <boost/math/tools/real_cast.hpp>
0010 #include <boost/math/tools/precision.hpp>
0011 #include <boost/math/tools/config.hpp>
0012 #include <boost/math/constants/constants.hpp>
0013 #include <boost/math/tools/roots.hpp>
0014 #include <boost/math/special_functions/fpclassify.hpp>
0015 #include <boost/math/bindings/detail/big_digamma.hpp>
0016 #include <boost/math/bindings/detail/big_lanczos.hpp>
0017 #include <stdexcept>
0018 #include <ostream>
0019 #include <istream>
0020 #include <cmath>
0021 #include <limits>
0022 #include <NTL/RR.h>
0023
0024 namespace boost{ namespace math{
0025
0026 namespace ntl
0027 {
0028
0029 class RR;
0030
0031 RR ldexp(RR r, int exp);
0032 RR frexp(RR r, int* exp);
0033
0034 class RR
0035 {
0036 public:
0037
0038 RR() {}
0039 RR(const ::NTL::RR& c) : m_value(c){}
0040 RR(char c)
0041 {
0042 m_value = c;
0043 }
0044 RR(wchar_t c)
0045 {
0046 m_value = c;
0047 }
0048 RR(unsigned char c)
0049 {
0050 m_value = c;
0051 }
0052 RR(signed char c)
0053 {
0054 m_value = c;
0055 }
0056 RR(unsigned short c)
0057 {
0058 m_value = c;
0059 }
0060 RR(short c)
0061 {
0062 m_value = c;
0063 }
0064 RR(unsigned int c)
0065 {
0066 assign_large_int(c);
0067 }
0068 RR(int c)
0069 {
0070 assign_large_int(c);
0071 }
0072 RR(unsigned long c)
0073 {
0074 assign_large_int(c);
0075 }
0076 RR(long c)
0077 {
0078 assign_large_int(c);
0079 }
0080 RR(unsigned long long c)
0081 {
0082 assign_large_int(c);
0083 }
0084 RR(long long c)
0085 {
0086 assign_large_int(c);
0087 }
0088 RR(float c)
0089 {
0090 m_value = c;
0091 }
0092 RR(double c)
0093 {
0094 m_value = c;
0095 }
0096 RR(long double c)
0097 {
0098 assign_large_real(c);
0099 }
0100
0101
0102 RR& operator=(char c) { m_value = c; return *this; }
0103 RR& operator=(unsigned char c) { m_value = c; return *this; }
0104 RR& operator=(signed char c) { m_value = c; return *this; }
0105 RR& operator=(wchar_t c) { m_value = c; return *this; }
0106 RR& operator=(short c) { m_value = c; return *this; }
0107 RR& operator=(unsigned short c) { m_value = c; return *this; }
0108 RR& operator=(int c) { assign_large_int(c); return *this; }
0109 RR& operator=(unsigned int c) { assign_large_int(c); return *this; }
0110 RR& operator=(long c) { assign_large_int(c); return *this; }
0111 RR& operator=(unsigned long c) { assign_large_int(c); return *this; }
0112 RR& operator=(long long c) { assign_large_int(c); return *this; }
0113 RR& operator=(unsigned long long c) { assign_large_int(c); return *this; }
0114 RR& operator=(float c) { m_value = c; return *this; }
0115 RR& operator=(double c) { m_value = c; return *this; }
0116 RR& operator=(long double c) { assign_large_real(c); return *this; }
0117
0118
0119 NTL::RR& value(){ return m_value; }
0120 NTL::RR const& value()const{ return m_value; }
0121
0122
0123 RR& operator+=(const RR& other)
0124 { m_value += other.value(); return *this; }
0125 RR& operator-=(const RR& other)
0126 { m_value -= other.value(); return *this; }
0127 RR& operator*=(const RR& other)
0128 { m_value *= other.value(); return *this; }
0129 RR& operator/=(const RR& other)
0130 { m_value /= other.value(); return *this; }
0131 RR operator-()const
0132 { return -m_value; }
0133 RR const& operator+()const
0134 { return *this; }
0135
0136
0137 const ::NTL::ZZ& mantissa() const
0138 { return m_value.mantissa(); }
0139 long exponent() const
0140 { return m_value.exponent(); }
0141
0142 static void SetPrecision(long p)
0143 { ::NTL::RR::SetPrecision(p); }
0144
0145 static long precision()
0146 { return ::NTL::RR::precision(); }
0147
0148 static void SetOutputPrecision(long p)
0149 { ::NTL::RR::SetOutputPrecision(p); }
0150 static long OutputPrecision()
0151 { return ::NTL::RR::OutputPrecision(); }
0152
0153
0154 private:
0155 ::NTL::RR m_value;
0156
0157 template <class V>
0158 void assign_large_real(const V& a)
0159 {
0160 using std::frexp;
0161 using std::ldexp;
0162 using std::floor;
0163 if (a == 0) {
0164 clear(m_value);
0165 return;
0166 }
0167
0168 if (a == 1) {
0169 NTL::set(m_value);
0170 return;
0171 }
0172
0173 if (!(boost::math::isfinite)(a))
0174 {
0175 throw std::overflow_error("Cannot construct an instance of NTL::RR with an infinite value.");
0176 }
0177
0178 int e;
0179 long double f, term;
0180 ::NTL::RR t;
0181 clear(m_value);
0182
0183 f = frexp(a, &e);
0184
0185 while(f)
0186 {
0187
0188 f = ldexp(f, 30);
0189 term = floor(f);
0190 e -= 30;
0191 conv(t.x, (int)term);
0192 t.e = e;
0193 m_value += t;
0194 f -= term;
0195 }
0196 }
0197
0198 template <class V>
0199 void assign_large_int(V a)
0200 {
0201 #ifdef _MSC_VER
0202 #pragma warning(push)
0203 #pragma warning(disable:4146)
0204 #endif
0205 clear(m_value);
0206 int exp = 0;
0207 NTL::RR t;
0208 bool neg = a < V(0) ? true : false;
0209 if(neg)
0210 a = -a;
0211 while(a)
0212 {
0213 t = static_cast<double>(a & 0xffff);
0214 m_value += ldexp(RR(t), exp).value();
0215 a >>= 16;
0216 exp += 16;
0217 }
0218 if(neg)
0219 m_value = -m_value;
0220 #ifdef _MSC_VER
0221 #pragma warning(pop)
0222 #endif
0223 }
0224 };
0225
0226
0227 inline RR operator+(const RR& a, const RR& b)
0228 {
0229 RR result(a);
0230 result += b;
0231 return result;
0232 }
0233 inline RR operator-(const RR& a, const RR& b)
0234 {
0235 RR result(a);
0236 result -= b;
0237 return result;
0238 }
0239 inline RR operator*(const RR& a, const RR& b)
0240 {
0241 RR result(a);
0242 result *= b;
0243 return result;
0244 }
0245 inline RR operator/(const RR& a, const RR& b)
0246 {
0247 RR result(a);
0248 result /= b;
0249 return result;
0250 }
0251
0252
0253 inline bool operator == (const RR& a, const RR& b)
0254 { return a.value() == b.value() ? true : false; }
0255 inline bool operator != (const RR& a, const RR& b)
0256 { return a.value() != b.value() ? true : false;}
0257 inline bool operator < (const RR& a, const RR& b)
0258 { return a.value() < b.value() ? true : false; }
0259 inline bool operator <= (const RR& a, const RR& b)
0260 { return a.value() <= b.value() ? true : false; }
0261 inline bool operator > (const RR& a, const RR& b)
0262 { return a.value() > b.value() ? true : false; }
0263 inline bool operator >= (const RR& a, const RR& b)
0264 { return a.value() >= b.value() ? true : false; }
0265
0266 #if 0
0267
0268 template <class T>
0269 inline bool operator == (const T& a, const RR& b)
0270 {
0271 return a == b.value();
0272 }
0273 template <class T>
0274 inline bool operator != (const T& a, const RR& b)
0275 {
0276 return a != b.value();
0277 }
0278 template <class T>
0279 inline bool operator < (const T& a, const RR& b)
0280 {
0281 return a < b.value();
0282 }
0283 template <class T>
0284 inline bool operator > (const T& a, const RR& b)
0285 {
0286 return a > b.value();
0287 }
0288 template <class T>
0289 inline bool operator <= (const T& a, const RR& b)
0290 {
0291 return a <= b.value();
0292 }
0293 template <class T>
0294 inline bool operator >= (const T& a, const RR& b)
0295 {
0296 return a >= b.value();
0297 }
0298 #endif
0299
0300
0301
0302
0303
0304
0305 inline RR cos(RR a)
0306 { return ::NTL::cos(a.value()); }
0307
0308
0309
0310
0311
0312
0313
0314
0315 inline RR ceil(RR a)
0316 { return ::NTL::ceil(a.value()); }
0317
0318
0319
0320
0321
0322
0323 inline RR exp(RR a)
0324 { return ::NTL::exp(a.value()); }
0325 inline RR fabs(RR a)
0326 { return ::NTL::fabs(a.value()); }
0327 inline RR abs(RR a)
0328 { return ::NTL::abs(a.value()); }
0329 inline RR floor(RR a)
0330 { return ::NTL::floor(a.value()); }
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344 inline RR log(RR a)
0345 { return ::NTL::log(a.value()); }
0346 inline RR log10(RR a)
0347 { return ::NTL::log10(a.value()); }
0348
0349
0350
0351
0352 inline RR pow(RR a, RR b)
0353 { return ::NTL::pow(a.value(), b.value()); }
0354 inline RR pow(RR a, int b)
0355 { return ::NTL::power(a.value(), b); }
0356 inline RR sin(RR a)
0357 { return ::NTL::sin(a.value()); }
0358
0359
0360
0361
0362 inline RR sqrt(RR a)
0363 { return ::NTL::sqrt(a.value()); }
0364
0365
0366
0367
0368 inline RR pow(const RR& r, long l)
0369 {
0370 return ::NTL::power(r.value(), l);
0371 }
0372 inline RR tan(const RR& a)
0373 {
0374 return sin(a)/cos(a);
0375 }
0376 inline RR frexp(RR r, int* exp)
0377 {
0378 *exp = r.value().e;
0379 r.value().e = 0;
0380 while(r >= 1)
0381 {
0382 *exp += 1;
0383 r.value().e -= 1;
0384 }
0385 while(r < 0.5)
0386 {
0387 *exp -= 1;
0388 r.value().e += 1;
0389 }
0390 BOOST_MATH_ASSERT(r < 1);
0391 BOOST_MATH_ASSERT(r >= 0.5);
0392 return r;
0393 }
0394 inline RR ldexp(RR r, int exp)
0395 {
0396 r.value().e += exp;
0397 return r;
0398 }
0399
0400
0401 template <class charT, class traits>
0402 inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const RR& a)
0403 {
0404 return os << a.value();
0405 }
0406 template <class charT, class traits>
0407 inline std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>& is, RR& a)
0408 {
0409 ::NTL::RR v;
0410 is >> v;
0411 a = v;
0412 return is;
0413 }
0414
0415 }
0416
0417 namespace lanczos{
0418
0419 struct ntl_lanczos
0420 {
0421 static ntl::RR lanczos_sum(const ntl::RR& z)
0422 {
0423 unsigned long p = ntl::RR::precision();
0424 if(p <= 72)
0425 return lanczos13UDT::lanczos_sum(z);
0426 else if(p <= 120)
0427 return lanczos22UDT::lanczos_sum(z);
0428 else if(p <= 170)
0429 return lanczos31UDT::lanczos_sum(z);
0430 else
0431 return lanczos61UDT::lanczos_sum(z);
0432 }
0433 static ntl::RR lanczos_sum_expG_scaled(const ntl::RR& z)
0434 {
0435 unsigned long p = ntl::RR::precision();
0436 if(p <= 72)
0437 return lanczos13UDT::lanczos_sum_expG_scaled(z);
0438 else if(p <= 120)
0439 return lanczos22UDT::lanczos_sum_expG_scaled(z);
0440 else if(p <= 170)
0441 return lanczos31UDT::lanczos_sum_expG_scaled(z);
0442 else
0443 return lanczos61UDT::lanczos_sum_expG_scaled(z);
0444 }
0445 static ntl::RR lanczos_sum_near_1(const ntl::RR& z)
0446 {
0447 unsigned long p = ntl::RR::precision();
0448 if(p <= 72)
0449 return lanczos13UDT::lanczos_sum_near_1(z);
0450 else if(p <= 120)
0451 return lanczos22UDT::lanczos_sum_near_1(z);
0452 else if(p <= 170)
0453 return lanczos31UDT::lanczos_sum_near_1(z);
0454 else
0455 return lanczos61UDT::lanczos_sum_near_1(z);
0456 }
0457 static ntl::RR lanczos_sum_near_2(const ntl::RR& z)
0458 {
0459 unsigned long p = ntl::RR::precision();
0460 if(p <= 72)
0461 return lanczos13UDT::lanczos_sum_near_2(z);
0462 else if(p <= 120)
0463 return lanczos22UDT::lanczos_sum_near_2(z);
0464 else if(p <= 170)
0465 return lanczos31UDT::lanczos_sum_near_2(z);
0466 else
0467 return lanczos61UDT::lanczos_sum_near_2(z);
0468 }
0469 static ntl::RR g()
0470 {
0471 unsigned long p = ntl::RR::precision();
0472 if(p <= 72)
0473 return lanczos13UDT::g();
0474 else if(p <= 120)
0475 return lanczos22UDT::g();
0476 else if(p <= 170)
0477 return lanczos31UDT::g();
0478 else
0479 return lanczos61UDT::g();
0480 }
0481 };
0482
0483 template<class Policy>
0484 struct lanczos<ntl::RR, Policy>
0485 {
0486 typedef ntl_lanczos type;
0487 };
0488
0489 }
0490
0491 namespace tools
0492 {
0493
0494 template<>
0495 inline int digits<boost::math::ntl::RR>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
0496 {
0497 return ::NTL::RR::precision();
0498 }
0499
0500 template <>
0501 inline float real_cast<float, boost::math::ntl::RR>(boost::math::ntl::RR t)
0502 {
0503 double r;
0504 conv(r, t.value());
0505 return static_cast<float>(r);
0506 }
0507 template <>
0508 inline double real_cast<double, boost::math::ntl::RR>(boost::math::ntl::RR t)
0509 {
0510 double r;
0511 conv(r, t.value());
0512 return r;
0513 }
0514
0515 namespace detail{
0516
0517 template<class I>
0518 void convert_to_long_result(NTL::RR const& r, I& result)
0519 {
0520 result = 0;
0521 I last_result(0);
0522 NTL::RR t(r);
0523 double term;
0524 do
0525 {
0526 conv(term, t);
0527 last_result = result;
0528 result += static_cast<I>(term);
0529 t -= term;
0530 }while(result != last_result);
0531 }
0532
0533 }
0534
0535 template <>
0536 inline long double real_cast<long double, boost::math::ntl::RR>(boost::math::ntl::RR t)
0537 {
0538 long double result(0);
0539 detail::convert_to_long_result(t.value(), result);
0540 return result;
0541 }
0542 template <>
0543 inline boost::math::ntl::RR real_cast<boost::math::ntl::RR, boost::math::ntl::RR>(boost::math::ntl::RR t)
0544 {
0545 return t;
0546 }
0547 template <>
0548 inline unsigned real_cast<unsigned, boost::math::ntl::RR>(boost::math::ntl::RR t)
0549 {
0550 unsigned result;
0551 detail::convert_to_long_result(t.value(), result);
0552 return result;
0553 }
0554 template <>
0555 inline int real_cast<int, boost::math::ntl::RR>(boost::math::ntl::RR t)
0556 {
0557 int result;
0558 detail::convert_to_long_result(t.value(), result);
0559 return result;
0560 }
0561 template <>
0562 inline long real_cast<long, boost::math::ntl::RR>(boost::math::ntl::RR t)
0563 {
0564 long result;
0565 detail::convert_to_long_result(t.value(), result);
0566 return result;
0567 }
0568 template <>
0569 inline long long real_cast<long long, boost::math::ntl::RR>(boost::math::ntl::RR t)
0570 {
0571 long long result;
0572 detail::convert_to_long_result(t.value(), result);
0573 return result;
0574 }
0575
0576 template <>
0577 inline boost::math::ntl::RR max_value<boost::math::ntl::RR>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
0578 {
0579 static bool has_init = false;
0580 static NTL::RR val;
0581 if(!has_init)
0582 {
0583 val = 1;
0584 val.e = NTL_OVFBND-20;
0585 has_init = true;
0586 }
0587 return val;
0588 }
0589
0590 template <>
0591 inline boost::math::ntl::RR min_value<boost::math::ntl::RR>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
0592 {
0593 static bool has_init = false;
0594 static NTL::RR val;
0595 if(!has_init)
0596 {
0597 val = 1;
0598 val.e = -NTL_OVFBND+20;
0599 has_init = true;
0600 }
0601 return val;
0602 }
0603
0604 template <>
0605 inline boost::math::ntl::RR log_max_value<boost::math::ntl::RR>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
0606 {
0607 static bool has_init = false;
0608 static NTL::RR val;
0609 if(!has_init)
0610 {
0611 val = 1;
0612 val.e = NTL_OVFBND-20;
0613 val = log(val);
0614 has_init = true;
0615 }
0616 return val;
0617 }
0618
0619 template <>
0620 inline boost::math::ntl::RR log_min_value<boost::math::ntl::RR>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
0621 {
0622 static bool has_init = false;
0623 static NTL::RR val;
0624 if(!has_init)
0625 {
0626 val = 1;
0627 val.e = -NTL_OVFBND+20;
0628 val = log(val);
0629 has_init = true;
0630 }
0631 return val;
0632 }
0633
0634 template <>
0635 inline boost::math::ntl::RR epsilon<boost::math::ntl::RR>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
0636 {
0637 return ldexp(boost::math::ntl::RR(1), 1-boost::math::policies::digits<boost::math::ntl::RR, boost::math::policies::policy<> >());
0638 }
0639
0640 }
0641
0642
0643
0644
0645
0646 namespace constants{
0647
0648 template<> inline boost::math::ntl::RR pi<boost::math::ntl::RR>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
0649 {
0650 NTL::RR result;
0651 ComputePi(result);
0652 return result;
0653 }
0654 template<> inline boost::math::ntl::RR e<boost::math::ntl::RR>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
0655 {
0656 NTL::RR result;
0657 result = 1;
0658 return exp(result);
0659 }
0660
0661 }
0662
0663 namespace ntl{
0664
0665
0666
0667
0668
0669
0670
0671
0672
0673 struct asin_root
0674 {
0675 asin_root(RR const& target) : t(target){}
0676
0677 boost::math::tuple<RR, RR, RR> operator()(RR const& p)
0678 {
0679 RR f0 = sin(p);
0680 RR f1 = cos(p);
0681 RR f2 = -f0;
0682 f0 -= t;
0683 return boost::math::make_tuple(f0, f1, f2);
0684 }
0685 private:
0686 RR t;
0687 };
0688
0689 inline RR asin(RR z)
0690 {
0691 double r;
0692 conv(r, z.value());
0693 return boost::math::tools::halley_iterate(
0694 asin_root(z),
0695 RR(std::asin(r)),
0696 RR(-boost::math::constants::pi<RR>()/2),
0697 RR(boost::math::constants::pi<RR>()/2),
0698 NTL::RR::precision());
0699 }
0700
0701 struct acos_root
0702 {
0703 acos_root(RR const& target) : t(target){}
0704
0705 boost::math::tuple<RR, RR, RR> operator()(RR const& p)
0706 {
0707 RR f0 = cos(p);
0708 RR f1 = -sin(p);
0709 RR f2 = -f0;
0710 f0 -= t;
0711 return boost::math::make_tuple(f0, f1, f2);
0712 }
0713 private:
0714 RR t;
0715 };
0716
0717 inline RR acos(RR z)
0718 {
0719 double r;
0720 conv(r, z.value());
0721 return boost::math::tools::halley_iterate(
0722 acos_root(z),
0723 RR(std::acos(r)),
0724 RR(-boost::math::constants::pi<RR>()/2),
0725 RR(boost::math::constants::pi<RR>()/2),
0726 NTL::RR::precision());
0727 }
0728
0729 struct atan_root
0730 {
0731 atan_root(RR const& target) : t(target){}
0732
0733 boost::math::tuple<RR, RR, RR> operator()(RR const& p)
0734 {
0735 RR c = cos(p);
0736 RR ta = tan(p);
0737 RR f0 = ta - t;
0738 RR f1 = 1 / (c * c);
0739 RR f2 = 2 * ta / (c * c);
0740 return boost::math::make_tuple(f0, f1, f2);
0741 }
0742 private:
0743 RR t;
0744 };
0745
0746 inline RR atan(RR z)
0747 {
0748 double r;
0749 conv(r, z.value());
0750 return boost::math::tools::halley_iterate(
0751 atan_root(z),
0752 RR(std::atan(r)),
0753 -boost::math::constants::pi<RR>()/2,
0754 boost::math::constants::pi<RR>()/2,
0755 NTL::RR::precision());
0756 }
0757
0758 inline RR atan2(RR y, RR x)
0759 {
0760 if(x > 0)
0761 return atan(y / x);
0762 if(x < 0)
0763 {
0764 return y < 0 ? atan(y / x) - boost::math::constants::pi<RR>() : atan(y / x) + boost::math::constants::pi<RR>();
0765 }
0766 return y < 0 ? -boost::math::constants::half_pi<RR>() : boost::math::constants::half_pi<RR>() ;
0767 }
0768
0769 inline RR sinh(RR z)
0770 {
0771 return (expm1(z.value()) - expm1(-z.value())) / 2;
0772 }
0773
0774 inline RR cosh(RR z)
0775 {
0776 return (exp(z) + exp(-z)) / 2;
0777 }
0778
0779 inline RR tanh(RR z)
0780 {
0781 return sinh(z) / cosh(z);
0782 }
0783
0784 inline RR fmod(RR x, RR y)
0785 {
0786
0787
0788 RR factor = floor(x/y);
0789 return x - factor * y;
0790 }
0791
0792 template <class Policy>
0793 inline int iround(RR const& x, const Policy& pol)
0794 {
0795 return tools::real_cast<int>(round(x, pol));
0796 }
0797
0798 template <class Policy>
0799 inline long lround(RR const& x, const Policy& pol)
0800 {
0801 return tools::real_cast<long>(round(x, pol));
0802 }
0803
0804 template <class Policy>
0805 inline long long llround(RR const& x, const Policy& pol)
0806 {
0807 return tools::real_cast<long long>(round(x, pol));
0808 }
0809
0810 template <class Policy>
0811 inline int itrunc(RR const& x, const Policy& pol)
0812 {
0813 return tools::real_cast<int>(trunc(x, pol));
0814 }
0815
0816 template <class Policy>
0817 inline long ltrunc(RR const& x, const Policy& pol)
0818 {
0819 return tools::real_cast<long>(trunc(x, pol));
0820 }
0821
0822 template <class Policy>
0823 inline long long lltrunc(RR const& x, const Policy& pol)
0824 {
0825 return tools::real_cast<long long>(trunc(x, pol));
0826 }
0827
0828 }
0829
0830 namespace detail{
0831
0832 template <class Policy>
0833 ntl::RR digamma_imp(ntl::RR x, const std::integral_constant<int, 0>* , const Policy& pol)
0834 {
0835
0836
0837
0838
0839 BOOST_MATH_STD_USING
0840
0841 ntl::RR result = 0;
0842
0843
0844
0845 if(x < 0)
0846 {
0847
0848 x = 1 - x;
0849
0850 ntl::RR remainder = x - floor(x);
0851
0852 if(remainder > 0.5)
0853 {
0854 remainder -= 1;
0855 }
0856
0857
0858
0859 if(remainder == 0)
0860 {
0861 return policies::raise_pole_error<ntl::RR>("boost::math::digamma<%1%>(%1%)", nullptr, (1-x), pol);
0862 }
0863 result = constants::pi<ntl::RR>() / tan(constants::pi<ntl::RR>() * remainder);
0864 }
0865 result += big_digamma(x);
0866 return result;
0867 }
0868
0869 }
0870
0871 }
0872 }
0873
0874 #endif
0875
0876