mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-10-31 04:50:34 -04:00 
			
		
		
		
	
		
			
	
	
		
			142 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			142 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|  | [section:tgamma Gamma] | ||
|  | 
 | ||
|  | [h4 Synopsis] | ||
|  | 
 | ||
|  | `` | ||
|  | #include <boost/math/special_functions/gamma.hpp> | ||
|  | `` | ||
|  | 
 | ||
|  |   namespace boost{ namespace math{ | ||
|  |    | ||
|  |   template <class T> | ||
|  |   ``__sf_result`` tgamma(T z); | ||
|  |    | ||
|  |   template <class T, class ``__Policy``> | ||
|  |   ``__sf_result`` tgamma(T z, const ``__Policy``&); | ||
|  |    | ||
|  |   template <class T> | ||
|  |   ``__sf_result`` tgamma1pm1(T dz); | ||
|  |    | ||
|  |   template <class T, class ``__Policy``> | ||
|  |   ``__sf_result`` tgamma1pm1(T dz, const ``__Policy``&); | ||
|  |    | ||
|  |   }} // namespaces | ||
|  |    | ||
|  | [h4 Description] | ||
|  | 
 | ||
|  |   template <class T> | ||
|  |   ``__sf_result`` tgamma(T z); | ||
|  |    | ||
|  |   template <class T, class ``__Policy``> | ||
|  |   ``__sf_result`` tgamma(T z, const ``__Policy``&); | ||
|  |    | ||
|  | Returns the "true gamma" (hence name tgamma) of value z: | ||
|  | 
 | ||
|  | [equation gamm1] | ||
|  | 
 | ||
|  | [graph tgamma] | ||
|  | 
 | ||
|  | [optional_policy] | ||
|  | 
 | ||
|  | There are effectively two versions of the [@http://en.wikipedia.org/wiki/Gamma_function tgamma] | ||
|  | function internally: a fully | ||
|  | generic version that is slow, but reasonably accurate, and a much more | ||
|  | efficient approximation that is used where the number of digits in the significand | ||
|  | of T correspond to a certain __lanczos.  In practice any built in | ||
|  | floating point type you will encounter has an appropriate __lanczos | ||
|  | defined for it.  It is also possible, given enough machine time, to generate | ||
|  | further __lanczos's using the program libs/math/tools/lanczos_generator.cpp. | ||
|  | 
 | ||
|  | The return type of this function is computed using the __arg_promotion_rules: | ||
|  | the result is `double` when T is an integer type, and T otherwise. | ||
|  | 
 | ||
|  |   template <class T> | ||
|  |   ``__sf_result`` tgamma1pm1(T dz); | ||
|  |    | ||
|  |   template <class T, class ``__Policy``> | ||
|  |   ``__sf_result`` tgamma1pm1(T dz, const ``__Policy``&); | ||
|  |    | ||
|  | Returns `tgamma(dz + 1) - 1`.  Internally the implementation does not make | ||
|  | use of the addition and subtraction implied by the definition, leading to | ||
|  | accurate results even for very small `dz`.  However, the implementation is | ||
|  | capped to either 35 digit accuracy, or to the precision of the __lanczos | ||
|  | associated with type T, whichever is more accurate. | ||
|  |    | ||
|  | The return type of this function is computed using the __arg_promotion_rules: | ||
|  | the result is `double` when T is an integer type, and T otherwise. | ||
|  | 
 | ||
|  | [optional_policy] | ||
|  | 
 | ||
|  | [h4 Accuracy] | ||
|  | 
 | ||
|  | The following table shows the peak errors (in units of epsilon)  | ||
|  | found on various platforms with various floating point types,  | ||
|  | along with comparisons to other common libraries. | ||
|  | Unless otherwise specified any floating point type that is narrower | ||
|  | than the one shown will have __zero_error. | ||
|  | 
 | ||
|  | [table_tgamma] | ||
|  | 
 | ||
|  | [table_tgamma1pm1] | ||
|  | 
 | ||
|  | [h4 Testing] | ||
|  | 
 | ||
|  | The gamma is relatively easy to test: factorials and half-integer factorials | ||
|  | can be calculated exactly by other means and compared with the gamma function. | ||
|  | In addition, some accuracy tests in known tricky areas were computed at high precision | ||
|  | using the generic version of this function. | ||
|  | 
 | ||
|  | The function `tgamma1pm1` is tested against values calculated very naively | ||
|  | using the formula `tgamma(1+dz)-1` with a lanczos approximation accurate | ||
|  | to around 100 decimal digits. | ||
|  | 
 | ||
|  | [h4 Implementation] | ||
|  | 
 | ||
|  | The generic version of the `tgamma` function is implemented Sterling's approximation | ||
|  | for lgamma for large z: | ||
|  | 
 | ||
|  | [equation gamma6] | ||
|  | 
 | ||
|  | Following exponentiation, downward recursion is then used for small values of z. | ||
|  | 
 | ||
|  | For types of known precision the __lanczos is used, a traits class  | ||
|  | `boost::math::lanczos::lanczos_traits` maps type T to an appropriate | ||
|  | approximation.   | ||
|  | 
 | ||
|  | For z in the range -20 < z < 1 then recursion is used to shift to z > 1 via: | ||
|  | 
 | ||
|  | [equation gamm3] | ||
|  | 
 | ||
|  | For very small z, this helps to preserve the identity: | ||
|  | 
 | ||
|  | [equation gamm4] | ||
|  | 
 | ||
|  | For z < -20 the reflection formula: | ||
|  | 
 | ||
|  | [equation gamm5] | ||
|  | 
 | ||
|  | is used.  Particular care has to be taken to evaluate the [^ z * sin([pi][space] * z)] part:  | ||
|  | a special routine is used to reduce z prior to multiplying by [pi][space] to ensure that the | ||
|  | result in is the range [0, [pi]/2]. Without this an excessive amount of error occurs | ||
|  | in this region (which is hard enough already, as the rate of change near a negative pole | ||
|  | is /exceptionally/ high). | ||
|  | 
 | ||
|  | Finally if the argument is a small integer then table lookup of the factorial | ||
|  | is used. | ||
|  | 
 | ||
|  | The function `tgamma1pm1` is implemented using rational approximations [jm_rationals] in the | ||
|  | region `-0.5 < dz < 2`.  These are the same approximations (and internal routines) | ||
|  | that are used for __lgamma, and so aren't detailed further here.  The result of | ||
|  | the approximation is `log(tgamma(dz+1))` which can fed into __expm1 to give | ||
|  | the desired result.  Outside the range `-0.5 < dz < 2` then the naive formula | ||
|  | `tgamma1pm1(dz) = tgamma(dz+1)-1` can be used directly. | ||
|  | 
 | ||
|  | [endsect][/section:tgamma The Gamma 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). | ||
|  | ] | ||
|  | 
 |