Program Listing for File meta_pow.hpp#

↰ Return to documentation for file (source/pele/meta_pow.hpp)

#ifndef _PELE_META_POW_H
#define _PELE_META_POW_H

/*
 *Usage: For integer (negative integer powers), one obtains x ^ N.
 *For half-integer (negative half-integer powers), one obtains sqrt(x ^ N).
 *Example: pos_int_pow<2>(x) is x ^ 2; neg_half_int_pow<5>(x) is x ^ (-2.5).
 *References:
 *Used here: general reference on template meta-programming and recursive
 *template functions:
 *http://www.itp.phys.ethz.ch/education/hs12/programming_techniques
 *Also used here: reference on template meta-programming power function:
 *http://stackoverflow.com/questions/16443682/c-power-of-integer-template-meta-programming
 **/

#include <cmath>        //for sqrt in half powers
#include <type_traits>  //for static asserts

namespace pele {

template <class T, int N>
struct meta_pow {
  static T f(const T x) { return meta_pow<T, N - 1>::f(x) * x; }
};

template <class T>
struct meta_pow<T, 12> {
  static T f(const T x) {
    T x4 = meta_pow<T, 4>::f(x);
    return x4 * x4 * x4;
  }
};

template <class T>
struct meta_pow<T, 10> {
  static T f(const T x) {
    T x5 = meta_pow<T, 5>::f(x);
    return x5 * x5;
  }
};

template <class T>
struct meta_pow<T, 9> {
  static T f(const T x) {
    T x3 = x * x * x;
    return x3 * x3 * x3;
  }
};

template <class T>
struct meta_pow<T, 8> {
  static T f(const T x) {
    T x4 = meta_pow<T, 4>::f(x);
    return x4 * x4;
  }
};

template <class T>
struct meta_pow<T, 6> {
  static T f(const T x) {
    T x3 = x * x * x;
    return x3 * x3;
  }
};

template <class T>
struct meta_pow<T, 4> {
  static T f(const T x) {
    T x2 = x * x;
    return x2 * x2;
  }
};

template <class T>
struct meta_pow<T, 0> {
  static T f(const T x) { return T(1); }
};

template <int N, class T>
inline T pos_int_pow(const T x) {
  static_assert(N >= 0, "illegal exponent input");
  return meta_pow<T, N>::f(x);
}

template <int N, class T>
inline T neg_int_pow(const T x) {
  static_assert(N <= 0, "illegal exponent input");
  return T(1) / meta_pow<T, -N>::f(x);
}

template <int N, class T>
inline T pos_half_int_pow(const T x) {
  static_assert(N >= 0, "illegal exponent input");
  return std::sqrt(meta_pow<T, N>::f(x));
}

template <int N, class T>
inline T neg_half_int_pow(const T x) {
  static_assert(N <= 0, "illegal exponent input");
  return T(1) / std::sqrt(meta_pow<T, -N>::f(x));
}

}  // namespace pele

#endif  //#ifndef _PELE_META_POW_H