Chris@16
|
1 // Copyright John Maddock 2007.
|
Chris@16
|
2 // Use, modification and distribution are subject to the
|
Chris@16
|
3 // Boost Software License, Version 1.0. (See accompanying file
|
Chris@16
|
4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
5
|
Chris@16
|
6 #ifndef BOOST_MATH_NTL_RR_HPP
|
Chris@16
|
7 #define BOOST_MATH_NTL_RR_HPP
|
Chris@16
|
8
|
Chris@16
|
9 #include <boost/config.hpp>
|
Chris@16
|
10 #include <boost/limits.hpp>
|
Chris@16
|
11 #include <boost/math/tools/real_cast.hpp>
|
Chris@16
|
12 #include <boost/math/tools/precision.hpp>
|
Chris@16
|
13 #include <boost/math/constants/constants.hpp>
|
Chris@16
|
14 #include <boost/math/tools/roots.hpp>
|
Chris@16
|
15 #include <boost/math/special_functions/fpclassify.hpp>
|
Chris@16
|
16 #include <boost/math/bindings/detail/big_digamma.hpp>
|
Chris@16
|
17 #include <boost/math/bindings/detail/big_lanczos.hpp>
|
Chris@16
|
18
|
Chris@16
|
19 #include <ostream>
|
Chris@16
|
20 #include <istream>
|
Chris@16
|
21 #include <boost/config/no_tr1/cmath.hpp>
|
Chris@16
|
22 #include <NTL/RR.h>
|
Chris@16
|
23
|
Chris@16
|
24 namespace boost{ namespace math{
|
Chris@16
|
25
|
Chris@16
|
26 namespace ntl
|
Chris@16
|
27 {
|
Chris@16
|
28
|
Chris@16
|
29 class RR;
|
Chris@16
|
30
|
Chris@16
|
31 RR ldexp(RR r, int exp);
|
Chris@16
|
32 RR frexp(RR r, int* exp);
|
Chris@16
|
33
|
Chris@16
|
34 class RR
|
Chris@16
|
35 {
|
Chris@16
|
36 public:
|
Chris@16
|
37 // Constructors:
|
Chris@16
|
38 RR() {}
|
Chris@16
|
39 RR(const ::NTL::RR& c) : m_value(c){}
|
Chris@16
|
40 RR(char c)
|
Chris@16
|
41 {
|
Chris@16
|
42 m_value = c;
|
Chris@16
|
43 }
|
Chris@16
|
44 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
|
Chris@16
|
45 RR(wchar_t c)
|
Chris@16
|
46 {
|
Chris@16
|
47 m_value = c;
|
Chris@16
|
48 }
|
Chris@16
|
49 #endif
|
Chris@16
|
50 RR(unsigned char c)
|
Chris@16
|
51 {
|
Chris@16
|
52 m_value = c;
|
Chris@16
|
53 }
|
Chris@16
|
54 RR(signed char c)
|
Chris@16
|
55 {
|
Chris@16
|
56 m_value = c;
|
Chris@16
|
57 }
|
Chris@16
|
58 RR(unsigned short c)
|
Chris@16
|
59 {
|
Chris@16
|
60 m_value = c;
|
Chris@16
|
61 }
|
Chris@16
|
62 RR(short c)
|
Chris@16
|
63 {
|
Chris@16
|
64 m_value = c;
|
Chris@16
|
65 }
|
Chris@16
|
66 RR(unsigned int c)
|
Chris@16
|
67 {
|
Chris@16
|
68 assign_large_int(c);
|
Chris@16
|
69 }
|
Chris@16
|
70 RR(int c)
|
Chris@16
|
71 {
|
Chris@16
|
72 assign_large_int(c);
|
Chris@16
|
73 }
|
Chris@16
|
74 RR(unsigned long c)
|
Chris@16
|
75 {
|
Chris@16
|
76 assign_large_int(c);
|
Chris@16
|
77 }
|
Chris@16
|
78 RR(long c)
|
Chris@16
|
79 {
|
Chris@16
|
80 assign_large_int(c);
|
Chris@16
|
81 }
|
Chris@16
|
82 #ifdef BOOST_HAS_LONG_LONG
|
Chris@16
|
83 RR(boost::ulong_long_type c)
|
Chris@16
|
84 {
|
Chris@16
|
85 assign_large_int(c);
|
Chris@16
|
86 }
|
Chris@16
|
87 RR(boost::long_long_type c)
|
Chris@16
|
88 {
|
Chris@16
|
89 assign_large_int(c);
|
Chris@16
|
90 }
|
Chris@16
|
91 #endif
|
Chris@16
|
92 RR(float c)
|
Chris@16
|
93 {
|
Chris@16
|
94 m_value = c;
|
Chris@16
|
95 }
|
Chris@16
|
96 RR(double c)
|
Chris@16
|
97 {
|
Chris@16
|
98 m_value = c;
|
Chris@16
|
99 }
|
Chris@16
|
100 RR(long double c)
|
Chris@16
|
101 {
|
Chris@16
|
102 assign_large_real(c);
|
Chris@16
|
103 }
|
Chris@16
|
104
|
Chris@16
|
105 // Assignment:
|
Chris@16
|
106 RR& operator=(char c) { m_value = c; return *this; }
|
Chris@16
|
107 RR& operator=(unsigned char c) { m_value = c; return *this; }
|
Chris@16
|
108 RR& operator=(signed char c) { m_value = c; return *this; }
|
Chris@16
|
109 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
|
Chris@16
|
110 RR& operator=(wchar_t c) { m_value = c; return *this; }
|
Chris@16
|
111 #endif
|
Chris@16
|
112 RR& operator=(short c) { m_value = c; return *this; }
|
Chris@16
|
113 RR& operator=(unsigned short c) { m_value = c; return *this; }
|
Chris@16
|
114 RR& operator=(int c) { assign_large_int(c); return *this; }
|
Chris@16
|
115 RR& operator=(unsigned int c) { assign_large_int(c); return *this; }
|
Chris@16
|
116 RR& operator=(long c) { assign_large_int(c); return *this; }
|
Chris@16
|
117 RR& operator=(unsigned long c) { assign_large_int(c); return *this; }
|
Chris@16
|
118 #ifdef BOOST_HAS_LONG_LONG
|
Chris@16
|
119 RR& operator=(boost::long_long_type c) { assign_large_int(c); return *this; }
|
Chris@16
|
120 RR& operator=(boost::ulong_long_type c) { assign_large_int(c); return *this; }
|
Chris@16
|
121 #endif
|
Chris@16
|
122 RR& operator=(float c) { m_value = c; return *this; }
|
Chris@16
|
123 RR& operator=(double c) { m_value = c; return *this; }
|
Chris@16
|
124 RR& operator=(long double c) { assign_large_real(c); return *this; }
|
Chris@16
|
125
|
Chris@16
|
126 // Access:
|
Chris@16
|
127 NTL::RR& value(){ return m_value; }
|
Chris@16
|
128 NTL::RR const& value()const{ return m_value; }
|
Chris@16
|
129
|
Chris@16
|
130 // Member arithmetic:
|
Chris@16
|
131 RR& operator+=(const RR& other)
|
Chris@16
|
132 { m_value += other.value(); return *this; }
|
Chris@16
|
133 RR& operator-=(const RR& other)
|
Chris@16
|
134 { m_value -= other.value(); return *this; }
|
Chris@16
|
135 RR& operator*=(const RR& other)
|
Chris@16
|
136 { m_value *= other.value(); return *this; }
|
Chris@16
|
137 RR& operator/=(const RR& other)
|
Chris@16
|
138 { m_value /= other.value(); return *this; }
|
Chris@16
|
139 RR operator-()const
|
Chris@16
|
140 { return -m_value; }
|
Chris@16
|
141 RR const& operator+()const
|
Chris@16
|
142 { return *this; }
|
Chris@16
|
143
|
Chris@16
|
144 // RR compatibity:
|
Chris@16
|
145 const ::NTL::ZZ& mantissa() const
|
Chris@16
|
146 { return m_value.mantissa(); }
|
Chris@16
|
147 long exponent() const
|
Chris@16
|
148 { return m_value.exponent(); }
|
Chris@16
|
149
|
Chris@16
|
150 static void SetPrecision(long p)
|
Chris@16
|
151 { ::NTL::RR::SetPrecision(p); }
|
Chris@16
|
152
|
Chris@16
|
153 static long precision()
|
Chris@16
|
154 { return ::NTL::RR::precision(); }
|
Chris@16
|
155
|
Chris@16
|
156 static void SetOutputPrecision(long p)
|
Chris@16
|
157 { ::NTL::RR::SetOutputPrecision(p); }
|
Chris@16
|
158 static long OutputPrecision()
|
Chris@16
|
159 { return ::NTL::RR::OutputPrecision(); }
|
Chris@16
|
160
|
Chris@16
|
161
|
Chris@16
|
162 private:
|
Chris@16
|
163 ::NTL::RR m_value;
|
Chris@16
|
164
|
Chris@16
|
165 template <class V>
|
Chris@16
|
166 void assign_large_real(const V& a)
|
Chris@16
|
167 {
|
Chris@16
|
168 using std::frexp;
|
Chris@16
|
169 using std::ldexp;
|
Chris@16
|
170 using std::floor;
|
Chris@16
|
171 if (a == 0) {
|
Chris@16
|
172 clear(m_value);
|
Chris@16
|
173 return;
|
Chris@16
|
174 }
|
Chris@16
|
175
|
Chris@16
|
176 if (a == 1) {
|
Chris@16
|
177 NTL::set(m_value);
|
Chris@16
|
178 return;
|
Chris@16
|
179 }
|
Chris@16
|
180
|
Chris@16
|
181 if (!(boost::math::isfinite)(a))
|
Chris@16
|
182 {
|
Chris@16
|
183 throw std::overflow_error("Cannot construct an instance of NTL::RR with an infinite value.");
|
Chris@16
|
184 }
|
Chris@16
|
185
|
Chris@16
|
186 int e;
|
Chris@16
|
187 long double f, term;
|
Chris@16
|
188 ::NTL::RR t;
|
Chris@16
|
189 clear(m_value);
|
Chris@16
|
190
|
Chris@16
|
191 f = frexp(a, &e);
|
Chris@16
|
192
|
Chris@16
|
193 while(f)
|
Chris@16
|
194 {
|
Chris@16
|
195 // extract 30 bits from f:
|
Chris@16
|
196 f = ldexp(f, 30);
|
Chris@16
|
197 term = floor(f);
|
Chris@16
|
198 e -= 30;
|
Chris@16
|
199 conv(t.x, (int)term);
|
Chris@16
|
200 t.e = e;
|
Chris@16
|
201 m_value += t;
|
Chris@16
|
202 f -= term;
|
Chris@16
|
203 }
|
Chris@16
|
204 }
|
Chris@16
|
205
|
Chris@16
|
206 template <class V>
|
Chris@16
|
207 void assign_large_int(V a)
|
Chris@16
|
208 {
|
Chris@16
|
209 #ifdef BOOST_MSVC
|
Chris@16
|
210 #pragma warning(push)
|
Chris@16
|
211 #pragma warning(disable:4146)
|
Chris@16
|
212 #endif
|
Chris@16
|
213 clear(m_value);
|
Chris@16
|
214 int exp = 0;
|
Chris@16
|
215 NTL::RR t;
|
Chris@16
|
216 bool neg = a < V(0) ? true : false;
|
Chris@16
|
217 if(neg)
|
Chris@16
|
218 a = -a;
|
Chris@16
|
219 while(a)
|
Chris@16
|
220 {
|
Chris@16
|
221 t = static_cast<double>(a & 0xffff);
|
Chris@16
|
222 m_value += ldexp(RR(t), exp).value();
|
Chris@16
|
223 a >>= 16;
|
Chris@16
|
224 exp += 16;
|
Chris@16
|
225 }
|
Chris@16
|
226 if(neg)
|
Chris@16
|
227 m_value = -m_value;
|
Chris@16
|
228 #ifdef BOOST_MSVC
|
Chris@16
|
229 #pragma warning(pop)
|
Chris@16
|
230 #endif
|
Chris@16
|
231 }
|
Chris@16
|
232 };
|
Chris@16
|
233
|
Chris@16
|
234 // Non-member arithmetic:
|
Chris@16
|
235 inline RR operator+(const RR& a, const RR& b)
|
Chris@16
|
236 {
|
Chris@16
|
237 RR result(a);
|
Chris@16
|
238 result += b;
|
Chris@16
|
239 return result;
|
Chris@16
|
240 }
|
Chris@16
|
241 inline RR operator-(const RR& a, const RR& b)
|
Chris@16
|
242 {
|
Chris@16
|
243 RR result(a);
|
Chris@16
|
244 result -= b;
|
Chris@16
|
245 return result;
|
Chris@16
|
246 }
|
Chris@16
|
247 inline RR operator*(const RR& a, const RR& b)
|
Chris@16
|
248 {
|
Chris@16
|
249 RR result(a);
|
Chris@16
|
250 result *= b;
|
Chris@16
|
251 return result;
|
Chris@16
|
252 }
|
Chris@16
|
253 inline RR operator/(const RR& a, const RR& b)
|
Chris@16
|
254 {
|
Chris@16
|
255 RR result(a);
|
Chris@16
|
256 result /= b;
|
Chris@16
|
257 return result;
|
Chris@16
|
258 }
|
Chris@16
|
259
|
Chris@16
|
260 // Comparison:
|
Chris@16
|
261 inline bool operator == (const RR& a, const RR& b)
|
Chris@16
|
262 { return a.value() == b.value() ? true : false; }
|
Chris@16
|
263 inline bool operator != (const RR& a, const RR& b)
|
Chris@16
|
264 { return a.value() != b.value() ? true : false;}
|
Chris@16
|
265 inline bool operator < (const RR& a, const RR& b)
|
Chris@16
|
266 { return a.value() < b.value() ? true : false; }
|
Chris@16
|
267 inline bool operator <= (const RR& a, const RR& b)
|
Chris@16
|
268 { return a.value() <= b.value() ? true : false; }
|
Chris@16
|
269 inline bool operator > (const RR& a, const RR& b)
|
Chris@16
|
270 { return a.value() > b.value() ? true : false; }
|
Chris@16
|
271 inline bool operator >= (const RR& a, const RR& b)
|
Chris@16
|
272 { return a.value() >= b.value() ? true : false; }
|
Chris@16
|
273
|
Chris@16
|
274 #if 0
|
Chris@16
|
275 // Non-member mixed compare:
|
Chris@16
|
276 template <class T>
|
Chris@16
|
277 inline bool operator == (const T& a, const RR& b)
|
Chris@16
|
278 {
|
Chris@16
|
279 return a == b.value();
|
Chris@16
|
280 }
|
Chris@16
|
281 template <class T>
|
Chris@16
|
282 inline bool operator != (const T& a, const RR& b)
|
Chris@16
|
283 {
|
Chris@16
|
284 return a != b.value();
|
Chris@16
|
285 }
|
Chris@16
|
286 template <class T>
|
Chris@16
|
287 inline bool operator < (const T& a, const RR& b)
|
Chris@16
|
288 {
|
Chris@16
|
289 return a < b.value();
|
Chris@16
|
290 }
|
Chris@16
|
291 template <class T>
|
Chris@16
|
292 inline bool operator > (const T& a, const RR& b)
|
Chris@16
|
293 {
|
Chris@16
|
294 return a > b.value();
|
Chris@16
|
295 }
|
Chris@16
|
296 template <class T>
|
Chris@16
|
297 inline bool operator <= (const T& a, const RR& b)
|
Chris@16
|
298 {
|
Chris@16
|
299 return a <= b.value();
|
Chris@16
|
300 }
|
Chris@16
|
301 template <class T>
|
Chris@16
|
302 inline bool operator >= (const T& a, const RR& b)
|
Chris@16
|
303 {
|
Chris@16
|
304 return a >= b.value();
|
Chris@16
|
305 }
|
Chris@16
|
306 #endif // Non-member mixed compare:
|
Chris@16
|
307
|
Chris@16
|
308 // Non-member functions:
|
Chris@16
|
309 /*
|
Chris@16
|
310 inline RR acos(RR a)
|
Chris@16
|
311 { return ::NTL::acos(a.value()); }
|
Chris@16
|
312 */
|
Chris@16
|
313 inline RR cos(RR a)
|
Chris@16
|
314 { return ::NTL::cos(a.value()); }
|
Chris@16
|
315 /*
|
Chris@16
|
316 inline RR asin(RR a)
|
Chris@16
|
317 { return ::NTL::asin(a.value()); }
|
Chris@16
|
318 inline RR atan(RR a)
|
Chris@16
|
319 { return ::NTL::atan(a.value()); }
|
Chris@16
|
320 inline RR atan2(RR a, RR b)
|
Chris@16
|
321 { return ::NTL::atan2(a.value(), b.value()); }
|
Chris@16
|
322 */
|
Chris@16
|
323 inline RR ceil(RR a)
|
Chris@16
|
324 { return ::NTL::ceil(a.value()); }
|
Chris@16
|
325 /*
|
Chris@16
|
326 inline RR fmod(RR a, RR b)
|
Chris@16
|
327 { return ::NTL::fmod(a.value(), b.value()); }
|
Chris@16
|
328 inline RR cosh(RR a)
|
Chris@16
|
329 { return ::NTL::cosh(a.value()); }
|
Chris@16
|
330 */
|
Chris@16
|
331 inline RR exp(RR a)
|
Chris@16
|
332 { return ::NTL::exp(a.value()); }
|
Chris@16
|
333 inline RR fabs(RR a)
|
Chris@16
|
334 { return ::NTL::fabs(a.value()); }
|
Chris@16
|
335 inline RR abs(RR a)
|
Chris@16
|
336 { return ::NTL::abs(a.value()); }
|
Chris@16
|
337 inline RR floor(RR a)
|
Chris@16
|
338 { return ::NTL::floor(a.value()); }
|
Chris@16
|
339 /*
|
Chris@16
|
340 inline RR modf(RR a, RR* ipart)
|
Chris@16
|
341 {
|
Chris@16
|
342 ::NTL::RR ip;
|
Chris@16
|
343 RR result = modf(a.value(), &ip);
|
Chris@16
|
344 *ipart = ip;
|
Chris@16
|
345 return result;
|
Chris@16
|
346 }
|
Chris@16
|
347 inline RR frexp(RR a, int* expon)
|
Chris@16
|
348 { return ::NTL::frexp(a.value(), expon); }
|
Chris@16
|
349 inline RR ldexp(RR a, int expon)
|
Chris@16
|
350 { return ::NTL::ldexp(a.value(), expon); }
|
Chris@16
|
351 */
|
Chris@16
|
352 inline RR log(RR a)
|
Chris@16
|
353 { return ::NTL::log(a.value()); }
|
Chris@16
|
354 inline RR log10(RR a)
|
Chris@16
|
355 { return ::NTL::log10(a.value()); }
|
Chris@16
|
356 /*
|
Chris@16
|
357 inline RR tan(RR a)
|
Chris@16
|
358 { return ::NTL::tan(a.value()); }
|
Chris@16
|
359 */
|
Chris@16
|
360 inline RR pow(RR a, RR b)
|
Chris@16
|
361 { return ::NTL::pow(a.value(), b.value()); }
|
Chris@16
|
362 inline RR pow(RR a, int b)
|
Chris@16
|
363 { return ::NTL::power(a.value(), b); }
|
Chris@16
|
364 inline RR sin(RR a)
|
Chris@16
|
365 { return ::NTL::sin(a.value()); }
|
Chris@16
|
366 /*
|
Chris@16
|
367 inline RR sinh(RR a)
|
Chris@16
|
368 { return ::NTL::sinh(a.value()); }
|
Chris@16
|
369 */
|
Chris@16
|
370 inline RR sqrt(RR a)
|
Chris@16
|
371 { return ::NTL::sqrt(a.value()); }
|
Chris@16
|
372 /*
|
Chris@16
|
373 inline RR tanh(RR a)
|
Chris@16
|
374 { return ::NTL::tanh(a.value()); }
|
Chris@16
|
375 */
|
Chris@16
|
376 inline RR pow(const RR& r, long l)
|
Chris@16
|
377 {
|
Chris@16
|
378 return ::NTL::power(r.value(), l);
|
Chris@16
|
379 }
|
Chris@16
|
380 inline RR tan(const RR& a)
|
Chris@16
|
381 {
|
Chris@16
|
382 return sin(a)/cos(a);
|
Chris@16
|
383 }
|
Chris@16
|
384 inline RR frexp(RR r, int* exp)
|
Chris@16
|
385 {
|
Chris@16
|
386 *exp = r.value().e;
|
Chris@16
|
387 r.value().e = 0;
|
Chris@16
|
388 while(r >= 1)
|
Chris@16
|
389 {
|
Chris@16
|
390 *exp += 1;
|
Chris@16
|
391 r.value().e -= 1;
|
Chris@16
|
392 }
|
Chris@16
|
393 while(r < 0.5)
|
Chris@16
|
394 {
|
Chris@16
|
395 *exp -= 1;
|
Chris@16
|
396 r.value().e += 1;
|
Chris@16
|
397 }
|
Chris@16
|
398 BOOST_ASSERT(r < 1);
|
Chris@16
|
399 BOOST_ASSERT(r >= 0.5);
|
Chris@16
|
400 return r;
|
Chris@16
|
401 }
|
Chris@16
|
402 inline RR ldexp(RR r, int exp)
|
Chris@16
|
403 {
|
Chris@16
|
404 r.value().e += exp;
|
Chris@16
|
405 return r;
|
Chris@16
|
406 }
|
Chris@16
|
407
|
Chris@16
|
408 // Streaming:
|
Chris@16
|
409 template <class charT, class traits>
|
Chris@16
|
410 inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const RR& a)
|
Chris@16
|
411 {
|
Chris@16
|
412 return os << a.value();
|
Chris@16
|
413 }
|
Chris@16
|
414 template <class charT, class traits>
|
Chris@16
|
415 inline std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>& is, RR& a)
|
Chris@16
|
416 {
|
Chris@16
|
417 ::NTL::RR v;
|
Chris@16
|
418 is >> v;
|
Chris@16
|
419 a = v;
|
Chris@16
|
420 return is;
|
Chris@16
|
421 }
|
Chris@16
|
422
|
Chris@16
|
423 } // namespace ntl
|
Chris@16
|
424
|
Chris@16
|
425 namespace lanczos{
|
Chris@16
|
426
|
Chris@16
|
427 struct ntl_lanczos
|
Chris@16
|
428 {
|
Chris@16
|
429 static ntl::RR lanczos_sum(const ntl::RR& z)
|
Chris@16
|
430 {
|
Chris@16
|
431 unsigned long p = ntl::RR::precision();
|
Chris@16
|
432 if(p <= 72)
|
Chris@16
|
433 return lanczos13UDT::lanczos_sum(z);
|
Chris@16
|
434 else if(p <= 120)
|
Chris@16
|
435 return lanczos22UDT::lanczos_sum(z);
|
Chris@16
|
436 else if(p <= 170)
|
Chris@16
|
437 return lanczos31UDT::lanczos_sum(z);
|
Chris@16
|
438 else //if(p <= 370) approx 100 digit precision:
|
Chris@16
|
439 return lanczos61UDT::lanczos_sum(z);
|
Chris@16
|
440 }
|
Chris@16
|
441 static ntl::RR lanczos_sum_expG_scaled(const ntl::RR& z)
|
Chris@16
|
442 {
|
Chris@16
|
443 unsigned long p = ntl::RR::precision();
|
Chris@16
|
444 if(p <= 72)
|
Chris@16
|
445 return lanczos13UDT::lanczos_sum_expG_scaled(z);
|
Chris@16
|
446 else if(p <= 120)
|
Chris@16
|
447 return lanczos22UDT::lanczos_sum_expG_scaled(z);
|
Chris@16
|
448 else if(p <= 170)
|
Chris@16
|
449 return lanczos31UDT::lanczos_sum_expG_scaled(z);
|
Chris@16
|
450 else //if(p <= 370) approx 100 digit precision:
|
Chris@16
|
451 return lanczos61UDT::lanczos_sum_expG_scaled(z);
|
Chris@16
|
452 }
|
Chris@16
|
453 static ntl::RR lanczos_sum_near_1(const ntl::RR& z)
|
Chris@16
|
454 {
|
Chris@16
|
455 unsigned long p = ntl::RR::precision();
|
Chris@16
|
456 if(p <= 72)
|
Chris@16
|
457 return lanczos13UDT::lanczos_sum_near_1(z);
|
Chris@16
|
458 else if(p <= 120)
|
Chris@16
|
459 return lanczos22UDT::lanczos_sum_near_1(z);
|
Chris@16
|
460 else if(p <= 170)
|
Chris@16
|
461 return lanczos31UDT::lanczos_sum_near_1(z);
|
Chris@16
|
462 else //if(p <= 370) approx 100 digit precision:
|
Chris@16
|
463 return lanczos61UDT::lanczos_sum_near_1(z);
|
Chris@16
|
464 }
|
Chris@16
|
465 static ntl::RR lanczos_sum_near_2(const ntl::RR& z)
|
Chris@16
|
466 {
|
Chris@16
|
467 unsigned long p = ntl::RR::precision();
|
Chris@16
|
468 if(p <= 72)
|
Chris@16
|
469 return lanczos13UDT::lanczos_sum_near_2(z);
|
Chris@16
|
470 else if(p <= 120)
|
Chris@16
|
471 return lanczos22UDT::lanczos_sum_near_2(z);
|
Chris@16
|
472 else if(p <= 170)
|
Chris@16
|
473 return lanczos31UDT::lanczos_sum_near_2(z);
|
Chris@16
|
474 else //if(p <= 370) approx 100 digit precision:
|
Chris@16
|
475 return lanczos61UDT::lanczos_sum_near_2(z);
|
Chris@16
|
476 }
|
Chris@16
|
477 static ntl::RR g()
|
Chris@16
|
478 {
|
Chris@16
|
479 unsigned long p = ntl::RR::precision();
|
Chris@16
|
480 if(p <= 72)
|
Chris@16
|
481 return lanczos13UDT::g();
|
Chris@16
|
482 else if(p <= 120)
|
Chris@16
|
483 return lanczos22UDT::g();
|
Chris@16
|
484 else if(p <= 170)
|
Chris@16
|
485 return lanczos31UDT::g();
|
Chris@16
|
486 else //if(p <= 370) approx 100 digit precision:
|
Chris@16
|
487 return lanczos61UDT::g();
|
Chris@16
|
488 }
|
Chris@16
|
489 };
|
Chris@16
|
490
|
Chris@16
|
491 template<class Policy>
|
Chris@16
|
492 struct lanczos<ntl::RR, Policy>
|
Chris@16
|
493 {
|
Chris@16
|
494 typedef ntl_lanczos type;
|
Chris@16
|
495 };
|
Chris@16
|
496
|
Chris@16
|
497 } // namespace lanczos
|
Chris@16
|
498
|
Chris@16
|
499 namespace tools
|
Chris@16
|
500 {
|
Chris@16
|
501
|
Chris@16
|
502 template<>
|
Chris@16
|
503 inline int digits<boost::math::ntl::RR>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
|
Chris@16
|
504 {
|
Chris@16
|
505 return ::NTL::RR::precision();
|
Chris@16
|
506 }
|
Chris@16
|
507
|
Chris@16
|
508 template <>
|
Chris@16
|
509 inline float real_cast<float, boost::math::ntl::RR>(boost::math::ntl::RR t)
|
Chris@16
|
510 {
|
Chris@16
|
511 double r;
|
Chris@16
|
512 conv(r, t.value());
|
Chris@16
|
513 return static_cast<float>(r);
|
Chris@16
|
514 }
|
Chris@16
|
515 template <>
|
Chris@16
|
516 inline double real_cast<double, boost::math::ntl::RR>(boost::math::ntl::RR t)
|
Chris@16
|
517 {
|
Chris@16
|
518 double r;
|
Chris@16
|
519 conv(r, t.value());
|
Chris@16
|
520 return r;
|
Chris@16
|
521 }
|
Chris@16
|
522
|
Chris@16
|
523 namespace detail{
|
Chris@16
|
524
|
Chris@16
|
525 template<class I>
|
Chris@16
|
526 void convert_to_long_result(NTL::RR const& r, I& result)
|
Chris@16
|
527 {
|
Chris@16
|
528 result = 0;
|
Chris@16
|
529 I last_result(0);
|
Chris@16
|
530 NTL::RR t(r);
|
Chris@16
|
531 double term;
|
Chris@16
|
532 do
|
Chris@16
|
533 {
|
Chris@16
|
534 conv(term, t);
|
Chris@16
|
535 last_result = result;
|
Chris@16
|
536 result += static_cast<I>(term);
|
Chris@16
|
537 t -= term;
|
Chris@16
|
538 }while(result != last_result);
|
Chris@16
|
539 }
|
Chris@16
|
540
|
Chris@16
|
541 }
|
Chris@16
|
542
|
Chris@16
|
543 template <>
|
Chris@16
|
544 inline long double real_cast<long double, boost::math::ntl::RR>(boost::math::ntl::RR t)
|
Chris@16
|
545 {
|
Chris@16
|
546 long double result(0);
|
Chris@16
|
547 detail::convert_to_long_result(t.value(), result);
|
Chris@16
|
548 return result;
|
Chris@16
|
549 }
|
Chris@16
|
550 template <>
|
Chris@16
|
551 inline boost::math::ntl::RR real_cast<boost::math::ntl::RR, boost::math::ntl::RR>(boost::math::ntl::RR t)
|
Chris@16
|
552 {
|
Chris@16
|
553 return t;
|
Chris@16
|
554 }
|
Chris@16
|
555 template <>
|
Chris@16
|
556 inline unsigned real_cast<unsigned, boost::math::ntl::RR>(boost::math::ntl::RR t)
|
Chris@16
|
557 {
|
Chris@16
|
558 unsigned result;
|
Chris@16
|
559 detail::convert_to_long_result(t.value(), result);
|
Chris@16
|
560 return result;
|
Chris@16
|
561 }
|
Chris@16
|
562 template <>
|
Chris@16
|
563 inline int real_cast<int, boost::math::ntl::RR>(boost::math::ntl::RR t)
|
Chris@16
|
564 {
|
Chris@16
|
565 int result;
|
Chris@16
|
566 detail::convert_to_long_result(t.value(), result);
|
Chris@16
|
567 return result;
|
Chris@16
|
568 }
|
Chris@16
|
569 template <>
|
Chris@16
|
570 inline long real_cast<long, boost::math::ntl::RR>(boost::math::ntl::RR t)
|
Chris@16
|
571 {
|
Chris@16
|
572 long result;
|
Chris@16
|
573 detail::convert_to_long_result(t.value(), result);
|
Chris@16
|
574 return result;
|
Chris@16
|
575 }
|
Chris@16
|
576 template <>
|
Chris@16
|
577 inline long long real_cast<long long, boost::math::ntl::RR>(boost::math::ntl::RR t)
|
Chris@16
|
578 {
|
Chris@16
|
579 long long result;
|
Chris@16
|
580 detail::convert_to_long_result(t.value(), result);
|
Chris@16
|
581 return result;
|
Chris@16
|
582 }
|
Chris@16
|
583
|
Chris@16
|
584 template <>
|
Chris@16
|
585 inline boost::math::ntl::RR max_value<boost::math::ntl::RR>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
|
Chris@16
|
586 {
|
Chris@16
|
587 static bool has_init = false;
|
Chris@16
|
588 static NTL::RR val;
|
Chris@16
|
589 if(!has_init)
|
Chris@16
|
590 {
|
Chris@16
|
591 val = 1;
|
Chris@16
|
592 val.e = NTL_OVFBND-20;
|
Chris@16
|
593 has_init = true;
|
Chris@16
|
594 }
|
Chris@16
|
595 return val;
|
Chris@16
|
596 }
|
Chris@16
|
597
|
Chris@16
|
598 template <>
|
Chris@16
|
599 inline boost::math::ntl::RR min_value<boost::math::ntl::RR>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
|
Chris@16
|
600 {
|
Chris@16
|
601 static bool has_init = false;
|
Chris@16
|
602 static NTL::RR val;
|
Chris@16
|
603 if(!has_init)
|
Chris@16
|
604 {
|
Chris@16
|
605 val = 1;
|
Chris@16
|
606 val.e = -NTL_OVFBND+20;
|
Chris@16
|
607 has_init = true;
|
Chris@16
|
608 }
|
Chris@16
|
609 return val;
|
Chris@16
|
610 }
|
Chris@16
|
611
|
Chris@16
|
612 template <>
|
Chris@16
|
613 inline boost::math::ntl::RR log_max_value<boost::math::ntl::RR>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
|
Chris@16
|
614 {
|
Chris@16
|
615 static bool has_init = false;
|
Chris@16
|
616 static NTL::RR val;
|
Chris@16
|
617 if(!has_init)
|
Chris@16
|
618 {
|
Chris@16
|
619 val = 1;
|
Chris@16
|
620 val.e = NTL_OVFBND-20;
|
Chris@16
|
621 val = log(val);
|
Chris@16
|
622 has_init = true;
|
Chris@16
|
623 }
|
Chris@16
|
624 return val;
|
Chris@16
|
625 }
|
Chris@16
|
626
|
Chris@16
|
627 template <>
|
Chris@16
|
628 inline boost::math::ntl::RR log_min_value<boost::math::ntl::RR>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
|
Chris@16
|
629 {
|
Chris@16
|
630 static bool has_init = false;
|
Chris@16
|
631 static NTL::RR val;
|
Chris@16
|
632 if(!has_init)
|
Chris@16
|
633 {
|
Chris@16
|
634 val = 1;
|
Chris@16
|
635 val.e = -NTL_OVFBND+20;
|
Chris@16
|
636 val = log(val);
|
Chris@16
|
637 has_init = true;
|
Chris@16
|
638 }
|
Chris@16
|
639 return val;
|
Chris@16
|
640 }
|
Chris@16
|
641
|
Chris@16
|
642 template <>
|
Chris@16
|
643 inline boost::math::ntl::RR epsilon<boost::math::ntl::RR>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
|
Chris@16
|
644 {
|
Chris@16
|
645 return ldexp(boost::math::ntl::RR(1), 1-boost::math::policies::digits<boost::math::ntl::RR, boost::math::policies::policy<> >());
|
Chris@16
|
646 }
|
Chris@16
|
647
|
Chris@16
|
648 } // namespace tools
|
Chris@16
|
649
|
Chris@16
|
650 //
|
Chris@16
|
651 // The number of digits precision in RR can vary with each call
|
Chris@16
|
652 // so we need to recalculate these with each call:
|
Chris@16
|
653 //
|
Chris@16
|
654 namespace constants{
|
Chris@16
|
655
|
Chris@16
|
656 template<> inline boost::math::ntl::RR pi<boost::math::ntl::RR>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
|
Chris@16
|
657 {
|
Chris@16
|
658 NTL::RR result;
|
Chris@16
|
659 ComputePi(result);
|
Chris@16
|
660 return result;
|
Chris@16
|
661 }
|
Chris@16
|
662 template<> inline boost::math::ntl::RR e<boost::math::ntl::RR>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
|
Chris@16
|
663 {
|
Chris@16
|
664 NTL::RR result;
|
Chris@16
|
665 result = 1;
|
Chris@16
|
666 return exp(result);
|
Chris@16
|
667 }
|
Chris@16
|
668
|
Chris@16
|
669 } // namespace constants
|
Chris@16
|
670
|
Chris@16
|
671 namespace ntl{
|
Chris@16
|
672 //
|
Chris@16
|
673 // These are some fairly brain-dead versions of the math
|
Chris@16
|
674 // functions that NTL fails to provide.
|
Chris@16
|
675 //
|
Chris@16
|
676
|
Chris@16
|
677
|
Chris@16
|
678 //
|
Chris@16
|
679 // Inverse trig functions:
|
Chris@16
|
680 //
|
Chris@16
|
681 struct asin_root
|
Chris@16
|
682 {
|
Chris@16
|
683 asin_root(RR const& target) : t(target){}
|
Chris@16
|
684
|
Chris@16
|
685 boost::math::tuple<RR, RR, RR> operator()(RR const& p)
|
Chris@16
|
686 {
|
Chris@16
|
687 RR f0 = sin(p);
|
Chris@16
|
688 RR f1 = cos(p);
|
Chris@16
|
689 RR f2 = -f0;
|
Chris@16
|
690 f0 -= t;
|
Chris@16
|
691 return boost::math::make_tuple(f0, f1, f2);
|
Chris@16
|
692 }
|
Chris@16
|
693 private:
|
Chris@16
|
694 RR t;
|
Chris@16
|
695 };
|
Chris@16
|
696
|
Chris@16
|
697 inline RR asin(RR z)
|
Chris@16
|
698 {
|
Chris@16
|
699 double r;
|
Chris@16
|
700 conv(r, z.value());
|
Chris@16
|
701 return boost::math::tools::halley_iterate(
|
Chris@16
|
702 asin_root(z),
|
Chris@16
|
703 RR(std::asin(r)),
|
Chris@16
|
704 RR(-boost::math::constants::pi<RR>()/2),
|
Chris@16
|
705 RR(boost::math::constants::pi<RR>()/2),
|
Chris@16
|
706 NTL::RR::precision());
|
Chris@16
|
707 }
|
Chris@16
|
708
|
Chris@16
|
709 struct acos_root
|
Chris@16
|
710 {
|
Chris@16
|
711 acos_root(RR const& target) : t(target){}
|
Chris@16
|
712
|
Chris@16
|
713 boost::math::tuple<RR, RR, RR> operator()(RR const& p)
|
Chris@16
|
714 {
|
Chris@16
|
715 RR f0 = cos(p);
|
Chris@16
|
716 RR f1 = -sin(p);
|
Chris@16
|
717 RR f2 = -f0;
|
Chris@16
|
718 f0 -= t;
|
Chris@16
|
719 return boost::math::make_tuple(f0, f1, f2);
|
Chris@16
|
720 }
|
Chris@16
|
721 private:
|
Chris@16
|
722 RR t;
|
Chris@16
|
723 };
|
Chris@16
|
724
|
Chris@16
|
725 inline RR acos(RR z)
|
Chris@16
|
726 {
|
Chris@16
|
727 double r;
|
Chris@16
|
728 conv(r, z.value());
|
Chris@16
|
729 return boost::math::tools::halley_iterate(
|
Chris@16
|
730 acos_root(z),
|
Chris@16
|
731 RR(std::acos(r)),
|
Chris@16
|
732 RR(-boost::math::constants::pi<RR>()/2),
|
Chris@16
|
733 RR(boost::math::constants::pi<RR>()/2),
|
Chris@16
|
734 NTL::RR::precision());
|
Chris@16
|
735 }
|
Chris@16
|
736
|
Chris@16
|
737 struct atan_root
|
Chris@16
|
738 {
|
Chris@16
|
739 atan_root(RR const& target) : t(target){}
|
Chris@16
|
740
|
Chris@16
|
741 boost::math::tuple<RR, RR, RR> operator()(RR const& p)
|
Chris@16
|
742 {
|
Chris@16
|
743 RR c = cos(p);
|
Chris@16
|
744 RR ta = tan(p);
|
Chris@16
|
745 RR f0 = ta - t;
|
Chris@16
|
746 RR f1 = 1 / (c * c);
|
Chris@16
|
747 RR f2 = 2 * ta / (c * c);
|
Chris@16
|
748 return boost::math::make_tuple(f0, f1, f2);
|
Chris@16
|
749 }
|
Chris@16
|
750 private:
|
Chris@16
|
751 RR t;
|
Chris@16
|
752 };
|
Chris@16
|
753
|
Chris@16
|
754 inline RR atan(RR z)
|
Chris@16
|
755 {
|
Chris@16
|
756 double r;
|
Chris@16
|
757 conv(r, z.value());
|
Chris@16
|
758 return boost::math::tools::halley_iterate(
|
Chris@16
|
759 atan_root(z),
|
Chris@16
|
760 RR(std::atan(r)),
|
Chris@16
|
761 -boost::math::constants::pi<RR>()/2,
|
Chris@16
|
762 boost::math::constants::pi<RR>()/2,
|
Chris@16
|
763 NTL::RR::precision());
|
Chris@16
|
764 }
|
Chris@16
|
765
|
Chris@16
|
766 inline RR atan2(RR y, RR x)
|
Chris@16
|
767 {
|
Chris@16
|
768 if(x > 0)
|
Chris@16
|
769 return atan(y / x);
|
Chris@16
|
770 if(x < 0)
|
Chris@16
|
771 {
|
Chris@16
|
772 return y < 0 ? atan(y / x) - boost::math::constants::pi<RR>() : atan(y / x) + boost::math::constants::pi<RR>();
|
Chris@16
|
773 }
|
Chris@16
|
774 return y < 0 ? -boost::math::constants::half_pi<RR>() : boost::math::constants::half_pi<RR>() ;
|
Chris@16
|
775 }
|
Chris@16
|
776
|
Chris@16
|
777 inline RR sinh(RR z)
|
Chris@16
|
778 {
|
Chris@16
|
779 return (expm1(z.value()) - expm1(-z.value())) / 2;
|
Chris@16
|
780 }
|
Chris@16
|
781
|
Chris@16
|
782 inline RR cosh(RR z)
|
Chris@16
|
783 {
|
Chris@16
|
784 return (exp(z) + exp(-z)) / 2;
|
Chris@16
|
785 }
|
Chris@16
|
786
|
Chris@16
|
787 inline RR tanh(RR z)
|
Chris@16
|
788 {
|
Chris@16
|
789 return sinh(z) / cosh(z);
|
Chris@16
|
790 }
|
Chris@16
|
791
|
Chris@16
|
792 inline RR fmod(RR x, RR y)
|
Chris@16
|
793 {
|
Chris@16
|
794 // This is a really crummy version of fmod, we rely on lots
|
Chris@16
|
795 // of digits to get us out of trouble...
|
Chris@16
|
796 RR factor = floor(x/y);
|
Chris@16
|
797 return x - factor * y;
|
Chris@16
|
798 }
|
Chris@16
|
799
|
Chris@16
|
800 template <class Policy>
|
Chris@16
|
801 inline int iround(RR const& x, const Policy& pol)
|
Chris@16
|
802 {
|
Chris@16
|
803 return tools::real_cast<int>(round(x, pol));
|
Chris@16
|
804 }
|
Chris@16
|
805
|
Chris@16
|
806 template <class Policy>
|
Chris@16
|
807 inline long lround(RR const& x, const Policy& pol)
|
Chris@16
|
808 {
|
Chris@16
|
809 return tools::real_cast<long>(round(x, pol));
|
Chris@16
|
810 }
|
Chris@16
|
811
|
Chris@16
|
812 template <class Policy>
|
Chris@16
|
813 inline long long llround(RR const& x, const Policy& pol)
|
Chris@16
|
814 {
|
Chris@16
|
815 return tools::real_cast<long long>(round(x, pol));
|
Chris@16
|
816 }
|
Chris@16
|
817
|
Chris@16
|
818 template <class Policy>
|
Chris@16
|
819 inline int itrunc(RR const& x, const Policy& pol)
|
Chris@16
|
820 {
|
Chris@16
|
821 return tools::real_cast<int>(trunc(x, pol));
|
Chris@16
|
822 }
|
Chris@16
|
823
|
Chris@16
|
824 template <class Policy>
|
Chris@16
|
825 inline long ltrunc(RR const& x, const Policy& pol)
|
Chris@16
|
826 {
|
Chris@16
|
827 return tools::real_cast<long>(trunc(x, pol));
|
Chris@16
|
828 }
|
Chris@16
|
829
|
Chris@16
|
830 template <class Policy>
|
Chris@16
|
831 inline long long lltrunc(RR const& x, const Policy& pol)
|
Chris@16
|
832 {
|
Chris@16
|
833 return tools::real_cast<long long>(trunc(x, pol));
|
Chris@16
|
834 }
|
Chris@16
|
835
|
Chris@16
|
836 } // namespace ntl
|
Chris@16
|
837
|
Chris@16
|
838 namespace detail{
|
Chris@16
|
839
|
Chris@16
|
840 template <class Policy>
|
Chris@16
|
841 ntl::RR digamma_imp(ntl::RR x, const mpl::int_<0>* , const Policy& pol)
|
Chris@16
|
842 {
|
Chris@16
|
843 //
|
Chris@16
|
844 // This handles reflection of negative arguments, and all our
|
Chris@16
|
845 // error handling, then forwards to the T-specific approximation.
|
Chris@16
|
846 //
|
Chris@16
|
847 BOOST_MATH_STD_USING // ADL of std functions.
|
Chris@16
|
848
|
Chris@16
|
849 ntl::RR result = 0;
|
Chris@16
|
850 //
|
Chris@16
|
851 // Check for negative arguments and use reflection:
|
Chris@16
|
852 //
|
Chris@16
|
853 if(x < 0)
|
Chris@16
|
854 {
|
Chris@16
|
855 // Reflect:
|
Chris@16
|
856 x = 1 - x;
|
Chris@16
|
857 // Argument reduction for tan:
|
Chris@16
|
858 ntl::RR remainder = x - floor(x);
|
Chris@16
|
859 // Shift to negative if > 0.5:
|
Chris@16
|
860 if(remainder > 0.5)
|
Chris@16
|
861 {
|
Chris@16
|
862 remainder -= 1;
|
Chris@16
|
863 }
|
Chris@16
|
864 //
|
Chris@16
|
865 // check for evaluation at a negative pole:
|
Chris@16
|
866 //
|
Chris@16
|
867 if(remainder == 0)
|
Chris@16
|
868 {
|
Chris@16
|
869 return policies::raise_pole_error<ntl::RR>("boost::math::digamma<%1%>(%1%)", 0, (1-x), pol);
|
Chris@16
|
870 }
|
Chris@16
|
871 result = constants::pi<ntl::RR>() / tan(constants::pi<ntl::RR>() * remainder);
|
Chris@16
|
872 }
|
Chris@16
|
873 result += big_digamma(x);
|
Chris@16
|
874 return result;
|
Chris@16
|
875 }
|
Chris@16
|
876
|
Chris@16
|
877 } // namespace detail
|
Chris@16
|
878
|
Chris@16
|
879 } // namespace math
|
Chris@16
|
880 } // namespace boost
|
Chris@16
|
881
|
Chris@16
|
882 #endif // BOOST_MATH_REAL_CONCEPT_HPP
|
Chris@16
|
883
|
Chris@16
|
884
|