• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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&#xed;n L&#xf3;pez Mu&#xf1;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