mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-11-03 13:30:52 -05:00 
			
		
		
		
	
		
			
	
	
		
			218 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			218 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								[section:expint Exponential Integrals]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[section:expint_n Exponential Integral En]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[h4 Synopsis]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								``
							 | 
						||
| 
								 | 
							
								#include <boost/math/special_functions/expint.hpp>
							 | 
						||
| 
								 | 
							
								``
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   namespace boost{ namespace math{
							 | 
						||
| 
								 | 
							
								   
							 | 
						||
| 
								 | 
							
								   template <class T>
							 | 
						||
| 
								 | 
							
								   ``__sf_result`` expint(unsigned n, T z);
							 | 
						||
| 
								 | 
							
								   
							 | 
						||
| 
								 | 
							
								   template <class T, class ``__Policy``>
							 | 
						||
| 
								 | 
							
								   ``__sf_result`` expint(unsigned n, T z, const ``__Policy``&);
							 | 
						||
| 
								 | 
							
								   
							 | 
						||
| 
								 | 
							
								   }} // namespaces
							 | 
						||
| 
								 | 
							
								   
							 | 
						||
| 
								 | 
							
								The return type of these functions is computed using the __arg_promotion_rules:
							 | 
						||
| 
								 | 
							
								the return type is `double` if T is an integer type, and T otherwise.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[optional_policy]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[h4 Description]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   template <class T>
							 | 
						||
| 
								 | 
							
								   ``__sf_result`` expint(unsigned n, T z);
							 | 
						||
| 
								 | 
							
								   
							 | 
						||
| 
								 | 
							
								   template <class T, class ``__Policy``>
							 | 
						||
| 
								 | 
							
								   ``__sf_result`` expint(unsigned n, T z, const ``__Policy``&);
							 | 
						||
| 
								 | 
							
								   
							 | 
						||
