Boost logo

Boost :

From: John Moeller (fishcorn_at_[hidden])
Date: 2008-05-15 10:40:30


Hervé Brönnimann <hervebronnimann <at> mac.com> writes:

>
> That would also have been my implementation:
>
> template <int N>
> struct positive_power
> {
> template <typename T>
> static typename tools::promote_args<T>::type result(T base)
> {
> typename tools::promote_args<T>::type power =
> positive_power<N/2>::result(base);
> return (N%2) ? base * power *power : power * power;
> }
> };
>
> with the two specializations:
>
> template <>
> struct positive_power<0>
> {
> template <typename T>
> static typename tools::promote_args<T>::type result(T base)
> {
> return 1;
> }
> };
>
> template <>
> struct positive_power<1>
> {
> template <typename T>
> static typename tools::promote_args<T>::type result(T base)
> {
> return base;
> }
> };
>
> (strictly speaking, <0> only is needed, but the compiler may not
> know to optimize multiplying by T(1), which is one criticism of
> previous post by John Moeller, who proposes essentially the same
> solution but with a factor ((N%2) ? base : 1) that I don't like).

Fair enough. I think, though, if you're going to try to make sure that
the compiler doesn't miss multiplication by 1, you may as well go all the
way and add another template parameter to capture N%2, and get rid of the
ternary statement:

template <int N, int M = N%2>
struct positive_power;

template <int N>
struct positive_power<N, 0>
{
     template <typename T>
     static typename tools::promote_args<T>::type result(T base)
     {
          typename tools::promote_args<T>::type power =
positive_power<N/2,(N/2)%2>::result(base);
          return power * power;
     }
};

template <int N>
struct positive_power<N, 1>
{
     template <typename T>
     static typename tools::promote_args<T>::type result(T base)
     {
          typename tools::promote_args<T>::type power =
positive_power<N/2,(N/2)%2>::result(base);
          return base * power * power;
     }
};

with the two specializations:

template <>
struct positive_power<0,0>
{
     template <typename T>
     static typename tools::promote_args<T>::type result(T base)
     {
          return 1;
     }
};

template <>
struct positive_power<1,1>
{
     template <typename T>
     static typename tools::promote_args<T>::type result(T base)
     {
          return base;
     }
};

Now all the compiler has to do is spit out multiplications, assuming that
things are inlined well.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk