27 return num_packets / 2;
42 const size_t num_packets,
43 const size_t row_offset,
47 size_t relpos = row_idx - row_offset;
48 assert(relpos % 2 == 0 && relpos + 1 < num_packets);
49 return row_offset + (relpos / 2) +
60 const size_t num_packets,
61 const size_t row_offset,
71 return (num_packets > 1 ? 2 * libff::log2(num_packets) - 1 : 0);
92 const std::vector<size_t> rhs_dests,
99 const size_t subnetwork_size = (hi - lo + 1);
100 assert(rhs_dests.size() == subnetwork_size);
102 assert(right - left + 1 >= subnetwork_width);
104 if (right - left + 1 > subnetwork_width) {
109 for (
size_t packet_idx = lo; packet_idx <= hi; ++packet_idx) {
110 neighbors[left][packet_idx].first =
111 neighbors[left][packet_idx].second = packet_idx;
112 neighbors[right][packet_idx].first =
113 neighbors[right][packet_idx].second =
114 rhs_dests[packet_idx - lo];
117 std::vector<size_t> new_rhs_dests(subnetwork_size, -1);
118 for (
size_t packet_idx = lo; packet_idx <= hi; ++packet_idx) {
119 new_rhs_dests[packet_idx - lo] = packet_idx;
123 left + 1, right - 1, lo, hi, new_rhs_dests, neighbors);
124 }
else if (subnetwork_size == 2) {
126 neighbors[left][lo].first = neighbors[left][hi].second = rhs_dests[0];
127 neighbors[left][lo].second = neighbors[left][hi].first = rhs_dests[1];
133 std::vector<size_t> new_rhs_dests(subnetwork_size, -1);
142 for (
size_t row_idx = lo;
143 row_idx < (subnetwork_size % 2 == 1 ? hi : hi + 1);
145 neighbors[left][row_idx].first =
147 subnetwork_size, lo, row_idx,
true);
148 neighbors[left][row_idx].second =
150 subnetwork_size, lo, row_idx,
false);
159 neighbors[right][row_idx].first =
160 neighbors[right][row_idx + 1].second = rhs_dests[row_idx - lo];
161 neighbors[right][row_idx].second =
162 neighbors[right][row_idx + 1].first =
163 rhs_dests[row_idx + 1 - lo];
166 if (subnetwork_size % 2 == 1) {
172 neighbors[left][hi].first = neighbors[left][hi].second = hi;
173 neighbors[right][hi].first = neighbors[right][hi].second =
175 new_rhs_dests[hi - lo] = hi;
182 neighbors[left][hi - 1].second = neighbors[left][hi - 1].first;
183 neighbors[left][hi].second = neighbors[left][hi].first;
187 const std::vector<size_t> new_rhs_dests_top(
188 new_rhs_dests.begin(), new_rhs_dests.begin() + d);
189 const std::vector<size_t> new_rhs_dests_bottom(
190 new_rhs_dests.begin() + d, new_rhs_dests.end());
193 left + 1, right - 1, lo, lo + d - 1, new_rhs_dests_top, neighbors);
195 left + 1, right - 1, lo + d, hi, new_rhs_dests_bottom, neighbors);
201 assert(num_packets > 1);
206 std::vector<std::pair<size_t, size_t>>(
207 num_packets, std::make_pair<size_t, size_t>(-1, -1)));
209 std::vector<size_t> rhs_dests(num_packets);
210 for (
size_t packet_idx = 0; packet_idx < num_packets; ++packet_idx) {
211 rhs_dests[packet_idx] = packet_idx;
215 0, width - 1, 0, num_packets - 1, rhs_dests, neighbors);
228 const size_t row_offset,
const size_t row_idx)
232 return (((row_idx - row_offset) & ~1) + row_offset);
246 const size_t row_offset,
const size_t packet_idx,
const bool use_top)
248 const size_t row_idx =
250 return (packet_idx == row_idx) ^ use_top;
264 const size_t row_offset,
const size_t packet_idx,
const bool switch_setting)
266 const size_t row_idx =
268 return (row_idx == packet_idx) ^ switch_setting;
276 const size_t row_offset,
const size_t packet_idx)
278 const size_t row_idx =
280 return (1 - (packet_idx - row_idx)) + row_idx;
288 const size_t row_offset,
const size_t packet_idx)
321 const size_t subnetwork_size = (hi - lo + 1);
323 assert(right - left + 1 >= subnetwork_width);
328 assert(permutation.
size() == subnetwork_size);
330 assert(permutation.
inverse() == permutation_inv);
333 if (right - left + 1 > subnetwork_width) {
340 left + 1, right - 1, lo, hi, permutation, permutation_inv, routing);
341 }
else if (subnetwork_size == 2) {
345 assert(permutation.
get(lo) == lo || permutation.
get(lo) == lo + 1);
347 permutation.
get(lo + 1) == lo || permutation.
get(lo + 1) == lo + 1);
348 assert(permutation.
get(lo) != permutation.
get(lo + 1));
350 routing[left][lo] = (permutation.
get(lo) != lo);
363 std::vector<bool> lhs_routed(subnetwork_size,
false);
369 if (subnetwork_size % 2 == 1) {
375 if (permutation.
get(hi) == hi) {
380 new_permutation.
set(hi, hi);
381 new_permutation_inv.
set(hi, hi);
390 const size_t rhs_switch =
392 const bool rhs_switch_setting =
394 lo, permutation.
get(hi),
false);
395 routing[right][rhs_switch] = rhs_switch_setting;
397 subnetwork_size, lo, rhs_switch,
false);
398 new_permutation.
set(hi, tprime);
399 new_permutation_inv.
set(tprime, hi);
406 lhs_routed[hi - lo] =
true;
407 max_unrouted = hi - 1;
413 routing[left][hi - 1] =
false;
426 const size_t lhs_switch =
428 if (routing[left].find(lhs_switch) == routing[left].end()) {
429 routing[left][lhs_switch] =
false;
431 const bool lhs_switch_setting = routing[left][lhs_switch];
434 lo, to_route, lhs_switch_setting);
436 subnetwork_size, lo, lhs_switch, use_top);
437 if (permutation.
get(to_route) == hi) {
442 new_permutation.
set(t, hi);
443 new_permutation_inv.
set(hi, t);
444 lhs_routed[to_route - lo] =
true;
445 to_route = max_unrouted;
449 lo, permutation.
get(to_route));
456 routing[right].find(rhs_switch) ==
457 routing[right].end());
458 routing[right][rhs_switch] =
460 lo, permutation.
get(to_route), use_top);
462 subnetwork_size, lo, rhs_switch, use_top);
463 new_permutation.
set(t, tprime);
464 new_permutation_inv.
set(tprime, t);
466 lhs_routed[to_route - lo] =
true;
468 lo, permutation.
get(to_route));
476 const size_t rhs_switch =
479 lo, permutation_inv.
get(to_route));
480 assert(routing[right].find(rhs_switch) != routing[right].end());
481 const bool rhs_switch_setting = routing[right][rhs_switch];
484 lo, to_route, rhs_switch_setting);
485 const bool lhs_switch_setting =
487 lo, permutation_inv.
get(to_route), use_top);
492 auto it = routing[left].find(lhs_switch);
495 it == routing[left].end() ||
496 it->second == lhs_switch_setting);
497 routing[left][lhs_switch] = lhs_switch_setting;
500 subnetwork_size, lo, rhs_switch, use_top);
502 subnetwork_size, lo, lhs_switch, use_top);
503 new_permutation.
set(tprime, t);
504 new_permutation_inv.
set(t, tprime);
506 lhs_routed[permutation_inv.
get(to_route) - lo] =
true;
508 lo, permutation_inv.
get(to_route));
514 if (!route_left || !lhs_routed[to_route - lo]) {
519 while (max_unrouted > lo && lhs_routed[max_unrouted - lo]) {
524 if (max_unrouted < lo || (max_unrouted == lo && lhs_routed[0])) {
528 to_route = max_unrouted;
533 if (subnetwork_size % 2 == 0) {
535 routing[left].erase(hi - 1);
540 new_permutation.
slice(lo, lo + d - 1);
542 new_permutation.
slice(lo + d, hi);
545 new_permutation_inv.
slice(lo, lo + d - 1);
547 new_permutation_inv.
slice(lo + d, hi);
554 new_permutation_upper,
555 new_permutation_inv_upper,
562 new_permutation_lower,
563 new_permutation_inv_lower,
571 const size_t num_packets = permutation.
size();
589 const size_t num_packets = permutation.
size();
595 for (
size_t column_idx = 0; column_idx < width; ++column_idx) {
597 for (
size_t packet_idx = 0; packet_idx < num_packets; ++packet_idx) {
598 size_t routed_packet_idx;
599 if (neighbors[column_idx][packet_idx].first ==
600 neighbors[column_idx][packet_idx].second) {
601 routed_packet_idx = neighbors[column_idx][packet_idx].first;
603 auto it = routing[column_idx].find(packet_idx);
604 auto it2 = routing[column_idx].find(packet_idx - 1);
606 (it != routing[column_idx].end()) ^
607 (it2 != routing[column_idx].end()));
608 const bool switch_setting =
609 (it != routing[column_idx].end() ? it->second
613 (switch_setting ? neighbors[column_idx][packet_idx].second
614 : neighbors[column_idx][packet_idx].first);
617 nextperm.
set(routed_packet_idx, curperm.
get(packet_idx));
623 return (curperm == permutation.
inverse());