mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-11-04 05:50:31 -05:00 
			
		
		
		
	
		
			
	
	
		
			158 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			158 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								[section:ct_pow Compile Time Power of a Runtime Base]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The `pow` function effectively computes the compile-time integral 
							 | 
						||
| 
								 | 
							
								power of a run-time base.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[h4 Synopsis]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[@../../../../boost/math/special_functions/pow.hpp `#include <boost/math/special_functions/pow.hpp>`]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    namespace boost { namespace math {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    template <int N, typename T>
							 | 
						||
| 
								 | 
							
								    ``__sf_result`` pow(T base);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    template <int N, typename T, class Policy>
							 | 
						||
| 
								 | 
							
								    ``__sf_result`` pow(T base, const Policy& policy);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    }}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[h4 Rationale and Usage]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Computing the power of a number with an exponent that is known 
							 | 
						||
| 
								 | 
							
								at compile time is a common need for programmers. In such cases, 
							 | 
						||
| 
								 | 
							
								the usual method is to avoid the overhead implied by
							 | 
						||
| 
								 | 
							
								the `pow`, `powf` and `powl` C functions by hardcoding an expression
							 | 
						||
| 
								 | 
							
								such as:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Hand-written 8th power of a 'base' variable
							 | 
						||
| 
								 | 
							
								    double result = base*base*base*base*base*base*base*base;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								However, this kind of expression is not really readable (knowing the 
							 | 
						||
| 
								 | 
							
								value of the exponent involves counting the number of occurrences of /base/), 
							 | 
						||
| 
								 | 
							
								error-prone (it's easy to forget an occurrence), syntactically bulky, and 
							 | 
						||
| 
								 | 
							
								non-optimal in terms of performance.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The pow function of Boost.Math helps writing this kind expression along 
							 | 
						||
| 
								 | 
							
								with solving all the problems listed above:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // 8th power of a 'base' variable using math::pow
							 | 
						||
| 
								 | 
							
								    double result = pow<8>(base);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The expression is now shorter, easier to read, safer, and even faster. 
							 | 
						||
| 
								 | 
							
								Indeed, `pow` will compute the expression such that only log2(N) 
							 | 
						||
| 
								 | 
							
								products are made for a power of N. For instance in the
							 | 
						||
| 
								 | 
							
								example above, the resulting expression will be the same as if we had 
							 | 
						||
| 
								 | 
							
								written this, with only one computation of each identical subexpression:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Internal effect of pow<8>(base)
							 | 
						||
| 
								 | 
							
								    double result = ((base*base)*(base*base))*((base*base)*(base*base));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Only 3 different products were actually computed.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[h4 Return Type]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The return type of these functions is computed using the __arg_promotion_rules. 
							 | 
						||
| 
								 | 
							
								For example:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* If T is a `float`, the return type is a `float`.
							 | 
						||
| 
								 | 
							
								* If T is a `long double`, the return type is a `long double`.
							 | 
						||
| 
								 | 
							
								* Otherwise, the return type is a `double`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[h4 Policies]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[optional_policy]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[h4 Error Handling]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Two cases of errors can occur when using `pow`:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* In case of null base and negative exponent, an __overflow_error occurs since 
							 | 
						||
| 
								 | 
							
								this operation is a division by 0 (it equals to 1/0).
							 | 
						||
| 
								 | 
							
								* In case of null base and null exponent, an __indeterminate_result_error
							 | 
						||
| 
								 | 
							
								occurs since the result of this operation is indeterminate.
							 | 
						||
| 
								 | 
							
								Those errors follow the
							 | 
						||
| 
								 | 
							
								[link math_toolkit.error_handling 
							 | 
						||
| 
								 | 
							
								general policies of error handling in Boost.Math].
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The default overflow error policy is `throw_on_error`. A call like `pow<-2>(0)` 
							 | 
						||
| 
								 | 
							
								will thus throw a `std::overflow_error` exception. As shown in the 
							 | 
						||
| 
								 | 
							
								link given above, other error handling policies can be used:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* `errno_on_error`: Sets `::errno`  to `ERANGE` and returns `std::numeric_limits<T>::infinity()`.
							 | 
						||
| 
								 | 
							
								* `ignore_error`: Returns `std::numeric_limits<T>::infinity()`.
							 | 
						||
| 
								 | 
							
								* `user_error`: Returns the result of `boost::math::policies::user_overflow_error`: 
							 | 
						||
| 
								 | 
							
								   this function must be defined by the user.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The default indeterminate result error policy is `ignore_error`, which for this
							 | 
						||
| 
								 | 
							
								function returns 1 since it's the most commonly chosen result for a power of 0.
							 | 
						||
| 
								 | 
							
								Here again, other error handling policies can be used:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* `throw_on_error`: Throws `std::domain_error`
							 | 
						||
| 
								 | 
							
								* `errno_on_error`: Sets `::errno`  to `EDOM` and returns 1.
							 | 
						||
| 
								 | 
							
								* `user_error`: Returns the result of `boost::math::policies::user_indeterminate_result_error`:
							 | 
						||
| 
								 | 
							
								   this function must be defined by the user.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Here is an example of error handling customization where we want to 
							 | 
						||
| 
								 | 
							
								specify the result that has to be returned in case of error. We will 
							 | 
						||
| 
								 | 
							
								thus use the `user_error` policy, by passing as second argument an 
							 | 
						||
| 
								 | 
							
								instance of an overflow_error policy templated with `user_error`:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // First we open the boost::math::policies namespace and define the `user_overflow_error`
							 | 
						||
| 
								 | 
							
								    // by making it return the value we want in case of error (-1 here)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    namespace boost { namespace math { namespace policies {
							 | 
						||
| 
								 | 
							
								    template <class T>
							 | 
						||
| 
								 | 
							
								    T user_overflow_error(const char*, const char*, const T&)
							 | 
						||
| 
								 | 
							
								    { return -1; }
							 | 
						||
| 
								 | 
							
								    }}}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Then we invoke pow and indicate that we want to use the user_error policy
							 | 
						||
