#include <array>
#include <utility>
namespace detail {
template<typename IntType, IntType(*Step)(IntType), IntType Start, IntType ...Is>
constexpr auto make_integer_array(std::integer_sequence<IntType,Is...>)
{
return std::array<IntType,sizeof...(Is)>{{Step(Start + Is)...}};
}
template<typename IntType, IntType(*Step)(IntType), IntType Start, std::size_t Length>
constexpr auto make_integer_array()
{
return make_integer_array<IntType,Step,Start>(
std::make_integer_sequence<IntType,Length>());
}
template<
typename IntType, std::size_t Cols,
IntType(*Step)(IntType),IntType Start, std::size_t ...Rs
>
constexpr auto make_integer_matrix(std::index_sequence<Rs...>)
{
return std::array<std::array<IntType,Cols>,sizeof...(Rs)>
{{make_integer_array<IntType,Step,Start + (Rs * Cols),Cols>()...}};
}
} // namespace detail
/*
Return a compiletime initialized matrix (`std::array` of std::array`)
of `Cols` columns by `Rows` rows. Ascending elements from [0,0]
in row-first order are populated with successive values of the
constexpr function `IntType Step(IntType i)` for `i` in
`[Start + 0,Start + (Rows * Cols))`
*/
template<
typename IntType, std::size_t Cols, std::size_t Rows,
IntType(*Step)(IntType), IntType Start
>
constexpr auto make_integer_matrix()
{
return detail::make_integer_matrix<IntType,Cols,Step,Start>(
std::make_index_sequence<Rows>());
}
/*
Return a compiletime initialized matrix (`std::array` of std::array`)
of `Cols` columns by `sizeof...(Starts)` rows. Successive rows are populated
with successive values of the constexpr function `IntType Step(IntType i)`
for `i` in `[start + 0,start + Cols)`, for `start` successively in `...Starts`.
*/
template<typename IntType, std::size_t Cols, IntType(*Step)(IntType), IntType ...Starts>
constexpr auto make_integer_matrix()
{
return std::array<std::array<IntType,Cols>,sizeof...(Starts)>
{{detail::make_integer_array<IntType,Step,Starts,Cols>()...}};
}
#include <iostream>
using namespace std;
template<typename IntType>
constexpr auto times_3(IntType i)
{
return i * 3;
}
static constexpr auto m4x6 = make_integer_matrix<int,4,6,×_3<int>,4>();
static constexpr auto m5x1 = make_integer_matrix<int,5,×_3<int>,7>();
static constexpr auto m6x5 = make_integer_matrix<int,6,×_3<int>,11,13,17,19,23>();
static_assert(m4x6[0][0] == 12,"");
int main()
{
cout << "A 4 x 6 matrix that wraps around in steps of `3i` from `i` = 4" << endl;
for (auto const & ar : m4x6) {
for (auto const & i : ar) {
cout << i << ' ';
}
cout << endl;
}
cout << endl;
cout << "A 6 x 5 matrix with rows of `3i` for initial `i` in <11,13,17,19,23>"
<< endl;
for (auto const & ar : m6x5) {
for (auto const & i : ar) {
cout << i << ' ';
}
cout << endl;
}
cout << endl;
cout << "A 5 x 1 matrix with rows of of ` 3i` for initial `i` in <7>"
<< endl;
for (auto const & ar : m5x1) {
for (auto const & i : ar) {
cout << i << ' ';
}
cout << endl;
}
return 0;
}
I2luY2x1ZGUgPGFycmF5PgojaW5jbHVkZSA8dXRpbGl0eT4KCm5hbWVzcGFjZSBkZXRhaWwgewogICAgCnRlbXBsYXRlPHR5cGVuYW1lIEludFR5cGUsIEludFR5cGUoKlN0ZXApKEludFR5cGUpLCBJbnRUeXBlIFN0YXJ0LCBJbnRUeXBlIC4uLklzPiAKY29uc3RleHByIGF1dG8gbWFrZV9pbnRlZ2VyX2FycmF5KHN0ZDo6aW50ZWdlcl9zZXF1ZW5jZTxJbnRUeXBlLElzLi4uPikKewogICAgcmV0dXJuIHN0ZDo6YXJyYXk8SW50VHlwZSxzaXplb2YuLi4oSXMpPnt7U3RlcChTdGFydCArIElzKS4uLn19Owp9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBJbnRUeXBlLCBJbnRUeXBlKCpTdGVwKShJbnRUeXBlKSwgSW50VHlwZSBTdGFydCwgc3RkOjpzaXplX3QgTGVuZ3RoPiAKY29uc3RleHByIGF1dG8gbWFrZV9pbnRlZ2VyX2FycmF5KCkKewogICAgcmV0dXJuIG1ha2VfaW50ZWdlcl9hcnJheTxJbnRUeXBlLFN0ZXAsU3RhcnQ+KAogICAgICAgIHN0ZDo6bWFrZV9pbnRlZ2VyX3NlcXVlbmNlPEludFR5cGUsTGVuZ3RoPigpKTsKfQoKCnRlbXBsYXRlPAogICAgdHlwZW5hbWUgSW50VHlwZSwgc3RkOjpzaXplX3QgQ29scywgCiAgICBJbnRUeXBlKCpTdGVwKShJbnRUeXBlKSxJbnRUeXBlIFN0YXJ0LCBzdGQ6OnNpemVfdCAuLi5Scwo+IApjb25zdGV4cHIgYXV0byBtYWtlX2ludGVnZXJfbWF0cml4KHN0ZDo6aW5kZXhfc2VxdWVuY2U8UnMuLi4+KQp7CiAgICByZXR1cm4gc3RkOjphcnJheTxzdGQ6OmFycmF5PEludFR5cGUsQ29scz4sc2l6ZW9mLi4uKFJzKT4gCiAgICAgICAge3ttYWtlX2ludGVnZXJfYXJyYXk8SW50VHlwZSxTdGVwLFN0YXJ0ICsgKFJzICogQ29scyksQ29scz4oKS4uLn19Owp9Cgp9IC8vIG5hbWVzcGFjZSBkZXRhaWwKCi8qCiAgICBSZXR1cm4gYSBjb21waWxldGltZSBpbml0aWFsaXplZCBtYXRyaXggKGBzdGQ6OmFycmF5YCBvZiBzdGQ6OmFycmF5YCkKICAgIG9mIGBDb2xzYCBjb2x1bW5zIGJ5IGBSb3dzYCByb3dzLiBBc2NlbmRpbmcgZWxlbWVudHMgZnJvbSBbMCwwXSAKICAgIGluIHJvdy1maXJzdCBvcmRlciBhcmUgcG9wdWxhdGVkIHdpdGggc3VjY2Vzc2l2ZSB2YWx1ZXMgb2YgdGhlCiAgICBjb25zdGV4cHIgZnVuY3Rpb24gYEludFR5cGUgU3RlcChJbnRUeXBlIGkpYCBmb3IgYGlgIGluCiAgICBgW1N0YXJ0ICsgMCxTdGFydCArIChSb3dzICogQ29scykpYCAKKi8KdGVtcGxhdGU8CiAgICB0eXBlbmFtZSBJbnRUeXBlLCBzdGQ6OnNpemVfdCBDb2xzLCBzdGQ6OnNpemVfdCBSb3dzLCAKICAgIEludFR5cGUoKlN0ZXApKEludFR5cGUpLCBJbnRUeXBlIFN0YXJ0Cj4gCmNvbnN0ZXhwciBhdXRvIG1ha2VfaW50ZWdlcl9tYXRyaXgoKQp7CiAgICByZXR1cm4gZGV0YWlsOjptYWtlX2ludGVnZXJfbWF0cml4PEludFR5cGUsQ29scyxTdGVwLFN0YXJ0PigKICAgICAgICBzdGQ6Om1ha2VfaW5kZXhfc2VxdWVuY2U8Um93cz4oKSk7Cn0KCi8qCiAgICBSZXR1cm4gYSBjb21waWxldGltZSBpbml0aWFsaXplZCBtYXRyaXggKGBzdGQ6OmFycmF5YCBvZiBzdGQ6OmFycmF5YCkKICAgIG9mIGBDb2xzYCBjb2x1bW5zIGJ5IGBzaXplb2YuLi4oU3RhcnRzKWAgcm93cy4gU3VjY2Vzc2l2ZSByb3dzIGFyZSBwb3B1bGF0ZWQKICAgIHdpdGggc3VjY2Vzc2l2ZSB2YWx1ZXMgb2YgdGhlIGNvbnN0ZXhwciBmdW5jdGlvbiBgSW50VHlwZSBTdGVwKEludFR5cGUgaSlgIAogICAgZm9yIGBpYCBpbiBgW3N0YXJ0ICsgMCxzdGFydCArIENvbHMpYCwgZm9yIGBzdGFydGAgc3VjY2Vzc2l2ZWx5IGluIGAuLi5TdGFydHNgLiAgCiovCnRlbXBsYXRlPHR5cGVuYW1lIEludFR5cGUsIHN0ZDo6c2l6ZV90IENvbHMsIEludFR5cGUoKlN0ZXApKEludFR5cGUpLCBJbnRUeXBlIC4uLlN0YXJ0cz4gCmNvbnN0ZXhwciBhdXRvIG1ha2VfaW50ZWdlcl9tYXRyaXgoKQp7CiAgICByZXR1cm4gc3RkOjphcnJheTxzdGQ6OmFycmF5PEludFR5cGUsQ29scz4sc2l6ZW9mLi4uKFN0YXJ0cyk+IAogICAgICAgIHt7ZGV0YWlsOjptYWtlX2ludGVnZXJfYXJyYXk8SW50VHlwZSxTdGVwLFN0YXJ0cyxDb2xzPigpLi4ufX07Cn0KCiNpbmNsdWRlIDxpb3N0cmVhbT4KCnVzaW5nIG5hbWVzcGFjZSBzdGQ7Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBJbnRUeXBlPgpjb25zdGV4cHIgYXV0byB0aW1lc18zKEludFR5cGUgaSkKewogICAgcmV0dXJuIGkgKiAzOwp9CgpzdGF0aWMgY29uc3RleHByIGF1dG8gbTR4NiA9IG1ha2VfaW50ZWdlcl9tYXRyaXg8aW50LDQsNiwmdGltZXNfMzxpbnQ+LDQ+KCk7CnN0YXRpYyBjb25zdGV4cHIgYXV0byBtNXgxID0gbWFrZV9pbnRlZ2VyX21hdHJpeDxpbnQsNSwmdGltZXNfMzxpbnQ+LDc+KCk7CnN0YXRpYyBjb25zdGV4cHIgYXV0byBtNng1ID0gbWFrZV9pbnRlZ2VyX21hdHJpeDxpbnQsNiwmdGltZXNfMzxpbnQ+LDExLDEzLDE3LDE5LDIzPigpOwpzdGF0aWNfYXNzZXJ0KG00eDZbMF1bMF0gPT0gMTIsIiIpOwoKaW50IG1haW4oKQp7CiAgICBjb3V0IDw8ICJBIDQgeCA2IG1hdHJpeCB0aGF0IHdyYXBzIGFyb3VuZCBpbiBzdGVwcyBvZiBgM2lgIGZyb20gYGlgID0gNCIgPDwgZW5kbDsgCiAgICBmb3IgKGF1dG8gY29uc3QgJiBhciAgOiBtNHg2KSB7CiAgICAgICAgZm9yIChhdXRvIGNvbnN0ICYgaSA6IGFyKSB7CiAgICAgICAgICAgIGNvdXQgPDwgaSA8PCAnICc7CiAgICAgICAgfQogICAgICAgIGNvdXQgPDwgZW5kbDsKICAgIH0KICAgIGNvdXQgPDwgZW5kbDsKICAgIGNvdXQgPDwgIkEgNiB4IDUgbWF0cml4IHdpdGggcm93cyBvZiBgM2lgIGZvciBpbml0aWFsIGBpYCBpbiA8MTEsMTMsMTcsMTksMjM+IiAKICAgICAgICA8PCBlbmRsOwogICAgZm9yIChhdXRvIGNvbnN0ICYgYXIgIDogbTZ4NSkgewogICAgICAgIGZvciAoYXV0byBjb25zdCAmIGkgOiBhcikgewogICAgICAgICAgICBjb3V0IDw8IGkgPDwgJyAnOwogICAgICAgIH0KICAgICAgICBjb3V0IDw8IGVuZGw7CiAgICB9CiAgICBjb3V0IDw8IGVuZGw7CiAgICBjb3V0IDw8ICJBIDUgeCAxIG1hdHJpeCB3aXRoIHJvd3Mgb2Ygb2YgYCAzaWAgZm9yIGluaXRpYWwgYGlgIGluIDw3PiIgCiAgICAgICAgPDwgZW5kbDsKICAgIGZvciAoYXV0byBjb25zdCAmIGFyICA6IG01eDEpIHsKICAgICAgICBmb3IgKGF1dG8gY29uc3QgJiBpIDogYXIpIHsKICAgICAgICAgICAgY291dCA8PCBpIDw8ICcgJzsKICAgICAgICB9CiAgICAgICAgY291dCA8PCBlbmRsOwogICAgfQoKCXJldHVybiAwOwp9Cg==