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).
 | |
| ]
 | |
| 
 |