| 
								 | 
							
								    using boost::math::policies;
							 | 
						||
| 
								 | 
							
								    double result = pow<-5>(base, policy<overflow_error<user_error> >());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // We can now test the returned value and treat the special case if needed:
							 | 
						||
| 
								 | 
							
								    if (result == -1)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        // there was an error, do something...
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Another way is to redefine the default `overflow_error` policy by using the
							 | 
						||
| 
								 | 
							
								BOOST_MATH_OVERFLOW_ERROR_POLICY macro. Once the `user_overflow_error` function 
							 | 
						||
| 
								 | 
							
								is defined as above, we can achieve the same result like this:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Redefine the default error_overflow policy
							 | 
						||
| 
								 | 
							
								    #define BOOST_MATH_OVERFLOW_ERROR_POLICY user_error
							 | 
						||
| 
								 | 
							
								    #include <boost/math/special_functions/pow.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // From this point, passing a policy in argument is no longer needed, a call like this one
							 | 
						||
| 
								 | 
							
								    // will return -1 in case of error:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    double result = pow<-5>(base);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[h4 Acknowledgements]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Bruno Lalande submitted this addition to Boost.Math.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								'''
							 | 
						||
| 
								 | 
							
								Thanks to Joaquín López Muñoz and Scott McMurray for their help in
							 | 
						||
| 
								 | 
							
								improving the implementation.
							 | 
						||
| 
								 | 
							
								'''
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[h4 References]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								D.E. Knuth, ['The Art of Computer Programming, Vol. 2: Seminumerical Algorithms], 2nd ed., Addison-Wesley, Reading, MA, 1981
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[endsect]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[/ 
							 | 
						||
| 
								 | 
							
								  Copyright 2008 Bruno Lalande.
							 | 
						||
| 
								 | 
							
								  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).
							 | 
						||
| 
								 | 
							
								]
							 | 
						||
| 
								 | 
							
								
							 |