如何在编译时计算mersenne数

时间:2016-07-15 18:29:16

标签: c++ c++11 constexpr

注意: 此Q& A与Mersenne twister无关,但Mersenne numbers

我想在编译时计算一个大小为N的数组,其中包含 n 中的Mersenne素数(2 n - 1) [0,N - 1]。

template <std::uint8_t N>
static constexpr std::array<std::uint16_t, N> mersenne_numbers()
{

    // Compute Mersenne numbers for N, N-1 ... 1 and return the array
    return { 1, 2, 3 };
};

int main()
{
    constexpr std::array<std::uint16_t, 5> arr = mersenne_numbers<5>();
}

我该如何实现?

3 个答案:

答案 0 :(得分:2)

因此,要在编译时计算(2 ^ n - 1)数组,您可以

template <std::size_t ... Is>
constexpr std::array<std::uint16_t, sizeof...(Is)>
mersenne_numbers(std::index_sequence<Is...>)
{
    return {{ ((1u << Is) - 1u)... }};
}

template <std::uint8_t N>
constexpr std::array<std::uint16_t, N>
mersenne_numbers()
{
    return mersenne_numbers(std::make_index_sequence<N>{});
}

Demo

index_sequence内容的实现可以在c ++ 11中完成,并且很容易在SO上找到。

甚至在c ++ 14中

template <std::uint8_t N>
constexpr std::array<std::uint16_t, N> mersenne_numbers()
{
    std::array<std::uint16_t, N> res{};
    for (uint i = 0; i != N; ++i)
    {
        res [i] = (1u << i) - 1;
    }
    return res;
}

Demo

答案 1 :(得分:0)

使用C ++ 14:

#include <iostream>
#include <array>
#include <type_traits>

constexpr int cpow2(int n) {
  return n == 0 ? 1 : 2 * cpow2(n-1);
}

template <size_t... Seq>
static constexpr std::array<size_t, sizeof...(Seq)> mersenne_numbers(std::index_sequence<Seq...> isq)
{
  return {(cpow2(Seq)-1)...};
}


int main() {
  static_assert (cpow2(4) == 16, "");
  auto arr = mersenne_numbers(std::make_index_sequence<5>());
  for (auto e : arr) std::cout << e << " ";
  std::cout << std::endl;
  return 0;
}

之间,@ Jarod42实现优于此。

答案 2 :(得分:0)

不太了解marsenne数字,但你总是可以修改这个例子 (计算x^x):

template <std::uint8_t N>
constexpr std::array<std::uint64_t, N> power_one
    (std::array<std::uint64_t, N> arr,
     const uint8_t num)
{
    arr[num] = static_cast<uint64_t>(std::pow(num, num));
    return arr;
}

template <std::uint8_t N>
constexpr std::array<std::uint64_t, N> self_powered
(std::array<std::uint64_t, N> arr = std::array<std::uint64_t, N>{0},
     const uint8_t step = 0)
{
    return step>=N? arr : self_powered(power_one(arr, step), step + 1);
}

s32 main()
{
    auto arr = self_powered<10>();
    for(auto& x : arr)
    {
        std::cout << x << std::endl;
    }
}