| 
								 | 
							
								Returns the [@http://mathworld.wolfram.com/En-Function.html exponential integral En]
							 | 
						||
| 
								 | 
							
								of z:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[equation expint_n_1]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[graph expint2]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[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 libraries.
							 | 
						||
| 
								 | 
							
								Unless otherwise specified any floating point type that is narrower
							 | 
						||
| 
								 | 
							
								than the one shown will have __zero_error.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[table_expint_En_]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[h4 Testing]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The tests for these functions come in two parts:
							 | 
						||
| 
								 | 
							
								basic sanity checks use spot values calculated using
							 | 
						||
| 
								 | 
							
								[@http://functions.wolfram.com/webMathematica/FunctionEvaluation.jsp?name=ExpIntegralE Mathworld's online evaluator],
							 | 
						||
| 
								 | 
							
								while accuracy checks use high-precision test values calculated at 1000-bit precision with
							 | 
						||
| 
								 | 
							
								[@http://shoup.net/ntl/doc/RR.txt NTL::RR] and this implementation. 
							 | 
						||
| 
								 | 
							
								Note that the generic and type-specific
							 | 
						||
| 
								 | 
							
								versions of these functions use differing implementations internally, so this
							 | 
						||
| 
								 | 
							
								gives us reasonably independent test data.  Using our test data to test other
							 | 
						||
| 
								 | 
							
								"known good" implementations also provides an additional sanity check. 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[h4 Implementation]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The generic version of this function uses the continued fraction:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[equation expint_n_3]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								for large /x/ and the infinite series:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[equation expint_n_2]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								for small /x/.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Where the precision of /x/ is known at compile time and is 113 bits or fewer
							 | 
						||
| 
								 | 
							
								in precision, then rational approximations [jm_rationals] are used for the 
							 | 
						||
| 
								 | 
							
								`n == 1` case.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								For `x < 1` the approximating form is a minimax approximation:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[equation expint_n_4]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								and for `x > 1` a Chebyshev interpolated approximation of the form:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[equation expint_n_5]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								is used.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[endsect]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[section:expint_i Exponential Integral Ei]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[h4 Synopsis]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								``
							 | 
						||
| 
								 | 
							
								#include <boost/math/special_functions/expint.hpp>
							 | 
						||
| 
								 | 
							
								``
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   namespace boost{ namespace math{
							 | 
						||
| 
								 | 
							
								   
							 | 
						||
| 
								 | 
							
								   template <class T>
							 | 
						||
| 
								 | 
							
								   ``__sf_result`` expint(T z);
							 | 
						||
| 
								 | 
							
								   
							 | 
						||
| 
								 | 
							
								   template <class T, class ``__Policy``>
							 | 
						||
| 
								 | 
							
								   ``__sf_result`` expint(T z, const ``__Policy``&);
							 | 
						||
| 
								 | 
							
								   
							 | 
						||
| 
								 | 
							
								   }} // namespaces
							 | 
						||
| 
								 | 
							
								   
							 | 
						||
| 
								 | 
							
								The return type of these functions is computed using the __arg_promotion_rules:
							 | 
						||
| 
								 | 
							
								the return type is `double` if T is an integer type, and T otherwise.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[optional_policy]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[h4 Description]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   template <class T>
							 | 
						||
| 
								 | 
							
								   ``__sf_result`` expint(T z);
							 | 
						||
| 
								 | 
							
								   
							 | 
						||
| 
								 | 
							
								   template <class T, class ``__Policy``>
							 | 
						||
| 
								 | 
							
								   ``__sf_result`` expint(T z, const ``__Policy``&);
							 | 
						||
| 
								 | 
							
								   
							 | 
						||
| 
								 | 
							
								Returns the [@http://mathworld.wolfram.com/ExponentialIntegral.html exponential integral]
							 | 
						||
| 
								 | 
							
								of z:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[equation expint_i_1]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[graph expint_i]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[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 Cody's SPECFUN implementation and the __gsl library.
							 | 
						||
| 
								 | 
							
								Unless otherwise specified any floating point type that is narrower
							 | 
						||
| 
								 | 
							
								than the one shown will have __zero_error.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[table_expint_Ei_]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								It should be noted that all three libraries tested above 
							 | 
						||
| 
								 | 
							
								offer sub-epsilon precision over most of their range.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								GSL has the greatest difficulty near the positive root of En, while
							 | 
						||
| 
								 | 
							
								Cody's SPECFUN along with this implementation increase their
							 | 
						||
| 
								 | 
							
								error rates very slightly over the range \[4,6\].
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[h4 Testing]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The tests for these functions come in two parts:
							 | 
						||
| 
								 | 
							
								basic sanity checks use spot values calculated using
							 | 
						||
| 
								 | 
							
								[@http://functions.wolfram.com/webMathematica/FunctionEvaluation.jsp?name=ExpIntegralEi Mathworld's online evaluator],
							 | 
						||
| 
								 | 
							
								while accuracy checks use high-precision test values calculated at 1000-bit precision with
							 | 
						||
| 
								 | 
							
								[@http://shoup.net/ntl/doc/RR.txt NTL::RR] and this implementation. 
							 | 
						||
| 
								 | 
							
								Note that the generic and type-specific
							 | 
						||
| 
								 | 
							
								versions of these functions use differing implementations internally, so this
							 | 
						||
| 
								 | 
							
								gives us reasonably independent test data.  Using our test data to test other
							 | 
						||
| 
								 | 
							
								"known good" implementations also provides an additional sanity check. 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[h4 Implementation]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								For x < 0 this function just calls __expint_n(1, -x): which in turn is implemented
							 | 
						||
| 
								 | 
							
								in terms of rational approximations when the type of x has 113 or fewer bits of
							 | 
						||
| 
								 | 
							
								precision.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								For x > 0 the generic version is implemented using the infinte series:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[equation expint_i_2]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								However, when the precision of the argument type is known at compile time
							 | 
						||
| 
								 | 
							
								and is 113 bits or less, then rational approximations [jm_rationals] are used.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								For 0 < z < 6 a root-preserving approximation of the form:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[equation expint_i_3]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								is used, where z[sub 0] is the positive root of the function, and
							 | 
						||
| 
								 | 
							
								R(z/3 - 1) is a minimax rational approximation rescaled so that
							 | 
						||
| 
								 | 
							
								it is evaluated over \[-1,1\].  Note that while the rational approximation
							 | 
						||
| 
								 | 
							
								over \[0,6\] converges rapidly to the minimax solution it is rather
							 | 
						||
| 
								 | 
							
								ill-conditioned in practice.  Cody and Thacher
							 | 
						||
| 
								 | 
							
								[footnote W. J. Cody and H. C. Thacher, Jr., 
							 | 
						||
| 
								 | 
							
								Rational Chebyshev approximations for the exponential integral E[sub 1](x), 
							 | 
						||
| 
								 | 
							
								Math. Comp. 22 (1968), 641-649,
							 | 
						||
| 
								 | 
							
								and W. J. Cody and H. C. Thacher, Jr., Chebyshev approximations for the 
							 | 
						||
| 
								 | 
							
								exponential integral Ei(x), Math. Comp. 23 (1969), 289-303.]
							 | 
						||
| 
								 | 
							
								experienced the same issue and 
							 | 
						||
| 
								 | 
							
								converted the polynomials into Chebeshev form to ensure stable
							 | 
						||
| 
								 | 
							
								computation.  By experiment we found that the polynomials are just as stable
							 | 
						||
| 
								 | 
							
								in polynomial as Chebyshev form, /provided/ they are computed
							 | 
						||
| 
								 | 
							
								over the interval \[-1,1\].
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Over the a series of intervals [a,b] and [b,INF] the rational approximation
							 | 
						||
| 
								 | 
							
								takes the form:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[equation expint_i_4]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								where /c/ is a constant, and R(t) is a minimax solution optimised for low
							 | 
						||
| 
								 | 
							
								absolute error compared to /c/.  Variable /t/ is `1/z` when the range in infinite
							 | 
						||
| 
								 | 
							
								and `2z/(b-a) - (2a/(b-a) + 1)` otherwise: this has the effect of scaling z to the 
							 | 
						||
| 
								 | 
							
								interval \[-1,1\].  As before rational approximations over arbitrary intervals
							 | 
						||
| 
								 | 
							
								were found to be ill-conditioned: Cody and Thacher solved this issue by 
							 | 
						||
| 
								 | 
							
								converting the polynomials to their J-Fraction equivalent.  However, as long
							 | 
						||
| 
								 | 
							
								as the interval of evaluation was \[-1,1\] and the number of terms carefully chosen,
							 | 
						||
| 
								 | 
							
								it was found that the polynomials /could/ be evaluated to suitable precision:
							 | 
						||
| 
								 | 
							
								error rates are typically 2 to 3 epsilon which is comparible to the error
							 | 
						||
| 
								 | 
							
								rate that Cody and Thacher achieved using J-Fractions, but marginally more
							 | 
						||
| 
								 | 
							
								efficient given that fewer divisions are involved.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[endsect]
							 | 
						||
| 
								 | 
							
								[endsect]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[/ 
							 | 
						||
| 
								 | 
							
								  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).
							 | 
						||
| 
								 | 
							
								]
							 |