43std::vector<std::vector<Input_> >
combine_to_factor(
const std::size_t n,
const std::vector<const Input_*>& inputs, Code_*
const codes) {
44 const auto ninputs = inputs.size();
45 auto output = sanisizer::create<std::vector<std::vector<Input_> > >(ninputs);
49 std::fill_n(codes, n, 0);
59 Combination(
const std::size_t i) : index(i) {}
68 auto cmp = [&](
const Combination& left,
const Combination& right) ->
bool {
69 for (
auto curf : inputs) {
70 if (curf[left.index] < curf[right.index]) {
72 }
else if (curf[left.index] > curf[right.index]) {
78 std::map<Combination, Code_, I<
decltype(cmp)> > mapping(std::move(cmp));
80 const auto eq = [&](
const Combination& left,
const Combination& right) ->
bool {
81 for (
auto curf : inputs) {
82 if (curf[left.index] != curf[right.index]) {
89 for (I<
decltype(n)> i = 0; i < n; ++i) {
90 Combination current(i);
91 const auto mIt = mapping.find(current);
92 if (mIt == mapping.end() || !eq(mIt->first, current)) {
93 Code_ alt = mapping.size();
94 mapping.insert(mIt, std::make_pair(current, alt));
97 codes[i] = mIt->second;
101 return std::vector<std::pair<Combination, Code_> >(mapping.begin(), mapping.end());
105 const auto nuniq = unique.size();
106 for (
auto& ofac : output) {
109 auto remapping = sanisizer::create<std::vector<Code_> >(nuniq);
110 for (I<
decltype(nuniq)> u = 0; u < nuniq; ++u) {
111 const auto ix = unique[u].first.index;
112 for (I<
decltype(ninputs)> f = 0; f < ninputs; ++f) {
113 output[f].push_back(inputs[f][ix]);
115 remapping[unique[u].second] = u;
119 for (I<
decltype(n)> i = 0; i < n; ++i) {
120 codes[i] = remapping[codes[i]];
149std::vector<std::vector<Input_> >
combine_to_factor_unused(
const std::size_t n,
const std::vector<std::pair<const Input_*, Number_> >& inputs, Code_*
const codes) {
150 const auto ninputs = inputs.size();
151 auto output = sanisizer::create<std::vector<std::vector<Input_> > >(ninputs);
155 std::fill_n(codes, n, 0);
159 sanisizer::resize(output[0], inputs[0].second);
160 std::iota(output[0].begin(), output[0].end(),
static_cast<Code_
>(0));
161 std::copy_n(inputs[0].first, n, codes);
166 std::copy_n(inputs[ninputs - 1].first, n, codes);
167 Code_ ncombos = inputs[ninputs - 1].second;
168 for (I<
decltype(ninputs)> f = ninputs - 1; f > 0; --f) {
169 const auto& finfo = inputs[f - 1];
170 const auto next_ncombos = sanisizer::product<Code_>(ncombos, finfo.second);
171 const auto ff = finfo.first;
172 for (I<
decltype(n)> i = 0; i < n; ++i) {
175 codes[i] += sanisizer::product_unsafe<Code_>(ncombos, ff[i]);
177 ncombos = next_ncombos;
180 sanisizer::cast<I<
decltype(output[0].size())> >(ncombos);
181 Code_ outer_repeats = ncombos;
182 Code_ inner_repeats = 1;
183 for (I<
decltype(ninputs)> f = ninputs; f > 0; --f) {
184 auto& out = output[f - 1];
185 out.reserve(ncombos);
187 const auto& finfo = inputs[f - 1];
188 const Code_ initial_size = inner_repeats * finfo.second;
189 out.resize(initial_size);
191 if (inner_repeats == 1) {
192 std::iota(out.begin(), out.end(),
static_cast<Code_
>(0));
194 auto oIt = out.begin();
195 for (Number_ l = 0; l < finfo.second; ++l) {
196 std::fill_n(oIt, inner_repeats, l);
197 oIt += inner_repeats;
200 inner_repeats = initial_size;
202 outer_repeats /= finfo.second;
203 for (Code_ r = 1; r < outer_repeats; ++r) {
206 out.insert(out.end(), out.begin(), out.begin() + initial_size);