Skip to content

Instantly share code, notes, and snippets.

@MaxXSoft
Last active November 16, 2018 00:59
Show Gist options
  • Save MaxXSoft/45ca7d0266c7c16e30129f24d228fc05 to your computer and use it in GitHub Desktop.
Save MaxXSoft/45ca7d0266c7c16e30129f24d228fc05 to your computer and use it in GitHub Desktop.
Generate an array containing the first 1000 terms of Fibonacci sequence, at compile time.
#include <iostream>
#include <utility>
#include <type_traits>
#include <cstdint>
#include <cstddef>
using namespace std;
// compile time string
template <char c, size_t n, char ...suffix>
struct CharRepeat : public CharRepeat<c, n - 1, c, suffix...> {};
template <char c, char ...suffix>
struct CharRepeat<c, 0, suffix...> {
static constexpr const char value[] = {suffix..., '\0'};
};
template <uint64_t num, uint64_t ...digits>
struct IntToString : public IntToString<num / 10, num % 10, digits...> {};
template <uint64_t ...digits>
struct IntToString<0, digits...> {
static constexpr const char value[] = {('0' + digits)..., '\0'};
};
constexpr size_t StringSize(const char *str) {
int i = 0;
while (*str++) ++i;
return i;
}
template <const char *s1, typename T1, const char *s2, typename T2>
struct StrConcatImpl;
template <const char *s1, size_t ...i1, const char *s2, size_t ...i2>
struct StrConcatImpl<s1, index_sequence<i1...>, s2, index_sequence<i2...>> {
static constexpr const char value[] = {s1[i1]..., s2[i2]..., '\0'};
};
template <const char *s1, const char *s2>
using StringConcat = StrConcatImpl<
s1, make_index_sequence<StringSize(s1)>,
s2, make_index_sequence<StringSize(s2)>
>;
// single digit
constexpr uint64_t kDigitLimit = 1e18;
constexpr uint64_t kDigitLen = 18;
template <uint64_t n, typename T>
struct Digit;
using ZeroDigit = Digit<0, nullptr_t>;
template <uint64_t n, typename T = ZeroDigit>
struct Digit {
public:
static_assert(n < kDigitLimit, "input parameter n is too big");
static constexpr uint64_t digit = n;
static constexpr uint64_t length = T::length + 1;
private:
using DigitString = IntToString<digit>;
using ExtendedString = StringConcat<
CharRepeat<'0', kDigitLen - StringSize(DigitString::value)>::value,
DigitString::value
>;
using FinalString = typename conditional<
is_same<T, ZeroDigit>{}(), DigitString, ExtendedString
>::type;
public:
static constexpr auto str = StringConcat<
T::str, FinalString::value
>::value;
};
template <>
struct Digit<0, nullptr_t> {
static constexpr uint64_t digit = 0;
static constexpr uint64_t length = 0;
static constexpr const char str[] = "";
};
// addition
template <typename A, typename B>
struct Sum;
template <>
struct Sum<ZeroDigit, ZeroDigit> {
using Result = ZeroDigit;
static constexpr uint64_t carry = 0;
};
template <uint64_t n, typename T>
struct Sum<ZeroDigit, Digit<n, T>> {
using Result = Digit<n, T>;
static constexpr uint64_t carry = 0;
};
template <uint64_t n, typename T>
struct Sum<Digit<n, T>, ZeroDigit> {
using Result = Digit<n, T>;
static constexpr uint64_t carry = 0;
};
template <uint64_t a, uint64_t b, typename Ta, typename Tb>
struct Sum<Digit<a, Ta>, Digit<b, Tb>> {
static constexpr uint64_t carry = a + b >= kDigitLimit ?
(a + b) / kDigitLimit : 0;
using Result = Digit<(a + b) % kDigitLimit,
typename Sum<
typename Sum<Ta, Tb>::Result,
typename conditional<carry == 0, ZeroDigit, Digit<carry>>::type
>::Result
>;
};
// fibonacci
template <uint64_t n>
struct Fib {
using Result = typename Sum<
typename Fib<n - 1>::Result, typename Fib<n - 2>::Result
>::Result;
};
template <>
struct Fib<1> {
using Result = Digit<1>;
};
template <>
struct Fib<2> {
using Result = Digit<1>;
};
template <uint64_t ...i>
using IntSeq = integer_sequence<uint64_t, i...>;
template <uint64_t n>
using MakeIntSeq = make_integer_sequence<uint64_t, n>;
template <typename T>
struct FibListImpl;
template <uint64_t ...n>
struct FibListImpl<IntSeq<n...>> {
static constexpr const char *fib_list[] = {(Fib<n + 1>::Result::str)...};
};
template <uint64_t len>
using FibList = FibListImpl<MakeIntSeq<len>>;
// main procedure
int main(int argc, const char *argv[]) {
constexpr auto fib_list = FibList<1000>::fib_list;
int i;
while (cin >> i) {
cout << fib_list[i] << endl;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment