Last active
July 1, 2020 04:10
-
-
Save ntabee/37a1995c54fb54cef949 to your computer and use it in GitHub Desktop.
Compile-time pseudo-random generator for C++, a la http://www.researchgate.net/profile/Zalan_Szgyi/publication/259005783_Random_number_generator_for_C_template_metaprograms/links/00b49529b48272c5a6000000.pdf ref: http://qiita.com/ntabee/items/c7ae21086d91514798cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <array> | |
#include <iostream> | |
#include "tempra.hpp" | |
template<unsigned n, typename R> | |
struct print_randoms { | |
static void print() { | |
typedef typename Next<R>::type RND; | |
std::cout << RND::value << std::endl; | |
print_randoms<n-1, RND>::print(); | |
}; | |
}; | |
template<typename R> | |
struct print_randoms<0, R> { | |
static void print() { | |
std::cout << Next<R>::value << std::endl; | |
}; | |
}; | |
template<unsigned n, typename R> | |
struct make_random_arity_array { | |
static void print() { | |
typedef typename Next<R>::type RND; | |
std::array<int, RND::value % 65536> a; | |
std::cout << "a is std::array<int, " << a.size() << ">" << std::endl; | |
make_random_arity_array<n-1, RND>::print(); | |
}; | |
}; | |
template<typename R> | |
struct make_random_arity_array<0, R> { | |
static void print() { | |
typedef typename Next<R>::type RND; | |
std::array<int, RND::value % 65536> a; | |
std::cout << "a is std::array<int, " << a.size() << ">" << std::endl; | |
}; | |
}; | |
int main(int ac, char** av) { | |
print_randoms<10, META_PRNG>::print(); | |
make_random_arity_array<10, META_PRNG>::print(); | |
return 0; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// tempra.hpp | |
#pragma once | |
#include <cstdint> | |
#include <climits> | |
template<uint32_t x, uint32_t y, uint32_t z, uint32_t w> | |
struct meta_xor128 { | |
static const uint32_t x_ = x; | |
static const uint32_t y_ = y; | |
static const uint32_t z_ = z; | |
static const uint32_t w_ = w; | |
static const uint32_t value = w; | |
}; | |
template<typename E> | |
struct eval { | |
typedef E type; | |
}; | |
template<typename E> | |
struct init { | |
typedef typename eval<E>::type type; | |
static const uint32_t value = type::value; | |
}; | |
template<uint32_t x, uint32_t y, uint32_t z, uint32_t w> | |
struct init<meta_xor128<x,y,z,w>> { | |
typedef typename eval<meta_xor128<x,y,z,w>>::type type; | |
static const uint32_t value = type::value; | |
}; | |
template<uint32_t x, uint32_t y, uint32_t z, uint32_t w> | |
struct eval<meta_xor128<x,y,z,w>> { | |
#define t (x ^ (x << 11 )) | |
static const uint32_t value = (w ^ (w>>19)) ^ (t ^ (t >> 8)); | |
typedef meta_xor128<y, z, w, (w ^ (w>>19)) ^ (t ^ (t >> 8))> type; | |
#undef t | |
}; | |
template<typename Engine> | |
struct Random { | |
typedef typename init<Engine>::type type; | |
static const decltype(type::value) value = type::value; | |
}; | |
template <typename R> | |
struct Next { | |
typedef typename eval<R>::type type; | |
static const decltype(type::value) value = type::value; | |
}; | |
constexpr char inits[] = __TIME__; | |
constexpr uint32_t DEFAULT_SEED = | |
(inits[0]-'0')*100000+(inits[1]-'0')*10000 + | |
(inits[3]-'0')*1000+(inits[4]-'0')*100+ | |
(inits[6]-'0')*10+inits[7]-'0'; | |
typedef typename Random<meta_xor128<DEFAULT_SEED, DEFAULT_SEED+13, DEFAULT_SEED+34, DEFAULT_SEED+89>>::type META_PRNG; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment