mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-11-03 21:40:52 -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).
 | 
						|
]
 | 
						|
 |