| [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_pomotion_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.main_overview.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). |
| ] |
| |