1[section:ct_pow Compile Time Power of a Runtime Base] 2 3The `pow` function effectively computes the compile-time integral 4power of a run-time base. 5 6[h4 Synopsis] 7 8[@../../../../boost/math/special_functions/pow.hpp `#include <boost/math/special_functions/pow.hpp>`] 9 10 namespace boost { namespace math { 11 12 template <int N, typename T> 13 ``__sf_result`` pow(T base); 14 15 template <int N, typename T, class Policy> 16 ``__sf_result`` pow(T base, const Policy& policy); 17 18 }} 19 20[h4 Rationale and Usage] 21 22Computing the power of a number with an exponent that is known 23at compile time is a common need for programmers. In such cases, 24the usual method is to avoid the overhead implied by 25the `pow`, `powf` and `powl` C functions by hardcoding an expression 26such as: 27 28 // Hand-written 8th power of a 'base' variable 29 double result = base*base*base*base*base*base*base*base; 30 31However, this kind of expression is not really readable (knowing the 32value of the exponent involves counting the number of occurrences of /base/), 33error-prone (it's easy to forget an occurrence), syntactically bulky, and 34non-optimal in terms of performance. 35 36The `pow` function of Boost.Math helps writing this kind expression along 37with solving all the problems listed above: 38 39 // 8th power of a 'base' variable using math::pow 40 double result = pow<8>(base); 41 42The expression is now shorter, easier to read, safer, and even faster. 43Indeed, `pow` will compute the expression such that only log2(N) 44products are made for a power of N. For instance in the 45example above, the resulting expression will be the same as if we had 46written this, with only one computation of each identical subexpression: 47 48 // Internal effect of pow<8>(base) 49 double result = ((base*base)*(base*base))*((base*base)*(base*base)); 50 51Only 3 different products were actually computed. 52 53 54[h4 Return Type] 55 56The return type of these functions is computed using the __arg_promotion_rules. 57For example: 58 59* If T is a `float`, the return type is a `float`. 60* If T is a `long double`, the return type is a `long double`. 61* Otherwise, the return type is a `double`. 62 63[h4 Policies] 64 65[optional_policy] 66 67[h4 Error Handling] 68 69Two cases of errors can occur when using `pow`: 70 71* In case of null base and negative exponent, an __overflow_error occurs since 72this operation is a division by 0 (it equals to 1/0). 73* In case of null base and null exponent, an __indeterminate_result_error 74occurs since the result of this operation is indeterminate. 75Those errors follow the 76[link math_toolkit.error_handling 77general policies of error handling in Boost.Math]. 78 79The default overflow error policy is `throw_on_error`. A call like `pow<-2>(0)` 80will thus throw a `std::overflow_error` exception. As shown in the 81link given above, other error handling policies can be used: 82 83* `errno_on_error`: Sets `::errno` to `ERANGE` and returns `std::numeric_limits<T>::infinity()`. 84* `ignore_error`: Returns `std::numeric_limits<T>::infinity()`. 85* `user_error`: Returns the result of `boost::math::policies::user_overflow_error`: 86 this function must be defined by the user. 87 88The default indeterminate result error policy is `ignore_error`, which for this 89function returns 1 since it's the most commonly chosen result for a power of 0. 90Here again, other error handling policies can be used: 91 92* `throw_on_error`: Throws `std::domain_error` 93* `errno_on_error`: Sets `::errno` to `EDOM` and returns 1. 94* `user_error`: Returns the result of `boost::math::policies::user_indeterminate_result_error`: 95 this function must be defined by the user. 96 97Here is an example of error handling customization where we want to 98specify the result that has to be returned in case of error. We will 99thus use the `user_error` policy, by passing as second argument an 100instance of an overflow_error policy templated with `user_error`: 101 102 // First we open the boost::math::policies namespace and define the `user_overflow_error` 103 // by making it return the value we want in case of error (-1 here) 104 105 namespace boost { namespace math { namespace policies { 106 template <class T> 107 T user_overflow_error(const char*, const char*, const T&) 108 { return -1; } 109 }}} 110 111 112 // Then we invoke pow and indicate that we want to use the user_error policy 113 using boost::math::policies; 114 double result = pow<-5>(base, policy<overflow_error<user_error> >()); 115 116 // We can now test the returned value and treat the special case if needed: 117 if (result == -1) 118 { 119 // there was an error, do something... 120 } 121 122Another way is to redefine the default `overflow_error` policy by using the 123BOOST_MATH_OVERFLOW_ERROR_POLICY macro. Once the `user_overflow_error` function 124is defined as above, we can achieve the same result like this: 125 126 // Redefine the default error_overflow policy 127 #define BOOST_MATH_OVERFLOW_ERROR_POLICY user_error 128 #include <boost/math/special_functions/pow.hpp> 129 130 // From this point, passing a policy in argument is no longer needed, a call like this one 131 // will return -1 in case of error: 132 133 double result = pow<-5>(base); 134 135[h4 Acknowledgements] 136 137Bruno Lalande submitted this addition to Boost.Math. 138 139''' 140Thanks to Joaquín López Muñoz and Scott McMurray for their help in 141improving the implementation. 142''' 143 144[h4 References] 145 146D.E. Knuth, ['The Art of Computer Programming, Vol. 2: Seminumerical Algorithms], 2nd ed., Addison-Wesley, Reading, MA, 1981 147 148[endsect] [/section:ct_pow Compile Time Power of a Runtime Base] 149 150 151[/ 152 Copyright 2008 Bruno Lalande. 153 Distributed under the Boost Software License, Version 1.0. 154 (See accompanying file LICENSE_1_0.txt or copy at 155 http://www.boost.org/LICENSE_1_0.txt). 156] 157 158