Template non-type arguments (Variadic templates) によるコンパイル時乱数生成
Variadic templates でコンパイル時に乱数を生成してみた。現段階ではエンジンとして linear congruential, Xorshift, mersenne twister を、Discrete Uniform Distribution として uniform_int_distribution を実装してみた。ただし Template non-type arguments に対して実数を扱わせる事はできないので*1、そのようなものに対する Discrete Uniform Distribution は linear congruential で用いられる方法を流用している*2。また、discard 的なものは未実装であるがこれも追々実装予定。実装した。
一応こんな感じに書ける。
make_random_sequence
という命名がなんだか微妙だが、make_index_sequence
に則って取り敢えずそうしている。それぞれ乱数エンジンの型は、result
とnext_type
型とdiscart_type
型を持っており、result
が現在の擬似乱数の生成された値、next_type
が次の擬似乱数を生成する型、discart_type
が指定された回数分内部状態が進んだ擬似乱数を生成する型となっている。
尚、パラメータパックの保持する値に対してランダムアクセスを行おうとすると、再帰によって値を1つ1つ捨てる他がないので、これが線形となってしまってとても時間がかかる。これを極力避けた。また、C++1z
からテンプレート引数型にauto
を記述する事ができるようになったが、これを再帰中に多様すると型推論の負荷が強く、手元のコンパイラ(GCC 7.1.0)では有限時間内にコンパイルが完了せず abort trap で死んだので、 mersenne twister の実装などでは特に型を明示するようにしている。
以下は、srook::anypack<>::random::mersenne_twister のテストコード。実装はこれをパスする。