Skip to content

Instantly share code, notes, and snippets.

@plasma-effect
Created November 15, 2016 14:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save plasma-effect/655c79d850f406fe0863b37b33ef661b to your computer and use it in GitHub Desktop.
Save plasma-effect/655c79d850f406fe0863b37b33ef661b to your computer and use it in GitHub Desktop.
ジャパニーズなかなか迷惑コード(TMPエラトステネス)
#include<iostream>
#include<type_traits>
#include<utility>
#include<functional>
namespace eratosthenes
{
template<std::size_t I, class Sequence>struct add;
template<std::size_t I, std::size_t... Is>struct add<I, std::index_sequence<Is...>>
{
typedef std::index_sequence<(I + Is)...> type;
};
constexpr std::size_t log2(std::size_t i)
{
return i == 0 ? 0 : i == 1 ? 0 : 1 + log2(i / 2);
}
template<std::size_t I, std::size_t S, bool, std::size_t U, std::size_t... Is>
struct make_sequence_i
{
typedef typename make_sequence_i<I%S, S / 2, I&S, 2 * U, Is..., (Is + U)...>::type type;
};
template<std::size_t I, std::size_t S, std::size_t U, std::size_t... Is>
struct make_sequence_i<I, S, true, U, Is...>
{
typedef typename make_sequence_i<I%S, S / 2, I&S, 2 * U + 1, Is..., (Is + U)..., 2 * U>::type type;
};
template<std::size_t U, std::size_t... Is>
struct make_sequence_i<0, 0, false, U, Is...>
{
typedef std::index_sequence<Is..., (Is + U)...> type;
};
template<std::size_t U, std::size_t... Is>
struct make_sequence_i<0, 0, true, U, Is...>
{
typedef std::index_sequence<Is..., (Is + U)..., 2 * U> type;
};
template<std::size_t Size>struct make_index_sequence
{
static constexpr auto val = 1 << log2(Size);
typedef typename make_sequence_i<Size % val, val / 2, Size&val, 0>::type type;
};
template<std::size_t Start, std::size_t End>struct make_range_sequence
{
typedef typename add<Start, typename make_index_sequence<End - Start + 1>::type>::type type;
};
template<std::size_t I, std::size_t B, bool, class Sequence,std::size_t... Rs>struct filter_i;
template<std::size_t I,std::size_t B,std::size_t T,std::size_t... Is,std::size_t... Rs>
struct filter_i<I, B, true, std::index_sequence<T, Is...>, Rs...>
{
typedef typename filter_i<I, T, T%I == 0, std::index_sequence<Is...>, Rs...>::type type;
};
template<std::size_t I, std::size_t B, std::size_t T, std::size_t... Is, std::size_t... Rs>
struct filter_i<I, B, false, std::index_sequence<T, Is...>, Rs...>
{
typedef typename filter_i<I, T, T%I == 0, std::index_sequence<Is...>, Rs..., B>::type type;
};
template<std::size_t I, std::size_t B, std::size_t... Rs>
struct filter_i<I, B, true, std::index_sequence<>, Rs...>
{
typedef std::index_sequence<Rs...> type;
};
template<std::size_t I, std::size_t B, std::size_t... Rs>
struct filter_i<I, B, false, std::index_sequence<>, Rs... >
{
typedef std::index_sequence<Rs..., B> type;
};
template<std::size_t I, class Sequence>struct filter;
template<std::size_t I, std::size_t T, std::size_t... Is>struct filter<I, std::index_sequence<T, Is...>>
{
typedef typename filter_i<I, T, T%I == 0, std::index_sequence<Is...>>::type type;
};
template<std::size_t I>struct filter<I, std::index_sequence<>>
{
typedef std::index_sequence<> type;
};
template<std::size_t I, class Sequence>using filter_t = typename filter<I, Sequence>::type;
template<class...>struct tuple {};
template<std::size_t Now, std::size_t End, std::size_t Rest, class... Ts>struct make_sequence_tuple_i
{
static constexpr auto val = Now + (End - Now) / Rest;
typedef typename make_sequence_tuple_i<val + 1, End, Rest - 1, Ts..., typename make_range_sequence<Now, val>::type>::type type;
};
template<std::size_t Now, std::size_t End, class... Ts>struct make_sequence_tuple_i<Now, End, 0, Ts...>
{
typedef tuple<Ts...> type;
};
constexpr std::size_t twice(std::size_t i)
{
return i*i;
}
constexpr std::size_t sqrt_i(std::size_t val, std::size_t min, std::size_t max)
{
return max - min <= 1 ? min :
twice((min + max) / 2) <= val ?
sqrt_i(val, (min + max) / 2, max) :
sqrt_i(val, min, (min + max) / 2);
}
constexpr std::size_t sqrt(std::size_t val)
{
return val == 0 ? 0 : val == 1 ? 1 : sqrt_i(val, 1, val);
}
template<std::size_t Start, std::size_t End>struct make_sequence_tuple
{
typedef typename make_sequence_tuple_i<Start, End, sqrt(End - Start)>::type type;
};
template<class Tuple, std::size_t...>struct sieve;
template<std::size_t... Us, class... Ts>
struct sieve<tuple<std::index_sequence<>, Ts...>, Us...>
{
typedef tuple<std::index_sequence<Us...>, tuple<Ts...>> type;
};
template<std::size_t T,std::size_t... Is,std::size_t... Us,class... Ts>
struct sieve<tuple<std::index_sequence<T, Is...>, Ts...>, Us...>
{
typedef typename sieve<tuple<typename filter<T, std::index_sequence<Is...>>::type,filter_t<T, Ts>...>, Us..., T>::type type;
};
template<class Tuple>struct projection1;
template<class T, class... Ts>struct projection1<tuple<T, Ts...>>
{
typedef T type;
};
template<class Tuple>struct projection2;
template<class U, class T, class... Ts>struct projection2<tuple<U, T, Ts...>>
{
typedef T type;
};
template<class Tuple, class... Ts>struct sieve2
{
typedef typename sieve<Tuple>::type first;
typedef typename sieve2<typename projection2<first>::type, Ts..., typename projection1<first>::type>::type type;
};
template<class... Ts>struct sieve2<tuple<>, Ts...>
{
typedef tuple<Ts...> type;
};
template<class Tuple,std::size_t...>struct sequence_merge;
template<std::size_t... Is, class... Ts, std::size_t... Us>struct sequence_merge<tuple<std::index_sequence<Is...>, Ts...>, Us...>
{
typedef typename sequence_merge<tuple<Ts...>, Us..., Is...>::type type;
};
template<std::size_t... Is>struct sequence_merge<tuple<>, Is...>
{
typedef std::index_sequence<Is...> type;
};
template<std::size_t Max>struct prime_sequence
{
typedef
typename sequence_merge<
typename sieve2<
typename make_sequence_tuple<2, Max>::type>::type>::type type;
};
}
int main()
{
typedef eratosthenes::prime_sequence<10000>::type primes;
std::cout << typeid(primes).name() << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment