mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-10-25 01:50:30 -04:00 
			
		
		
		
	
		
			
	
	
		
			143 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			143 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|  | [section:digamma Digamma] | ||
|  | 
 | ||
|  | [h4 Synopsis] | ||
|  | 
 | ||
|  | `` | ||
|  | #include <boost/math/special_functions/digamma.hpp> | ||
|  | `` | ||
|  | 
 | ||
|  |   namespace boost{ namespace math{ | ||
|  |    | ||
|  |   template <class T> | ||
|  |   ``__sf_result`` digamma(T z); | ||
|  |    | ||
|  |   template <class T, class ``__Policy``> | ||
|  |   ``__sf_result`` digamma(T z, const ``__Policy``&); | ||
|  |    | ||
|  |   }} // namespaces | ||
|  |    | ||
|  | [h4 Description] | ||
|  | 
 | ||
|  | Returns the digamma or psi function of /x/. Digamma is defined as the logarithmic | ||
|  | derivative of the gamma function: | ||
|  | 
 | ||
|  | [equation digamma1] | ||
|  | 
 | ||
|  | [graph digamma] | ||
|  | 
 | ||
|  | [optional_policy] | ||
|  | 
 | ||
|  | The return type of this function is computed using the __arg_promotion_rules: | ||
|  | the result is of type `double` when T is an integer type, and type T otherwise. | ||
|  | 
 | ||
|  | [h4 Accuracy] | ||
|  | 
 | ||
|  | The following table shows the peak errors (in units of epsilon)  | ||
|  | found on various platforms with various floating point types. | ||
|  | Unless otherwise specified any floating point type that is narrower | ||
|  | than the one shown will have __zero_error. | ||
|  | 
 | ||
|  | [table_digamma] | ||
|  | 
 | ||
|  | As shown above, error rates for positive arguments are generally very low. | ||
|  | For negative arguments there are an infinite number of irrational roots: | ||
|  | relative errors very close to these can be arbitrarily large, although | ||
|  | absolute error will remain very low. | ||
|  | 
 | ||
|  | [h4 Testing] | ||
|  | 
 | ||
|  | There are two sets of tests: spot values are computed using | ||
|  | the online calculator at functions.wolfram.com, while random test values | ||
|  | are generated using the high-precision reference implementation (a  | ||
|  | differentiated __lanczos see below). | ||
|  | 
 | ||
|  | [h4 Implementation] | ||
|  | 
 | ||
|  | The implementation is divided up into the following domains: | ||
|  | 
 | ||
|  | For Negative arguments the reflection formula: | ||
|  | 
 | ||
|  |    digamma(1-x) = digamma(x) + pi/tan(pi*x); | ||
|  |     | ||
|  | is used to make /x/ positive. | ||
|  | 
 | ||
|  | For arguments in the range [0,1] the recurrence relation: | ||
|  | 
 | ||
|  |    digamma(x) = digamma(x+1) - 1/x | ||
|  |     | ||
|  | is used to shift the evaluation to [1,2]. | ||
|  | 
 | ||
|  | For arguments in the range [1,2] a rational approximation [jm_rationals] is used (see below). | ||
|  | 
 | ||
|  | For arguments in the range [2,BIG] the recurrence relation: | ||
|  | 
 | ||
|  |    digamma(x+1) = digamma(x) + 1/x; | ||
|  |     | ||
|  | is used to shift the evaluation to the range [1,2]. | ||
|  | 
 | ||
|  | For arguments > BIG the asymptotic expansion: | ||
|  | 
 | ||
|  | [equation digamma2] | ||
|  | 
 | ||
|  | can be used.  However, this expansion is divergent after a few terms:  | ||
|  | exactly how many terms depends on the size of /x/.  Therefore the value | ||
|  | of /BIG/ must be chosen so that the series can be truncated at a term | ||
|  | that is too small to have any effect on the result when evaluated at /BIG/. | ||
|  | Choosing BIG=10 for up to 80-bit reals, and BIG=20 for 128-bit reals allows | ||
|  | the series to truncated after a suitably small number of terms and evaluated | ||
|  | as a polynomial in `1/(x*x)`. | ||
|  | 
 | ||
|  | The arbitrary precision version of this function uses recurrence relations until | ||
|  | x > BIG, and then evaluation via the asymptotic expansion above.  As special cases | ||
|  | integer and half integer arguments are handled via: | ||
|  | 
 | ||
|  | [equation digamma4] | ||
|  | 
 | ||
|  | [equation digamma5] | ||
|  | 
 | ||
|  | The rational approximation [jm_rationals] in the range [1,2] is derived as follows. | ||
|  | 
 | ||
|  | First a high precision approximation to digamma was constructed using a 60-term | ||
|  | differentiated __lanczos, the form used is: | ||
|  | 
 | ||
|  | [equation digamma3] | ||
|  | 
 | ||
|  | Where P(x) and Q(x) are the polynomials from the rational form of the Lanczos sum, | ||
|  | and P'(x) and Q'(x) are their first derivatives.  The Lanzos part of this | ||
|  | approximation has a theoretical precision of ~100 decimal digits.  However,  | ||
|  | cancellation in the above sum will reduce that to around `99-(1/y)` digits | ||
|  | if /y/ is the result.  This approximation was used to calculate the positive root | ||
|  | of digamma, and was found to agree with the value used by  | ||
|  | Cody to 25 digits (See Math. Comp. 27, 123-127 (1973) by Cody, Strecok and Thacher) | ||
|  | and with the value used by Morris to 35 digits (See TOMS Algorithm 708). | ||
|  | 
 | ||
|  | Likewise a few spot tests agreed with values calculated using | ||
|  | functions.wolfram.com to >40 digits. | ||
|  | That's sufficiently precise to insure that the approximation below is | ||
|  | accurate to double precision.  Achieving 128-bit long double precision requires that | ||
|  | the location of the root is known to ~70 digits, and it's not clear whether  | ||
|  | the value calculated by this method meets that requirement: the difficulty | ||
|  | lies in independently verifying the value obtained. | ||
|  | 
 | ||
|  | The rational approximation [jm_rationals] was optimised for absolute error using the form: | ||
|  | 
 | ||
|  |    digamma(x) = (x - X0)(Y + R(x - 1)); | ||
|  |     | ||
|  | Where X0 is the positive root of digamma, Y is a constant, and R(x - 1) is the | ||
|  | rational approximation.  Note that since X0 is irrational, we need twice as many | ||
|  | digits in X0 as in x in order to avoid cancellation error during the subtraction | ||
|  | (this assumes that /x/ is an exact value, if it's not then all bets are off).  That | ||
|  | means that even when x is the value of the root rounded to the nearest  | ||
|  | representable value, the result of digamma(x) ['[*will not be zero]]. | ||
|  | 
 | ||
|  | 
 | ||
|  | [endsect][/section:digamma The Digamma Function] | ||
|  | 
 | ||
|  | [/  | ||
|  |   Copyright 2006 John Maddock and Paul A. Bristow. | ||
|  |   Distributed under 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). | ||
|  | ] | ||
|  | 
 |