mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-10-25 01:50:30 -04: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). | ||
|  | ] | ||
|  | 
 |