Merge bitcoin/bitcoin#34257: txgraph: deterministic optimal transaction order

6f113cb184 txgraph: use fallback order to sort chunks (feature) (Pieter Wuille)
0a3351947e txgraph: use fallback order when linearizing (feature) (Pieter Wuille)
fba004a3df txgraph: pass fallback_order to TxGraph (preparation) (Pieter Wuille)
941c432a46 txgraph test: subclass TxGraph::Ref like mempool does (preparation) (Pieter Wuille)
39d0052cbf clusterlin: make optimal linearizations deterministic (feature) (Pieter Wuille)
8bfbba3207 txgraph: sort distinct-cluster chunks by equal-feerate-prefix size (feature) (Pieter Wuille)
e0bc73ba92 clusterlin: sort tx in chunk by feerate and size (feature) (Pieter Wuille)
6c1bcb2c7c txgraph: clear cluster's chunk index in ~Ref (preparation) (Pieter Wuille)
7427c7d098 txgraph: update chunk index on Compact (preparation) (Pieter Wuille)
3ddafceb9a txgraph: initialize Ref in AddTransaction (preparation) (Pieter Wuille)

Pull request description:

  Part of #30289.

  TxGraph's fundamental responsibility is deciding the order of transactions in the mempool. It relies on the `cluster_linearize.h` code to optimize it, but there can and often will be many different orderings that are essentially equivalent from a quality perspective, so we have to pick one. At a high level, the solution will involve one or more of:
  * Deciding based on **internal identifiers** (`Cluster::m_sequence`, `DepGraphIndex`). This is very simple, but risks leaking information about transaction receive order.
  * Deciding **randomly**, which is private, but may interfere with relay expectations, block propagation, and ability to monitor network behavior.
  * Deciding **based on txid**, which is private and deterministic, but risks incentivizing grinding to get an edge (though we haven't really seen such behavior).
  * Deciding **based on size** (e.g. prefer smaller transactions), which is somewhat related to quality, but not unconditionally (depending on mempool layout, the ideal ordering might call for smaller transactions first, last, or anywhere in between). It's also not a strong ordering as there can be many identically-sized transactions. However, if it were to encourage grinding behavior, incentivizing smaller transactions is probably not a bad thing.

  As of #32545, the current behavior is primarily picking randomly, though inconsistently, as some code paths also use internal identifiers and size. #33335 sought to change it to use random (preferring size in a few places), with the downsides listed above.

  This PR is an alternative to that, which changes the order to tie-break based on size everywhere possible, and use lowest-txid-first as final fallback. This is fully deterministic: for any given set of mempool transactions, if all linearized optimally, the transaction order exposed by TxGraph is deterministic.

  The transactions within a chunk are sorted according to:
  1. `PostLinearize` (which improves sub-chunk order), using an initial linearization created using the rules 2-5 below.
  2. Topology (parents before children).
  3. Individual transaction feerate (high to low)
  4. Individual transaction weight (small to large)
  5. Txid (low to high txid)

  The chunks within a cluster are sorted according to:
  1. Topology (chunks after their dependencies)
  2. Chunk feerate (high to low)
  3. Chunk weight (small to large)
  4. Max-txid (chunk with lowest maximum-txid first)

  The chunks across clusters are sorted according to:
  1. Feerate (high to low)
  2. Equal-feerate-chunk-prefix weight (small to large)
  3. Max-txid (chunk with lowest maximum-txid first)

  The equal-feerate-chunk-prefix weight of a chunk C is defined as the sum of the weights of all chunks in the same cluster as C, with the same feerate as C, up to and including C itself, in linearization order (but excluding such chunks that appear after C). This is a well-defined approximation of sorting chunks from small to large across clusters, while remaining consistent with intra-cluster linearization order.

ACKs for top commit:
  ajtowns:
    reACK 6f113cb184 it was good before and now it's better
  instagibbs:
    ACK 6f113cb184
  marcofleon:
    light crACK 6f113cb184

Tree-SHA512: 16dc43c62b7e83c81db1ee14c01e068ae2f06c1ffaa0898837d87271fa7179dd98baeb74abc9fe79220e01fdba6876defe60022c2b72badc21d770644a0fe0ac
This commit is contained in:
merge-script committed 2026-02-11 17:40:38 +00:00
commit c134b1a4bc
20 files changed
+836 -394

No files matched your search

+1 -1
View File
@@ -22,7 +22,7 @@
static void AddTx(const CTransactionRef& tx, const CAmount& fee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs) static void AddTx(const CTransactionRef& tx, const CAmount& fee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs)
{ {
LockPoints lp; LockPoints lp;
TryAddToMempool(pool, CTxMemPoolEntry(TxGraph::Ref(), tx, fee, /*time=*/0, /*entry_height=*/1, /*entry_sequence=*/0, /*spends_coinbase=*/false, /*sigops_cost=*/4, lp)); TryAddToMempool(pool, CTxMemPoolEntry(tx, fee, /*time=*/0, /*entry_height=*/1, /*entry_sequence=*/0, /*spends_coinbase=*/false, /*sigops_cost=*/4, lp));
} }
namespace { namespace {
+3 -3
View File
@@ -55,7 +55,7 @@ void BenchLinearizeOptimallyTotal(benchmark::Bench& bench, const std::string& na
// Benchmark the total time to optimal. // Benchmark the total time to optimal.
uint64_t rng_seed = 0; uint64_t rng_seed = 0;
bench.name(bench_name).run([&] { bench.name(bench_name).run([&] {
auto [_lin, optimal, _cost] = Linearize(depgraph, /*max_iterations=*/10000000, rng_seed++); auto [_lin, optimal, _cost] = Linearize(depgraph, /*max_iterations=*/10000000, rng_seed++, IndexTxOrder{});
assert(optimal); assert(optimal);
}); });
} }
@@ -72,7 +72,7 @@ void BenchLinearizeOptimallyPerCost(benchmark::Bench& bench, const std::string&
// Determine the cost of 100 rng_seeds. // Determine the cost of 100 rng_seeds.
uint64_t total_cost = 0; uint64_t total_cost = 0;
for (uint64_t iter = 0; iter < 100; ++iter) { for (uint64_t iter = 0; iter < 100; ++iter) {
auto [_lin, optimal, cost] = Linearize(depgraph, /*max_iterations=*/10000000, /*rng_seed=*/iter); auto [_lin, optimal, cost] = Linearize(depgraph, /*max_iterations=*/10000000, /*rng_seed=*/iter, IndexTxOrder{});
total_cost += cost; total_cost += cost;
} }
@@ -80,7 +80,7 @@ void BenchLinearizeOptimallyPerCost(benchmark::Bench& bench, const std::string&
bench.name(bench_name).unit("cost").batch(total_cost).run([&] { bench.name(bench_name).unit("cost").batch(total_cost).run([&] {
uint64_t recompute_cost = 0; uint64_t recompute_cost = 0;
for (uint64_t iter = 0; iter < 100; ++iter) { for (uint64_t iter = 0; iter < 100; ++iter) {
auto [_lin, optimal, cost] = Linearize(depgraph, /*max_iterations=*/10000000, /*rng_seed=*/iter); auto [_lin, optimal, cost] = Linearize(depgraph, /*max_iterations=*/10000000, /*rng_seed=*/iter, IndexTxOrder{});
assert(optimal); assert(optimal);
recompute_cost += cost; recompute_cost += cost;
} }
+1 -1
View File
@@ -29,7 +29,7 @@ static void AddTx(const CTransactionRef& tx, CTxMemPool& pool) EXCLUSIVE_LOCKS_R
unsigned int sigOpCost{4}; unsigned int sigOpCost{4};
uint64_t fee{0}; uint64_t fee{0};
LockPoints lp; LockPoints lp;
TryAddToMempool(pool, CTxMemPoolEntry(TxGraph::Ref(), TryAddToMempool(pool, CTxMemPoolEntry(
tx, fee, nTime, nHeight, sequence, tx, fee, nTime, nHeight, sequence,
spendsCoinbase, sigOpCost, lp)); spendsCoinbase, sigOpCost, lp));
} }
+1 -1
View File
@@ -27,7 +27,7 @@ static void AddTx(const CTransactionRef& tx, const CAmount& nFee, CTxMemPool& po
bool spendsCoinbase = false; bool spendsCoinbase = false;
unsigned int sigOpCost = 4; unsigned int sigOpCost = 4;
LockPoints lp; LockPoints lp;
TryAddToMempool(pool, CTxMemPoolEntry(TxGraph::Ref(), TryAddToMempool(pool, CTxMemPoolEntry(
tx, nFee, nTime, nHeight, sequence, tx, nFee, nTime, nHeight, sequence,
spendsCoinbase, sigOpCost, lp)); spendsCoinbase, sigOpCost, lp));
} }
+1 -1
View File
@@ -29,7 +29,7 @@ static void AddTx(const CTransactionRef& tx, CTxMemPool& pool, FastRandomContext
bool spendsCoinbase = false; bool spendsCoinbase = false;
unsigned int sigOpCost = 4; unsigned int sigOpCost = 4;
LockPoints lp; LockPoints lp;
TryAddToMempool(pool, CTxMemPoolEntry(TxGraph::Ref(), tx, det_rand.randrange(10000)+1000, nTime, nHeight, sequence, spendsCoinbase, sigOpCost, lp)); TryAddToMempool(pool, CTxMemPoolEntry(tx, det_rand.randrange(10000)+1000, nTime, nHeight, sequence, spendsCoinbase, sigOpCost, lp));
} }
struct Available { struct Available {
+1 -1
View File
@@ -22,7 +22,7 @@
static void AddTx(const CTransactionRef& tx, const CAmount& fee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs) static void AddTx(const CTransactionRef& tx, const CAmount& fee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs)
{ {
LockPoints lp; LockPoints lp;
TryAddToMempool(pool, CTxMemPoolEntry(TxGraph::Ref(), tx, fee, /*time=*/0, /*entry_height=*/1, /*entry_sequence=*/0, /*spends_coinbase=*/false, /*sigops_cost=*/4, lp)); TryAddToMempool(pool, CTxMemPoolEntry(tx, fee, /*time=*/0, /*entry_height=*/1, /*entry_sequence=*/0, /*spends_coinbase=*/false, /*sigops_cost=*/4, lp));
} }
static void RpcMempool(benchmark::Bench& bench) static void RpcMempool(benchmark::Bench& bench)
+9 -3
View File
@@ -12,6 +12,11 @@
namespace { namespace {
std::strong_ordering PointerComparator(const TxGraph::Ref& a, const TxGraph::Ref& b) noexcept
{
return (&a) <=> (&b);
}
void BenchTxGraphTrim(benchmark::Bench& bench) void BenchTxGraphTrim(benchmark::Bench& bench)
{ {
// The from-block transactions consist of 1000 fully linear clusters, each with 64 // The from-block transactions consist of 1000 fully linear clusters, each with 64
@@ -60,14 +65,14 @@ void BenchTxGraphTrim(benchmark::Bench& bench)
std::vector<size_t> top_components; std::vector<size_t> top_components;
InsecureRandomContext rng(11); InsecureRandomContext rng(11);
auto graph = MakeTxGraph(MAX_CLUSTER_COUNT, MAX_CLUSTER_SIZE, NUM_ACCEPTABLE_ITERS); auto graph = MakeTxGraph(MAX_CLUSTER_COUNT, MAX_CLUSTER_SIZE, NUM_ACCEPTABLE_ITERS, PointerComparator);
// Construct the top chains. // Construct the top chains.
for (int chain = 0; chain < NUM_TOP_CHAINS; ++chain) { for (int chain = 0; chain < NUM_TOP_CHAINS; ++chain) {
for (int chaintx = 0; chaintx < NUM_TX_PER_TOP_CHAIN; ++chaintx) { for (int chaintx = 0; chaintx < NUM_TX_PER_TOP_CHAIN; ++chaintx) {
int64_t fee = rng.randbits<27>() + 100; int64_t fee = rng.randbits<27>() + 100;
FeePerWeight feerate{fee, 1}; FeePerWeight feerate{fee, 1};
top_refs.push_back(graph->AddTransaction(feerate)); graph->AddTransaction(top_refs.emplace_back(), feerate);
// Add internal dependencies linking the chain transactions together. // Add internal dependencies linking the chain transactions together.
if (chaintx > 0) { if (chaintx > 0) {
graph->AddDependency(*(top_refs.rbegin()), *(top_refs.rbegin() + 1)); graph->AddDependency(*(top_refs.rbegin()), *(top_refs.rbegin() + 1));
@@ -85,7 +90,8 @@ void BenchTxGraphTrim(benchmark::Bench& bench)
// Construct the transaction. // Construct the transaction.
int64_t fee = rng.randbits<27>() + 100; int64_t fee = rng.randbits<27>() + 100;
FeePerWeight feerate{fee, 1}; FeePerWeight feerate{fee, 1};
auto bottom_tx = graph->AddTransaction(feerate); TxGraph::Ref bottom_tx;
graph->AddTransaction(bottom_tx, feerate);
// Determine the number of dependencies this transaction will have. // Determine the number of dependencies this transaction will have.
int deps = std::min<int>(NUM_DEPS_PER_BOTTOM_TX, top_components.size()); int deps = std::min<int>(NUM_DEPS_PER_BOTTOM_TX, top_components.size());
for (int dep = 0; dep < deps; ++dep) { for (int dep = 0; dep < deps; ++dep) {
+117 -37
View File
@@ -12,6 +12,7 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <attributes.h>
#include <memusage.h> #include <memusage.h>
#include <random.h> #include <random.h>
#include <span.h> #include <span.h>
@@ -461,6 +462,16 @@ std::vector<FeeFrac> ChunkLinearization(const DepGraph<SetType>& depgraph, std::
return ret; return ret;
} }
/** Concept for function objects that return std::strong_ordering when invoked with two Args. */
template<typename F, typename Arg>
concept StrongComparator =
std::regular_invocable<F, Arg, Arg> &&
std::is_same_v<std::invoke_result_t<F, Arg, Arg>, std::strong_ordering>;
/** Simple default transaction ordering function for SpanningForestState::GetLinearization() and
* Linearize(), which just sorts by DepGraphIndex. */
using IndexTxOrder = std::compare_three_way;
/** Class to represent the internal state of the spanning-forest linearization (SFL) algorithm. /** Class to represent the internal state of the spanning-forest linearization (SFL) algorithm.
* *
* At all times, each dependency is marked as either "active" or "inactive". The subset of active * At all times, each dependency is marked as either "active" or "inactive". The subset of active
@@ -635,7 +646,7 @@ private:
InsecureRandomContext m_rng; InsecureRandomContext m_rng;
/** Data type to represent indexing into m_tx_data. */ /** Data type to represent indexing into m_tx_data. */
using TxIdx = uint32_t; using TxIdx = DepGraphIndex;
/** Data type to represent indexing into m_dep_data. */ /** Data type to represent indexing into m_dep_data. */
using DepIdx = uint32_t; using DepIdx = uint32_t;
@@ -687,6 +698,9 @@ private:
/** The number of updated transactions in activations/deactivations. */ /** The number of updated transactions in activations/deactivations. */
uint64_t m_cost{0}; uint64_t m_cost{0};
/** The DepGraph we are trying to linearize. */
const DepGraph<SetType>& m_depgraph;
/** Pick a random transaction within a set (which must be non-empty). */ /** Pick a random transaction within a set (which must be non-empty). */
TxIdx PickRandomTx(const SetType& tx_idxs) noexcept TxIdx PickRandomTx(const SetType& tx_idxs) noexcept
{ {
@@ -959,7 +973,8 @@ private:
public: public:
/** Construct a spanning forest for the given DepGraph, with every transaction in its own chunk /** Construct a spanning forest for the given DepGraph, with every transaction in its own chunk
* (not topological). */ * (not topological). */
explicit SpanningForestState(const DepGraph<SetType>& depgraph, uint64_t rng_seed) noexcept : m_rng(rng_seed) explicit SpanningForestState(const DepGraph<SetType>& depgraph LIFETIMEBOUND, uint64_t rng_seed) noexcept :
m_rng(rng_seed), m_depgraph(depgraph)
{ {
m_transaction_idxs = depgraph.Positions(); m_transaction_idxs = depgraph.Positions();
auto num_transactions = m_transaction_idxs.Count(); auto num_transactions = m_transaction_idxs.Count();
@@ -1235,15 +1250,30 @@ public:
} }
/** Construct a topologically-valid linearization from the current forest state. Must be /** Construct a topologically-valid linearization from the current forest state. Must be
* topological. */ * topological. fallback_order is a comparator that defines a strong order for DepGraphIndexes
std::vector<DepGraphIndex> GetLinearization() noexcept * in this cluster, used to order equal-feerate transactions and chunks.
*
* Specifically, the resulting order consists of:
* - The chunks of the current SFL state, sorted by (in decreasing order of priority):
* - topology (parents before children)
* - highest chunk feerate first
* - smallest chunk size first
* - the chunk with the lowest maximum transaction, by fallback_order, first
* - The transactions within a chunk, sorted by (in decreasing order of priority):
* - topology (parents before children)
* - highest tx feerate first
* - smallest tx size first
* - the lowest transaction, by fallback_order, first
*/
std::vector<DepGraphIndex> GetLinearization(const StrongComparator<DepGraphIndex> auto& fallback_order) const noexcept
{ {
/** The output linearization. */ /** The output linearization. */
std::vector<DepGraphIndex> ret; std::vector<DepGraphIndex> ret;
ret.reserve(m_transaction_idxs.Count()); ret.reserve(m_transaction_idxs.Count());
/** A heap with all chunks (by representative) that can currently be included, sorted by /** A heap with all chunks (by representative) that can currently be included, sorted by
* chunk feerate and a random tie-breaker. */ * chunk feerate (high to low), chunk size (small to large), and by least maximum element
std::vector<std::pair<TxIdx, uint64_t>> ready_chunks; * according to the fallback order (which is the second pair element). */
std::vector<std::pair<TxIdx, TxIdx>> ready_chunks;
/** Information about chunks: /** Information about chunks:
* - The first value is only used for chunk representatives, and counts the number of * - The first value is only used for chunk representatives, and counts the number of
* unmet dependencies this chunk has on other chunks (not including dependencies within * unmet dependencies this chunk has on other chunks (not including dependencies within
@@ -1253,7 +1283,8 @@ public:
std::vector<std::pair<TxIdx, TxIdx>> chunk_deps(m_tx_data.size(), {0, 0}); std::vector<std::pair<TxIdx, TxIdx>> chunk_deps(m_tx_data.size(), {0, 0});
/** The set of all chunk representatives. */ /** The set of all chunk representatives. */
SetType chunk_reps; SetType chunk_reps;
/** A list with all transactions within the current chunk that can be included. */ /** A heap with all transactions within the current chunk that can be included, sorted by
* tx feerate (high to low), tx size (small to large), and fallback order. */
std::vector<TxIdx> ready_tx; std::vector<TxIdx> ready_tx;
// Populate chunk_deps[c] with the number of {out-of-chunk dependencies, dependencies} the // Populate chunk_deps[c] with the number of {out-of-chunk dependencies, dependencies} the
// child has. // child has.
@@ -1267,27 +1298,69 @@ public:
chunk_deps[chl_chunk_rep].first += (par_chunk_rep != chl_chunk_rep); chunk_deps[chl_chunk_rep].first += (par_chunk_rep != chl_chunk_rep);
} }
} }
// Construct a heap with all chunks that have no out-of-chunk dependencies. /** Function to compute the highest element of a chunk, by fallback_order. */
/** Comparison function for the heap. */ auto max_fallback_fn = [&](TxIdx chunk_rep) noexcept {
auto chunk_cmp_fn = [&](const std::pair<TxIdx, uint64_t>& a, const std::pair<TxIdx, uint64_t>& b) noexcept { auto& chunk = m_tx_data[chunk_rep].chunk_setinfo.transactions;
auto& chunk_a = m_tx_data[a.first]; auto it = chunk.begin();
auto& chunk_b = m_tx_data[b.first]; DepGraphIndex ret = *it;
Assume(chunk_a.chunk_rep == a.first); ++it;
Assume(chunk_b.chunk_rep == b.first); while (it != chunk.end()) {
// First sort by chunk feerate. if (fallback_order(*it, ret) > 0) ret = *it;
if (chunk_a.chunk_setinfo.feerate != chunk_b.chunk_setinfo.feerate) { ++it;
return chunk_a.chunk_setinfo.feerate < chunk_b.chunk_setinfo.feerate;
} }
// Tie-break randomly. return ret;
if (a.second != b.second) return a.second < b.second;
// Lastly, tie-break by chunk representative.
return a.first < b.first;
}; };
/** Comparison function for the transaction heap. Note that it is a max-heap, so
* tx_cmp_fn(a, b) == true means "a appears after b in the linearization". */
auto tx_cmp_fn = [&](const auto& a, const auto& b) noexcept {
// Bail out for identical transactions.
if (a == b) return false;
// First sort by increasing transaction feerate.
auto& a_feerate = m_depgraph.FeeRate(a);
auto& b_feerate = m_depgraph.FeeRate(b);
auto feerate_cmp = FeeRateCompare(a_feerate, b_feerate);
if (feerate_cmp != 0) return feerate_cmp < 0;
// Then by decreasing transaction size.
if (a_feerate.size != b_feerate.size) {
return a_feerate.size > b_feerate.size;
}
// Tie-break by decreasing fallback_order.
auto fallback_cmp = fallback_order(a, b);
if (fallback_cmp != 0) return fallback_cmp > 0;
// This should not be hit, because fallback_order defines a strong ordering.
Assume(false);
return a < b;
};
// Construct a heap with all chunks that have no out-of-chunk dependencies.
/** Comparison function for the chunk heap. Note that it is a max-heap, so
* chunk_cmp_fn(a, b) == true means "a appears after b in the linearization". */
auto chunk_cmp_fn = [&](const auto& a, const auto& b) noexcept {
// Bail out for identical chunks.
if (a.first == b.first) return false;
// First sort by increasing chunk feerate.
auto& chunk_feerate_a = m_tx_data[a.first].chunk_setinfo.feerate;
auto& chunk_feerate_b = m_tx_data[b.first].chunk_setinfo.feerate;
auto feerate_cmp = FeeRateCompare(chunk_feerate_a, chunk_feerate_b);
if (feerate_cmp != 0) return feerate_cmp < 0;
// Then by decreasing chunk size.
if (chunk_feerate_a.size != chunk_feerate_b.size) {
return chunk_feerate_a.size > chunk_feerate_b.size;
}
// Tie-break by decreasing fallback_order.
auto fallback_cmp = fallback_order(a.second, b.second);
if (fallback_cmp != 0) return fallback_cmp > 0;
// This should not be hit, because fallback_order defines a strong ordering.
Assume(false);
return a.second < b.second;
};
// Construct a heap with all chunks that have no out-of-chunk dependencies.
for (TxIdx chunk_rep : chunk_reps) { for (TxIdx chunk_rep : chunk_reps) {
if (chunk_deps[chunk_rep].first == 0) ready_chunks.emplace_back(chunk_rep, m_rng.rand64()); if (chunk_deps[chunk_rep].first == 0) {
ready_chunks.emplace_back(chunk_rep, max_fallback_fn(chunk_rep));
}
} }
std::make_heap(ready_chunks.begin(), ready_chunks.end(), chunk_cmp_fn); std::make_heap(ready_chunks.begin(), ready_chunks.end(), chunk_cmp_fn);
// Pop chunks off the heap, highest-feerate ones first. // Pop chunks off the heap.
while (!ready_chunks.empty()) { while (!ready_chunks.empty()) {
auto [chunk_rep, _rnd] = ready_chunks.front(); auto [chunk_rep, _rnd] = ready_chunks.front();
std::pop_heap(ready_chunks.begin(), ready_chunks.end(), chunk_cmp_fn); std::pop_heap(ready_chunks.begin(), ready_chunks.end(), chunk_cmp_fn);
@@ -1296,21 +1369,18 @@ public:
Assume(chunk_deps[chunk_rep].first == 0); Assume(chunk_deps[chunk_rep].first == 0);
const auto& chunk_txn = m_tx_data[chunk_rep].chunk_setinfo.transactions; const auto& chunk_txn = m_tx_data[chunk_rep].chunk_setinfo.transactions;
// Build heap of all includable transactions in chunk. // Build heap of all includable transactions in chunk.
Assume(ready_tx.empty());
for (TxIdx tx_idx : chunk_txn) { for (TxIdx tx_idx : chunk_txn) {
if (chunk_deps[tx_idx].second == 0) { if (chunk_deps[tx_idx].second == 0) ready_tx.push_back(tx_idx);
ready_tx.push_back(tx_idx);
}
} }
Assume(!ready_tx.empty()); Assume(!ready_tx.empty());
// Pick transactions from the ready queue, append them to linearization, and decrement std::make_heap(ready_tx.begin(), ready_tx.end(), tx_cmp_fn);
// Pick transactions from the ready heap, append them to linearization, and decrement
// dependency counts. // dependency counts.
while (!ready_tx.empty()) { while (!ready_tx.empty()) {
// Move a random queue element to the back. // Pop an element from the tx_ready heap.
auto pos = m_rng.randrange(ready_tx.size()); auto tx_idx = ready_tx.front();
if (pos != ready_tx.size() - 1) std::swap(ready_tx.back(), ready_tx[pos]); std::pop_heap(ready_tx.begin(), ready_tx.end(), tx_cmp_fn);
// Pop from the back.
auto tx_idx = ready_tx.back();
Assume(chunk_txn[tx_idx]);
ready_tx.pop_back(); ready_tx.pop_back();
// Append to linearization. // Append to linearization.
ret.push_back(tx_idx); ret.push_back(tx_idx);
@@ -1321,15 +1391,16 @@ public:
// Decrement tx dependency count. // Decrement tx dependency count.
Assume(chunk_deps[chl_idx].second > 0); Assume(chunk_deps[chl_idx].second > 0);
if (--chunk_deps[chl_idx].second == 0 && chunk_txn[chl_idx]) { if (--chunk_deps[chl_idx].second == 0 && chunk_txn[chl_idx]) {
// Child tx has no dependencies left, and is in this chunk. Add it to the tx queue. // Child tx has no dependencies left, and is in this chunk. Add it to the tx heap.
ready_tx.push_back(chl_idx); ready_tx.push_back(chl_idx);
std::push_heap(ready_tx.begin(), ready_tx.end(), tx_cmp_fn);
} }
// Decrement chunk dependency count if this is out-of-chunk dependency. // Decrement chunk dependency count if this is out-of-chunk dependency.
if (chl_data.chunk_rep != chunk_rep) { if (chl_data.chunk_rep != chunk_rep) {
Assume(chunk_deps[chl_data.chunk_rep].first > 0); Assume(chunk_deps[chl_data.chunk_rep].first > 0);
if (--chunk_deps[chl_data.chunk_rep].first == 0) { if (--chunk_deps[chl_data.chunk_rep].first == 0) {
// Child chunk has no dependencies left. Add it to the chunk heap. // Child chunk has no dependencies left. Add it to the chunk heap.
ready_chunks.emplace_back(chl_data.chunk_rep, m_rng.rand64()); ready_chunks.emplace_back(chl_data.chunk_rep, max_fallback_fn(chl_data.chunk_rep));
std::push_heap(ready_chunks.begin(), ready_chunks.end(), chunk_cmp_fn); std::push_heap(ready_chunks.begin(), ready_chunks.end(), chunk_cmp_fn);
} }
} }
@@ -1521,6 +1592,9 @@ public:
* @param[in] rng_seed A random number seed to control search order. This prevents peers * @param[in] rng_seed A random number seed to control search order. This prevents peers
* from predicting exactly which clusters would be hard for us to * from predicting exactly which clusters would be hard for us to
* linearize. * linearize.
* @param[in] fallback_order A comparator to order transactions, used to sort equal-feerate
* chunks and transactions. See SpanningForestState::GetLinearization
* for details.
* @param[in] old_linearization An existing linearization for the cluster, or empty. * @param[in] old_linearization An existing linearization for the cluster, or empty.
* @param[in] is_topological (Only relevant if old_linearization is not empty) Whether * @param[in] is_topological (Only relevant if old_linearization is not empty) Whether
* old_linearization is topologically valid. * old_linearization is topologically valid.
@@ -1532,7 +1606,13 @@ public:
* - How many optimization steps were actually performed. * - How many optimization steps were actually performed.
*/ */
template<typename SetType> template<typename SetType>
std::tuple<std::vector<DepGraphIndex>, bool, uint64_t> Linearize(const DepGraph<SetType>& depgraph, uint64_t max_iterations, uint64_t rng_seed, std::span<const DepGraphIndex> old_linearization = {}, bool is_topological = true) noexcept std::tuple<std::vector<DepGraphIndex>, bool, uint64_t> Linearize(
const DepGraph<SetType>& depgraph,
uint64_t max_iterations,
uint64_t rng_seed,
const StrongComparator<DepGraphIndex> auto& fallback_order,
std::span<const DepGraphIndex> old_linearization = {},
bool is_topological = true) noexcept
{ {
/** Initialize a spanning forest data structure for this cluster. */ /** Initialize a spanning forest data structure for this cluster. */
SpanningForestState forest(depgraph, rng_seed); SpanningForestState forest(depgraph, rng_seed);
@@ -1562,7 +1642,7 @@ std::tuple<std::vector<DepGraphIndex>, bool, uint64_t> Linearize(const DepGraph<
} }
} while (forest.GetCost() < max_iterations); } while (forest.GetCost() < max_iterations);
} }
return {forest.GetLinearization(), optimal, forest.GetCost()}; return {forest.GetLinearization(fallback_order), optimal, forest.GetCost()};
} }
/** Improve a given linearization. /** Improve a given linearization.
+2 -3
View File
@@ -84,12 +84,11 @@ private:
public: public:
virtual ~CTxMemPoolEntry() = default; virtual ~CTxMemPoolEntry() = default;
CTxMemPoolEntry(TxGraph::Ref&& ref, const CTransactionRef& tx, CAmount fee, CTxMemPoolEntry(const CTransactionRef& tx, CAmount fee,
int64_t time, unsigned int entry_height, uint64_t entry_sequence, int64_t time, unsigned int entry_height, uint64_t entry_sequence,
bool spends_coinbase, bool spends_coinbase,
int64_t sigops_cost, LockPoints lp) int64_t sigops_cost, LockPoints lp)
: TxGraph::Ref(std::move(ref)), : tx{tx},
tx{tx},
nFee{fee}, nFee{fee},
nTxWeight{GetTransactionWeight(*tx)}, nTxWeight{GetTransactionWeight(*tx)},
nUsageSize{RecursiveDynamicUsage(tx)}, nUsageSize{RecursiveDynamicUsage(tx)},
+2 -1
View File
@@ -9,6 +9,7 @@
#include <uint256.h> #include <uint256.h>
#include <util/types.h> #include <util/types.h>
#include <compare>
#include <cstddef> #include <cstddef>
#include <optional> #include <optional>
#include <string> #include <string>
@@ -42,7 +43,7 @@ public:
template <typename Other> template <typename Other>
bool operator==(const Other& other) const { return Compare(other) == 0; } bool operator==(const Other& other) const { return Compare(other) == 0; }
template <typename Other> template <typename Other>
bool operator<(const Other& other) const { return Compare(other) < 0; } std::strong_ordering operator<=>(const Other& other) const { return Compare(other) <=> 0; }
const uint256& ToUint256() const LIFETIMEBOUND { return m_wrapped; } const uint256& ToUint256() const LIFETIMEBOUND { return m_wrapped; }
static transaction_identifier FromUint256(const uint256& id) { return {id}; } static transaction_identifier FromUint256(const uint256& id) { return {id}; }
+230 -233
View File
@@ -54,7 +54,7 @@ void TestDepGraphSerialization(const std::vector<std::pair<FeeFrac, SetType>>& c
BOOST_CHECK(depgraph == depgraph_read); BOOST_CHECK(depgraph == depgraph_read);
} }
void TestOptimalLinearization(const std::vector<uint8_t>& enc, const std::vector<FeeFrac>& optimal_diagram) void TestOptimalLinearization(std::span<const uint8_t> enc, std::initializer_list<DepGraphIndex> optimal_linearization)
{ {
DepGraphIndex tx_count = 0; DepGraphIndex tx_count = 0;
FastRandomContext rng; FastRandomContext rng;
@@ -88,14 +88,11 @@ void TestOptimalLinearization(const std::vector<uint8_t>& enc, const std::vector
is_topological = false; is_topological = false;
break; break;
} }
std::tie(lin, opt, cost) = Linearize(depgraph, 1000000000000, rng.rand64(), lin, is_topological); std::tie(lin, opt, cost) = Linearize(depgraph, 1000000000000, rng.rand64(), IndexTxOrder{}, lin, is_topological);
BOOST_CHECK(opt); BOOST_CHECK(opt);
BOOST_CHECK(cost <= MaxOptimalLinearizationIters(depgraph.TxCount())); BOOST_CHECK(cost <= MaxOptimalLinearizationIters(depgraph.TxCount()));
SanityCheck(depgraph, lin); SanityCheck(depgraph, lin);
auto chunking = ChunkLinearization(depgraph, lin); BOOST_CHECK(std::ranges::equal(lin, optimal_linearization));
BOOST_CHECK(std::is_eq(CompareChunks(chunking, optimal_diagram)));
// Verify that the chunks are minimal.
BOOST_CHECK_EQUAL(chunking.size(), optimal_diagram.size());
} }
tx_count = depgraph.PositionRange(); tx_count = depgraph.PositionRange();
}; };
@@ -244,239 +241,239 @@ BOOST_AUTO_TEST_CASE(depgraph_optimal_tests)
// Compare linearizations with known-optimal chunk feerate diagrams. // Compare linearizations with known-optimal chunk feerate diagrams.
// Hard clusters (according to various metrics) that appeared in replayed 2023 mempool data, ranging from 2 to 64 transactions. // Hard clusters (according to various metrics) that appeared in replayed 2023 mempool data, ranging from 2 to 64 transactions.
TestOptimalLinearization("9276fa3a009c3b80cd4001a21680d85c02927bfa5403934280845404a04c80cf0805c75b82c22206a46880f532079c7e80b85608965780916a09a04a80cf080a9823809b3e0bb27b81ec0c0c8540c60e0c0c993e80c86a0d0b8540c2020c0c9352809f780c09972f80f84a080c85449900080c875da164080c875081ae54070c8335af4c071f9c6781a72a13010f99108190160e000e85419f2c07168332903c05158540819e54041216ba5183907a140000001182428d080024a25c83c11201040400010609b6668487240004060000000000"_hex_v_u8, {{47188, 8550}, {42800, 7755}, {325314, 79021}, {2070, 833}, {900, 450}, {2226, 1117}, {1664, 836}, {1118, 562}}); TestOptimalLinearization("9276fa3a009c3b80cd4001a21680d85c02927bfa5403934280845404a04c80cf0805c75b82c22206a46880f532079c7e80b85608965780916a09a04a80cf080a9823809b3e0bb27b81ec0c0c8540c60e0c0c993e80c86a0d0b8540c2020c0c9352809f780c09972f80f84a080c85449900080c875da164080c875081ae54070c8335af4c071f9c6781a72a13010f99108190160e000e85419f2c07168332903c05158540819e54041216ba5183907a140000001182428d080024a25c83c11201040400010609b6668487240004060000000000"_hex_u8, {3, 0, 1, 2, 4, 28, 29, 5, 16, 10, 12, 22, 24, 9, 14, 11, 13, 17, 19, 18, 27, 6, 7, 8, 20, 30, 21, 15, 25, 23, 26});
TestOptimalLinearization("850d81fd4000850e81fd400000850d81fd400000850d81fd400000850e8285000000850d8285000000850e8288600000850e8288600000850e828860000000"_hex_v_u8, {{223440, 7034}}); TestOptimalLinearization("850d81fd4000850e81fd400000850d81fd400000850d81fd400000850e8285000000850d8285000000850e8288600000850e8288600000850e828860000000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8});
TestOptimalLinearization("818f1c8a935a0083219530000083219530010083219530020083219530030083219530040083219530050083219530060083219530070083219530080000"_hex_v_u8, {{104325, 39749}}); TestOptimalLinearization("818f1c8a935a0083219530000083219530010083219530020083219530030083219530040083219530050083219530060083219530070083219530080000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9});
TestOptimalLinearization("836880bf4000834c80b6600000836880bf400100834c80b6600001836880bf400101834c80b6600002836880bf400102834c80b6600003836880bf400103834c80b6600004836880bf400104834c80b6600005836880bf400105836880bf400006834c80b6600106834c80b6600106836880bf400206834c80b6600008836880bf400108836880bf40000900"_hex_v_u8, {{12320, 616}, {11760, 588}, {12320, 616}, {11760, 588}, {12320, 616}, {11760, 588}, {12320, 616}, {11760, 588}, {12320, 616}, {11760, 588}, {12320, 616}, {11760, 588}, {12320, 616}, {11760, 588}, {12320, 616}, {11760, 588}, {12320, 616}, {11760, 588}, {12320, 616}, {12320, 616}}); TestOptimalLinearization("836880bf4000834c80b6600000836880bf400100834c80b6600001836880bf400101834c80b6600002836880bf400102834c80b6600003836880bf400103834c80b6600004836880bf400104834c80b6600005836880bf400105836880bf400006834c80b6600106834c80b6600106836880bf400206834c80b6600008836880bf400108836880bf40000900"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 13, 15, 16, 17, 18, 19});
TestOptimalLinearization("84a22e8fce380083208c38000083208c38010083208c38020083208c38030083208c38040083208c38050083208c38060083208c38070083208c38080083208c38090000"_hex_v_u8, {{144756, 91886}}); TestOptimalLinearization("84a22e8fce380083208c38000083208c38010083208c38020083208c38030083208c38040083208c38050083208c38060083208c38070083208c38080083208c38090000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
TestOptimalLinearization("8361a8340084309730000000"_hex_v_u8, {{2650, 609}, {1560, 688}}); TestOptimalLinearization("8361a8340084309730000000"_hex_u8, {0, 1});
TestOptimalLinearization("829428f0fe20008319809604000183198096040100831980960402008319809604030083198096040400831980960405008319809604060083198096040700831980960408008319809604090083198096040a0083198096040b0083198096040c0083198096040d0083198096040e0083198096040f008319809604100083198096041100831980960412008319809604130083198096041400831980960415008319809604160083198096041700831980960418008319809604190083198096041a0000"_hex_v_u8, {{933840, 51880}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}}); TestOptimalLinearization("829428f0fe20008319809604000183198096040100831980960402008319809604030083198096040400831980960405008319809604060083198096040700831980960408008319809604090083198096040a0083198096040b0083198096040c0083198096040d0083198096040e0083198096040f008319809604100083198096041100831980960412008319809604130083198096041400831980960415008319809604160083198096041700831980960418008319809604190083198096041a0000"_hex_u8, {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27});
TestOptimalLinearization("854ec47200854ec4720001854ec4720001854ec4720001854ec4720001854ec4720001854ec4720001854ec4720001854ec4720001854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec472000000"_hex_v_u8, {{4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}}); TestOptimalLinearization("854ec47200854ec4720001854ec4720001854ec4720001854ec4720001854ec4720001854ec4720001854ec4720001854ec4720001854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec472000000"_hex_u8, {8, 0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24});
TestOptimalLinearization("d1378f927c00e81293cc4001f36095ef5202f20195c33203e93a93817404e76793d0700b80ba72a3e82806fd4697e52207da5d91894608c73d8d98401480990c9d954a0af73292e73a0b8090259bba640c808f689bac760de50692fc1e0eac40888c1a0fbf308bcf481080a3259f980c11c30282fd78128b6f83c2300612932d8ba65e0b09896a88837c010011886281d6380e0000040f953c8594580b000000129e0491c0381300000000148235f72802228653818c08021db40c9180620229833180991c011f854081a95c0020833180bd66002082418097740020953c8784000e00000000000201030d8d7c838d0c04011a874f84842a001600"_hex_v_u8, {{248978, 14346}, {1136423, 78068}, {270282, 20244}, {1423139, 109038}, {903617, 69567}, {106746, 10092}}); TestOptimalLinearization("d1378f927c00e81293cc4001f36095ef5202f20195c33203e93a93817404e76793d0700b80ba72a3e82806fd4697e52207da5d91894608c73d8d98401480990c9d954a0af73292e73a0b8090259bba640c808f689bac760de50692fc1e0eac40888c1a0fbf308bcf481080a3259f980c11c30282fd78128b6f83c2300612932d8ba65e0b09896a88837c010011886281d6380e0000040f953c8594580b000000129e0491c0381300000000148235f72802228653818c08021db40c9180620229833180991c011f854081a95c0020833180bd66002082418097740020953c8784000e00000000000201030d8d7c838d0c04011a874f84842a001600"_hex_u8, {13, 33, 0, 1, 2, 3, 4, 6, 7, 26, 27, 8, 9, 10, 11, 12, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 34, 30, 31, 32, 28, 29, 25, 35, 36});
TestOptimalLinearization("836880ba5807845d80df200000836880ba580100845d80df200001836880bd0c0101845d80e2100002836880bf400102845d80e5000003836880bf400103845d80e5000004854e818800010300854e818800000300854e818800000200854e818800000100854e819178000000836880ed1c0000845f819b500017854e818b28001700"_hex_v_u8, {{252408, 12326}, {17172, 846}}); TestOptimalLinearization("836880ba5807845d80df200000836880ba580100845d80df200001836880bd0c0101845d80e2100002836880bf400102845d80e5000003836880bf400103845d80e5000004854e818800010300854e818800000300854e818800000200854e818800000100854e819178000000836880ed1c0000845f819b500017854e818b28001700"_hex_u8, {9, 10, 11, 13, 15, 16, 17, 18, 19, 14, 12, 20, 21, 22, 23, 24, 0, 1});
TestOptimalLinearization("854e829b580088318881580000a37a90ae600000a37a90ae600100a37a90ae600200a37a90ae600300835a819e680303835a819e680403835a819e680503835a819e680603835a819e680703835a819e680803835a819e680903835a819e680a03835a819e680b03835a819e680c03835a819e680d03835a819e680e03835a819e680f03835a819e681003835a819e681103835a819e681203835a819e681303835a819e681403835a819e681503835a819e681603835a819e681703835a819e681803835a819e681903835a819e681a03835a819e681902835a819e681b01835a819e681c01835a819e681c02835a819e681e01835a819e681f01835a819e682001835a819e682002835a819e682102835a819e682301835a819e682302835a819e682501835a819e682502835a819e682602835a819e682801835a819e682802835a819e682a01835a819e682a02835a819e682b02835a819e682d01835a819e682d02835a819e682f01835a819e682f02835a819e683002835a819e68320100"_hex_v_u8, {{100312, 2047}, {584400, 19178}, {381780, 12556}, {363360, 11954}, {142320, 4730}}); TestOptimalLinearization("854e829b580088318881580000a37a90ae600000a37a90ae600100a37a90ae600200a37a90ae600300835a819e680303835a819e680403835a819e680503835a819e680603835a819e680703835a819e680803835a819e680903835a819e680a03835a819e680b03835a819e680c03835a819e680d03835a819e680e03835a819e680f03835a819e681003835a819e681103835a819e681203835a819e681303835a819e681403835a819e681503835a819e681603835a819e681703835a819e681803835a819e681903835a819e681a03835a819e681902835a819e681b01835a819e681c01835a819e681c02835a819e681e01835a819e681f01835a819e682001835a819e682002835a819e682102835a819e682301835a819e682302835a819e682501835a819e682502835a819e682602835a819e682801835a819e682802835a819e682a01835a819e682a02835a819e682b02835a819e682d01835a819e682d02835a819e682f01835a819e682f02835a819e683002835a819e68320100"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 28, 30, 33, 37, 38, 40, 42, 43, 45, 47, 48, 50, 52, 53, 27, 31, 32, 34, 35, 36, 39, 41, 44, 46, 49, 51, 54, 29});
TestOptimalLinearization("83688095520089c17481b5cf780000842d809c700000842d809c700100842d809c700200842d809c700300842d809c700400842d809c700500842d809c700600842d809c700700842d809c700800842d809c700900842d809c700a00842d809c700b00842d809c700c00842d809c700d00842d809c700e00842d809c700f00842d809c701000842d809c701100842d809c701200842d809c701300842d809c701400842d809c701500842d809c701600842d809c701700842d809c701800842d809c701900842d809c701a00842d809c701b00842d809c701c00842d809c701d00842d809c701e00842d809c701f00842d809c702000842d809c702100842d809c702200842d809c702300842d809c702400842d809c702500842d809c702600842d809c702700842d809c702800842d809c702900842d809c702a00842d809c702b00842d809c702c00842d809c702d00842d809c702e00842d809c702f00842d809c703000842d809c703100842d809c703200842d809c70330000"_hex_v_u8, {{9641, 616}, {2544700, 172404}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}}); TestOptimalLinearization("83688095520089c17481b5cf780000842d809c700000842d809c700100842d809c700200842d809c700300842d809c700400842d809c700500842d809c700600842d809c700700842d809c700800842d809c700900842d809c700a00842d809c700b00842d809c700c00842d809c700d00842d809c700e00842d809c700f00842d809c701000842d809c701100842d809c701200842d809c701300842d809c701400842d809c701500842d809c701600842d809c701700842d809c701800842d809c701900842d809c701a00842d809c701b00842d809c701c00842d809c701d00842d809c701e00842d809c701f00842d809c702000842d809c702100842d809c702200842d809c702300842d809c702400842d809c702500842d809c702600842d809c702700842d809c702800842d809c702900842d809c702a00842d809c702b00842d809c702c00842d809c702d00842d809c702e00842d809c702f00842d809c703000842d809c703100842d809c703200842d809c70330000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53});
TestOptimalLinearization("99469a2e008e638f32018e638f32028e638718038e638718048e638718058e648c44068e659002078e639340088f74873c098e6488380a8d6586340b894784240c894784240d8b56852c0ea71993100f8b6d8538108b56852c118e628b76128e638b76138e638b76148e628b76158e648b7616a06c8f78178e638b76188e628838198e638b761a8e6388381b894784241c9412894c1d8e6690521e9c538e1c05199b10f15017000400189527955a1a0000000000001a9e5d8e70120000000000000117b372993c000300000000000000000000000000001800"_hex_v_u8, {{11835, 11678}, {1129, 2022}, {1751, 3398}, {866, 2020}, {827, 2018}, {827, 2018}, {827, 2019}, {827, 2019}, {827, 2019}, {827, 2019}, {827, 2020}, {3025, 8912}, {604, 2018}, {604, 2019}, {604, 2020}, {974, 3795}, {678, 2706}, {542, 2164}, {412, 1645}, {474, 1893}, {1288, 5145}, {406, 1622}, {406, 1622}, {1084, 4332}, {3724, 14884}}); TestOptimalLinearization("99469a2e008e638f32018e638f32028e638718038e638718048e638718058e648c44068e659002078e639340088f74873c098e6488380a8d6586340b894784240c894784240d8b56852c0ea71993100f8b6d8538108b56852c118e628b76128e638b76138e638b76148e628b76158e648b7616a06c8f78178e638b76188e628838198e638b761a8e6388381b894784241c9412894c1d8e6690521e9c538e1c05199b10f15017000400189527955a1a0000000000001a9e5d8e70120000000000000117b372993c000300000000000000000000000000001800"_hex_u8, {9, 8, 1, 2, 10, 34, 0, 6, 22, 25, 23, 24, 28, 30, 26, 3, 4, 5, 7, 29, 31, 12, 35, 33, 11, 20, 13, 17, 16, 21, 27, 14, 15, 32, 18, 19});
TestOptimalLinearization("833583380083368338000083328334000083318334000083328334000083368338000083358338000083328334000000"_hex_v_u8, {{284, 565}, {848, 1689}, {850, 1693}, {282, 562}}); TestOptimalLinearization("833583380083368338000083328334000083318334000083328334000083368338000083358338000083328334000000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7});
TestOptimalLinearization("80f96f88ab2a008235839b0600008a4880b31801008604ec3c02008235a97c0300833dab7204008752d502050000"_hex_v_u8, {{140794, 37044}}); TestOptimalLinearization("80f96f88ab2a008235839b0600008a4880b31801008604ec3c02008235a97c0300833dab7204008752d502050000"_hex_u8, {0, 1, 2, 3, 4, 5, 6});
TestOptimalLinearization("f9718def4800823ab01c01833980c238028544848f20038478e07c04887280ef2a05823680a54e068081149ea80a07808714ac995208823680a55c0980b85cbcdc020abb759acf180b8338fe680c82359eac280c0c824280a9620d0c857cf9400e0c823ae5520a0c823590c744090c823584ef14090c847c80a32a0a0c8451808b100b0c824280a9420a0c823580a52c0b0c823586bf2c0c0c857c8186200d0c847882c63a0d0c854081cf060e0c833880b66e0f0c8338808e40100b8368809552110b8241de74130a8242c34c1608894480bc48102a851e818356050e0fad56888c401d00000000198fe81c808fc7501a0000000410933d86e120031300000a00"_hex_v_u8, {{42000, 836}, {255465, 8557}, {21507, 832}, {10670, 438}, {10663, 438}, {588686, 25096}, {389673, 16616}, {418483, 17865}, {400487, 17097}, {12508, 569}, {11767, 568}, {16848, 892}, {24863, 1366}, {83604, 4861}, {9184, 568}, {9641, 616}, {10517, 764}, {6138, 449}, {21950, 1708}, {8968, 721}, {84012, 7176}, {4390, 450}, {1184296, 275612}}); TestOptimalLinearization("f9718def4800823ab01c01833980c238028544848f20038478e07c04887280ef2a05823680a54e068081149ea80a07808714ac995208823680a55c0980b85cbcdc020abb759acf180b8338fe680c82359eac280c0c824280a9620d0c857cf9400e0c823ae5520a0c823590c744090c823584ef14090c847c80a32a0a0c8451808b100b0c824280a9420a0c823580a52c0b0c823586bf2c0c0c857c8186200d0c847882c63a0d0c854081cf060e0c833880b66e0f0c8338808e40100b8368809552110b8241de74130a8242c34c1608894480bc48102a851e818356050e0fad56888c401d00000000198fe81c808fc7501a0000000410933d86e120031300000a00"_hex_u8, {7, 26, 27, 28, 20, 12, 21, 24, 23, 22, 0, 1, 2, 15, 16, 13, 14, 6, 29, 25, 30, 31, 3, 4, 34, 32, 33, 17, 35, 10, 11, 18, 8, 5, 9, 36, 19});
TestOptimalLinearization("82369e200084459e200186569e200282369e200384459e200488649e200586559e200684459e200788649e200886549e200984449e200a82369e200b9961dc600ca34b81da7800000000000000000000000000008368af4c0000869520c6dd6800008368af3800008368af3801008368af3802008368af3803008368af3804008368af3805008368af3806008368af3807008368af3808008368af3809008368af380a008368af380b008368af380c008368af380d008368af380e008368af380f0000"_hex_v_u8, {{692678, 145712}}); TestOptimalLinearization("82369e200084459e200186569e200282369e200384459e200488649e200586559e200684459e200788649e200886549e200984449e200a82369e200b9961dc600ca34b81da7800000000000000000000000000008368af4c0000869520c6dd6800008368af3800008368af3801008368af3802008368af3803008368af3804008368af3805008368af3806008368af3807008368af3808008368af3809008368af380a008368af380b008368af380c008368af380d008368af380e008368af380f0000"_hex_u8, {0, 3, 11, 10, 1, 4, 7, 9, 6, 2, 12, 5, 8, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31});
TestOptimalLinearization("8335862e008335862e00008335862e00008335862e00008335862e00008335862e00008335862e00008335862e00008331862600008335862e00008335862e00008335862e00008335862e00008335862e00008335862e0000833d863a00008335862e00008335862e00008544896a000000"_hex_v_u8, {{471, 565}, {471, 565}, {471, 565}, {471, 565}, {471, 565}, {471, 565}, {471, 565}, {471, 565}, {3293, 3951}, {1419, 1703}, {693, 836}}); TestOptimalLinearization("8335862e008335862e00008335862e00008335862e00008335862e00008335862e00008335862e00008335862e00008331862600008335862e00008335862e00008335862e00008335862e00008335862e00008335862e0000833d863a00008335862e00008335862e00008544896a000000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18});
TestOptimalLinearization("836183f20200842b84b82e00008a1089f33e0100842a849a7c00018361838f420101842b83ca680002836282f8280102842983b00c000300"_hex_v_u8, {{40129, 609}, {44631, 683}, {89375, 1424}, {42750, 682}, {33825, 609}, {37620, 683}, {32340, 610}, {35910, 681}}); TestOptimalLinearization("836183f20200842b84b82e00008a1089f33e0100842a849a7c00018361838f420101842b83ca680002836282f8280102842983b00c000300"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7});
TestOptimalLinearization("80fc6c80fd300080e03c80f50e01823aaf3402823aac060380f42080f55e04833d84200580ea0580ea6006833e855a0780ce7c81b724088235898b1c08088474bd2c0908875180a10e0a08857cb0000b088239ad260c088336b8180d0889448e660e08823588db0e0e088242ac5a0c08823588df180d08854588660e088478d670120584498a440f08833dbb1e0f088474ea3810088470d83a1108823588ac7812088242844a13088546886614088545d67e1705823a84181b02875c8c0a1707854088601a058241ae3c1b05823587a67e180887548b7e19088241ae3c21018600d6401b08823a84141c088336854825008755f34a1e088335b6001c2d81d25ca2f16e27001e902d80ea6a250318894ce9202206068336d140034c9969829e282800001d82f57fb48c2e260000040e00"_hex_v_u8, {{3098, 442}, {2883, 442}, {1070885, 209051}, {148942, 39219}, {107942, 30418}, {3136, 892}, {738, 713}, {357, 450}, {332, 442}, {624, 832}, {831, 1108}, {837, 1116}, {1011, 1348}, {627, 837}, {627, 838}, {330, 442}, {420, 566}}); TestOptimalLinearization("80fc6c80fd300080e03c80f50e01823aaf3402823aac060380f42080f55e04833d84200580ea0580ea6006833e855a0780ce7c81b724088235898b1c08088474bd2c0908875180a10e0a08857cb0000b088239ad260c088336b8180d0889448e660e08823588db0e0e088242ac5a0c08823588df180d08854588660e088478d670120584498a440f08833dbb1e0f088474ea3810088470d83a1108823588ac7812088242844a13088546886614088545d67e1705823a84181b02875c8c0a1707854088601a058241ae3c1b05823587a67e180887548b7e19088241ae3c21018600d6401b08823a84141c088336854825008755f34a1e088335b6001c2d81d25ca2f16e27001e902d80ea6a250318894ce9202206068336d140034c9969829e282800001d82f57fb48c2e260000040e00"_hex_u8, {13, 14, 31, 22, 10, 11, 21, 42, 24, 28, 26, 27, 25, 0, 1, 3, 12, 32, 7, 8, 5, 6, 2, 15, 17, 18, 20, 37, 33, 16, 38, 39, 46, 43, 41, 4, 23, 29, 34, 36, 40, 35, 9, 19, 30, 44, 45});
TestOptimalLinearization("80e67480e6740080d53480d56e0180d04881bd62028f108f1c038335cb7204847ce13e0404824184240504823594990c0604823580d07c07048235a6160804857cdd4009048474f2640904823592ce5c0a04833692700b048540ad300d038608b37c0c04823583e0720d048500a9000e048239841c0f048242b70011038540cc681203833e855a13038470bf7c13048545956a16008600be000d1a8f1880990a17000d8a448a4c1600048544f63c1603018f18f1180c0d0b8600ac40041f00"_hex_v_u8, {{4921, 565}, {221979, 33050}, {185495, 29087}, {4980, 832}, {2507, 437}, {9861, 2072}, {4032, 896}, {2968, 832}, {2912, 896}, {76978, 31757}, {1272, 566}, {1461, 837}, {334, 441}, {338, 449}, {429, 574}, {1038, 2064}, {742, 1476}}); TestOptimalLinearization("80e67480e6740080d53480d56e0180d04881bd62028f108f1c038335cb7204847ce13e0404824184240504823594990c0604823580d07c07048235a6160804857cdd4009048474f2640904823592ce5c0a04833692700b048540ad300d038608b37c0c04823583e0720d048500a9000e048239841c0f048242b70011038540cc681203833e855a13038470bf7c13048545956a16008600be000d1a8f1880990a17000d8a448a4c1600048544f63c1603018f18f1180c0d0b8600ac40041f00"_hex_u8, {27, 0, 3, 4, 28, 1, 6, 8, 10, 9, 21, 22, 5, 12, 7, 13, 20, 14, 16, 24, 15, 17, 18, 11, 29, 19, 2, 23, 25, 26});
TestOptimalLinearization("84418c6a0080fe1d86fc00000080b97084ea50000080de1c85fc00010080ed4986b930020080a17b848a70030080d07b85c670040080a86b84a630050080e405869320060080db1185ef50070080d11b85c770080080d00185c310090000"_hex_v_u8, {{593589, 297030}}); TestOptimalLinearization("84418c6a0080fe1d86fc00000080b97084ea50000080de1c85fc00010080ed4986b930020080a17b848a70030080d07b85c670040080a86b84a630050080e405869320060080db1185ef50070080d11b85c770080080d00185c310090000"_hex_u8, {0, 1, 2, 3, 11, 9, 8, 4, 5, 7, 6, 10});
TestOptimalLinearization("856ea51800856da5180000856eab080002856eab080002856dab080002856dab08000000"_hex_v_u8, {{16168, 5265}}); TestOptimalLinearization("856ea51800856da5180000856eab080002856eab080002856dab080002856dab08000000"_hex_u8, {3, 4, 0, 1, 2, 5});
TestOptimalLinearization("83318c2a00833d8c400183318c1c0283318c1c020283318c1c020283358c28020283318c1e020683318c1c020583318c1c0204833d8c40020a833d8c40020883318c1c020683318c1c020e83318c1c020b8331943e0208833d8c40021283318c1e020e83319a0c020a83358d58011183318c1e031083318d08011383318c1c0113833d8c40011583319a0c011483318c1c01169260809308021583358c280118a84380f9100a021383318c1c011983319430001983319938001983319a1c001883319a0c00188540a71609030683319a0c011983319a0c011283319a0c011283319a0c0113833d9a56011483319b52011483359a26011583359b6c011583319a0c011783319b52011683319a0c011983319b52011783319b52011b83319b520118833d9d6a001983309d18001900"_hex_v_u8, {{88836, 35145}}); TestOptimalLinearization("83318c2a00833d8c400183318c1c0283318c1c020283318c1c020283358c28020283318c1e020683318c1c020583318c1c0204833d8c40020a833d8c40020883318c1c020683318c1c020e83318c1c020b8331943e0208833d8c40021283318c1e020e83319a0c020a83358d58011183318c1e031083318d08011383318c1c0113833d8c40011583319a0c011483318c1c01169260809308021583358c280118a84380f9100a021383318c1c011983319430001983319938001983319a1c001883319a0c00188540a71609030683319a0c011983319a0c011283319a0c011283319a0c0113833d9a56011483319b52011483359a26011583359b6c011583319a0c011783319b52011683319a0c011983319b52011783319b52011b83319b520118833d9d6a001983309d18001900"_hex_u8, {0, 1, 2, 28, 29, 30, 31, 32, 33, 3, 4, 5, 16, 20, 27, 34, 35, 38, 43, 44, 45, 46, 47, 48, 49, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 23, 17, 18, 19, 21, 22, 24, 25, 26, 36, 37, 39, 40, 41, 42});
TestOptimalLinearization("80886c99f50c00835df5600000835df5600100835df5600200835df5600300835df5600400835df5600500835df5600600835df5600700835df5600800835df5600900835df5600a00835df5600b00835df5600c00835df5600d00835df5600e00835df5600f00835df5601000835df5601100835df5601200835df5601300835df5601400835df5601500835df5601600835df5601700836880cd78180080895badcb740018835b80c9740018835b80c9740118835b80c9740218835b80c9740318835b80c9740418835b80c9740518835b80c9740618835b80c9740718835b80c9740818835b80c9740918835b80c9740a18835b80c9740b18835b80c9740c18835b80c9740d18835b80c9740e18835b80c9740f18835b80c9741018835b80c974111800"_hex_v_u8, {{849296, 46869}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}}); TestOptimalLinearization("80886c99f50c00835df5600000835df5600100835df5600200835df5600300835df5600400835df5600500835df5600600835df5600700835df5600800835df5600900835df5600a00835df5600b00835df5600c00835df5600d00835df5600e00835df5600f00835df5601000835df5601100835df5601200835df5601300835df5601400835df5601500835df5601600835df5601700836880cd78180080895badcb740018835b80c9740018835b80c9740118835b80c9740218835b80c9740318835b80c9740418835b80c9740518835b80c9740618835b80c9740718835b80c9740818835b80c9740918835b80c9740a18835b80c9740b18835b80c9740c18835b80c9740d18835b80c9740e18835b80c9740f18835b80c9741018835b80c974111800"_hex_u8, {0, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24});
TestOptimalLinearization("8514d518008344be3800008514d51801008344be3800018514d51801018514d51800028344be3801028344be3801028514d51802028344be3800048514d51801048344be3800058514d51801058514d51800068344be3801068344be3801068514d51802068344be3800088514d51801088344be3800098514d51801098514d518000a00"_hex_v_u8, {{5516, 788}, {4060, 580}, {5516, 788}, {4060, 580}, {5516, 788}, {4060, 580}, {5516, 788}, {4060, 580}, {5516, 788}, {4060, 580}, {5516, 788}, {4060, 580}, {5516, 788}, {4060, 580}, {5516, 788}, {4060, 580}, {5516, 788}, {4060, 580}, {5516, 788}, {4060, 580}, {5516, 788}, {5516, 788}}); TestOptimalLinearization("8514d518008344be3800008514d51801008344be3800018514d51801018514d51800028344be3801028344be3801028514d51802028344be3800048514d51801048344be3800058514d51801058514d51800068344be3801068344be3801068514d51802068344be3800088514d51801088344be3800098514d51801098514d518000a00"_hex_u8, {0, 1, 2, 3, 4, 6, 5, 7, 8, 9, 10, 11, 12, 14, 13, 15, 16, 17, 18, 19, 20, 21});
TestOptimalLinearization("8442922e009069bd3a0000872d9c1a010083618f5e010183618f5e020183618f5e030183618f5e040183618f5e050183618f5e060183618f5e070183618f5e080183618f5e09019743a36609018442922e0a01835f8610010b835f8610020b835f8610030b835f8610040b835f8610050b835f8610060b835f8610070b835f8610080b835f8610090b835f86100a0b835f86100b0b835f86100c0b8442d82a0c0b8441e332001700"_hex_v_u8, {{16489, 3892}, {13636, 7762}, {7827, 10423}}); TestOptimalLinearization("8442922e009069bd3a0000872d9c1a010083618f5e010183618f5e020183618f5e030183618f5e040183618f5e050183618f5e060183618f5e070183618f5e080183618f5e09019743a36609018442922e0a01835f8610010b835f8610020b835f8610030b835f8610040b835f8610050b835f8610060b835f8610070b835f8610080b835f8610090b835f86100a0b835f86100b0b835f86100c0b8442d82a0c0b8441e332001700"_hex_u8, {0, 11, 25, 26, 27, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24});
TestOptimalLinearization("9420928e2c008368f11a0000c52488dd700000834acf100000834acf100100834acf100200834acf100300834acf100400834acf100500834acf100600834acf100700834acf100800834acf100900834acf100a00834acf100b00834acf100c00834acf100d00834acf100e00834acf100f00834acf101000834acf101100834acf101200834acf101300834acf10140000"_hex_v_u8, {{156630, 2720}, {7309, 616}, {79800, 8996}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}}); TestOptimalLinearization("9420928e2c008368f11a0000c52488dd700000834acf100000834acf100100834acf100200834acf100300834acf100400834acf100500834acf100600834acf100700834acf100800834acf100900834acf100a00834acf100b00834acf100c00834acf100d00834acf100e00834acf100f00834acf101000834acf101100834acf101200834acf101300834acf10140000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23});
TestOptimalLinearization("9d2c83920200856cf66200008570f7280100856bf65202008567f60c03008563f54604008572f74c0500856ef7060600856af6400700856af64008008561f52209008566f57a0a008566f57a0b008575f8000c008571f73a0d008571f73a0e00856df6740f00856df67410008565f56811008561f522120000"_hex_v_u8, {{102774, 11745}, {7569, 865}, {7569, 865}, {7604, 869}, {7674, 877}, {7674, 877}, {7709, 881}, {7709, 881}, {7744, 885}, {7665, 876}, {7700, 880}}); TestOptimalLinearization("9d2c83920200856cf66200008570f7280100856bf65202008567f60c03008563f54604008572f74c0500856ef7060600856af6400700856af64008008561f52209008566f57a0a008566f57a0b008575f8000c008571f73a0d008571f73a0e00856df6740f00856df67410008565f56811008561f522120000"_hex_u8, {0, 5, 4, 3, 11, 12, 8, 9, 7, 6, 10, 19, 18, 16, 17, 14, 15, 13, 1, 2});
TestOptimalLinearization("854e80806600854e80806600008368e25000008462f54200008368e50601008463f8340001854e80b25c010000854e80b606000183688089400001846280a3620001854e80c00401000083688095520001846280b21c000100"_hex_v_u8, {{120967, 9647}}); TestOptimalLinearization("854e80806600854e80806600008368e25000008462f54200008368e50601008463f8340001854e80b25c010000854e80b606000183688089400001846280a3620001854e80c00401000083688095520001846280b21c000100"_hex_u8, {0, 1, 2, 4, 5, 3, 6, 7, 8, 10, 11, 12, 9});
TestOptimalLinearization("836186101483618872001583608842001584508d74001583618812011500"_hex_v_u8, {{2652, 2546}, {585, 609}}); TestOptimalLinearization("836186101483618872001583608842001584508d74001583618812011500"_hex_u8, {24, 0, 1, 2, 3});
TestOptimalLinearization("8ee34aafe24c0083208c1a000083208c1a010083208c1a020083208c1a030083208c1a040083208c1a050083208c1a060083208c1a070083208c1a080083208c1a090083208c1a0a0083208c1a0b0083208c1a0c0083208c1a0d0083208c1a0e0083208c1a0f0083208c1a100083208c1a110083208c1a120083208c1a130083208c1a140083208c1a150083208c1a160083208c1a170083208c1a180083208c1a190083208c1a1a0083208c1a1b0083208c1a1c0083208c1a1d0083208c1a1e0083208c1a1f0083208c1a200083208c1a210083208c1a220083208c1a230083208c1a240083208c1a250083208c1a260083208c1a270083208c1a280083208c1a290083208c1a2a0083208c1a2b0083208c1a2c0083208c1a2d0083208c1a2e0083208c1a2f0083208c1a300083208c1a310083208c1a320083208c1a330083208c1a340083208c1a350083208c1a360083208c1a370083208c1a380083208c1a390083208c1a3a0083208c1a3b0000"_hex_v_u8, {{450290, 291274}}); TestOptimalLinearization("8ee34aafe24c0083208c1a000083208c1a010083208c1a020083208c1a030083208c1a040083208c1a050083208c1a060083208c1a070083208c1a080083208c1a090083208c1a0a0083208c1a0b0083208c1a0c0083208c1a0d0083208c1a0e0083208c1a0f0083208c1a100083208c1a110083208c1a120083208c1a130083208c1a140083208c1a150083208c1a160083208c1a170083208c1a180083208c1a190083208c1a1a0083208c1a1b0083208c1a1c0083208c1a1d0083208c1a1e0083208c1a1f0083208c1a200083208c1a210083208c1a220083208c1a230083208c1a240083208c1a250083208c1a260083208c1a270083208c1a280083208c1a290083208c1a2a0083208c1a2b0083208c1a2c0083208c1a2d0083208c1a2e0083208c1a2f0083208c1a300083208c1a310083208c1a320083208c1a330083208c1a340083208c1a350083208c1a360083208c1a370083208c1a380083208c1a390083208c1a3a0083208c1a3b0000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60});
TestOptimalLinearization("a34c88ff6400835c80a4140000835c80a4140100835c80a4140200835c80a4140300835c80a4140400835c80a4140500835c80a4140600835c80a4140700835c80a4140800835c80a4140900835c80a4140a00835c80a4140b00835c80a4140c00835c80a4140d00835c80a4140e00835c80a4140f00835c80a414100000"_hex_v_u8, {{81970, 4684}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}}); TestOptimalLinearization("a34c88ff6400835c80a4140000835c80a4140100835c80a4140200835c80a4140300835c80a4140400835c80a4140500835c80a4140600835c80a4140700835c80a4140800835c80a4140900835c80a4140a00835c80a4140b00835c80a4140c00835c80a4140d00835c80a4140e00835c80a4140f00835c80a414100000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17});
TestOptimalLinearization("83369734008331903c01a41680dd2e02b24989886c0380cb0a86fe4404a97680ff680582368c60068451a53407df7783c500088806b80c09a74a80f1660a841e9644080a823581c71e070a854cb37c09098236ee2e080a8452a534070a8753b2580b068235a104080a847ced5e090a831695740e06895080b7340b0a8312955e0c0a8478de000d088755d57e0e088908c0140f088235910210088500a6001603831199701208833da73013088545a6301b001b85419f541700178451a5340f1e8331b40e1218847cdc000e1b880682bf201800108a4880b84018010f85708088401611824183a3560b188541a52407358335b37c06278752b7220a1900228544a954002221896ac558001805001700"_hex_v_u8, {{82550, 6601}, {136779, 19257}, {12190, 1724}, {3399, 561}, {3390, 565}, {5567, 1109}, {2178, 437}, {2584, 573}, {27411, 6674}, {23563, 5932}, {2458, 721}, {4916, 1443}, {86513, 26559}, {1720, 529}, {2496, 768}, {4170, 1288}, {30286, 10050}, {3308, 1107}, {1466, 534}, {1455, 530}, {5420, 2104}, {1506, 670}}); TestOptimalLinearization("83369734008331903c01a41680dd2e02b24989886c0380cb0a86fe4404a97680ff680582368c60068451a53407df7783c500088806b80c09a74a80f1660a841e9644080a823581c71e070a854cb37c09098236ee2e080a8452a534070a8753b2580b068235a104080a847ced5e090a831695740e06895080b7340b0a8312955e0c0a8478de000d088755d57e0e088908c0140f088235910210088500a6001603831199701208833da73013088545a6301b001b85419f541700178451a5340f1e8331b40e1218847cdc000e1b880682bf201800108a4880b84018010f85708088401611824183a3560b188541a52407358335b37c06278752b7220a1900228544a954002221896ac558001805001700"_hex_u8, {5, 29, 19, 30, 23, 26, 34, 27, 38, 42, 10, 36, 24, 33, 35, 22, 41, 31, 32, 11, 12, 16, 17, 18, 7, 9, 40, 39, 37, 3, 0, 1, 2, 6, 8, 20, 21, 25, 28, 13, 14, 15, 4});
TestOptimalLinearization("83689e4c0085599314000083689e4c0100864cc014010185599314010183689e4c0201864cc014010300"_hex_v_u8, {{2022, 616}, {2022, 616}, {2022, 616}, {5460, 1829}, {5460, 1829}}); TestOptimalLinearization("83689e4c0085599314000083689e4c0100864cc014010185599314010183689e4c0201864cc014010300"_hex_u8, {0, 3, 6, 1, 2, 4, 5});
TestOptimalLinearization("81c47cafb03400835bd8540000835bd8540100835bd8540200835bd8540300835bd8540400835bd8540500835bd8540600835bd8540700835bd8540800835bd8540900835bd8540a00835bd8540b00835bd8540c00835bd8540d00835bd8540e00835bd8540f00835bd8541000835bd8541100835bd8541200835bd8541300835bd8541400835bd8541500835bd8541600835bd8541700835bd8541800835bd8541900835bd8541a00835bd8541b00835bd8541c00835bd8541d00835bd8541e00835bd8541f00835bd8542000835bd8542100835bd8542200835bd8542300835bd8542400835bd8542500835bd8542600835bd8542700835bd8542800835bd8542900835bd8542a0000"_hex_v_u8, {{643112, 67653}}); TestOptimalLinearization("81c47cafb03400835bd8540000835bd8540100835bd8540200835bd8540300835bd8540400835bd8540500835bd8540600835bd8540700835bd8540800835bd8540900835bd8540a00835bd8540b00835bd8540c00835bd8540d00835bd8540e00835bd8540f00835bd8541000835bd8541100835bd8541200835bd8541300835bd8541400835bd8541500835bd8541600835bd8541700835bd8541800835bd8541900835bd8541a00835bd8541b00835bd8541c00835bd8541d00835bd8541e00835bd8541f00835bd8542000835bd8542100835bd8542200835bd8542300835bd8542400835bd8542500835bd8542600835bd8542700835bd8542800835bd8542900835bd8542a0000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43});
TestOptimalLinearization("83359d2c0083359d2c000083359d2c000283359d2c000283359d2c000200"_hex_v_u8, {{1942, 565}, {1942, 565}, {1942, 565}, {1942, 565}, {1942, 565}}); TestOptimalLinearization("83359d2c0083359d2c000083359d2c000283359d2c000283359d2c000200"_hex_u8, {3, 4, 0, 1, 2});
TestOptimalLinearization("a335b4af0400832f85b3280000832f85b3280100832f85b3280200832f85b3280300832f85b3280400832f85b3280500832f85b3280600832f85b3280700832f85b3280800832f85b3280900832f85b3280a00832f85b3280b00832f85b3280c00832f85b3280d00832f85b3280e00832f85b3280f00832f85b3281000832f85b328110000"_hex_v_u8, {{1382250, 14723}}); TestOptimalLinearization("a335b4af0400832f85b3280000832f85b3280100832f85b3280200832f85b3280300832f85b3280400832f85b3280500832f85b3280600832f85b3280700832f85b3280800832f85b3280900832f85b3280a00832f85b3280b00832f85b3280c00832f85b3280d00832f85b3280e00832f85b3280f00832f85b3281000832f85b328110000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18});
TestOptimalLinearization("833284fd3a00833581fc3801823684d50e02833181fb500383358695480480d77881b6f12005857c89bf7c0681a21d82999c300780d81d81b3ec6808844581a474098332899a7e0909833185bb04090984398190380809823587ae06070982358ddc1e080982368688220909823585cb000a09823586b3120b09823687aa6e0a0982359bf34a0b09823592ed040b09860880af480f05833286e0460b1d833185ba620b1c833288e64a0b1a833188a270022a833186bb5e0228833e89976a0225833186eb0a012b8332898512012783358a9130012d823986ff5a012883358a8f00012fed4996937e04020b000000000000000100"_hex_v_u8, {{272375, 2247}, {438299, 3939}, {46471, 438}, {353620, 3397}, {58788, 565}, {2916860, 29954}, {86078, 892}, {3665780, 38152}, {2692854, 28242}, {18810, 709}, {189759, 14153}, {11300, 904}}); TestOptimalLinearization("833284fd3a00833581fc3801823684d50e02833181fb500383358695480480d77881b6f12005857c89bf7c0681a21d82999c300780d81d81b3ec6808844581a474098332899a7e0909833185bb04090984398190380809823587ae06070982358ddc1e080982368688220909823585cb000a09823586b3120b09823687aa6e0a0982359bf34a0b09823592ed040b09860880af480f05833286e0460b1d833185ba620b1c833288e64a0b1a833188a270022a833186bb5e0228833e89976a0225833186eb0a012b8332898512012783358a9130012d823986ff5a012883358a8f00012fed4996937e04020b000000000000000100"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 20, 24, 22, 23, 25, 26, 28, 27, 29, 30, 31, 32, 33});
TestOptimalLinearization("883180ae7800a37a81cc480001a37a81cc480100a37a81cc480204835aaa160101835aaa160102835aaa160301835aaa160401835aaa160501835aaa160601835aaa160602835aaa160900835aaa160901835aaa160a01835aaa160b01835aaa160c01835aaa160c02835aaa160e01835aaa160f01835aaa160f02835aaa161101835aaa161201835aaa161301835aaa161401835aaa161600835aaa161700835aaa161800835aaa161702835aaa161802835aaa161902835aaa161c00835aaa161b02835aaa161e0000"_hex_v_u8, {{11260, 1201}, {62793, 13760}, {43452, 9546}, {37926, 8342}}); TestOptimalLinearization("883180ae7800a37a81cc480001a37a81cc480100a37a81cc480204835aaa160101835aaa160102835aaa160301835aaa160401835aaa160501835aaa160601835aaa160602835aaa160900835aaa160901835aaa160a01835aaa160b01835aaa160c01835aaa160c02835aaa160e01835aaa160f01835aaa160f02835aaa161101835aaa161201835aaa161301835aaa161401835aaa161600835aaa161700835aaa161800835aaa161702835aaa161802835aaa161902835aaa161c00835aaa161b02835aaa161e0000"_hex_u8, {1, 2, 5, 7, 8, 9, 10, 13, 14, 15, 16, 18, 19, 21, 22, 23, 24, 4, 6, 11, 17, 20, 28, 29, 30, 32, 0, 12, 25, 26, 27, 31, 33});
TestOptimalLinearization("a25c81b56200832fa5000000832fa5000100832fa5000200832fa5000300832fa5000400832fa5000500832fa5000600832fa5000700832fa5000800832fa5000900832fa5000a00832fa5000b00832fa5000c00832fa5000d00832fa5000e00832fa5000f00832fa5001000832fa5001100832fa5001200832fa5001300832fa500140000"_hex_v_u8, {{70961, 16311}}); TestOptimalLinearization("a25c81b56200832fa5000000832fa5000100832fa5000200832fa5000300832fa5000400832fa5000500832fa5000600832fa5000700832fa5000800832fa5000900832fa5000a00832fa5000b00832fa5000c00832fa5000d00832fa5000e00832fa5000f00832fa5001000832fa5001100832fa5001200832fa5001300832fa500140000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21});
TestOptimalLinearization("8368d63c00b273aaf80001842dec5e0101854e829f0201018f6681fb320103854e828b060300019e228ea20a0202835aea780206835aea780306835aea780406835aea780506835aea780606835aea780706835aea780806835aea780906835aea780a06842dec720a05836281a96a0a04836281a96a0b04836281a96a0c04836281a96a0d04836281a96a0e04836281a96a0f04836281a96a1004836281a96a1104836281a96a1204836281a96a1304836281a96a1404836281a96a1504836281a96a1604836281a96a1704836281a96a1804836281a96a1904836281a96a1a04836281a96a1b04836281a96a1c049d1e84a95e132200"_hex_v_u8, {{360000, 6643}, {26625, 846}, {488500, 15592}, {30945, 1462}, {93540, 8253}, {50728, 4555}}); TestOptimalLinearization("8368d63c00b273aaf80001842dec5e0101854e829f0201018f6681fb320103854e828b060300019e228ea20a0202835aea780206835aea780306835aea780406835aea780506835aea780606835aea780706835aea780806835aea780906835aea780a06842dec720a05836281a96a0a04836281a96a0b04836281a96a0c04836281a96a0d04836281a96a0e04836281a96a0f04836281a96a1004836281a96a1104836281a96a1204836281a96a1304836281a96a1404836281a96a1504836281a96a1604836281a96a1704836281a96a1804836281a96a1904836281a96a1a04836281a96a1b04836281a96a1c049d1e84a95e132200"_hex_u8, {12, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 0, 13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 14, 15});
TestOptimalLinearization("80de6ebba3280081a442d1976601990e86a22a02996686ba6a0381cb6bdcce060480e358beea3205823590802e0506847480cb6c06058241e47a0705845280a22e0805824180ab2c09058241e5120a05854580fd100b05833580b34e0b058235919c180c05833280b8080d05823593c3700b0586048189660c05906383fd600d0582358db5100d0582358087700e05823a8088400f058242e47a10058241eb4016008235ec001304874f81ec4a1701860881896608198a77829b761700000e900f83e20e160002000300"_hex_v_u8, {{644225, 29540}, {935163, 43040}, {822655, 38007}, {641121, 29709}, {23397, 1103}, {11844, 562}, {11559, 565}, {8760, 437}, {8800, 442}, {16264, 837}, {17075, 900}, {17075, 904}, {40880, 2275}, {39111, 2191}, {59605, 3342}, {61173, 3430}, {13110, 756}, {26427, 1527}, {6976, 437}, {6944, 449}, {6537, 449}, {6525, 449}, {6525, 450}, {10455, 722}}); TestOptimalLinearization("80de6ebba3280081a442d1976601990e86a22a02996686ba6a0381cb6bdcce060480e358beea3205823590802e0506847480cb6c06058241e47a0705845280a22e0805824180ab2c09058241e5120a05854580fd100b05833580b34e0b058235919c180c05833280b8080d05823593c3700b0586048189660c05906383fd600d0582358db5100d0582358087700e05823a8088400f058242e47a10058241eb4016008235ec001304874f81ec4a1701860881896608198a77829b761700000e900f83e20e160002000300"_hex_u8, {1, 0, 5, 15, 16, 8, 10, 20, 21, 28, 11, 9, 22, 23, 7, 17, 18, 19, 25, 12, 13, 2, 14, 27, 26, 6, 3, 24, 4});
TestOptimalLinearization("836280c06000836180c06001836280c06002834280b1600202836180c0600302834280b1600302836180c0600402834280b1600402836280c0600502877e81fc200509833a80b1600509836280c0600609877f81fc200608834180b1600608877e81fc200607836280c0600607834180b1600707836180c0600715834280b1600614836280c0600611836180c060050f834380b160050d834180b1600420834380b1600318834280b1600315836180c0600510836280c0600511877f81fc200428880281f96011030e836280c0600315836280c060022e834280b1600030836180c0600130880281fc20080710834280b1600132836280c060022e877f81fc200c0915833b80b1600131877e81fc2002022e877f81fc200a0610877e81fc20010230877f81fc2004110c877e81fc2000130d877f81fc2002110d877e81f96006021500"_hex_v_u8, {{96480, 4675}, {48240, 2338}, {48240, 2338}, {482080, 23373}, {12400, 609}, {12400, 610}, {12400, 610}}); TestOptimalLinearization("836280c06000836180c06001836280c06002834280b1600202836180c0600302834280b1600302836180c0600402834280b1600402836280c0600502877e81fc200509833a80b1600509836280c0600609877f81fc200608834180b1600608877e81fc200607836280c0600607834180b1600707836180c0600715834280b1600614836280c0600611836180c060050f834380b160050d834180b1600420834380b1600318834280b1600315836180c0600510836280c0600511877f81fc200428880281f96011030e836280c0600315836280c060022e834280b1600030836180c0600130880281fc20080710834280b1600132836280c060022e877f81fc200c0915833b80b1600131877e81fc2002022e877f81fc200a0610877e81fc20010230877f81fc2004110c877e81fc2000130d877f81fc2002110d877e81f96006021500"_hex_u8, {0, 1, 2, 3, 4, 5, 18, 19, 20, 27, 28, 29, 10, 21, 30, 6, 8, 12, 14, 22, 32, 33, 11, 26, 15, 23, 35, 7, 16, 9, 17, 38, 13, 31, 34, 41, 24, 25, 37, 39, 36, 40, 42, 43, 44});
TestOptimalLinearization("818e6ca18c5000834fc8700001834fc8700100834fc8700200834fc8700300834fc8700400834fc8700500834fc8700600834fc8700700834fc8700800834fc8700900834fc8700a00834fc8700b00834fc8700c00834fc8700d00834fc8700e00834fc8700f00834fc8701000834fc8701100834fc8701200834fc8701300834fc8701400834fc8701500834fc8701600834fc8701700834fc8701800834fc8701900834fc8701a00834fc8701b00834fc8701c00834fc8701d00834fc8701e00834fc8701f00834fc8702000834fc8702100834fc8702200834fc8702300834fc8702400834fc8702500834fc8702600834fc8702700834fc870280000"_hex_v_u8, {{279400, 34796}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}}); TestOptimalLinearization("818e6ca18c5000834fc8700001834fc8700100834fc8700200834fc8700300834fc8700400834fc8700500834fc8700600834fc8700700834fc8700800834fc8700900834fc8700a00834fc8700b00834fc8700c00834fc8700d00834fc8700e00834fc8700f00834fc8701000834fc8701100834fc8701200834fc8701300834fc8701400834fc8701500834fc8701600834fc8701700834fc8701800834fc8701900834fc8701a00834fc8701b00834fc8701c00834fc8701d00834fc8701e00834fc8701f00834fc8702000834fc8702100834fc8702200834fc8702300834fc8702400834fc8702500834fc8702600834fc8702700834fc870280000"_hex_u8, {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41});
TestOptimalLinearization("8442872600c61981fd680000835a8c420000835a8c420100835a8c420200835a8c420300835a8c420400835a8c420500835a8c420600835a8c420700835a8c420800835a8c420900835a8c420a00835a8c420b00835a8c420c00835a8c420d00835a8c420e00835a8c420f00835a8c421000835a8c421100835a8c421200835a8c421300835a8c421400835a8c421500835a8c421600835a8c421700835a8c42180000"_hex_v_u8, {{25031, 9819}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}}); TestOptimalLinearization("8442872600c61981fd680000835a8c420000835a8c420100835a8c420200835a8c420300835a8c420400835a8c420500835a8c420600835a8c420700835a8c420800835a8c420900835a8c420a00835a8c420b00835a8c420c00835a8c420d00835a8c420e00835a8c420f00835a8c421000835a8c421100835a8c421200835a8c421300835a8c421400835a8c421500835a8c421600835a8c421700835a8c42180000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26});
TestOptimalLinearization("8540e74000833180831801875dd14e00000000"_hex_v_u8, {{8460, 561}, {6688, 832}, {5287, 1117}}); TestOptimalLinearization("8540e74000833180831801875dd14e00000000"_hex_u8, {1, 0, 2});
TestOptimalLinearization("808a5292d06800835ad3780000835ad3780100835ad3780200835ad3780300835ad3780400835ad3780500835ad3780600835ad3780700835ad3780800835ad3780900835ad3780a00835ad3780b00835ad3780c00835ad3780d00835ad3780e00835ad3780f00835ad3781000835ad3781100835ad3781200835ad3781300835ad3781400835ad3781500835ad3781600835ad3781700835ad3781800835ad3781900835ad3781a00835ad3781b00835ad3781c0000"_hex_v_u8, {{318528, 35332}}); TestOptimalLinearization("808a5292d06800835ad3780000835ad3780100835ad3780200835ad3780300835ad3780400835ad3780500835ad3780600835ad3780700835ad3780800835ad3780900835ad3780a00835ad3780b00835ad3780c00835ad3780d00835ad3780e00835ad3780f00835ad3781000835ad3781100835ad3781200835ad3781300835ad3781400835ad3781500835ad3781600835ad3781700835ad3781800835ad3781900835ad3781a00835ad3781b00835ad3781c0000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29});
TestOptimalLinearization("8a0d8a54008368843000008a0d8a5401008368843000018a0d8a54010000836884300001996cc3320100008a449d1e00018d20a37e01000000"_hex_v_u8, {{11949, 12847}}); TestOptimalLinearization("8a0d8a54008368843000008a0d8a5401008368843000018a0d8a54010000836884300001996cc3320100008a449d1e00018d20a37e01000000"_hex_u8, {0, 1, 2, 3, 4, 6, 7, 5, 8});
TestOptimalLinearization("80ba1386a6640080c14d86cc1001809b10858b500280927684e2580380e9458893680480b6538695240580bb2086ac2006942981e1240000000000000000900e819b3a0100000000000000e2528bf6420200000000000000854dca54020200"_hex_v_u8, {{565214, 183924}}); TestOptimalLinearization("80ba1386a6640080c14d86cc1001809b10858b500280927684e2580380e9458893680480b6538695240580bb2086ac2006942981e1240000000000000000900e819b3a0100000000000000e2528bf6420200000000000000854dca54020200"_hex_u8, {1, 3, 4, 5, 0, 2, 6, 9, 7, 10, 8});
TestOptimalLinearization("80cc3fb8e500008327809a2000018327809a2001008327809a2002008327809a2003008327809a2004008327809a2005008327809a2006008327809a2007008327809a2008008327809a2009008327809a200a008327809a200b008327809a200c008327809a200d008327809a200e008327809a200f008327809a2010008327809a2011008327809a2012008327809a2013008327809a2014008327809a2015008327809a2016008327809a2017008327809a2018008327809a2019008327809a201a008327809a201b008327809a201c008327809a201d008327809a201e008327809a201f008327809a2020008327809a2021008327809a2022008327809a2023008327809a2024008327809a2025008327809a2026008327809a2027008327809a2028008327809a2029008327809a202a008327809a202b008327809a202c0000"_hex_v_u8, {{920592, 51098}}); TestOptimalLinearization("80cc3fb8e500008327809a2000018327809a2001008327809a2002008327809a2003008327809a2004008327809a2005008327809a2006008327809a2007008327809a2008008327809a2009008327809a200a008327809a200b008327809a200c008327809a200d008327809a200e008327809a200f008327809a2010008327809a2011008327809a2012008327809a2013008327809a2014008327809a2015008327809a2016008327809a2017008327809a2018008327809a2019008327809a201a008327809a201b008327809a201c008327809a201d008327809a201e008327809a201f008327809a2020008327809a2021008327809a2022008327809a2023008327809a2024008327809a2025008327809a2026008327809a2027008327809a2028008327809a2029008327809a202a008327809a202b008327809a202c0000"_hex_u8, {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45});
TestOptimalLinearization("83ea5fb6be1a0083c44cb2c86c0182ff47abfc140285940cc6dd7c038c3281d1740303841f80a25c0402870880f9740403833d809c400503896a81fb500603897680940608028a4c80b9560603836580941807038365819f0e0803833180874c0903851e80c0600d008331ad6e0c02833180874c0c0383358088480d03833180874c0e0383388089441101833880894412018338808944130183388089441500836180931c1501907d83ae781600158a4d81e82c150010912a84831c16000f8335808848091583388089440616851e80c0600815907583ad001a00000f91238aba401c000007833580884804208338808944041ca84c898e1c1e000000118235809e56042c83388089440220833180874c041e823580ee4c0331833180874c012200"_hex_v_u8, {{2460632, 356111}, {9539, 1398}, {2999, 561}}); TestOptimalLinearization("83ea5fb6be1a0083c44cb2c86c0182ff47abfc140285940cc6dd7c038c3281d1740303841f80a25c0402870880f9740403833d809c400503896a81fb500603897680940608028a4c80b9560603836580941807038365819f0e0803833180874c0903851e80c0600d008331ad6e0c02833180874c0c0383358088480d03833180874c0e0383388089441101833880894412018338808944130183388089441500836180931c1501907d83ae781600158a4d81e82c150010912a84831c16000f8335808848091583388089440616851e80c0600815907583ad001a00000f91238aba401c000007833580884804208338808944041ca84c898e1c1e000000118235809e56042c83388089440220833180874c041e823580ee4c0331833180874c012200"_hex_u8, {10, 15, 20, 23, 25, 24, 26, 28, 37, 38, 14, 12, 0, 4, 36, 21, 1, 2, 6, 7, 29, 30, 31, 32, 34, 35, 39, 3, 5, 33, 9, 27, 13, 16, 18, 11, 17, 19, 8, 22});
TestOptimalLinearization("8368aa5e008368aa5e018368aa5e028368aa5e02028368aa5e02028368aa5e0202836897260500836897260501a35780b6380106a35780b6380106836797080108836797080208836797080308836797080408836797080508836797080608836797080708836797080808836797080908836797080a08836797080b08836797080c08836797080d08836797080e08836797080f08836797081008836797081108836797081208836797081308836797081408836797081407836797081507836797081607836797081707836797081807836797081907836797081a07836797081b07836797081c07836797081d07836797081e07836797081f078367970820078367970821078367970822078367970823078367970824078367970825078734cb0a2a00002a00"_hex_v_u8, {{2799, 616}, {2799, 616}, {2799, 616}, {2799, 616}, {2799, 616}, {2799, 616}, {4869, 1076}, {1555, 616}, {1555, 616}, {42540, 16995}, {39460, 15765}}); TestOptimalLinearization("8368aa5e008368aa5e018368aa5e028368aa5e02028368aa5e02028368aa5e0202836897260500836897260501a35780b6380106a35780b6380106836797080108836797080208836797080308836797080408836797080508836797080608836797080708836797080808836797080908836797080a08836797080b08836797080c08836797080d08836797080e08836797080f08836797081008836797081108836797081208836797081308836797081408836797081407836797081507836797081607836797081707836797081807836797081907836797081a07836797081b07836797081c07836797081d07836797081e07836797081f078367970820078367970821078367970822078367970823078367970824078367970825078734cb0a2a00002a00"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 29, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48});
TestOptimalLinearization("854887862000854887862000008548878a0000008548878a0000008548878d6000008548879520000000"_hex_v_u8, {{397920, 5040}}); TestOptimalLinearization("854887862000854887862000008548878a0000008548878a0000008548878d6000008548879520000000"_hex_u8, {0, 1, 2, 3, 4, 5});
TestOptimalLinearization("8331f924008336fa1400008331f70e00008335f56200008331ee3000008336ef1600008335e17c00008335df62000000"_hex_v_u8, {{7826, 561}, {7882, 566}, {7687, 561}, {7601, 565}, {7128, 561}, {7179, 566}, {6334, 565}, {6193, 565}}); TestOptimalLinearization("8331f924008336fa1400008331f70e00008335f56200008331ee3000008336ef1600008335e17c00008335df62000000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7});
TestOptimalLinearization("808962829f2c0083628d2c000183628d2c010183628d2c020083628d2c030083628d2c040083628d2c050083628d2c060083628d2c070083628d2c080083628d2c090083628d2c0a0083628d2c0b0083628d2c0c0083628d2c0d0083628d2c0e0083628d2c0f0083628d2c100083628d2c110083628d2c120083628d2c130083628d2c140083628d2c150083628d2c160083628d2c170083628d2c180083628d2c190083628d2c1a0083628d2c1b0083628d2c1c0083628d2c1d0083628d2c1e0083628d2c1f0083628d2c200083628d2c210083628d2c220083628d2c230083628d2c240083628d2c250083628d2c260000"_hex_v_u8, {{62448, 41552}}); TestOptimalLinearization("808962829f2c0083628d2c000183628d2c010183628d2c020083628d2c030083628d2c040083628d2c050083628d2c060083628d2c070083628d2c080083628d2c090083628d2c0a0083628d2c0b0083628d2c0c0083628d2c0d0083628d2c0e0083628d2c0f0083628d2c100083628d2c110083628d2c120083628d2c130083628d2c140083628d2c150083628d2c160083628d2c170083628d2c180083628d2c190083628d2c1a0083628d2c1b0083628d2c1c0083628d2c1d0083628d2c1e0083628d2c1f0083628d2c200083628d2c210083628d2c220083628d2c230083628d2c240083628d2c250083628d2c260000"_hex_u8, {2, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39});
TestOptimalLinearization("b27883865800833e81de3601833ea76a029d1d8e1003af4f82e54804c06484911005ad2d82ce6006ae2c82d86007b10082f32808af3882e35809833eba080aa13681d7300bbc1283e2480ca41d81f3400d847088140d0d824180f0280e0d8331a67e0d0d865adf4a0d0d8241ab120c0d86088081540d0d833eaa600e0d854e88720f0d823580c4580e0d8541b9260f0d833ead6c100d8545c014110d8542885e120d823680cd00120d8446bc7c130d83319d42140d8544c658140d8546c658130d8474f034130c854dca56200083318199601b06833281a4021e04865982aa6c1e05854e81e8681c088239c9121d08847c81b4181d09844582987a1b0c854dca5622068608f1242504833e8a142505857ceb401f0c847caa4c23099254828a502c002a8335a7221e378574b95a1c338332ce7419328335ad1819328331d2241731854680f04628001b8235b706122c9260828a503200012c833db00a06548235d332044a833ea76a0931895080a07e023e80dd6690b7682d0000010000000000031100"_hex_v_u8, {{22491, 574}, {83836, 9123}, {72635, 9291}, {6944, 892}, {74024, 9613}, {77864, 10309}, {57207, 7689}, {51363, 6931}, {50808, 6964}, {41279, 5818}, {42972, 6497}, {8845, 1395}, {2825, 449}, {17265, 2817}, {4843, 845}, {4843, 845}, {3966, 710}, {4588, 836}, {4588, 838}, {5954, 1139}, {166740, 33283}, {4170, 837}, {2800, 574}, {7749, 1700}, {2613, 574}, {32469, 7383}, {2790, 764}, {1953, 561}, {714, 574}, {586, 752}, {633, 846}, {623, 834}}); TestOptimalLinearization("b27883865800833e81de3601833ea76a029d1d8e1003af4f82e54804c06484911005ad2d82ce6006ae2c82d86007b10082f32808af3882e35809833eba080aa13681d7300bbc1283e2480ca41d81f3400d847088140d0d824180f0280e0d8331a67e0d0d865adf4a0d0d8241ab120c0d86088081540d0d833eaa600e0d854e88720f0d823580c4580e0d8541b9260f0d833ead6c100d8545c014110d8542885e120d823680cd00120d8446bc7c130d83319d42140d8544c658140d8546c658130d8474f034130c854dca56200083318199601b06833281a4021e04865982aa6c1e05854e81e8681c088239c9121d08847c81b4181d09844582987a1b0c854dca5622068608f1242504833e8a142505857ceb401f0c847caa4c23099254828a502c002a8335a7221e378574b95a1c338332ce7419328335ad1819328331d2241731854680f04628001b8235b706122c9260828a503200012c833db00a06548235d332044a833ea76a0931895080a07e023e80dd6690b7682d0000010000000000031100"_hex_u8, {3, 28, 29, 50, 51, 30, 31, 40, 53, 43, 58, 0, 2, 4, 12, 48, 14, 11, 47, 56, 19, 45, 46, 34, 52, 36, 37, 38, 20, 21, 22, 23, 13, 16, 17, 49, 44, 54, 32, 35, 39, 24, 25, 41, 42, 26, 15, 5, 6, 7, 55, 8, 10, 9, 59, 33, 57, 1, 18, 27});
TestOptimalLinearization("a25c82906c00835fb17e0000835fb17e0100835fb17e0200835fb17e0300835fb17e0400835fb17e0500835fb17e0600835fb17e0700835fb17e0800835fb17e0900835fb17e0a00835fb17e0b00835fb17e0c00835fb17e0d00835fb17e0e00835fb17e0f00835fb17e1000835fb17e1100835fb17e1200835fb17e1300835fb17e140000"_hex_v_u8, {{25718, 4572}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}}); TestOptimalLinearization("a25c82906c00835fb17e0000835fb17e0100835fb17e0200835fb17e0300835fb17e0400835fb17e0500835fb17e0600835fb17e0700835fb17e0800835fb17e0900835fb17e0a00835fb17e0b00835fb17e0c00835fb17e0d00835fb17e0e00835fb17e0f00835fb17e1000835fb17e1100835fb17e1200835fb17e1300835fb17e140000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21});
TestOptimalLinearization("834180872600834a808726018361808b3c028362808b3c03877f81914c0303877e81914c0303834280804c0303834280804c030383618086500208836280841a04048342fc1001098342f97201088361808650020883628081640406877f819142030d8341fc10020b8362808906030b8342f754030a83618086500313877e8196160705088342fe2e030e83628086500218877e819142060906836280865003138346fc10050f8361809028031d83618086500317836180865003178341fc100612834bfc10051383418085080424836180925e05248362808650051d8361809028051c8342fc1006188343fc1008178342808726042d836180902804258347fc10051b8342808508012a877f81881008121c836280902800368342808508003600"_hex_v_u8, {{26297, 1728}, {26297, 1736}, {139807, 9456}, {8990, 610}, {68514, 4674}, {35240, 2406}, {26660, 1828}, {8835, 610}, {8294, 578}, {8151, 578}, {8008, 577}, {8008, 578}, {8008, 579}, {8008, 582}, {8008, 583}, {8370, 610}, {8008, 587}, {7722, 578}}); TestOptimalLinearization("834180872600834a808726018361808b3c028362808b3c03877f81914c0303877e81914c0303834280804c0303834280804c030383618086500208836280841a04048342fc1001098342f97201088361808650020883628081640406877f819142030d8341fc10020b8362808906030b8342f754030a83618086500313877e8196160705088342fe2e030e83628086500218877e819142060906836280865003138346fc10050f8361809028031d83618086500317836180865003178341fc100612834bfc10051383418085080424836180925e05248362808650051d8361809028051c8342fc1006188343fc1008178342808726042d836180902804258347fc10051b8342808508012a877f81881008121c836280902800368342808508003600"_hex_u8, {0, 1, 2, 3, 5, 6, 4, 7, 8, 9, 10, 11, 13, 14, 12, 15, 16, 17, 18, 19, 22, 23, 24, 20, 21, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 41, 40, 42});
TestOptimalLinearization("a44d9db27a00824081e92c0000824081e92c0100824081e92c0200824081e92c0300824081e92c0400824081e92c0500824081e92c0600824081e92c070000"_hex_v_u8, {{434605, 8397}}); TestOptimalLinearization("a44d9db27a00824081e92c0000824081e92c0100824081e92c0200824081e92c0300824081e92c0400824081e92c0500824081e92c0600824081e92c070000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8});
TestOptimalLinearization("880180cf2200829428c7e9180000831ce0040000831ce0040100831ce0040200831ce0040300831ce004040000"_hex_v_u8, {{13329, 1153}, {596620, 51880}, {6210, 540}, {6210, 540}, {6210, 540}, {6210, 540}, {6210, 540}}); TestOptimalLinearization("880180cf2200829428c7e9180000831ce0040000831ce0040100831ce0040200831ce0040300831ce004040000"_hex_u8, {0, 1, 2, 3, 4, 5, 6});
TestOptimalLinearization("f90bc0b7520080840cc7e7780194268aae4602823581931c0202823681931c0302857882dc2e0402857c82de400502823581911c0602860482e26407028236819f1e0802823984a6160902823681a11e0a02860082e55a0b02847082c60a0c02847482c60a0d02847482c60a0e02826684a6160f02847082b8721002824180f0721102852282a8341202850082af001302823681bf201402823581bf201402823681bf201502823681b9701602847c83df681702823581b1201802857882e55a1902860882b0401a02823681c9221b02852982b0241c02847c82e6781d02850082b32a1f01823983b1521e028235819b1e20018235a5441e208242848b1a1c1f8242889a3819238a4485a45424000a823480e96408218a4c85a4542500028d07e0bb1a1100000500001900"_hex_v_u8, {{2320269, 40741}, {38964, 764}, {21137, 438}, {20152, 438}, {19600, 437}, {18447, 438}, {18191, 437}, {31228, 764}, {129164, 3167}, {17678, 437}, {17678, 438}, {28281, 752}, {27925, 768}, {27648, 768}, {31149, 888}, {51562, 1476}, {31149, 896}, {51562, 1484}, {15481, 449}, {30551, 888}, {30688, 892}, {30962, 900}, {42756, 1245}, {27226, 802}, {27744, 904}, {2466, 437}}); TestOptimalLinearization("f90bc0b7520080840cc7e7780194268aae4602823581931c0202823681931c0302857882dc2e0402857c82de400502823581911c0602860482e26407028236819f1e0802823984a6160902823681a11e0a02860082e55a0b02847082c60a0c02847482c60a0d02847482c60a0e02826684a6160f02847082b8721002824180f0721102852282a8341202850082af001302823681bf201402823581bf201402823681bf201502823681b9701602847c83df681702823581b1201802857882e55a1902860882b0401a02823681c9221b02852982b0241c02847c82e6781d02850082b32a1f01823983b1521e028235819b1e20018235a5441e208242848b1a1c1f8242889a3819238a4485a45424000a823480e96408218a4c85a4542500028d07e0bb1a1100000500001900"_hex_u8, {23, 24, 25, 0, 9, 17, 22, 10, 12, 5, 11, 14, 15, 16, 27, 28, 33, 26, 30, 8, 41, 35, 38, 39, 1, 2, 18, 37, 21, 31, 29, 13, 40, 19, 3, 4, 7, 34, 36, 20, 32, 6});
TestOptimalLinearization("8361a17a008430a138000000"_hex_v_u8, {{2237, 609}, {2204, 688}}); TestOptimalLinearization("8361a17a008430a138000000"_hex_u8, {0, 1});
TestOptimalLinearization("fc7d88962000f93b87f516018a50809c6401018235a10402018235f65203018236cd1004018a4c80bb6405018235956e06018604de2c07018332fc480801847cdc0009018336fc700a018a50809e340b0182418c540c01831dcf020d01893c809f400d018470df300e018474dc640f01857cdd4010018802c83811018608dc00120183159a0a14008578dc0015008600dc001501823acf7c0e15857cf12412128336b6760a14926881943019000400"_hex_v_u8, {{171970, 27015}, {134824, 24317}, {2178, 437}, {4700, 1154}, {1463, 437}, {1733, 533}, {874, 449}}); TestOptimalLinearization("fc7d88962000f93b87f516018a50809c6401018235a10402018235f65203018236cd1004018a4c80bb6405018235956e06018604de2c07018332fc480801847cdc0009018336fc700a018a50809e340b0182418c540c01831dcf020d01893c809f400d018470df300e018474dc640f01857cdd4010018802c83811018608dc00120183159a0a14008578dc0015008600dc001501823acf7c0e15857cf12412128336b6760a14926881943019000400"_hex_u8, {0, 3, 8, 10, 11, 4, 15, 5, 12, 9, 13, 1, 7, 26, 16, 18, 19, 17, 23, 21, 27, 24, 20, 2, 22, 6, 25, 14});
TestOptimalLinearization("829428f0fe20008319809604000183198096040100831980960402008319809604030083198096040400831980960405008319809604060083198096040700831980960408008319809604090083198096040a0083198096040b0083198096040c0083198096040d0083198096040e0083198096040f008319809604100083198096041100831980960412008319809604130083198096041400831980960415008319809604160083198096041700831980960418008319809604190083198096041a0083198096041b0083198096041c0083198096041d0083198096041e0083198096041f008319809604200083198096042100831980960422008319809604230083198096042400831980960425008319809604260083198096042700831980960428008319809604290083198096042a0083198096042b0083198096042c0083198096042d0083198096042e0083198096042f0083198096043000831980960431008319809604320083198096043300831980960434008319809604350000"_hex_v_u8, {{933840, 51880}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}}); TestOptimalLinearization("829428f0fe20008319809604000183198096040100831980960402008319809604030083198096040400831980960405008319809604060083198096040700831980960408008319809604090083198096040a0083198096040b0083198096040c0083198096040d0083198096040e0083198096040f008319809604100083198096041100831980960412008319809604130083198096041400831980960415008319809604160083198096041700831980960418008319809604190083198096041a0083198096041b0083198096041c0083198096041d0083198096041e0083198096041f008319809604200083198096042100831980960422008319809604230083198096042400831980960425008319809604260083198096042700831980960428008319809604290083198096042a0083198096042b0083198096042c0083198096042d0083198096042e0083198096042f0083198096043000831980960431008319809604320083198096043300831980960434008319809604350000"_hex_u8, {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54});
TestOptimalLinearization("870180db6e00841580832400008416808d5400008416eb7800008416808d54000000"_hex_v_u8, {{14135, 1025}, {17596, 1323}, {16102, 1324}}); TestOptimalLinearization("870180db6e00841580832400008416808d5400008416eb7800008416808d54000000"_hex_u8, {0, 1, 2, 3, 4});
TestOptimalLinearization("818f1c85840c0083208b08000083208b08010083208b08020083208b08030083208b08040083208b08050083208b08060083208b08070083208b08080083208b08090083208b080a0083208b080b0083208b080c0083208b080d0083208b080e0083208b080f0083208b08100083208b08110083208b08120083208b08130083208b08140083208b08150083208b08160000"_hex_v_u8, {{49478, 34844}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}}); TestOptimalLinearization("818f1c85840c0083208b08000083208b08010083208b08020083208b08030083208b08040083208b08050083208b08060083208b08070083208b08080083208b08090083208b080a0083208b080b0083208b080c0083208b080d0083208b080e0083208b080f0083208b08100083208b08110083208b08120083208b08130083208b08140083208b08150083208b08160000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23});
TestOptimalLinearization("81b8668092af300080da66e0f02801a36e8dc30a0280e87af0a9080380de2bdfea4a0480d709ef9f1405860081bd40068332ee300780cb48f1a11c08844682a01808088235d7dc300908826580f94c0a08824180e7600b088316818b4c0c088235c39c320c08833e81a31a0d08833280dd240e08854d81ce401007824280e4421008854b8df30e100893588984141108824180ad041208847483e97c12088235bdb51c1308824280b2261408824180b27e1508824180f66e19058448829a1a1a05823580fc1c1a068235c6f26c1808823581b2221908823981fa1a1a08860982d7681b088336819f0e1c08875d82ba3e1d088235b28b2a1d08823a8188381e08824180be341f08823680ba662008857881bc0a20088235a6d9061f08823a81a1182008824280e45c2108833680de6e2208823a80b2022308833281e41a2c00845182806e2c0024833581ac261d32831d81d04e2224854582ea7a2b010e823980c408062c896483ae002a0404866283d5781717158e10878014210f011fab528cf5380e1f050900"_hex_v_u8, {{1406632, 29465}, {1934192, 40603}, {1338143, 28094}, {1360813, 28571}, {1479376, 31139}, {1261329, 26621}, {19665, 437}, {241164, 5561}, {18572, 442}, {22861, 562}, {16988, 442}, {54538, 1431}, {31485, 837}, {26700, 710}, {26317, 712}, {38797, 1075}, {15863, 449}, {24695, 721}, {65610, 1936}, {30260, 905}, {14896, 449}, {16038, 485}, {14702, 450}, {14689, 450}, {18701, 574}, {18439, 566}, {82250, 2648}, {40755, 1410}, {12019, 438}, {12250, 449}, {26939, 1007}, {35776, 1380}, {11457, 442}, {11519, 449}, {11475, 450}, {28383, 1117}, {14226, 562}, {11138, 449}, {40677, 1784}, {121204, 6276}}); TestOptimalLinearization("81b8668092af300080da66e0f02801a36e8dc30a0280e87af0a9080380de2bdfea4a0480d709ef9f1405860081bd40068332ee300780cb48f1a11c08844682a01808088235d7dc300908826580f94c0a08824180e7600b088316818b4c0c088235c39c320c08833e81a31a0d08833280dd240e08854d81ce401007824280e4421008854b8df30e100893588984141108824180ad041208847483e97c12088235bdb51c1308824280b2261408824180b27e1508824180f66e19058448829a1a1a05823580fc1c1a068235c6f26c1808823581b2221908823981fa1a1a08860982d7681b088336819f0e1c08875d82ba3e1d088235b28b2a1d08823a8188381e08824180be341f08823680ba662008857881bc0a20088235a6d9061f08823a81a1182008824280e45c2108833680de6e2208823a80b2022308833281e41a2c00845182806e2c0024833581ac261d32831d81d04e2224854582ea7a2b010e823980c408062c896483ae002a0404866283d5781717158e10878014210f011fab528cf5380e1f050900"_hex_u8, {28, 29, 31, 0, 2, 36, 37, 6, 7, 18, 20, 19, 46, 47, 30, 14, 15, 48, 54, 38, 27, 35, 40, 1, 26, 5, 25, 24, 10, 22, 32, 4, 3, 49, 12, 8, 33, 16, 11, 13, 41, 39, 50, 51, 53, 52, 23, 21, 34, 9, 17, 42, 43, 44, 45});
TestOptimalLinearization("80ba43afe456008b358582100180c16cb587240280d261c0c11a0380d924bbc75c04833180ad5805900e84e9260682359b9b5c060782398087040706823598f2560606823599eb60050684788199680606823594a33c0805823580a95e0905854081f70c0d02824183c8280e028eb06183c190480b00058a7183aa0c0a000400ad428fc3340d000000000800"_hex_v_u8, {{49352, 1589}, {692467, 25721}, {711083, 27542}, {655101, 25377}, {716126, 28377}, {10927, 437}, {18100, 760}, {135450, 5954}, {94469, 4272}, {8706, 441}, {4736100, 252129}}); TestOptimalLinearization("80ba43afe456008b358582100180c16cb587240280d261c0c11a0380d924bbc75c04833180ad5805900e84e9260682359b9b5c060782398087040706823598f2560606823599eb60050684788199680606823594a33c0805823580a95e0905854081f70c0d02824183c8280e028eb06183c190480b00058a7183aa0c0a000400ad428fc3340d000000000800"_hex_u8, {3, 1, 0, 14, 13, 6, 11, 4, 5, 7, 8, 12, 9, 10, 17, 16, 18, 2, 15});
TestOptimalLinearization("a25c86f87e008362808722000083628087220100836280872202008362808722030083628087220400836280872205008362808722060083628087220700836280872208008362808722090083628087220a0083628087220b0083628087220c0083628087220d0083628087220e0083628087220f008362808722100083628087221100836280872212008362808722130000"_hex_v_u8, {{239571, 16772}}); TestOptimalLinearization("a25c86f87e008362808722000083628087220100836280872202008362808722030083628087220400836280872205008362808722060083628087220700836280872208008362808722090083628087220a0083628087220b0083628087220c0083628087220d0083628087220e0083628087220f008362808722100083628087221100836280872212008362808722130000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20});
TestOptimalLinearization("864a828f7a008b6384a51401854181d76c02833180e754038431819c3a04892a87a42205894587ba5c06853981d44607861c81ca2c0107857881bb3a010785008193000306823582ee280505854e81ec5a0a000a853581e22c0014896183d36c0007000007833e80f734000e860481c37000098642829e5c0106078a588398500108854181e744010f9659899c24000707843a81ac70000e857881b50e010c860481fb26020788358393240210833180f7420012843e81b51a0011874082e014000807853581ea0a000f853681ea0a000f833e80fc66000e833580f924000e833580fe4c000d00"_hex_v_u8, {{99621, 1759}, {69358, 1349}, {594899, 21560}, {24339, 900}, {20792, 900}, {17664, 768}, {34408, 1496}, {21206, 924}, {20253, 888}, {19847, 888}}); TestOptimalLinearization("864a828f7a008b6384a51401854181d76c02833180e754038431819c3a04892a87a42205894587ba5c06853981d44607861c81ca2c0107857881bb3a010785008193000306823582ee280505854e81ec5a0a000a853581e22c0014896183d36c0007000007833e80f734000e860481c37000098642829e5c0106078a588398500108854181e744010f9659899c24000707843a81ac70000e857881b50e010c860481fb26020788358393240210833180f7420012843e81b51a0011874082e014000807853581ea0a000f853681ea0a000f833e80fc66000e833580f924000e833580fe4c000d00"_hex_u8, {9, 31, 12, 1, 5, 6, 19, 4, 0, 2, 3, 7, 8, 10, 11, 13, 14, 15, 16, 18, 20, 21, 22, 24, 25, 27, 32, 28, 29, 30, 17, 26, 23});
TestOptimalLinearization("818e6ca18c5000834fc8700001834fc8700100834fc8700200834fc8700300834fc8700400834fc8700500834fc8700600834fc8700700834fc8700800834fc8700900834fc8700a00834fc8700b00834fc8700c00834fc8700d00834fc8700e00834fc8700f00834fc8701000834fc8701100834fc8701200834fc8701300834fc8701400834fc8701500834fc8701600834fc8701700834fc8701800834fc8701900834fc8701a00834fc8701b00834fc8701c00834fc8701d00834fc8701e00834fc8701f00834fc8702000834fc8702100834fc8702200834fc8702300834fc8702400834fc8702500834fc8702600834fc870270000"_hex_v_u8, {{279400, 34796}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}}); TestOptimalLinearization("818e6ca18c5000834fc8700001834fc8700100834fc8700200834fc8700300834fc8700400834fc8700500834fc8700600834fc8700700834fc8700800834fc8700900834fc8700a00834fc8700b00834fc8700c00834fc8700d00834fc8700e00834fc8700f00834fc8701000834fc8701100834fc8701200834fc8701300834fc8701400834fc8701500834fc8701600834fc8701700834fc8701800834fc8701900834fc8701a00834fc8701b00834fc8701c00834fc8701d00834fc8701e00834fc8701f00834fc8702000834fc8702100834fc8702200834fc8702300834fc8702400834fc8702500834fc8702600834fc870270000"_hex_u8, {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40});
TestOptimalLinearization("c7128ac61a00837ae46e0000837ae46e0100837ae46e0200837ae46e0300837ae46e0400837ae46e0500837ae46e0600837ae46e0700837ae46e0800837ae46e0900837ae46e0a00837ae46e0b00837ae46e0c00837ae46e0d00837ae46e0e00837ae46e0f00837ae46e1000837ae46e1100837ae46e1200837ae46e1300837ae46e1400837ae46e1500837ae46e1600837ae46e1700837ae46e1800837ae46e1900837ae46e1a00837ae46e1b00837ae46e1c00837ae46e1d00837ae46e1e0000"_hex_v_u8, {{296758, 28888}}); TestOptimalLinearization("c7128ac61a00837ae46e0000837ae46e0100837ae46e0200837ae46e0300837ae46e0400837ae46e0500837ae46e0600837ae46e0700837ae46e0800837ae46e0900837ae46e0a00837ae46e0b00837ae46e0c00837ae46e0d00837ae46e0e00837ae46e0f00837ae46e1000837ae46e1100837ae46e1200837ae46e1300837ae46e1400837ae46e1500837ae46e1600837ae46e1700837ae46e1800837ae46e1900837ae46e1a00837ae46e1b00837ae46e1c00837ae46e1d00837ae46e1e0000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31});
TestOptimalLinearization("8440881a0084408c5e000000"_hex_v_u8, {{1468, 1408}}); TestOptimalLinearization("8440881a0084408c5e000000"_hex_u8, {0, 1});
TestOptimalLinearization("a22d80e478008e4be10000008e4be42e00029031f0120002903284fe200000d25c9b8d380000835b80c71c0002835b80c71c0102835b80c71c0202835b80c71c0300835b80c71c0400835b80c71c0500835b80c71c0600835b80c71c0700835b80c71c0800835b80c71c0900835b80c71c0a00835b80c71c0b00835b80c71c0c00835b80c71c0d00835b80c71c0e00835b80c71c0f00835b80c71c1000835b80c71c1100835b80c71c1200835b80c71c1300835b80c71c1400835b80c71c1500835b80c71c1600835b80c71c1700835b80c71c1800835b80c71c1900835b80c71c1a00835b80c71c1b00835b80c71c1c00835b80c71c1d00835b80c71c1e00835b80c71c1f00835b80c71c2000835b80c71c2100835b80c71c2200835b80c71c2300835b80c71c2400835b80c71c2500835b80c71c2600835b80c71c2700835b80c71c2800835b80c71c2900835b80c71c2a00835b80c71c2b00835b80c71c2c00835b80c71c2d00835b80c71c2e00835b80c71c2f00835b80c71c3000835b80c71c3100835b80c71c3200835b80c71c3300835b80c71c3400835b80c71c350000"_hex_v_u8, {{1006076, 56244}}); TestOptimalLinearization("a22d80e478008e4be10000008e4be42e00029031f0120002903284fe200000d25c9b8d380000835b80c71c0002835b80c71c0102835b80c71c0202835b80c71c0300835b80c71c0400835b80c71c0500835b80c71c0600835b80c71c0700835b80c71c0800835b80c71c0900835b80c71c0a00835b80c71c0b00835b80c71c0c00835b80c71c0d00835b80c71c0e00835b80c71c0f00835b80c71c1000835b80c71c1100835b80c71c1200835b80c71c1300835b80c71c1400835b80c71c1500835b80c71c1600835b80c71c1700835b80c71c1800835b80c71c1900835b80c71c1a00835b80c71c1b00835b80c71c1c00835b80c71c1d00835b80c71c1e00835b80c71c1f00835b80c71c2000835b80c71c2100835b80c71c2200835b80c71c2300835b80c71c2400835b80c71c2500835b80c71c2600835b80c71c2700835b80c71c2800835b80c71c2900835b80c71c2a00835b80c71c2b00835b80c71c2c00835b80c71c2d00835b80c71c2e00835b80c71c2f00835b80c71c3000835b80c71c3100835b80c71c3200835b80c71c3300835b80c71c3400835b80c71c350000"_hex_u8, {2, 3, 0, 1, 7, 8, 4, 5, 6, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59});
TestOptimalLinearization("8472e52e008473e52e018473e52e028473e52e038472e52e048472f85c058472e77405058472e52e05058473e52e05058473e52e05058473e52e05058472fe0005058472ef1e050f8473809e14050e8473e874050d8239ad42060d8473809e14060c8472e874060b8472fb58060a847280b024061a847280837406188473e674061684738083740514847280b91405128473fb580424847380cd24031e8472fb58031a8472f85c03178473fb58032b8473f85c03238472f85c031e847380ab14031a8472f85c03318472f85c03288473fe0003228473fb58031d8472f85c03378473f85c011d8473f85c031c8472808028023c8472f85c021e8473f85c021f8473f85c01208473f85c00218e0b81d3280a03010514901a8089000c000502020800"_hex_v_u8, {{50602, 4526}, {196414, 18533}, {7980, 755}, {23898, 2262}, {15918, 1509}, {23856, 2262}, {15580, 1509}, {7790, 755}, {7790, 755}, {7790, 755}, {7790, 755}, {2977, 441}, {8832, 2202}}); TestOptimalLinearization("8472e52e008473e52e018473e52e028473e52e038472e52e048472f85c058472e77405058472e52e05058473e52e05058473e52e05058473e52e05058472fe0005058472ef1e050f8473809e14050e8473e874050d8239ad42060d8473809e14060c8472e874060b8472fb58060a847280b024061a847280837406188473e674061684738083740514847280b91405128473fb580424847380cd24031e8472fb58031a8472f85c03178473fb58032b8473f85c03238472f85c031e847380ab14031a8472f85c03318472f85c03288473fe0003228473fb58031d8472f85c03378473f85c011d8473f85c031c8472808028023c8472f85c021e8473f85c021f8473f85c01208473f85c00218e0b81d3280a03010514901a8089000c000502020800"_hex_u8, {29, 30, 31, 32, 33, 34, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 28, 35, 36, 37, 38, 26, 27, 6, 7, 8, 40, 42, 41, 43, 44, 45, 20, 39});
TestOptimalLinearization("8361c74a0084a108cec45c0000831cbe5e0000831cbe5e0100831cbe5e0200831cbe5e0300831cbe5e0400831cbe5e0500831cbe5e0600831cbe5e0700831cbe5e0800831cbe5e0900831cbe5e0a00831cbe5e0b00831cbe5e0c00831cbe5e0d00831cbe5e0e00831cbe5e0f00831cbe5e1000831cbe5e1100831cbe5e1200831cbe5e1300831cbe5e1400831cbe5e1500831cbe5e1600831cbe5e1700831cbe5e1800831cbe5e1900831cbe5e1a00831cbe5e1b00831cbe5e1c00831cbe5e1d00831cbe5e1e00831cbe5e1f00831cbe5e2000831cbe5e2100831cbe5e2200831cbe5e2300831cbe5e2400831cbe5e2500831cbe5e2600831cbe5e270000"_hex_v_u8, {{4645, 609}, {814790, 107880}}); TestOptimalLinearization("8361c74a0084a108cec45c0000831cbe5e0000831cbe5e0100831cbe5e0200831cbe5e0300831cbe5e0400831cbe5e0500831cbe5e0600831cbe5e0700831cbe5e0800831cbe5e0900831cbe5e0a00831cbe5e0b00831cbe5e0c00831cbe5e0d00831cbe5e0e00831cbe5e0f00831cbe5e1000831cbe5e1100831cbe5e1200831cbe5e1300831cbe5e1400831cbe5e1500831cbe5e1600831cbe5e1700831cbe5e1800831cbe5e1900831cbe5e1a00831cbe5e1b00831cbe5e1c00831cbe5e1d00831cbe5e1e00831cbe5e1f00831cbe5e2000831cbe5e2100831cbe5e2200831cbe5e2300831cbe5e2400831cbe5e2500831cbe5e2600831cbe5e270000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41});
TestOptimalLinearization("8431e564008369a158018369a15c028369a162038550ae20048369a17a058501a94a068501a946078430e72e088369a178098500a93a0a842fe5640b8502a9360c8501a8740d83699f5a0e8431e5640f8431e564108369a144118550ae2211118737ba280a118369a178081183699f5a051183699e4605118374b1601204891ec536060b0682199b70021582199b70041482199b7006138540ab7c031a853fab76001db6219ddc1007000000000100000000000000000000001e00"_hex_v_u8, {{327699, 22688}, {3248, 628}, {1848, 409}, {1848, 409}, {1848, 409}, {2210, 617}, {10260, 2973}}); TestOptimalLinearization("8431e564008369a158018369a15c028369a162038550ae20048369a17a058501a94a068501a946078430e72e088369a178098500a93a0a842fe5640b8502a9360c8501a8740d83699f5a0e8431e5640f8431e564108369a144118550ae2211118737ba280a118369a178081183699f5a051183699e4605118374b1601204891ec536060b0682199b70021582199b70041482199b7006138540ab7c031a853fab76001db6219ddc1007000000000100000000000000000000001e00"_hex_u8, {10, 14, 1, 19, 21, 7, 12, 15, 5, 4, 3, 2, 6, 8, 9, 13, 16, 11, 17, 18, 20, 22, 0, 27, 28, 29, 30, 23, 24, 25, 26});
TestOptimalLinearization("836881f0280088318cba380000a37a9986500000a37a9986500100a37a9986500200a37a9986500300835a82ae5c0303835a82ae5c0403835a82ae5c0503835a82ae5c0603835a82ae5c0703835a82ae5c0803835a82ae5c0903835a82ae5c0a03835a82ae5c0b03835a82ae5c0c03835a82ae5c0d03835a82ae5c0e03835a82ae5c0f03835a82ae5c1003835a82ae5c1103835a82ae5c1203835a82ae5c1303835a82ae5c1403835a82ae5c1503835a82ae5c1603835a82ae5c1703835a82ae5c1803835a82ae5c1903835a82ae5c1a03835a82ae5c1a02835a82ae5c1a02835a82ae5c1c01835a82ae5c1c02835a82ae5c1e01835a82ae5c1e02835a82ae5c2001835a82ae5c2002835a82ae5c2102835a82ae5c2301835a82ae5c2302835a82ae5c2402835a82ae5c2502835a82ae5c2701835a82ae5c2801835a82ae5c2901835a82ae5c2a01835a82ae5c2a02835a82ae5c2c01835a82ae5c2d01835a82ae5c2d02835a82ae5c2f01835a82ae5c3001835a82ae5c3101835a82ae5c3102835a82ae5c3301835a82ae5c330200"_hex_v_u8, {{133936, 1817}, {876600, 19178}, {627930, 13760}, {545040, 11954}, {213480, 4730}}); TestOptimalLinearization("836881f0280088318cba380000a37a9986500000a37a9986500100a37a9986500200a37a9986500300835a82ae5c0303835a82ae5c0403835a82ae5c0503835a82ae5c0603835a82ae5c0703835a82ae5c0803835a82ae5c0903835a82ae5c0a03835a82ae5c0b03835a82ae5c0c03835a82ae5c0d03835a82ae5c0e03835a82ae5c0f03835a82ae5c1003835a82ae5c1103835a82ae5c1203835a82ae5c1303835a82ae5c1403835a82ae5c1503835a82ae5c1603835a82ae5c1703835a82ae5c1803835a82ae5c1903835a82ae5c1a03835a82ae5c1a02835a82ae5c1a02835a82ae5c1c01835a82ae5c1c02835a82ae5c1e01835a82ae5c1e02835a82ae5c2001835a82ae5c2002835a82ae5c2102835a82ae5c2301835a82ae5c2302835a82ae5c2402835a82ae5c2502835a82ae5c2701835a82ae5c2801835a82ae5c2901835a82ae5c2a01835a82ae5c2a02835a82ae5c2c01835a82ae5c2d01835a82ae5c2d02835a82ae5c2f01835a82ae5c3001835a82ae5c3101835a82ae5c3102835a82ae5c3301835a82ae5c330200"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 29, 32, 34, 36, 39, 43, 44, 45, 46, 48, 49, 51, 52, 53, 55, 28, 31, 33, 35, 37, 38, 40, 41, 42, 47, 50, 54, 56, 30});
TestOptimalLinearization("836884c43c00a30da899200000847285dd280000856c86e6180100853586aa700200846085c6400300853586aa70040085168686300500853a86af38060085238694080700844f85b4200800853b86af380900850985f8580a00850185ef480b00853d86b4000c00853c86af380d00855d86d8400e00853e86b4000f00845985c1781000846485cb081100844c85af581200853e86b4001300845085b420140000"_hex_v_u8, {{45406, 616}, {1043316, 14258}, {52560, 719}, {58692, 803}, {60444, 827}, {52268, 716}, {52560, 720}, {53728, 736}, {54020, 740}, {60444, 828}, {63948, 876}}); TestOptimalLinearization("836884c43c00a30da899200000847285dd280000856c86e6180100853586aa700200846085c6400300853586aa70040085168686300500853a86af38060085238694080700844f85b4200800853b86af380900850985f8580a00850185ef480b00853d86b4000c00853c86af380d00855d86d8400e00853e86b4000f00845985c1781000846485cb081100844c85af581200853e86b4001300845085b420140000"_hex_u8, {0, 1, 18, 13, 12, 4, 6, 14, 16, 2, 7, 8, 17, 21, 10, 9, 11, 20, 22, 5, 19, 15, 3});
TestOptimalLinearization("8369821a008369821a0185018272028369821a038369821a0485018272058431892e0685018272078369821a088431892e09850182720a850182720b855083280c855083280d8369821a0e8369821a0f8369821a108369821a1185028272128369821a138369821a148369821a1585508328168369821a17823d834a188369821a198369821a1a8369821a1b855083281c8430892e1d842f892e1e843086101f8369821a208369821a0e338369821a1b208b0586542218860b8a381a208550832811208e538870111d8550832809208737843609208369821a09208369821a1c0d8369821a09498369821a032b8369821a032a8369821a0b2283699e5a04298369821a032c9d7181ea04012d8369821a012f8359a46c012e8369821a0131833983380034bc5285e37a110000110000000000000000000000000020bf6983b65e09000200000400000000000000000000100900"_hex_v_u8, {{25744, 6035}, {2422, 601}, {61527, 21962}, {43202, 25453}, {899, 2420}, {205, 617}, {205, 617}, {205, 617}}); TestOptimalLinearization("8369821a008369821a0185018272028369821a038369821a0485018272058431892e0685018272078369821a088431892e09850182720a850182720b855083280c855083280d8369821a0e8369821a0f8369821a108369821a1185028272128369821a138369821a148369821a1585508328168369821a17823d834a188369821a198369821a1a8369821a1b855083281c8430892e1d842f892e1e843086101f8369821a208369821a0e338369821a1b208b0586542218860b8a381a208550832811208e538870111d8550832809208737843609208369821a09208369821a1c0d8369821a09498369821a032b8369821a032a8369821a0b2283699e5a04298369821a032c9d7181ea04012d8369821a012f8359a46c012e8369821a0131833983380034bc5285e37a110000110000000000000000000000000020bf6983b65e09000200000400000000000000000000100900"_hex_u8, {18, 49, 53, 54, 55, 8, 13, 14, 1, 3, 5, 6, 9, 11, 19, 20, 21, 17, 4, 7, 10, 15, 16, 12, 22, 39, 37, 42, 32, 23, 25, 27, 28, 30, 33, 34, 35, 43, 44, 45, 26, 29, 36, 38, 24, 40, 41, 31, 46, 48, 51, 52, 50, 0, 2, 47});
TestOptimalLinearization("8089328682520083329b52000083329b52010083329b52020083329b52030083329b52040083329b52050083329b52060083329b52070083329b52080083329b52090083329b520a0083329b520b0083329b520c0083329b520d0083329b520e0083329b520f0083329b52100083329b52110083329b52120083329b52130083329b52140083329b52150083329b52160083329b52170083329b52180083329b52190083329b521a0083329b521b0083329b521c0083329b521d0083329b521e0000"_hex_v_u8, {{114400, 35136}}); TestOptimalLinearization("8089328682520083329b52000083329b52010083329b52020083329b52030083329b52040083329b52050083329b52060083329b52070083329b52080083329b52090083329b520a0083329b520b0083329b520c0083329b520d0083329b520e0083329b520f0083329b52100083329b52110083329b52120083329b52130083329b52140083329b52150083329b52160083329b52170083329b52180083329b52190083329b521a0083329b521b0083329b521c0083329b521d0083329b521e0000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31});
TestOptimalLinearization("872d8f58009928c064000089509a400000895d99700100860d90680200860a905e03008655921c0400872b936e0500857f904006008603904a07008608905408008602904a0900861f91100a00862591240b0000"_hex_v_u8, {{20428, 16489}}); TestOptimalLinearization("872d8f58009928c064000089509a400000895d99700100860d90680200860a905e03008655921c0400872b936e0500857f904006008603904a07008608905408008602904a0900861f91100a00862591240b0000"_hex_u8, {0, 1, 2, 4, 13, 6, 11, 5, 3, 8, 9, 12, 7, 10});
TestOptimalLinearization("8472cf14008472cf14018472cf14028473cf1402028473cf1401028472cf1403018472cf1401098472cf1403068473cf1402048473cf1402058473cf1402068472cf1402068472cf1402078472cf1402088473cf1402088472cf1402098473cf14020a8472cf14020a8472cf14010d8473cf14030b8473cf14020cb42181bf200d00010e8473cf14020e8472cf14040d8472cf14030e8472cf1402108473cf1402118473cf1402118473cf1402128472cf1402138472cf140213886f80845e090b01148473cf1402158472cf1404148472cf1403158472cf1402188472cf1402178473cf1402188472cf14021b8473cf14001b00"_hex_v_u8, {{5130, 754}, {5130, 754}, {5130, 754}, {5130, 754}, {25650, 3772}, {61560, 9053}, {46170, 6790}, {30780, 4527}, {5130, 755}, {5130, 755}, {29055, 8080}}); TestOptimalLinearization("8472cf14008472cf14018472cf14028473cf1402028473cf1401028472cf1403018472cf1401098472cf1403068473cf1402048473cf1402058473cf1402068472cf1402068472cf1402078472cf1402088473cf1402088472cf1402098473cf14020a8472cf14020a8472cf14010d8473cf14030b8473cf14020cb42181bf200d00010e8473cf14020e8472cf14040d8472cf14030e8472cf1402108473cf1402118473cf1402118473cf1402128472cf1402138472cf140213886f80845e090b01148473cf1402158472cf1404148472cf1403158472cf1402188472cf1402178473cf1402188472cf14021b8473cf14001b00"_hex_u8, {1, 4, 5, 8, 6, 0, 9, 13, 16, 2, 3, 10, 14, 17, 18, 23, 26, 29, 31, 33, 35, 12, 15, 19, 21, 24, 27, 30, 34, 36, 20, 22, 25, 28, 32, 37, 38, 39, 7, 11});
TestOptimalLinearization("808967889a74008367a77400018367a77401008367a77402008367a77403008367a77404008367a77405008367a77406008367a77407008367a77408008367a77409008367a7740a008367a7740b008367a7740c008367a7740d008367a7740e008367a7740f008367a77410008367a77411008367a77412008367a77413008367a77414008367a77415008367a77416008367a77417008367a77418008367a77419008367a7741a008367a7741b008367a7741c008367a7741d0000"_hex_v_u8, {{154054, 36217}}); TestOptimalLinearization("808967889a74008367a77400018367a77401008367a77402008367a77403008367a77404008367a77405008367a77406008367a77407008367a77408008367a77409008367a7740a008367a7740b008367a7740c008367a7740d008367a7740e008367a7740f008367a77410008367a77411008367a77412008367a77413008367a77414008367a77415008367a77416008367a77417008367a77418008367a77419008367a7741a008367a7741b008367a7741c008367a7741d0000"_hex_u8, {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30});
TestOptimalLinearization("8335b816008335c44c00008335c44c00008331c40c00008335c44c00008335c44c00008335c44c00008335c44c0000833dc54800008335c44c00008331c40c00008335c44c00008335c44c00008335c44c00008335c44c00008335c44c0000833dc54800008331c40c00008331c40c00008335c44c00008335c44c00008335c44c00008335c44c000000"_hex_v_u8, {{101643, 12995}}); TestOptimalLinearization("8335b816008335c44c00008335c44c00008331c40c00008335c44c00008335c44c00008335c44c00008335c44c0000833dc54800008335c44c00008331c40c00008335c44c00008335c44c00008335c44c00008335c44c00008335c44c0000833dc54800008331c40c00008331c40c00008335c44c00008335c44c00008335c44c00008335c44c000000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22});
TestOptimalLinearization("89c0788087d818008448c72800008448c72801008448c72802008448c72803008448c72804008448c72805008448c72806008448c72807008448c72808008448c72809008448c7280a008448c7280b008448c7280c008448c7280d008448c7280e008448c7280f008448c72810008448c72811008448c72812008448c72813008448c72814008448c72815008448c72816008448c72817008448c72818008448c72819008448c7281a008448c7281b008448c7281c008448c7281d008448c7281e008448c7281f008448c72820008448c72821008448c72822008448c728230000"_hex_v_u8, {{1119820, 172280}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}}); TestOptimalLinearization("89c0788087d818008448c72800008448c72801008448c72802008448c72803008448c72804008448c72805008448c72806008448c72807008448c72808008448c72809008448c7280a008448c7280b008448c7280c008448c7280d008448c7280e008448c7280f008448c72810008448c72811008448c72812008448c72813008448c72814008448c72815008448c72816008448c72817008448c72818008448c72819008448c7281a008448c7281b008448c7281c008448c7281d008448c7281e008448c7281f008448c72820008448c72821008448c72822008448c728230000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36});
TestOptimalLinearization("81c62aebef0200823580816a01819771dba4680280d371c4eb600381ac0ee3960604854080ae0c05845081ce140505823580a59b260605857c82bb400705824180e86008058a4884bc36090582428188380a05833182d3140b058235808f93460a05860881fc300b05832480c92c0c058332818f7a0c05860082b74c0d05844482c1160e058235ed82480f058545828578100583368186741105854c829a121205823980f8361205823981906e13058235809892121405845181b2001505833180f3481605823a8188141705860482b12c1921857c81f5401d00847c82a7201b038b7e84bf581c03824180ef6a1c04875382d1161f02826581ce621e04875385b93a2300854d83c1702400833e81ce202203823681bf182402823581bf182403823581bf182503823681bf182702823681bf182a00823681c75a270484448394622c00823581c75a2d00823981eb302e008a4484cd682533860482e96c2831824181e6282534845182fa5430012797518b902c310028833281b9381930845181dc44300018ad5688bd082e1b857c82dc2e075f823982ac58045c9b698c944e3500021d00"_hex_v_u8, {{2075276, 38979}, {2283550, 42896}, {1937047, 36390}, {1473556, 27686}, {23320, 441}, {22996, 449}, {34161, 708}, {21037, 437}, {21037, 438}, {52893, 1107}, {20492, 437}, {20492, 437}, {20492, 438}, {20492, 438}, {20492, 438}, {32490, 721}, {21489, 485}, {37048, 845}, {28811, 708}, {17527, 441}, {16970, 442}, {16988, 450}, {21456, 574}, {15963, 441}, {27152, 764}, {15413, 449}, {135287, 4031}, {59862, 1792}, {14960, 449}, {35776, 1123}, {121446, 3848}, {28198, 896}, {26313, 844}, {17469, 562}, {27798, 900}, {25020, 837}, {16890, 566}, {21450, 720}, {107879, 3689}, {19648, 721}, {45100, 1662}, {24408, 904}, {29835, 1107}, {23968, 892}, {12950, 548}, {33576, 1553}, {77700, 5974}}); TestOptimalLinearization("81c62aebef0200823580816a01819771dba4680280d371c4eb600381ac0ee3960604854080ae0c05845081ce140505823580a59b260605857c82bb400705824180e86008058a4884bc36090582428188380a05833182d3140b058235808f93460a05860881fc300b05832480c92c0c058332818f7a0c05860082b74c0d05844482c1160e058235ed82480f058545828578100583368186741105854c829a121205823980f8361205823981906e13058235809892121405845181b2001505833180f3481605823a8188141705860482b12c1921857c81f5401d00847c82a7201b038b7e84bf581c03824180ef6a1c04875382d1161f02826581ce621e04875385b93a2300854d83c1702400833e81ce202203823681bf182402823581bf182403823581bf182503823681bf182702823681bf182a00823681c75a270484448394622c00823581c75a2d00823981eb302e008a4484cd682533860482e96c2831824181e6282534845182fa5430012797518b902c310028833281b9381930845181dc44300018ad5688bd082e1b857c82dc2e075f823982ac58045c9b698c944e3500021d00"_hex_u8, {28, 32, 0, 2, 10, 13, 17, 20, 24, 59, 11, 57, 58, 56, 48, 52, 53, 51, 54, 55, 14, 47, 49, 23, 31, 36, 6, 50, 29, 43, 45, 12, 15, 16, 3, 9, 4, 34, 35, 5, 7, 8, 22, 27, 21, 41, 25, 26, 1, 30, 33, 44, 18, 46, 42, 19, 37, 38, 39});
TestOptimalLinearization("8368aa5e008368aa5e018368aa5e028368aa5e038368aa5e0483689726058368aa5e05058368aa5e05058368aa5e05058368aa5e05058368aa5e05058368aa5e05058368972608038368aa5e010b854ea024080005a35780b638020ba35780b638010e83679708010d83679708020d83679708030d83679708040d83679708050d83679708060d83679708070d83679708080d83679708090d836797080a0d836797080b0d836797080c0d836797080d0d836797080e0d854eba7414001c836797080f1d83679708101d83679708111d83679708121d83679708131d83679708141d83679708151d83679708161d83679708171d83679708181d83679708191d836797081a1d836797081b1d836797081c1d836797081d1d836797081e1d836797081f1d83679708201d83679708211d8734cb0a2a0000308734cf280013112600"_hex_v_u8, {{2799, 616}, {2799, 616}, {2799, 616}, {2799, 616}, {2799, 616}, {2799, 616}, {2799, 616}, {2799, 616}, {2799, 616}, {2799, 616}, {3834, 846}, {4869, 1076}, {12293, 2924}, {1555, 616}, {2130, 846}, {41000, 16380}, {33300, 13305}}); TestOptimalLinearization("8368aa5e008368aa5e018368aa5e028368aa5e038368aa5e0483689726058368aa5e05058368aa5e05058368aa5e05058368aa5e05058368aa5e05058368aa5e05058368972608038368aa5e010b854ea024080005a35780b638020ba35780b638010e83679708010d83679708020d83679708030d83679708040d83679708050d83679708060d83679708070d83679708080d83679708090d836797080a0d836797080b0d836797080c0d836797080d0d836797080e0d854eba7414001c836797080f1d83679708101d83679708111d83679708121d83679708131d83679708141d83679708151d83679708161d83679708171d83679708181d83679708191d836797081a1d836797081b1d836797081c1d836797081d1d836797081e1d836797081f1d83679708201d83679708211d8734cb0a2a0000308734cf280013112600"_hex_u8, {0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 6, 12, 13, 14, 15, 37, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52});
TestOptimalLinearization("8361ee3400877f80d86401877e80d864028362ee3403877e80d86404877e80d86405877e80d864068362ee34078341e5640707877e80d86408078362ee3408078362ee340807877f80d86408078346e56409078361ee3409078361ee340907877f80f97608078342e56409078361ee340b068361ee340918877e80f51809178346e5640a178360f80c0a168342e5640b168362ee340b158361f80c0a148341e5640b148361fa420b138342e5640c138361fa420a118341e5640b118343e5640b2c8361fa420c2c8361fa420a288341ee5c0b288361fa420a268342e5640b268361fa420b238343ee5c0c23877e80f5180b218343f07a0c21877f80f5180b1c8343f07a0c1c8341f07a0a42877e80f5180b42877f80f5180b3b8341f07a0c3b877e80f5180b378342f07a0c37877f80f5180b338341f07a0c33877f819a421e0a2d877f819a420a1511877f819b2c031921877e819a42061121877e819a42090c3b877e819a420b0737877e819a4203141600"_hex_v_u8, {{263296, 19845}, {267965, 20479}, {7293, 577}, {7293, 577}, {7293, 577}, {7293, 578}, {7293, 579}, {7293, 579}, {7150, 577}, {7150, 579}, {6578, 577}, {6578, 578}, {6578, 582}}); TestOptimalLinearization("8361ee3400877f80d86401877e80d864028362ee3403877e80d86404877e80d86405877e80d864068362ee34078341e5640707877e80d86408078362ee3408078362ee340807877f80d86408078346e56409078361ee3409078361ee340907877f80f97608078342e56409078361ee340b068361ee340918877e80f51809178346e5640a178360f80c0a168342e5640b168362ee340b158361f80c0a148341e5640b148361fa420b138342e5640c138361fa420a118341e5640b118343e5640b2c8361fa420c2c8361fa420a288341ee5c0b288361fa420a268342e5640b268361fa420b238343ee5c0c23877e80f5180b218343f07a0c21877f80f5180b1c8343f07a0c1c8341f07a0a42877e80f5180b42877f80f5180b3b8341f07a0c3b877e80f5180b378342f07a0c37877f80f5180b338341f07a0c33877f819a421e0a2d877f819a420a1511877f819b2c031921877e819a42061121877e819a42090c3b877e819a420b0737877e819a4203141600"_hex_u8, {31, 47, 8, 0, 32, 33, 34, 35, 51, 52, 53, 9, 10, 48, 49, 1, 12, 56, 50, 54, 11, 39, 57, 2, 13, 40, 3, 5, 7, 41, 42, 43, 14, 15, 16, 17, 22, 23, 24, 25, 26, 28, 30, 45, 46, 4, 21, 6, 18, 36, 27, 44, 55, 19, 37, 38, 20, 29});
TestOptimalLinearization("80de1a89c02e0080dd1c8aac460180d10789b70202b04282ee2803854da96204833da30005ae0e82d6200682429268078608ac7408833e973a09b4558397700a823589e10e0a0a8331b54c0b0a8335a0000c0a823588ec180c0a8544ac400d0a8242bd000d0a8235899b7e0e0a8546ac500f0a8544ac5011098242974e12098545d03a110a8331a42215058241974015068545d35c140883319d5017068578b37c130a8541d3261408f43185ba60120a82429b001607833282b6161a048235ac5a140a8336b87219068331b54c14288f1c81a34020001a8751bb1e2000178540ac341f001483359d6611228241cc781024833db67c101a8b708099280d1dbf3a85a62a2301021483319d4a0634833d9e1e0633dd3884c704230000108a58d654120f0a9e65829c580438880ff5100010208474e9700030894880bd1002013200"_hex_v_u8, {{59807, 6900}, {10201, 1286}, {5422, 837}, {173248, 27774}, {454202, 73978}, {39260, 7429}, {5967, 1134}, {13266, 2536}, {37285, 7306}, {61944, 14794}, {1792, 450}, {68941, 17522}, {5610, 1496}, {2112, 565}, {1575, 450}, {1960, 561}, {2920, 836}, {1568, 449}, {3855, 1105}, {1971, 565}, {1957, 561}, {2920, 838}, {2912, 836}, {7642, 2250}}); TestOptimalLinearization("80de1a89c02e0080dd1c8aac460180d10789b70202b04282ee2803854da96204833da30005ae0e82d6200682429268078608ac7408833e973a09b4558397700a823589e10e0a0a8331b54c0b0a8335a0000c0a823588ec180c0a8544ac400d0a8242bd000d0a8235899b7e0e0a8546ac500f0a8544ac5011098242974e12098545d03a110a8331a42215058241974015068545d35c140883319d5017068578b37c130a8541d3261408f43185ba60120a82429b001607833282b6161a048235ac5a140a8336b87219068331b54c14288f1c81a34020001a8751bb1e2000178540ac341f001483359d6611228241cc781024833db67c101a8b708099280d1dbf3a85a62a2301021483319d4a0634833d9e1e0633dd3884c704230000108a58d654120f0a9e65829c580438880ff5100010208474e9700030894880bd1002013200"_hex_u8, {16, 45, 17, 24, 29, 9, 11, 10, 20, 5, 6, 0, 1, 8, 21, 28, 2, 4, 31, 49, 37, 25, 42, 32, 44, 46, 47, 34, 33, 35, 36, 43, 38, 39, 40, 41, 48, 3, 15, 30, 14, 27, 13, 22, 23, 12, 7, 18, 19, 26});
TestOptimalLinearization("81903fc9ee3800819170cfe6520180d334bef35002819540d0d4480380da6ebdd94a0482359094100405823580a7120504823589bd760504847c819d100504823585f11c060482358d8d6a0604823589c62e0604823580b5520704a51586dd5008000000000000"_hex_v_u8, {{784665, 36085}, {764717, 35881}, {611877, 29016}, {598334, 28389}, {747940, 35621}, {63400, 4885}}); TestOptimalLinearization("81903fc9ee3800819170cfe6520180d334bef35002819540d0d4480380da6ebdd94a0482359094100405823580a7120504823589bd760504847c819d100504823585f11c060482358d8d6a0604823589c62e0604823580b5520704a51586dd5008000000000000"_hex_u8, {8, 9, 1, 0, 2, 10, 11, 12, 5, 7, 6, 3, 4, 13});
TestOptimalLinearization("808963829f2c0083638d2c000183638d2c010083638d2c020083638d2c030083638d2c040083638d2c050083638d2c060083638d2c070083638d2c080083638d2c090083638d2c0a0083638d2c0b0083638d2c0c0083638d2c0d0083638d2c0e0083638d2c0f0083638d2c100083638d2c110083638d2c120083638d2c130083638d2c140083638d2c150083638d2c160083638d2c170083638d2c180083638d2c190083638d2c1a0083638d2c1b0083638d2c1c0083638d2c1d0083638d2c1e0083638d2c1f0083638d2c200083638d2c210083638d2c220000"_hex_v_u8, {{58776, 39148}}); TestOptimalLinearization("808963829f2c0083638d2c000183638d2c010083638d2c020083638d2c030083638d2c040083638d2c050083638d2c060083638d2c070083638d2c080083638d2c090083638d2c0a0083638d2c0b0083638d2c0c0083638d2c0d0083638d2c0e0083638d2c0f0083638d2c100083638d2c110083638d2c120083638d2c130083638d2c140083638d2c150083638d2c160083638d2c170083638d2c180083638d2c190083638d2c1a0083638d2c1b0083638d2c1c0083638d2c1d0083638d2c1e0083638d2c1f0083638d2c200083638d2c210083638d2c220000"_hex_u8, {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35});
TestOptimalLinearization("8d29889718008368809064018368809064028d1386db10020292618bd5080302846380ac380301846380ac38030283688090640307854e80c6580500038360b8540403824182812a0503844682b6300603846380ac38040e8368809064050e8368809064050b846380ac38060a842ebf400609846380ac38031683688090640415846380ac380410846380ac38011a854e80c65802030b846380ac3800108368809064010e846280ac38000f8368809064010d846280ac38000e8368809064010e846380ac38000f00"_hex_v_u8, {{203813, 4811}, {28120, 710}, {63240, 1811}, {9330, 616}, {9330, 616}, {9330, 616}, {9330, 616}, {9330, 616}, {62880, 4156}, {11100, 738}, {11100, 738}, {11100, 739}, {11100, 739}, {11100, 739}, {11100, 739}, {11100, 739}, {11100, 739}, {11100, 739}, {11100, 739}, {11100, 739}, {3690, 608}, {4128, 686}}); TestOptimalLinearization("8d29889718008368809064018368809064028d1386db10020292618bd5080302846380ac380301846380ac38030283688090640307854e80c6580500038360b8540403824182812a0503844682b6300603846380ac38040e8368809064050e8368809064050b846380ac38060a842ebf400609846380ac38031683688090640415846380ac380410846380ac38011a854e80c65802030b846380ac3800108368809064010e846280ac38000f8368809064010d846280ac38000e8368809064010e846380ac38000f00"_hex_u8, {0, 6, 23, 24, 1, 2, 4, 7, 9, 10, 11, 12, 17, 21, 25, 27, 22, 26, 3, 5, 8, 13, 14, 15, 16, 18, 28, 19, 20});
TestOptimalLinearization("81bd6f8dc370008544a9200180df1588f04e028541ac340380c97c88b0240480e74989ca6c0583359a38068608d7240606854ec40a070687128091760806941381c52009068608d7240a06854de8200b05a32081e9680c058445c4200d058335ad300e05823580b40e0f05875d80856810058450809a380f068578d60e10068545d03a11068546b63212068a54808b20130682419c7214068474b93e15068235a26216068608d7241706833ead6c1806823580840a19068242cd221a068754c4081b06847480971a19068235c5281a068a58809c641b068474d2101c068239c2041d06854cd11e1e06823aa16e1f06ab7282a6702006823580887621068608a22825028540af5224048500e23425048336c0502604823abf2627048235fa3a2804896a80984e2904823997162a048803bd7a2b04823a97082c0483329d4a2d048332b1343002857cd64028388d7c818d0033002d8500ca0022328452ec581d36845180804835011a8545b9541a368546c658242dac1f82811c3702178450af18360210a70de536270e10854dee6c2c0c0400"_hex_v_u8, {{248259, 59175}, {180475, 43031}, {27624, 6624}, {167256, 41844}, {116449, 30424}, {3113, 832}, {1547, 441}, {4029, 1155}, {1540, 442}, {1957, 562}, {1756, 565}, {2260, 904}, {6555, 5133}}); TestOptimalLinearization("81bd6f8dc370008544a9200180df1588f04e028541ac340380c97c88b0240480e74989ca6c0583359a38068608d7240606854ec40a070687128091760806941381c52009068608d7240a06854de8200b05a32081e9680c058445c4200d058335ad300e05823580b40e0f05875d80856810058450809a380f068578d60e10068545d03a11068546b63212068a54808b20130682419c7214068474b93e15068235a26216068608d7241706833ead6c1806823580840a19068242cd221a068754c4081b06847480971a19068235c5281a068a58809c641b068474d2101c068239c2041d06854cd11e1e06823aa16e1f06ab7282a6702006823580887621068608a22825028540af5224048500e23425048336c0502604823abf2627048235fa3a2804896a80984e2904823997162a048803bd7a2b04823a97082c0483329d4a2d048332b1343002857cd64028388d7c818d0033002d8500ca0022328452ec581d36845180804835011a8545b9541a368546c658242dac1f82811c3702178450af18360210a70de536270e10854dee6c2c0c0400"_hex_u8, {7, 0, 13, 3, 8, 9, 14, 4, 11, 1, 5, 6, 12, 2, 10, 15, 28, 16, 30, 29, 17, 22, 26, 18, 20, 62, 24, 25, 27, 23, 21, 19, 33, 31, 32, 34, 36, 37, 47, 38, 39, 42, 41, 40, 43, 44, 45, 46, 35, 55, 54, 61, 52, 53, 56, 51, 57, 58, 59, 60, 48, 49, 50});
TestOptimalLinearization("c554baaa4600835c82fa220000835c82fa220100835c82fa220200835c82fa220300835c82fa220400835c82fa220500835c82fa220600835c82fa220700835c82fa220800835c82fa220900835c82fa220a0000"_hex_v_u8, {{486115, 9044}, {32465, 604}, {32465, 604}, {32465, 604}, {32465, 604}, {32465, 604}, {32465, 604}, {32465, 604}, {32465, 604}, {32465, 604}, {32465, 604}, {32465, 604}}); TestOptimalLinearization("c554baaa4600835c82fa220000835c82fa220100835c82fa220200835c82fa220300835c82fa220400835c82fa220500835c82fa220600835c82fa220700835c82fa220800835c82fa220900835c82fa220a0000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11});
TestOptimalLinearization("8184258aa316008185018287740180f14981ea6c028183288285600381a93a82c0180481831082a64005818a4182b2460681884983ae0a0781911684fd2208857cc81608088950904409088a4480d3240a08823590e0460a0882358fba2e0a08823590d1380a08823593963a0a08823590ed140908823590ae680b07823584640b08823a9f540d078235846e100585159a640f078541886014038478b41015038a54f370120782368a7a1604823588be08190282358fde161308854188601408823ab9661a03823a85101a048544c0141906844487281c048332aa561b068239a6181b078944e9201b0882358ee5281b088540bf6c1c08850088001d088c5f934a1e088445be0e2601833587662206854ce25a26038236856c22088541c30c2a018332875e0d2a8444c554250408875dd152121716833d8776023080970e80e35a013a9c6d81aa082b0000000000002400"_hex_v_u8, {{188460, 36250}, {175929, 34601}, {161920, 31928}, {182991, 36239}, {179050, 35516}, {176697, 35119}, {179744, 35778}, {194089, 38639}, {169428, 33733}, {7480, 1492}, {19140, 3821}, {4170, 836}, {4150, 832}, {2795, 562}, {2090, 442}, {3400, 760}, {5913, 1950}, {1778, 789}, {765, 438}, {438, 438}, {563, 565}, {1130, 1135}, {392, 442}, {375, 437}, {370, 437}, {1122, 1360}, {14637, 19470}, {532, 708}, {576, 768}, {624, 833}, {1317, 1759}}); TestOptimalLinearization("8184258aa316008185018287740180f14981ea6c028183288285600381a93a82c0180481831082a64005818a4182b2460681884983ae0a0781911684fd2208857cc81608088950904409088a4480d3240a08823590e0460a0882358fba2e0a08823590d1380a08823593963a0a08823590ed140908823590ae680b07823584640b08823a9f540d078235846e100585159a640f078541886014038478b41015038a54f370120782368a7a1604823588be08190282358fde161308854188601408823ab9661a03823a85101a048544c0141906844487281c048332aa561b068239a6181b078944e9201b0882358ee5281b088540bf6c1c08850088001d088c5f934a1e088445be0e2601833587662206854ce25a26038236856c22088541c30c2a018332875e0d2a8444c554250408875dd152121716833d8776023080970e80e35a013a9c6d81aa082b0000000000002400"_hex_u8, {0, 25, 3, 1, 8, 9, 48, 6, 7, 30, 39, 40, 44, 4, 5, 46, 50, 13, 15, 37, 26, 27, 38, 10, 11, 12, 16, 23, 14, 32, 41, 34, 18, 22, 28, 29, 20, 24, 49, 47, 35, 45, 31, 19, 17, 2, 36, 33, 42, 21, 43});
TestOptimalLinearization("836880ed0e00d724a0e46400008430818630000084308186300100842c81846c02008430818630030084308186300400842c81846c0500842c81846c060084308186300700842c81846c080084308186300900842c81846c0a0084308186300b0084308186300c0084308186300d00842c81846c0e00842c81846c0f0084308186301000842c81846c11008430818630120000"_hex_v_u8, {{15239, 616}, {276850, 11300}, {16758, 684}, {16758, 684}, {16758, 684}, {16758, 684}, {16758, 684}, {16758, 684}, {16758, 684}, {16758, 684}, {16856, 688}, {16856, 688}, {16856, 688}, {16856, 688}, {16856, 688}, {16856, 688}, {16856, 688}, {16856, 688}, {16856, 688}, {16856, 688}, {16856, 688}}); TestOptimalLinearization("836880ed0e00d724a0e46400008430818630000084308186300100842c81846c02008430818630030084308186300400842c81846c0500842c81846c060084308186300700842c81846c080084308186300900842c81846c0a0084308186300b0084308186300c0084308186300d00842c81846c0e00842c81846c0f0084308186301000842c81846c11008430818630120000"_hex_u8, {0, 1, 4, 7, 8, 10, 12, 16, 17, 19, 2, 3, 5, 6, 9, 11, 13, 14, 15, 18, 20});
TestOptimalLinearization("d02a82c24800fe6b84ff6001de7983ff08028235930202028578e04803028336915204028a48809e3405028474829172060285409a3807028474e30c08028a48809e34090283128d3c0a0283118d3c0b028608e1700c028948fd600d02857ce4060e028a5880aa140e028542b5700f028a4480a70e100282359f0412018600e44012028600e8001302b62180aa301402854182ad48150282368f0216028a4cef3417028a50d65418028500ee761a018600e4401a028236a3041b0286538292241d018578eb021e01823684fe6c1e028235a9061e028478f1241f02857cee4020028474dd4021028236ad0623018235a50423028241f41824028235a104250282418f0225238a5480a83c2800188235900a1e20824181834e181e82359f3e270f8a5080b9002b01078241a9060d2700"_hex_v_u8, {{119706, 15443}, {6467, 892}, {178169, 24786}, {6244, 888}, {6328, 904}, {10202, 1480}, {10202, 1480}, {2947, 438}, {8112, 1352}, {2306, 438}, {90860, 18386}, {7194, 1484}, {3512, 834}, {5610, 1488}, {3272, 1003}, {1281, 437}, {1025, 438}, {1025, 449}, {1756, 832}, {2019, 966}, {926, 530}, {10968, 7073}}); TestOptimalLinearization("d02a82c24800fe6b84ff6001de7983ff08028235930202028578e04803028336915204028a48809e3405028474829172060285409a3807028474e30c08028a48809e34090283128d3c0a0283118d3c0b028608e1700c028948fd600d02857ce4060e028a5880aa140e028542b5700f028a4480a70e100282359f0412018600e44012028600e8001302b62180aa301402854182ad48150282368f0216028a4cef3417028a50d65418028500ee761a018600e4401a028236a3041b0286538292241d018578eb021e01823684fe6c1e028235a9061e028478f1241f02857cee4020028474dd4021028236ad0623018235a50423028241f41824028235a104250282418f0225238a5480a83c2800188235900a1e20824181834e181e82359f3e270f8a5080b9002b01078241a9060d2700"_hex_u8, {0, 5, 33, 29, 7, 35, 20, 32, 14, 15, 36, 25, 23, 16, 19, 18, 21, 30, 2, 12, 4, 9, 44, 13, 31, 37, 46, 41, 43, 42, 39, 38, 40, 45, 47, 27, 17, 28, 3, 34, 1, 26, 8, 6, 11, 22, 10, 24});
TestOptimalLinearization("80896681da040083668b04000183668b04010083668b04020083668b04030083668b04040083668b04050083668b04060083668b04070083668b04080083668b04090083668b040a0083668b040b0083668b040c0083668b040d0083668b040e0083668b040f0083668b04100083668b04110083668b04120083668b04130083668b04140083668b04150083668b04160083668b04170083668b04180083668b04190083668b041a0083668b041b0083668b041c0083668b041d0083668b041e0083668b041f0083668b04200083668b04210083668b04220083668b04230083668b04240083668b04250083668b04260083668b04270083668b04280083668b04290083668b042a0083668b042b0000"_hex_v_u8, {{56090, 44782}}); TestOptimalLinearization("80896681da040083668b04000183668b04010083668b04020083668b04030083668b04040083668b04050083668b04060083668b04070083668b04080083668b04090083668b040a0083668b040b0083668b040c0083668b040d0083668b040e0083668b040f0083668b04100083668b04110083668b04120083668b04130083668b04140083668b04150083668b04160083668b04170083668b04180083668b04190083668b041a0083668b041b0083668b041c0083668b041d0083668b041e0083668b041f0083668b04200083668b04210083668b04220083668b04230083668b04240083668b04250083668b04260083668b04270083668b04280083668b04290083668b042a0083668b042b0000"_hex_u8, {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44});
TestOptimalLinearization("80ea55a1fc3c0080e47da4dc2c0180e159a1c3340280e411a4ca500380d35ba1f20c04823586f77404048a5080b00405048265994a0604823a994a07048242c90a08048500e91a0904823680830e0904850081884e0a0482358397480b048474d8080c0485208194460d048542bf6c0e04854dc40a0f048239c92010048335ad181203823585e33a1104853f80871812048474e80613048236e47a1304823582a2261404823582894414048241c86a1504854cc40a17038658d0301704854dc0641804865fc4601c00138546c3361c0109833eb00a041c8452ba141c0004875c80c2541e0002833ead6c032900"_hex_v_u8, {{386635, 31880}, {338487, 29454}, {351640, 30602}, {341304, 30204}, {311144, 27664}, {12522, 1116}, {4752, 441}, {4741, 450}, {4725, 449}, {8716, 831}, {6723, 756}, {6797, 768}, {11330, 1488}, {5700, 756}, {7562, 1418}, {5208, 984}, {3786, 722}, {4421, 845}, {2956, 565}, {4379, 838}, {2998, 574}, {4210, 845}, {4150, 834}, {4464, 991}, {1701, 442}, {1701, 485}}); TestOptimalLinearization("80ea55a1fc3c0080e47da4dc2c0180e159a1c3340280e411a4ca500380d35ba1f20c04823586f77404048a5080b00405048265994a0604823a994a07048242c90a08048500e91a0904823680830e0904850081884e0a0482358397480b048474d8080c0485208194460d048542bf6c0e04854dc40a0f048239c92010048335ad181203823585e33a1104853f80871812048474e80613048236e47a1304823582a2261404823582894414048241c86a1504854cc40a17038658d0301704854dc0641804865fc4601c00138546c3361c0109833eb00a041c8452ba141c0004875c80c2541e0002833ead6c032900"_hex_u8, {7, 10, 13, 9, 8, 18, 19, 0, 1, 24, 26, 25, 27, 28, 35, 16, 5, 29, 20, 21, 6, 2, 12, 30, 31, 32, 33, 15, 17, 22, 23, 34, 14, 11, 4, 3});
TestOptimalLinearization("83698158008570832e0183698158028361831403875387440483698158058369815806b95d82d2480785018222088369815809836981580a836981580b836981580c8669831a0d836981580e836198220f8369815810860b843211836981581111843083221111bf69a814111183698158121184308336121183698158101188018362101183698158130a836981580e108430883c0b1183698158092b8339836c092a83698158082983698158082883698158082583698158061f83698158061c83698158091883698158073b83698158073983698158052983698158042383698158042183698158044687538744052d83698158042d83698158042883698158034d83698158012a836981580329836981580252823d880c022b83698158013d83698158003e83698158003d857c8968050a1f823d8400013eb623c2281104000004010500000000000019a63281c2600b0100010203050000000f00"_hex_v_u8, {{29924, 7517}, {1617, 609}, {25754, 20468}, {754, 1062}, {546, 1107}, {1036, 2126}, {7609, 17367}, {1180, 3530}, {2634, 8297}, {172, 617}, {172, 617}}); TestOptimalLinearization("83698158008570832e0183698158028361831403875387440483698158058369815806b95d82d2480785018222088369815809836981580a836981580b836981580c8669831a0d836981580e836198220f8369815810860b843211836981581111843083221111bf69a814111183698158121184308336121183698158101188018362101183698158130a836981580e108430883c0b1183698158092b8339836c092a83698158082983698158082883698158082583698158061f83698158061c83698158091883698158073b83698158073983698158052983698158042383698158042183698158044687538744052d83698158042d83698158042883698158034d83698158012a836981580329836981580252823d880c022b83698158013d83698158003e83698158003d857c8968050a1f823d8400013eb623c2281104000004010500000000000019a63281c2600b0100010203050000000f00"_hex_u8, {23, 43, 44, 49, 0, 1, 2, 3, 37, 4, 19, 20, 21, 22, 28, 31, 34, 38, 39, 42, 45, 46, 47, 48, 41, 50, 51, 53, 18, 40, 52, 54, 15, 16, 7, 8, 9, 10, 11, 13, 14, 17, 26, 27, 29, 25, 24, 30, 5, 6, 32, 33, 35, 36, 12, 55, 56});
TestOptimalLinearization("836280c06000836180c06001836280c06002834280b1600202836180c0600302834280b1600302836180c0600402834280b1600402836280c0600502877e81fc200509833a80b1600509836280c0600609877f81fc200608834180b1600608877e81fc200607836280c0600607834180b1600707836180c0600715834280b1600614836280c0600611836180c060050f834380b160050d834180b1600420834380b1600318834280b1600315836180c0600510877f81fc200327880281f96010030d836280c060012b834280b160002c836180c060012c880281fc2006070e834280b160012e836280c060022a877f81fc200a0913833b80b160012d877e81fc2002022a877f81fc2009050e877e81fc2001022c877f81fc20040f0a877e81fc2000110b877f81fc20020f0b877e81f96006021100"_hex_v_u8, {{96480, 4675}, {48240, 2338}, {48240, 2338}, {482080, 23373}, {12400, 609}}); TestOptimalLinearization("836280c06000836180c06001836280c06002834280b1600202836180c0600302834280b1600302836180c0600402834280b1600402836280c0600502877e81fc200509833a80b1600509836280c0600609877f81fc200608834180b1600608877e81fc200607836280c0600607834180b1600707836180c0600715834280b1600614836280c0600611836180c060050f834380b160050d834180b1600420834380b1600318834280b1600315836180c0600510877f81fc200327880281f96010030d836280c060012b834280b160002c836180c060012c880281fc2006070e834280b160012e836280c060022a877f81fc200a0913833b80b160012d877e81fc2002022a877f81fc2009050e877e81fc2001022c877f81fc20040f0a877e81fc2000110b877f81fc20020f0b877e81f96006021100"_hex_u8, {0, 1, 2, 3, 4, 5, 18, 19, 20, 27, 28, 29, 10, 21, 30, 6, 8, 12, 14, 22, 32, 33, 11, 26, 15, 23, 35, 7, 16, 9, 17, 38, 13, 31, 34, 41, 24, 25, 37, 39, 36, 40, 42});
TestOptimalLinearization("836880bf4000834c80b6600000836880bf400100834c80b6600001836880bf400101834c80b6600002836880bf400102834c80b6600003836880bf400103834c80b6600004836880bf400104834c80b6600005836880bf400105834c80b6600006836880bf400106834c80b6600007836880bf400107834c80b6600008836881b768010800"_hex_v_u8, {{130900, 6160}, {11760, 588}, {11760, 588}, {11760, 588}, {11760, 588}, {11760, 588}, {11760, 588}, {11760, 588}, {11760, 588}, {11760, 588}}); TestOptimalLinearization("836880bf4000834c80b6600000836880bf400100834c80b6600001836880bf400101834c80b6600002836880bf400102834c80b6600003836880bf400103834c80b6600004836880bf400104834c80b6600005836880bf400105834c80b6600006836880bf400106834c80b6600007836880bf400107834c80b6600008836881b768010800"_hex_u8, {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 1, 3, 5, 7, 9, 11, 13, 15, 17});
TestOptimalLinearization("8369817400885084460183698174028369817403842482760485028244058501824406836981740783698174088550827609866883460a836981740b836981740c850282440d836981740e836981740f8550827610836983261183698326128550846613836983261483698326158501841c168501841c1783698326188550846619836981741a836983261b836983261c836983261d842486681e836983261f83698326208501841c2185508276228550827647850182442483698174258550827626836981742783698174288369817429836981742a866783462b836981742c836981742d836981742e836981742e2f956f9220152f873786240e2f8667855c142a8b0589240f23823d897c0453bc50d70c06000000000000000000000024bf66db78061e00000000000000000000000000000035c30085961a0200020b000000000000000000000000000000003500"_hex_v_u8, {{59283, 28013}, {7894, 15440}, {9513, 20143}, {466, 1079}, {430, 999}}); TestOptimalLinearization("8369817400885084460183698174028369817403842482760485028244058501824406836981740783698174088550827609866883460a836981740b836981740c850282440d836981740e836981740f8550827610836983261183698326128550846613836983261483698326158501841c168501841c1783698326188550846619836981741a836983261b836983261c836983261d842486681e836983261f83698326208501841c2185508276228550827647850182442483698174258550827626836981742783698174288369817429836981742a866783462b836981742c836981742d836981742e836981742e2f956f9220152f873786240e2f8667855c142a8b0589240f23823d897c0453bc50d70c06000000000000000000000024bf66db78061e00000000000000000000000000000035c30085961a0200020b000000000000000000000000000000003500"_hex_u8, {35, 21, 22, 24, 25, 28, 32, 33, 34, 36, 37, 23, 29, 26, 27, 38, 0, 1, 17, 30, 31, 39, 43, 56, 19, 45, 47, 48, 49, 50, 52, 53, 54, 46, 44, 51, 55, 6, 4, 5, 9, 10, 13, 14, 16, 18, 11, 20, 8, 7, 15, 12, 3, 2, 40, 41});
TestOptimalLinearization("cc1b8ae36800d6628bd74401912d81d342028368d406038e54819144048f7481a73405af7687b42806d35e8aa12c078416ab0c088f4781d31609a42e85905a0909b53087da7c07098459e30a0809cc4789cd7e0709912881db4405098422de500509a84b8693220e000d901e828d56050f823cce0e030f9017828c2201158608809b340807000d901e81d8420116925282b97c080600020a901c81d8420117901f81d8420012ca088ab75202010102020200"_hex_v_u8, {{68948, 6262}, {127805, 11981}, {21771, 2119}, {44226, 4410}, {22113, 2207}, {146849, 14665}, {162611, 16557}, {31803, 3253}, {151865, 16609}, {6120, 674}, {216238, 23904}, {6405, 729}}); TestOptimalLinearization("cc1b8ae36800d6628bd74401912d81d342028368d406038e54819144048f7481a73405af7687b42806d35e8aa12c078416ab0c088f4781d31609a42e85905a0909b53087da7c07098459e30a0809cc4789cd7e0709912881db4405098422de500509a84b8693220e000d901e828d56050f823cce0e030f9017828c2201158608809b340807000d901e81d8420116925282b97c080600020a901c81d8420117901f81d8420012ca088ab75202010102020200"_hex_u8, {12, 5, 6, 14, 15, 22, 16, 17, 25, 0, 1, 2, 3, 4, 8, 9, 10, 11, 13, 23, 18, 19, 20, 21, 24, 7});
TestOptimalLinearization("8530af0600853daf60018930cd0602893abe00038638b70204862db62805853da600068a39e134078531af060707853caf600707853ca60007078531af0607078530af0606078530a53808068332b77408078540e6600c04883cc62009078500dc3e0c058500dc3e0a078312bf5e0b07853caf600b198531af060b168a4cd6180a1682359d5e09148241a0200b11853caf6008138239be4c09138541bf6c0b0e853daf60072b8745bf1c06258530af06081d8751d50209148f4bfb581200188531af0604278530b53a03228500dc3e05208638ab68032d8332b774042c8531af0604298a4880a930032b853db940051f8c33e3640b10248931cd0605348235a44806348530b53a052a8570f4340423853ca600044387548091640430853db9400328937081fa741410002e8835c564033c8a4c80a9300b12168236b366012a8c3be4200a0e23894480997c021c138e4bf4180102308f1c80cc6e06020832853ca60001338654f55602298534a55001338824ce14003f853ca600003f00"_hex_v_u8, {{16424, 2763}, {9568, 1720}, {54506, 9812}, {11635, 2160}, {45440, 8447}, {20893, 4158}, {4150, 833}, {5505, 1105}, {7182, 1503}, {68976, 14854}, {1967, 437}, {11126, 2482}, {24695, 5526}, {13379, 3279}, {10034, 2836}, {2496, 828}}); TestOptimalLinearization("8530af0600853daf60018930cd0602893abe00038638b70204862db62805853da600068a39e134078531af060707853caf600707853ca60007078531af0607078530af0606078530a53808068332b77408078540e6600c04883cc62009078500dc3e0c058500dc3e0a078312bf5e0b07853caf600b198531af060b168a4cd6180a1682359d5e09148241a0200b11853caf6008138239be4c09138541bf6c0b0e853daf60072b8745bf1c06258530af06081d8751d50209148f4bfb581200188531af0604278530b53a03228500dc3e05208638ab68032d8332b774042c8531af0604298a4880a930032b853db940051f8c33e3640b10248931cd0605348235a44806348530b53a052a8570f4340423853ca600044387548091640430853db9400328937081fa741410002e8835c564033c8a4c80a9300b12168236b366012a8c3be4200a0e23894480997c021c138e4bf4180102308f1c80cc6e06020832853ca60001338654f55602298534a55001338824ce14003f853ca600003f00"_hex_u8, {51, 53, 52, 16, 49, 10, 11, 12, 13, 48, 36, 50, 54, 6, 29, 0, 1, 2, 3, 4, 5, 7, 8, 9, 31, 44, 57, 60, 59, 56, 17, 28, 18, 32, 14, 19, 21, 27, 15, 30, 61, 22, 25, 24, 23, 41, 20, 37, 38, 47, 39, 40, 42, 55, 26, 33, 45, 58, 43, 46, 34, 35});
TestOptimalLinearization("80884d94bf40008349db4000018349db4001008349db4002008349db4003008349db4004008349db4005008349db4006008349db4007008349db4008008349db4009008349db400a008349db400b008349db400c008349db400d008349db400e008349db400f008349db4010008349db4011008349db4012008349db4013008349db4014008349db4015008349db4016008349db4017008349db4018008349db4019008349db401a008349db401b008349db401c008349db401d008349db401e008349db401f008349db4020008349db4021008349db4022008349db4023008349db4024008349db4025008349db4026008349db4027008349db4028008349db4029008349db402a008349db402b008349db402c008349db402d008349db402e008349db402f0000"_hex_v_u8, {{460320, 45693}}); TestOptimalLinearization("80884d94bf40008349db4000018349db4001008349db4002008349db4003008349db4004008349db4005008349db4006008349db4007008349db4008008349db4009008349db400a008349db400b008349db400c008349db400d008349db400e008349db400f008349db4010008349db4011008349db4012008349db4013008349db4014008349db4015008349db4016008349db4017008349db4018008349db4019008349db401a008349db401b008349db401c008349db401d008349db401e008349db401f008349db4020008349db4021008349db4022008349db4023008349db4024008349db4025008349db4026008349db4027008349db4028008349db4029008349db402a008349db402b008349db402c008349db402d008349db402e008349db402f0000"_hex_u8, {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48});
TestOptimalLinearization("80cc00829900008449c452018336c318028335b4200380c95c86c57004ce3488a30c0580b63281ed680683358c1a078477da46088336b37c0988728092340a8540955c0b9f0a82831c0c8474c2760c0c82359094240d0c8335b2160e0c8239af7e0f0c823aad50100c9738c840110c8478c3520e0c823581db200f0c82358ae40e100c847cbb000f0c8478cf74100c8331a006110c8311af5c120c82358dd418130c8239ab58140c8331b97c1708854d926018088478c32419088600cf401e048621b8701f048235b13a1c088336bc4a160c8242b01c1e048335b216142d8331b97c08268474d14c131b967e81f164040a0a000009bd6580a1061f00000000000000000f00"_hex_v_u8, {{5859, 759}, {4364, 566}, {76038, 10164}, {9434, 1266}, {187130, 27709}, {3774, 561}, {3774, 561}, {172985, 27560}, {4457, 713}, {209015, 34252}, {3408, 565}, {3118, 529}, {3275, 565}, {3275, 565}, {4393, 760}, {4347, 756}, {4370, 760}, {5152, 896}, {3840, 764}, {3704, 929}, {2115, 561}, {9990, 3884}, {1264, 845}, {845, 565}, {10371, 8037}}); TestOptimalLinearization("80cc00829900008449c452018336c318028335b4200380c95c86c57004ce3488a30c0580b63281ed680683358c1a078477da46088336b37c0988728092340a8540955c0b9f0a82831c0c8474c2760c0c82359094240d0c8335b2160e0c8239af7e0f0c823aad50100c9738c840110c8478c3520e0c823581db200f0c82358ae40e100c847cbb000f0c8478cf74100c8331a006110c8311af5c120c82358dd418130c8239ab58140c8331b97c1708854d926018088478c32419088600cf401e048621b8701f048235b13a1c088336bc4a160c8242b01c1e048335b216142d8331b97c08268474d14c131b967e81f164040a0a000009bd6580a1061f00000000000000000f00"_hex_u8, {24, 9, 15, 35, 11, 14, 13, 33, 40, 26, 27, 0, 2, 4, 6, 8, 38, 34, 36, 37, 16, 21, 18, 39, 22, 10, 20, 3, 5, 12, 1, 30, 31, 17, 32, 19, 7, 29, 28, 23, 25});
TestOptimalLinearization("cf0884cf6c008324a54400008324a54401008324a54402008324a54403008324a54404008324a54405008324a54406008324a54407008324a54408008324a54409008324a5440a008324a5440b008324a5440c008324a5440d008324a5440e0000"_hex_v_u8, {{46134, 10248}, {2466, 548}, {2466, 548}, {2466, 548}, {2466, 548}, {2466, 548}, {2466, 548}, {2466, 548}, {2466, 548}, {2466, 548}, {2466, 548}, {2466, 548}, {2466, 548}, {2466, 548}, {2466, 548}, {2466, 548}}); TestOptimalLinearization("cf0884cf6c008324a54400008324a54401008324a54402008324a54403008324a54404008324a54405008324a54406008324a54407008324a54408008324a54409008324a5440a008324a5440b008324a5440c008324a5440d008324a5440e0000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
TestOptimalLinearization("8474ad70008474ad70018470ad70028470ad70038470ad70048470ad70058470ad70068474ad70078474ad70088470ad70098474ad700a8474ad700b8474ad700c8470ad700d8474ad700e8474ad700fb83285d734000000000000000000000000000000000f00"_hex_v_u8, {{102810, 19414}}); TestOptimalLinearization("8474ad70008474ad70018470ad70028470ad70038470ad70048470ad70058470ad70068474ad70078474ad70088470ad70098474ad700a8474ad700b8474ad700c8470ad700d8474ad700e8474ad700fb83285d734000000000000000000000000000000000f00"_hex_u8, {3, 4, 5, 6, 7, 10, 14, 0, 2, 8, 9, 11, 12, 13, 15, 16, 1});
TestOptimalLinearization("a408f07c00832c8c320000832c8c320100832c8c320200832c8c320300832c8c320400832c8c320500832c8c320600832c8c320700832c8c320800832c8c32090083308c3e0a0083308c3e0b0083308c3e0c0083308c3e0d00832f8c3a0e00832f8c3a0f00832f8c3a1000832f8c3a1100832f8c3a1200832d8c341300832d8c341400832d8c341500832d8c34160000"_hex_v_u8, {{27053, 17567}}); TestOptimalLinearization("a408f07c00832c8c320000832c8c320100832c8c320200832c8c320300832c8c320400832c8c320500832c8c320600832c8c320700832c8c320800832c8c32090083308c3e0a0083308c3e0b0083308c3e0c0083308c3e0d00832f8c3a0e00832f8c3a0f00832f8c3a1000832f8c3a1100832f8c3a1200832d8c341300832d8c341400832d8c341500832d8c34160000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 20, 21, 22, 23, 15, 16, 17, 18, 19});
TestOptimalLinearization("8362861c00da64e1740000832a83460000832a83460100832e834a02008331834e0300832a83460400832a83460500832a83460600832a83460700832a83460800832a83460900832a83460a00832a83460b00832a83460c00832a83460d0000"_hex_v_u8, {{462, 610}, {6330, 11748}, {295, 561}, {291, 554}, {291, 554}, {291, 554}, {291, 554}, {291, 554}, {291, 554}, {291, 554}, {291, 554}, {291, 554}, {291, 554}, {291, 554}, {291, 554}, {293, 558}}); TestOptimalLinearization("8362861c00da64e1740000832a83460000832a83460100832e834a02008331834e0300832a83460400832a83460500832a83460600832a83460700832a83460800832a83460900832a83460a00832a83460b00832a83460c00832a83460d0000"_hex_u8, {0, 1, 5, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 4});
TestOptimalLinearization("80df4cacb754009e3d87e13a0180f36aac8350028541808e5803833180867004833180ce0a05971285db6206ab6d8bbe0407854180f21608841280c278099a2e86ce3c0a83328086700ba81f8abc700c857c80ef360d860080fb000e8331809e140f857881922210ad498bfa16118331808e1a1281c806d98a341380d468ad813a148235a4fa741415824180a40015148239d05c1614823ad22017148236d1101714847480bc561714823980804018148235ace32819148331e7681a138236e35c1d11833580d5681e11854480c66a19148236f9301614833280a23e1c0d8331808612181285788187681514857c81a01a1414846681882e1414823a809620151482359ec46414148335f12e151482359392721514854480a5161614847c80f9502b008241e252191382358082122b02833df27e1130857c818b260b338578818b260b31854d80aa041d1105857c819222013d857881aa5403358a7581d40e3100000029857c81aa540133c92091aa5e2a0000000000000000011e823580a6480035a10988bb460103010b0e000000000d00"_hex_v_u8, {{13253, 561}, {707608, 30199}, {996428, 42555}, {743996, 31775}, {16040, 764}, {36126, 1780}, {88603, 4456}, {34788, 1780}, {542102, 27805}, {8393, 437}, {12540, 658}, {8288, 441}, {15563, 833}, {10463, 562}, {132850, 7145}, {10186, 561}, {70262, 3940}, {71837, 4029}, {55089, 3090}, {102338, 5741}, {94072, 5279}, {15387, 892}, {265139, 15986}, {12139, 756}, {8649, 561}, {12789, 836}, {6446, 438}, {6377, 449}, {31027, 2358}, {7319, 565}, {10946, 845}, {10635, 836}, {14131, 1134}, {5328, 442}, {5256, 438}, {5230, 441}}); TestOptimalLinearization("80df4cacb754009e3d87e13a0180f36aac8350028541808e5803833180867004833180ce0a05971285db6206ab6d8bbe0407854180f21608841280c278099a2e86ce3c0a83328086700ba81f8abc700c857c80ef360d860080fb000e8331809e140f857881922210ad498bfa16118331808e1a1281c806d98a341380d468ad813a148235a4fa741415824180a40015148239d05c1614823ad22017148236d1101714847480bc561714823980804018148235ace32819148331e7681a138236e35c1d11833580d5681e11854480c66a19148236f9301614833280a23e1c0d8331808612181285788187681514857c81a01a1414846681882e1414823a809620151482359ec46414148335f12e151482359392721514854480a5161614847c80f9502b008241e252191382358082122b02833df27e1130857c818b260b338578818b260b31854d80aa041d1105857c819222013d857881aa5403358a7581d40e3100000029857c81aa540133c92091aa5e2a0000000000000000011e823580a6480035a10988bb460103010b0e000000000d00"_hex_u8, {17, 1, 0, 15, 2, 44, 45, 7, 10, 54, 36, 37, 32, 33, 34, 48, 55, 38, 39, 50, 51, 57, 22, 9, 21, 28, 40, 41, 42, 35, 23, 24, 5, 18, 20, 26, 31, 43, 16, 25, 27, 49, 47, 8, 30, 19, 14, 56, 11, 12, 46, 53, 52, 13, 29, 4, 6, 3});
TestOptimalLinearization("846ea73e00846ebc68018540ab6602846ebc68038540ab6604846ebc6805846ea73e06846ebc68078540c33208846ebc6809846ea73e0a8540ab660b8540ab660c8517a9520a0c8517a9520a098517a952030c8540ab660e000e8540ab660e000d8540ab660d000d8540ab660e030a8540c3320d000d8540ab660e000d8540c3320d000c8540ab660e000c8540ab660b02098540ab660e00098540ab660a020d8540ab6601178540c3320e010a8540ab66021b8517c00c01198540ab6609071b8540ab660907178540ab660d02198540ab6609090d8540ab660e021b8540ab660c041b8540ab660a00178540ab660a04138540c3320702168540ab660605178540ab6604031b8540ab660411108540ab6601228540ab6605031a8540ab66020b168540ab66050e108653b72a0a00032800"_hex_v_u8, {{3956, 750}, {3956, 750}, {3956, 750}, {3956, 750}, {3956, 750}, {4377, 832}, {4377, 832}, {6968, 1582}, {17006, 4078}, {10111, 2496}, {20807, 5971}, {2591, 750}, {2591, 750}, {2729, 791}, {2729, 791}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}}); TestOptimalLinearization("846ea73e00846ebc68018540ab6602846ebc68038540ab6604846ebc6805846ea73e06846ebc68078540c33208846ebc6809846ea73e0a8540ab660b8540ab660c8517a9520a0c8517a9520a098517a952030c8540ab660e000e8540ab660e000d8540ab660d000d8540ab660e030a8540c3320d000d8540ab660e000d8540c3320d000c8540ab660e000c8540ab660b02098540ab660e00098540ab660a020d8540ab6601178540c3320e010a8540ab66021b8517c00c01198540ab6609071b8540ab660907178540ab660d02198540ab6609090d8540ab660e021b8540ab660c041b8540ab660a00178540ab660a04138540c3320702168540ab660605178540ab6604031b8540ab660411108540ab6601228540ab6605031a8540ab66020b168540ab66050e108653b72a0a00032800"_hex_u8, {1, 6, 10, 16, 25, 17, 18, 11, 12, 3, 4, 27, 45, 46, 13, 14, 47, 5, 7, 8, 19, 21, 23, 24, 0, 26, 15, 28, 2, 9, 20, 22, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44});
TestOptimalLinearization("836880d74800836880d74801836880d74802836880d74803834c80cf100303836880d7480403834c80cf100403836880d7480503834c80cf100503836880d7480603836880d7480603834c80cf100703834c80cf10060d836880d748070d834c80cf10060c836880d748070c834c80cf10060b836880d748070b834c80cf10070a834c80cf100519836880d7480619836880d7480516834c80cf100616836880d7480513834c80cf100613834c80cf100423836880d7480523834c80cf10051e836880d748061e834c80cf100519836880d7480619834c80cf10042c836880d748052c834c80cf100426836880d7480526834c80cf10041f834c80cf100334834c80cf10022b887685bb3e0301010b0300"_hex_v_u8, {{316363, 12974}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}}); TestOptimalLinearization("836880d74800836880d74801836880d74802836880d74803834c80cf100303836880d7480403834c80cf100403836880d7480503834c80cf100503836880d7480603836880d7480603834c80cf100703834c80cf10060d836880d748070d834c80cf10060c836880d748070c834c80cf10060b836880d748070b834c80cf10070a834c80cf100519836880d7480619836880d7480516834c80cf100616836880d7480513834c80cf100613834c80cf100423836880d7480523834c80cf10051e836880d748061e834c80cf100519836880d7480619834c80cf10042c836880d748052c834c80cf100426836880d7480526834c80cf10041f834c80cf100334834c80cf10022b887685bb3e0301010b0300"_hex_u8, {0, 2, 4, 6, 8, 10, 12, 14, 16, 17, 19, 21, 24, 26, 28, 29, 31, 34, 35, 38, 1, 3, 5, 7, 9, 11, 13, 15, 18, 20, 22, 23, 25, 27, 30, 32, 33, 36, 37});
TestOptimalLinearization("808934829e280083348c28000183348c28010083348c28020083348c28030083348c28040083348c28050083348c28060083348c28070083348c28080083348c28090083348c280a0083348c280b0083348c280c0083348c280d0083348c280e0083348c280f0083348c28100083348c28110083348c28120083348c28130083348c28140083348c28150083348c28160083348c28170083348c28180083348c28190083348c281a0083348c281b0083348c281c0083348c281d0083348c281e0083348c281f0083348c28200083348c28210083348c28220083348c28230083348c28240083348c28250083348c28260083348c28270083348c28280083348c28290083348c282a0000"_hex_v_u8, {{63216, 41968}}); TestOptimalLinearization("808934829e280083348c28000183348c28010083348c28020083348c28030083348c28040083348c28050083348c28060083348c28070083348c28080083348c28090083348c280a0083348c280b0083348c280c0083348c280d0083348c280e0083348c280f0083348c28100083348c28110083348c28120083348c28130083348c28140083348c28150083348c28160083348c28170083348c28180083348c28190083348c281a0083348c281b0083348c281c0083348c281d0083348c281e0083348c281f0083348c28200083348c28210083348c28220083348c28230083348c28240083348c28250083348c28260083348c28270083348c28280083348c28290083348c282a0000"_hex_u8, {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43});
TestOptimalLinearization("80af1a838c0a0080b37b82af76018335854e028335a64e03867cb2760483358a0c0580cd6485e13206854c8f3a0606823586e37207068241894608068750901a0906857cf2400a06823aab020b06824194060c068541bc500d068608f3440e068241a2000e06854ebd420f06823588b41610068500e13e11068241a2501206894480c21413068500905a1406854d8f3a150683368766160683358a0c1306823a983a1306823586bd7e140685458f261506833da17616068242a0341321854dc0641d000a83318a02061d854dc064120d8751901a0124b524808a58091200000000000200"_hex_v_u8, {{128151, 26614}, {4001, 846}, {127437, 27752}, {2535, 565}, {116824, 26905}, {2235, 573}, {1629, 442}, {3323, 1020}, {1347, 449}, {3239, 1554}, {675, 449}, {1133, 768}, {2125, 1691}, {1053, 844}, {9363, 7513}, {1053, 845}, {1043, 837}, {1101, 1105}, {563, 566}}); TestOptimalLinearization("80af1a838c0a0080b37b82af76018335854e028335a64e03867cb2760483358a0c0580cd6485e13206854c8f3a0606823586e37207068241894608068750901a0906857cf2400a06823aab020b06824194060c068541bc500d068608f3440e068241a2000e06854ebd420f06823588b41610068500e13e11068241a2501206894480c21413068500905a1406854d8f3a150683368766160683358a0c1306823a983a1306823586bd7e140685458f261506833da17616068242a0341321854dc0641d000a83318a02061d854dc064120d8751901a0124b524808a58091200000000000200"_hex_u8, {11, 14, 17, 15, 16, 12, 13, 0, 2, 5, 10, 7, 21, 9, 35, 23, 29, 31, 34, 30, 24, 8, 4, 6, 3, 18, 25, 26, 27, 1, 22, 33, 19, 32, 28, 20});
TestOptimalLinearization("818241dbac3c0081c70c809fe6240180d740e79b0c0280eb5af7b4420380bf15cec96a0480fa208081cf4c0580ee2bf89d3a06950d8a8d7e0780c557e3bb7c0881866980839b52098235829f6a090982359fbf3209098335818f5a0a098331818d620b09823596fa1e0b09847882bc280c09823580e97e0d09845081de320e09823592c7020e09847482d4420f0985428291041306824281ec6c1208847882955c12098235a1b3181209863083f66a1309823580fa20130982358fec3c1409823593a460140984788298581608823680dc761609824180d87c1807863d83f32e160982358fc3761709823596ca261709857c82de401809823a80805019098239cb261b088948ce1c1b09a04c90d5682400228449829160220015866083b07022010c845181fa581f000b875183ee50210304857c82f460082186618381462800001e896d849d302500001200"_hex_v_u8, {{1073483, 28599}, {974262, 25978}, {28500, 760}, {1176771, 31491}, {1583595, 42433}, {1276412, 34206}, {1159437, 31072}, {998800, 26825}, {1208196, 32597}, {16080, 437}, {35960, 992}, {25776, 713}, {39912, 1105}, {62800, 1784}, {26220, 760}, {15039, 437}, {26030, 760}, {24300, 721}, {32931, 993}, {14203, 438}, {91071, 2829}, {22489, 720}, {13950, 449}, {17453, 565}, {17329, 561}, {42904, 1389}, {953801, 38788}, {8296, 442}, {4883, 441}, {5070, 1352}}); TestOptimalLinearization("818241dbac3c0081c70c809fe6240180d740e79b0c0280eb5af7b4420380bf15cec96a0480fa208081cf4c0580ee2bf89d3a06950d8a8d7e0780c557e3bb7c0881866980839b52098235829f6a090982359fbf3209098335818f5a0a098331818d620b09823596fa1e0b09847882bc280c09823580e97e0d09845081de320e09823592c7020e09847482d4420f0985428291041306824281ec6c1208847882955c12098235a1b3181209863083f66a1309823580fa20130982358fec3c1409823593a460140984788298581608823680dc761609824180d87c1807863d83f32e160982358fc3761709823596ca261709857c82de401809823a80805019098239cb261b088948ce1c1b09a04c90d5682400228449829160220015866083b07022010c845181fa581f000b875183ee50210304857c82f460082186618381462800001e896d849d302500001200"_hex_u8, {7, 8, 17, 19, 20, 21, 9, 12, 13, 14, 2, 3, 37, 38, 26, 27, 34, 36, 35, 23, 25, 24, 33, 22, 44, 39, 45, 28, 10, 18, 40, 15, 29, 30, 11, 31, 5, 6, 32, 0, 1, 4, 16, 41, 42, 43});
TestOptimalLinearization("a91cb4e81c00fc20809ebc6801a454aef86e02ad6cbad74c03e044fba04e04c020d2950605a004a9893e06a004a9893e07a454aef86e089b38a39a1009a928b4e81c0a8d4c91cc040b8d4c91cc040c81940681dfa368000000000000000000000000000000"_hex_v_u8, {{440910, 5404}, {681347, 8352}, {152386, 1868}, {152386, 1868}, {488998, 5996}, {1017959, 12484}, {344735, 4228}, {344735, 4228}, {392823, 4820}, {392823, 4820}, {296648, 3640}, {1306484, 16032}, {440910, 5416}, {2885940, 35462}}); TestOptimalLinearization("a91cb4e81c00fc20809ebc6801a454aef86e02ad6cbad74c03e044fba04e04c020d2950605a004a9893e06a004a9893e07a454aef86e089b38a39a1009a928b4e81c0a8d4c91cc040b8d4c91cc040c81940681dfa368000000000000000000000000000000"_hex_u8, {0, 5, 11, 12, 3, 4, 6, 7, 2, 8, 9, 1, 10, 13});
TestOptimalLinearization("836181ba1c0088318bdc580000a34a97cd280000a34a97cd280100a34a97cd280200a34a97cd280300832a82965e0303832a82965e0403832a82965e0503832a82965e0603832a82965e0703832a82965e0803832a82965e0903832a82965e0a03832a82965e0b03832a82965e0c03832a82965e0d03832a82965e0e03832a82965e0f03832a82965e1003832a82965e1103832a82965e1203832a82965e1303832a82965e1403832a82965e1503832a82965e1603832a82965e1703832a82965e1803832a82965e1903832a82965e1a03832a82965e1902832a82965e1b01832a82965e1c01832a82965e1d01832a82965e1d02832a82965e1f01832a82965e1f02832a82965e2002832a82965e2201832a82965e2301832a82965e2302832a82965e2402832a82965e2502832a82965e2701832a82965e2801832a82965e2901832a82965e2a01832a82965e2a02832a82965e2b02832a82965e2d01832a82965e2d02832a82965e2f01832a82965e300100"_hex_v_u8, {{124474, 1810}, {827900, 17978}, {540855, 11884}, {462570, 10222}, {201620, 4682}}); TestOptimalLinearization("836181ba1c0088318bdc580000a34a97cd280000a34a97cd280100a34a97cd280200a34a97cd280300832a82965e0303832a82965e0403832a82965e0503832a82965e0603832a82965e0703832a82965e0803832a82965e0903832a82965e0a03832a82965e0b03832a82965e0c03832a82965e0d03832a82965e0e03832a82965e0f03832a82965e1003832a82965e1103832a82965e1203832a82965e1303832a82965e1403832a82965e1503832a82965e1603832a82965e1703832a82965e1803832a82965e1903832a82965e1a03832a82965e1902832a82965e1b01832a82965e1c01832a82965e1d01832a82965e1d02832a82965e1f01832a82965e1f02832a82965e2002832a82965e2201832a82965e2301832a82965e2302832a82965e2402832a82965e2502832a82965e2701832a82965e2801832a82965e2901832a82965e2a01832a82965e2a02832a82965e2b02832a82965e2d01832a82965e2d02832a82965e2f01832a82965e300100"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 31, 32, 33, 35, 38, 39, 43, 44, 45, 46, 49, 51, 52, 28, 30, 34, 36, 37, 40, 41, 42, 47, 48, 50, 29});
TestOptimalLinearization("921a84f92a008312809d6801841280c870028b7082891803945985e91004997e87ad7c0580b815ada40006941185c61807974d86cf62089f0a88f80209926d85932e0a963686a0560b945a85dc400c8d2183b53c0d9c5288972a0e9b4e87ee380f943585d12c108e1183d818119625869b5a128f3184896213911a84d154149305859a6415914284de0816980986e22e17920d84f54e18841280c2061818875c82817a1918854d818c5c1518823583bf4c1518861c818d101717857080d7481718866081cc2017188235fe2c1618866281d13e1518847880e9441518857880eb781318894c82b7781218850df5601018847c80ed601018854d80e51e0f18847480ed601018854280a71e1018850081a50002298d7f84983828000025dd44a5ec3425000025823980ac38014e866081f670022726ac7cc3fd5016000000000000000000000000000000000001042900"_hex_v_u8, {{1679688, 62029}, {24765, 1116}, {21663, 994}, {76772, 3548}, {21328, 992}, {28220, 1356}, {33551, 1613}, {17262, 845}, {790344, 39015}, {15280, 756}, {15280, 764}, {15010, 760}, {12483, 658}, {17288, 924}, {49284, 2640}, {8150, 437}, {15164, 888}, {13860, 880}, {10767, 834}, {7600, 781}}); TestOptimalLinearization("921a84f92a008312809d6801841280c870028b7082891803945985e91004997e87ad7c0580b815ada40006941185c61807974d86cf62089f0a88f80209926d85932e0a963686a0560b945a85dc400c8d2183b53c0d9c5288972a0e9b4e87ee380f943585d12c108e1183d818119625869b5a128f3184896213911a84d154149305859a6415914284de0816980986e22e17920d84f54e18841280c2061818875c82817a1918854d818c5c1518823583bf4c1518861c818d101717857080d7481718866081cc2017188235fe2c1618866281d13e1518847880e9441518857880eb781318894c82b7781218850df5601018847c80ed601018854d80e51e0f18847480ed601018854280a71e1018850081a50002298d7f84983828000025dd44a5ec3425000025823980ac38014e866081f670022726ac7cc3fd5016000000000000000000000000000000000001042900"_hex_u8, {28, 33, 36, 46, 23, 39, 18, 32, 35, 20, 42, 41, 37, 0, 26, 24, 11, 30, 29, 21, 6, 2, 25, 4, 3, 7, 8, 19, 34, 43, 44, 12, 10, 13, 15, 14, 45, 40, 27, 1, 16, 5, 9, 22, 31, 17, 47, 38});
TestOptimalLinearization("836880832c00850d80a738000000"_hex_v_u8, {{19250, 1397}}); TestOptimalLinearization("836880832c00850d80a738000000"_hex_u8, {0, 1});
TestOptimalLinearization("836883680084428f4c01836883680284428f4c03836883680483688368058368836806836883680783688368088368836809836883680a836883680b80a70f80a7100b0b809b7c809b7c0a0a809947809948090b809b3e809b40090b80a12b80a12c090b809a2d809a30090b809c0b809c0c090b809554809554090b809913809914090b809b53809b54090b854e80aa4c091f854e80a13a091c872d9804140111854e80a76a0a1b854e80a44e0a1a854e80a9000a19854e80a1440a18854e80a44a0a17854e809d0a0a16854e80a3140a15854e80a13c0a1484418f4c082e867a80c3560628854e8188060c131f854e81887c0c121d84428f4c033184428f4c0034854e80ea2a0d002c84418f4c012a867a80bc3407062b84418f4c012b84418f4c002984428f4c002684428f4c0023854e80a45003072284428f4c0123886080be340a020427854e80a300050620854ed83c05051d886080be7402090524854ed84600092900"_hex_v_u8, {{38835, 23106}, {40075, 24533}, {37668, 23160}, {110289, 72339}, {1062, 705}, {1062, 705}, {1062, 706}, {1062, 706}, {1062, 706}, {33045, 22510}, {30667, 21592}, {31176, 22039}, {26458, 22359}}); TestOptimalLinearization("836883680084428f4c01836883680284428f4c03836883680483688368058368836806836883680783688368088368836809836883680a836883680b80a70f80a7100b0b809b7c809b7c0a0a809947809948090b809b3e809b40090b80a12b80a12c090b809a2d809a30090b809c0b809c0c090b809554809554090b809913809914090b809b53809b54090b854e80aa4c091f854e80a13a091c872d9804140111854e80a76a0a1b854e80a44e0a1a854e80a9000a19854e80a1440a18854e80a44a0a17854e809d0a0a16854e80a3140a15854e80a13c0a1484418f4c082e867a80c3560628854e8188060c131f854e81887c0c121d84428f4c033184428f4c0034854e80ea2a0d002c84418f4c012a867a80bc3407062b84418f4c012b84418f4c002984428f4c002684428f4c0023854e80a45003072284428f4c0123886080be340a020427854e80a300050620854ed83c05051d886080be7402090524854ed84600092900"_hex_u8, {6, 5, 7, 8, 9, 3, 0, 1, 2, 4, 10, 12, 13, 14, 15, 11, 20, 21, 34, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 41, 46, 51, 52, 16, 17, 18, 19, 37, 38, 39, 40, 42, 43, 44, 45, 47, 48, 49, 50});
TestOptimalLinearization("8a4481f65e008f7783dc7c00008f7783c70801008f6f83c70801008f7083c7080100008f7783bf620100008f7783bf620100008f7783bf620100008f7783c70801019b1686e862000200"_hex_v_u8, {{313375, 18069}, {36913, 2167}, {36913, 2167}}); TestOptimalLinearization("8a4481f65e008f7783dc7c00008f7783c70801008f6f83c70801008f7083c7080100008f7783bf620100008f7783bf620100008f7783bf620100008f7783c70801019b1686e862000200"_hex_u8, {0, 1, 3, 2, 4, 6, 8, 9, 5, 7});
TestOptimalLinearization("dd5096a94c00db479a8f2201de64999944028236809310020285008082080302847c8083020402857c80830205028a5480d9140602847080f950070285008083020802857cfc38090283318c9b520a02823686d3220a02824187b83c0b02823680ad120c028236e65c0d028478fd180e028239c5640f028a5480d91410028a4880d60811028544e5301202854588ba341302847c8082641402823a87f5101402823687ab7e1502823680a1121602823580ad121702823680a7121802833e80c05e1902823ae9161a028241e1381b02850080966c1c0284788083361d028500fe641e02857c8083021f028a4480d9142002847cee0021028578ff7622028a4480d32423028500eb0024028a4c80cf582502833dc52826028a4c80d914280016824185df5e1128823a80ad1211288a4480cf582a000100"_hex_v_u8, {{431706, 13571}, {421921, 14027}, {11145, 437}, {11145, 438}, {11145, 442}, {10761, 438}, {299471, 12673}, {9480, 438}, {12399, 574}, {16040, 752}, {6795, 442}, {6638, 438}, {6300, 449}, {9718, 768}, {8475, 760}, {8449, 764}, {8434, 764}, {8449, 768}, {8388, 768}, {8178, 768}, {8076, 760}, {4530, 441}, {8449, 892}, {8449, 892}, {13962, 1476}, {13962, 1484}, {13962, 1492}, {13962, 1492}, {13764, 1480}, {7104, 764}, {8251, 888}, {13586, 1476}, {13356, 1476}, {6912, 768}, {8028, 892}, {13356, 1484}, {4500, 573}, {6552, 836}}); TestOptimalLinearization("dd5096a94c00db479a8f2201de64999944028236809310020285008082080302847c8083020402857c80830205028a5480d9140602847080f950070285008083020802857cfc38090283318c9b520a02823686d3220a02824187b83c0b02823680ad120c028236e65c0d028478fd180e028239c5640f028a5480d91410028a4880d60811028544e5301202854588ba341302847c8082641402823a87f5101402823687ab7e1502823680a1121602823580ad121702823680a7121802833e80c05e1902823ae9161a028241e1381b02850080966c1c0284788083361d028500fe641e02857c8083021f028a4480d9142002847cee0021028578ff7622028a4480d32423028500eb0024028a4c80cf582502833dc52826028a4c80d914280016824185df5e1128823a80ad1211288a4480cf582a000100"_hex_u8, {10, 12, 11, 21, 23, 24, 25, 26, 27, 28, 13, 29, 30, 0, 9, 1, 31, 6, 32, 14, 33, 34, 35, 3, 22, 7, 2, 36, 15, 16, 4, 37, 38, 20, 5, 17, 18, 39, 40, 41, 45, 42, 8, 43, 44, 19});
TestOptimalLinearization("e05381ab28008756a16001904deb4a02a2608a900003971e81fb4604f32981e44005f179829b2606a51f80ea6a07e15182bc4208e55583b34e099029ed540a8d7adb1c0b882cc9200c8d29d72e0d9235f6600ef77284982a0f823581ea3c0f0f8235975c100b8600e1000c0f823582ab740d0f8265900c0e0f823581ed660e0f964181f340110d9838829b241609823a80cc6a100f857ceb40100f823580da10110f8474829172120f8235b94c130f8235fb58130f82419504160c82358c76140e82428c76150e85429632190b823980a002130f854480b348140f823580a61a140f80c7638487361e000418809e1a83c44421000000002080cf6484a24207130000000e9121d5361800000003020500"_hex_v_u8, {{91200, 4576}, {48195, 6111}, {29525, 3762}, {28266, 5337}, {79016, 15147}, {68868, 16192}, {4752, 1196}, {1582, 437}, {56602, 16222}, {53282, 15911}, {49862, 15150}, {44115, 13578}, {7082, 2217}, {1410, 449}, {5655, 1833}, {6949, 2253}, {5902, 1914}, {5531, 2337}, {1094, 485}, {891, 437}, {2224, 1110}, {891, 450}, {37218, 20378}, {1497, 834}, {43233, 26724}, {41499, 25699}}); TestOptimalLinearization("e05381ab28008756a16001904deb4a02a2608a900003971e81fb4604f32981e44005f179829b2606a51f80ea6a07e15182bc4208e55583b34e099029ed540a8d7adb1c0b882cc9200c8d29d72e0d9235f6600ef77284982a0f823581ea3c0f0f8235975c100b8600e1000c0f823582ab740d0f8265900c0e0f823581ed660e0f964181f340110d9838829b241609823a80cc6a100f857ceb40100f823580da10110f8474829172120f8235b94c130f8235fb58130f82419504160c82358c76140e82428c76150e85429632190b823980a002130f854480b348140f823580a61a140f80c7638487361e000418809e1a83c44421000000002080cf6484a24207130000000e9121d5361800000003020500"_hex_u8, {4, 5, 15, 35, 36, 37, 17, 18, 19, 22, 21, 23, 20, 0, 1, 16, 33, 7, 8, 10, 9, 38, 39, 12, 13, 24, 25, 26, 27, 34, 3, 28, 40, 11, 29, 2, 30, 6, 31, 32, 14});
TestOptimalLinearization("80d25b87e93a0081fc0b8ef06a01d96182e34002d51082ca6603c36081ee3c04e02a83865e05d43882c72606c24581e7500780a61285fb1a08bc3f81c73409d87582df160ac74d8282560bce0f82a5480c808b3084ec3a0dc57681f96a0e80852c84cc0a0fce1482a54810be2b81d12011833e9c0011118241956e121183158e5013118450a3501311857c80b80414118242956e15118416ad3e1211857ced5e131182419b20141182399c3e1411847480971a1511880fde3414118544bc7614118331977015118336aa7e1511847cd30015118608f34416118449f54c1611854dc40a17118241a2141711844ab62c17118335993218118241921419118a5080b574181183369b4c1911847ca3001a11954880fc6026058451a540270583158e50193d8474808526183c8451a3502800218331aa56123483168e50035983168358005caa17c280442200000000000000000000000000000000002d00"_hex_v_u8, {{1360002, 282751}, {2975, 662}, {1887, 441}, {1808, 449}, {2464, 721}, {1463, 449}, {2344, 720}, {1463, 450}, {2344, 721}, {1856, 574}, {1830, 566}, {2304, 764}, {1689, 565}, {1592, 561}, {1226, 449}, {1000, 533}, {1000, 533}, {1000, 534}, {300, 534}}); TestOptimalLinearization("80d25b87e93a0081fc0b8ef06a01d96182e34002d51082ca6603c36081ee3c04e02a83865e05d43882c72606c24581e7500780a61285fb1a08bc3f81c73409d87582df160ac74d8282560bce0f82a5480c808b3084ec3a0dc57681f96a0e80852c84cc0a0fce1482a54810be2b81d12011833e9c0011118241956e121183158e5013118450a3501311857c80b80414118242956e15118416ad3e1211857ced5e131182419b20141182399c3e1411847480971a1511880fde3414118544bc7614118331977015118336aa7e1511847cd30015118608f34416118449f54c1611854dc40a17118241a2141711844ab62c17118335993218118241921419118a5080b574181183369b4c1911847ca3001a11954880fc6026058451a540270583158e50193d8474808526183c8451a3502800218331aa56123483168e50035983168358005caa17c280442200000000000000000000000000000000002d00"_hex_u8, {15, 41, 42, 36, 37, 38, 20, 22, 27, 28, 29, 50, 31, 32, 16, 18, 51, 33, 35, 34, 0, 23, 39, 40, 14, 13, 46, 47, 25, 26, 45, 8, 7, 10, 11, 17, 21, 19, 52, 2, 9, 12, 24, 1, 48, 49, 43, 30, 44, 3, 4, 5, 6});
// Hard clusters (according to various metrics) in synthetically generated clusters, with 26-64 transactions. // Hard clusters (according to various metrics) in synthetically generated clusters, with 26-64 transactions.
TestOptimalLinearization("826db830008414a23c01744d028723d67e0103845cb0480201846ca1060202802d8b0e030104852dc545040104800e825f040283548424000f830aba39010a8241991402068612d67503030d8360b66301108712eb58070003843b905805040d8449865e05000b8503cd1908040003825ca40b03060204844b8a3c03030313852e8456030404000c834c9d1107000103000b8717b2590a00000200000b8035901106030003000f810c8a1c0a00000003000f862ea7130608000b816aa87706040400188112905b05070a8327bb040d02000000000d844cce410a05010009807994720502040e803c84690a0202020000058061813301050520800e8d6f0906010000001c84288f45090204000100001f820aa37607020206000d8073857c0602091f8539c4120602020502001a8728c826050c01078364c673060c0106832da9030b02020300000000286c877903040a00258466be7b050606000020840e9b7105010a23815f9321080300040002000000867fdf300500000a02002285168b50060008000100010123841ac7210704000200000101001c834d816706020302020000000022845ace070505000000010000000f81419e650207000002002c844eb3520b0000000100000000001582129f1c0b000000020000000008807b98060a0200020000000000038011825908010102000000000100001580378e3006040200000000038561ac27030103020e82459c170002000202000b8336a9420203000000000000000f00"_hex_v_u8, {{3672, 493}, {9871, 2079}, {7901, 1719}, {3172, 732}, {1434, 591}, {1470, 1295}, {734, 715}, {-3533, 9003}, {-3439, 2406}, {-1059, 680}, {-15211, 8262}, {-2491, 993}, {-1297, 351}, {-11899, 3148}, {-1868, 453}}); TestOptimalLinearization("826db830008414a23c01744d028723d67e0103845cb0480201846ca1060202802d8b0e030104852dc545040104800e825f040283548424000f830aba39010a8241991402068612d67503030d8360b66301108712eb58070003843b905805040d8449865e05000b8503cd1908040003825ca40b03060204844b8a3c03030313852e8456030404000c834c9d1107000103000b8717b2590a00000200000b8035901106030003000f810c8a1c0a00000003000f862ea7130608000b816aa87706040400188112905b05070a8327bb040d02000000000d844cce410a05010009807994720502040e803c84690a0202020000058061813301050520800e8d6f0906010000001c84288f45090204000100001f820aa37607020206000d8073857c0602091f8539c4120602020502001a8728c826050c01078364c673060c0106832da9030b02020300000000286c877903040a00258466be7b050606000020840e9b7105010a23815f9321080300040002000000867fdf300500000a02002285168b50060008000100010123841ac7210704000200000101001c834d816706020302020000000022845ace070505000000010000000f81419e650207000002002c844eb3520b0000000100000000001582129f1c0b000000020000000008807b98060a0200020000000000038011825908010102000000000100001580378e3006040200000000038561ac27030103020e82459c170002000202000b8336a9420203000000000000000f00"_hex_u8, {16, 36, 20, 46, 57, 32, 18, 42, 53, 56, 1, 17, 7, 26, 22, 2, 27, 34, 29, 24, 40, 39, 25, 41, 35, 23, 19, 9, 44, 52, 49, 13, 5, 50, 28, 51, 31, 10, 0, 4, 11, 15, 38, 33, 3, 48, 8, 55, 30, 12, 14, 54, 58, 37, 21, 6, 43, 45, 47});
TestOptimalLinearization("823f9b1b00864fa2680182328c07028017890c02038607d0770105864dd04a0205852f80020108801e8c6c0208840aac1c050006813f9b0e010e826b9340040006806b856006000969823108000000870bb1230403010c837cb754040502867f934c0600010983388872050100088549c578060001010f861b812304040109872daf3004050109841f8a3208010100000a86008b0d04000407824ea36902090015850f802d01081881068d7f0501000310862fab02000915827e961f0308000011855ac76f030405028668b31a0202061c8602a81b020700001e82029017010a8351af460105000009801b866601030300010e837aa96602030200010e8420af76020400000008850fb76701000201000014861fc37804000100001000"_hex_v_u8, {{9571, 3032}, {9352, 6065}, {1318, 1023}, {633, 568}, {729, 671}, {7060, 11184}, {-8300, 1641}}); TestOptimalLinearization("823f9b1b00864fa2680182328c07028017890c02038607d0770105864dd04a0205852f80020108801e8c6c0208840aac1c050006813f9b0e010e826b9340040006806b856006000969823108000000870bb1230403010c837cb754040502867f934c0600010983388872050100088549c578060001010f861b812304040109872daf3004050109841f8a3208010100000a86008b0d04000407824ea36902090015850f802d01081881068d7f0501000310862fab02000915827e961f0308000011855ac76f030405028668b31a0202061c8602a81b020700001e82029017010a8351af460105000009801b866601030300010e837aa96602030200010e8420af76020400000008850fb76701000201000014861fc37804000100001000"_hex_u8, {31, 34, 24, 13, 27, 6, 16, 12, 2, 32, 25, 10, 9, 8, 23, 17, 26, 18, 30, 3, 35, 5, 22, 14, 7, 1, 36, 21, 19, 4, 11, 0, 29, 20, 28, 33, 15});
TestOptimalLinearization("8365c026008371c34b01841bc8160284789d30038141a3160486478906058645803806855f977d078175a27308831dab3e0986188b780a8031876b0b8539c1050c8708ea770d825b88020e82588c000f814d9f59108560de11118643c124128058856b13833da2251483229a35158723cc5116800e80241780108e5418807e9432198269a64c1a855cb10d1b82628d431c834cb73600000000000000000000000000000000000000000000000000000000001d8545a35601000000000000000000000000000000000000000000000000000000001c866bd03002000000000000000000000000000000000000000000000000000000001a8251a152030000000000000000000000000000000000000000000000000000000019847d8c2104000000000000000000000000000000000000000000000000000000001887129a26050000000000000000000000000000000000000000000000000000000017840b8517060000000000000000000000000000000000000000000000000000000015857c9c7f0700000000000000000000000000000000000000000000000000000000148608860d080000000000000000000000000000000000000000000000000000000013855d987a0900000000000000000000000000000000000000000000000000000000128461a33f0a00000000000000000000000000000000000000000000000000000000128701e97a0b0000000000000000000000000000000000000000000000000000000010820e84790c00000000000000000000000000000000000000000000000000000000108521d6290d00000000000000000000000000000000000000000000000000000000108406bd0e0e000000000000000000000000000000000000000000000000000000000d850e9f140f000000000000000000000000000000000000000000000000000000000b8424b46510000000000000000000000000000000000000000000000000000000000a830e9c6e110000000000000000000000000000000000000000000000000000000009850d894912000000000000000000000000000000000000000000000000000000000881308b0c1300000000000000000000000000000000000000000000000000000000058273a1581400000000000000000000000000000000000000000000000000000000048426cc27150000000000000000000000000000000000000000000000000000000002817f9964160000000000000000000000000000000000000000000000000000000001873ad510170000000000000000000000000000000000000000000000000000000001816f832a180000000000000000000000000000000000000000000000000000000001874aaf1c19000000000000000000000000000000000000000000000000000000000100"_hex_v_u8, {{2315, 321}, {4683, 667}, {1002, 144}, {4179, 613}, {1369, 254}, {2847, 541}, {2534, 489}, {4242, 963}, {1944, 760}, {832, 472}, {577, 475}, {828, 920}, {643, 967}, {82, 142}, {3527, 21301}, {-455, 904}, {-396, 651}, {-677, 781}, {-381, 398}, {-849, 765}, {-1920, 892}, {-2336, 737}, {-3443, 676}, {-5589, 801}, {-4948, 678}}); TestOptimalLinearization("8365c026008371c34b01841bc8160284789d30038141a3160486478906058645803806855f977d078175a27308831dab3e0986188b780a8031876b0b8539c1050c8708ea770d825b88020e82588c000f814d9f59108560de11118643c124128058856b13833da2251483229a35158723cc5116800e80241780108e5418807e9432198269a64c1a855cb10d1b82628d431c834cb73600000000000000000000000000000000000000000000000000000000001d8545a35601000000000000000000000000000000000000000000000000000000001c866bd03002000000000000000000000000000000000000000000000000000000001a8251a152030000000000000000000000000000000000000000000000000000000019847d8c2104000000000000000000000000000000000000000000000000000000001887129a26050000000000000000000000000000000000000000000000000000000017840b8517060000000000000000000000000000000000000000000000000000000015857c9c7f0700000000000000000000000000000000000000000000000000000000148608860d080000000000000000000000000000000000000000000000000000000013855d987a0900000000000000000000000000000000000000000000000000000000128461a33f0a00000000000000000000000000000000000000000000000000000000128701e97a0b0000000000000000000000000000000000000000000000000000000010820e84790c00000000000000000000000000000000000000000000000000000000108521d6290d00000000000000000000000000000000000000000000000000000000108406bd0e0e000000000000000000000000000000000000000000000000000000000d850e9f140f000000000000000000000000000000000000000000000000000000000b8424b46510000000000000000000000000000000000000000000000000000000000a830e9c6e110000000000000000000000000000000000000000000000000000000009850d894912000000000000000000000000000000000000000000000000000000000881308b0c1300000000000000000000000000000000000000000000000000000000058273a1581400000000000000000000000000000000000000000000000000000000048426cc27150000000000000000000000000000000000000000000000000000000002817f9964160000000000000000000000000000000000000000000000000000000001873ad510170000000000000000000000000000000000000000000000000000000001816f832a180000000000000000000000000000000000000000000000000000000001874aaf1c19000000000000000000000000000000000000000000000000000000000100"_hex_u8, {8, 4, 44, 1, 46, 17, 47, 34, 6, 29, 28, 19, 10, 42, 12, 13, 54, 36, 22, 40, 49, 38, 41, 23, 15, 31, 27, 3, 32, 24, 30, 0, 5, 51, 7, 50, 45, 37, 53, 2, 33, 43, 20, 11, 52, 18, 14, 39, 25, 9, 16, 21, 35, 26, 48});
TestOptimalLinearization("8741984d008704eb3f01815799390281319457038626a424048661dc1705861fbf1106814685750782448178088331af0c098525ae120a8662aa220b816d450c8210a2430d870e9a160e804692290f845690751081158744118029844312871ac2091381589435148520ad471580548441168512d313178422b948188647b82e198267a50f1a81479b4d1b815c8c291c8640a8031d851faa720000000000000000000000000000000000000000000000000000000000001d813587770100000000000000000000000000000000000000000000000000000000001d84268e170200000000000000000000000000000000000000000000000000000000001a815f99300300000000000000000000000000000000000000000000000000000000001783569c6c04000000000000000000000000000000000000000000000000000000000016850fa31c05000000000000000000000000000000000000000000000000000000000015833eac460600000000000000000000000000000000000000000000000000000000001081589c4e0700000000000000000000000000000000000000000000000000000000000c805395560800000000000000000000000000000000000000000000000000000000000b817a83730900000000000000000000000000000000000000000000000000000000000a807e8e530a00000000000000000000000000000000000000000000000000000000000a842ac5360b000000000000000000000000000000000000000000000000000000000009803388160c00000000000000000000000000000000000000000000000000000000000785069b4d0d000000000000000000000000000000000000000000000000000000000007831b9e0b0e000000000000000000000000000000000000000000000000000000000003803989220f0000000000000000000000000000000000000000000000000000000000038663ca511000000000000000000000000000000000000000000000000000000000000383789013110000000000000000000000000000000000000000000000000000000000028418907f1200000000000000000000000000000000000000000000000000000000000286178422130000000000000000000000000000000000000000000000000000000000028072935e140000000000000000000000000000000000000000000000000000000000018222825e1500000000000000000000000000000000000000000000000000000000000000"_hex_v_u8, {{3748, 674}, {3078, 561}, {3671, 967}, {3017, 805}, {2769, 994}, {2386, 934}, {546, 277}, {1739, 1038}, {188, 452}, {-35, 365}, {-443, 326}, {-27524, 18833}, {-1152, 664}, {-1098, 632}, {-572, 309}, {-1831, 774}, {-1990, 539}, {-1002, 254}, {-4841, 995}}); TestOptimalLinearization("8741984d008704eb3f01815799390281319457038626a424048661dc1705861fbf1106814685750782448178088331af0c098525ae120a8662aa220b816d450c8210a2430d870e9a160e804692290f845690751081158744118029844312871ac2091381589435148520ad471580548441168512d313178422b948188647b82e198267a50f1a81479b4d1b815c8c291c8640a8031d851faa720000000000000000000000000000000000000000000000000000000000001d813587770100000000000000000000000000000000000000000000000000000000001d84268e170200000000000000000000000000000000000000000000000000000000001a815f99300300000000000000000000000000000000000000000000000000000000001783569c6c04000000000000000000000000000000000000000000000000000000000016850fa31c05000000000000000000000000000000000000000000000000000000000015833eac460600000000000000000000000000000000000000000000000000000000001081589c4e0700000000000000000000000000000000000000000000000000000000000c805395560800000000000000000000000000000000000000000000000000000000000b817a83730900000000000000000000000000000000000000000000000000000000000a807e8e530a00000000000000000000000000000000000000000000000000000000000a842ac5360b000000000000000000000000000000000000000000000000000000000009803388160c00000000000000000000000000000000000000000000000000000000000785069b4d0d000000000000000000000000000000000000000000000000000000000007831b9e0b0e000000000000000000000000000000000000000000000000000000000003803989220f0000000000000000000000000000000000000000000000000000000000038663ca511000000000000000000000000000000000000000000000000000000000000383789013110000000000000000000000000000000000000000000000000000000000028418907f1200000000000000000000000000000000000000000000000000000000000286178422130000000000000000000000000000000000000000000000000000000000028072935e140000000000000000000000000000000000000000000000000000000000018222825e1500000000000000000000000000000000000000000000000000000000000000"_hex_u8, {38, 15, 39, 16, 17, 7, 24, 21, 13, 18, 11, 0, 23, 34, 26, 48, 50, 33, 31, 28, 9, 5, 4, 40, 44, 19, 8, 22, 3, 37, 27, 32, 25, 49, 20, 10, 42, 1, 35, 12, 14, 51, 47, 29, 6, 46, 45, 2, 36, 41, 30, 43});
TestOptimalLinearization("814e9f7400857edb66018043813402821fa96e038608bd4c048348bc2d05815ca33c06833387610780068b7408842ca841098059823d0a835382320b85418e4b0c84079d380d814b93520e83218a1a0f816b83491084088a4f11802e910512810a8e67138418c1541480408b2715845aaf6d1682529e5c000000000000000000000000000000000000000000000016837e88730100000000000000000000000000000000000000000000148733ce200200000000000000000000000000000000000000000000118279913c0300000000000000000000000000000000000000000000118276af0204000000000000000000000000000000000000000000000f80598c2405000000000000000000000000000000000000000000000f8734e31706000000000000000000000000000000000000000000000e804b803507000000000000000000000000000000000000000000000a85308b320800000000000000000000000000000000000000000000098418c039090000000000000000000000000000000000000000000008852898740a0000000000000000000000000000000000000000000006807596680b000000000000000000000000000000000000000000000585389e3e0c00000000000000000000000000000000000000000000058612cd260d00000000000000000000000000000000000000000000048338a41c0e000000000000000000000000000000000000000000000486068d430f0000000000000000000000000000000000000000000004806595121000000000000000000000000000000000000000000000038719de681100000000000000000000000000000000000000000000038301ab6912000000000000000000000000000000000000000000000380158b2b1300000000000000000000000000000000000000000000038138844b1400000000000000000000000000000000000000000000038465cb1615000000000000000000000000000000000000000000000386768e491600000000000000000000000000000000000000000000028072920f17000000000000000000000000000000000000000000000200"_hex_v_u8, {{2334, 348}, {5939, 894}, {2743, 415}, {4266, 664}, {2106, 334}, {826, 134}, {4006, 904}, {1321, 331}, {1948, 647}, {22824, 14732}, {793, 816}, {-91, 203}, {-997, 1014}, {-634, 638}, {-930, 902}, {-358, 312}, {-1224, 242}, {-790, 149}, {-2869, 513}, {-6412, 1076}, {-4189, 664}}); TestOptimalLinearization("814e9f7400857edb66018043813402821fa96e038608bd4c048348bc2d05815ca33c06833387610780068b7408842ca841098059823d0a835382320b85418e4b0c84079d380d814b93520e83218a1a0f816b83491084088a4f11802e910512810a8e67138418c1541480408b2715845aaf6d1682529e5c000000000000000000000000000000000000000000000016837e88730100000000000000000000000000000000000000000000148733ce200200000000000000000000000000000000000000000000118279913c0300000000000000000000000000000000000000000000118276af0204000000000000000000000000000000000000000000000f80598c2405000000000000000000000000000000000000000000000f8734e31706000000000000000000000000000000000000000000000e804b803507000000000000000000000000000000000000000000000a85308b320800000000000000000000000000000000000000000000098418c039090000000000000000000000000000000000000000000008852898740a0000000000000000000000000000000000000000000006807596680b000000000000000000000000000000000000000000000585389e3e0c00000000000000000000000000000000000000000000058612cd260d00000000000000000000000000000000000000000000048338a41c0e000000000000000000000000000000000000000000000486068d430f0000000000000000000000000000000000000000000004806595121000000000000000000000000000000000000000000000038719de681100000000000000000000000000000000000000000000038301ab6912000000000000000000000000000000000000000000000380158b2b1300000000000000000000000000000000000000000000038138844b1400000000000000000000000000000000000000000000038465cb1615000000000000000000000000000000000000000000000386768e491600000000000000000000000000000000000000000000028072920f17000000000000000000000000000000000000000000000200"_hex_u8, {10, 2, 5, 42, 0, 14, 6, 23, 21, 25, 3, 18, 26, 11, 17, 28, 19, 35, 16, 45, 46, 31, 7, 41, 29, 36, 12, 37, 32, 8, 1, 33, 13, 30, 9, 27, 22, 20, 43, 4, 34, 40, 44, 39, 38, 15, 24});
TestOptimalLinearization("84648d7e00851fb02200018604a232010185649025020084139c5b0300863fc31200000384248d2d010003843d822e020002816f9c360400018432830704000009851fa258060000048045826d060001008618c665070000000881138c4305010008825497140305038263985006030002845e9d0404030000000c8140884a010402000986549e79030401000380198b7c03030001011382409164060300000011831598630701000000001181778c2b070200000000000f82118565040005098464b735040300000000007b8863010501001181229368020501000e82039006000300038014817f010001000000000003804e8d080100010000001b00"_hex_v_u8, {{4112, 1539}, {2265, 900}, {8705, 4603}, {2414, 2781}, {76, 1413}, {-1707, 2591}, {-854, 375}, {-4513, 1397}, {-3611, 740}}); TestOptimalLinearization("84648d7e00851fb02200018604a232010185649025020084139c5b0300863fc31200000384248d2d010003843d822e020002816f9c360400018432830704000009851fa258060000048045826d060001008618c665070000000881138c4305010008825497140305038263985006030002845e9d0404030000000c8140884a010402000986549e79030401000380198b7c03030001011382409164060300000011831598630701000000001181778c2b070200000000000f82118565040005098464b735040300000000007b8863010501001181229368020501000e82039006000300038014817f010001000000000003804e8d080100010000001b00"_hex_u8, {7, 1, 6, 12, 25, 18, 20, 16, 24, 21, 22, 27, 0, 19, 10, 15, 3, 14, 4, 23, 17, 13, 5, 29, 8, 11, 9, 2, 26, 28});
TestOptimalLinearization("6f856d0087059a220172853002813d9a2c038730867604803d820c05842e9b53068066806e07873bb577088146922009847891710a865ba91f0b8018825d0c807e8b550d803789560e810e9c370f8361a271108455c650118440c30b1282068341137f8939148010841515802d917b168736c03217871f801718847ac31819805a211a82569d310000000000000000000000000000000000000000000000000000001b803a916b01000000000000000000000000000000000000000000000000000019836d912a0200000000000000000000000000000000000000000000000000001980348345030000000000000000000000000000000000000000000000000000168124804004000000000000000000000000000000000000000000000000000016843eb63705000000000000000000000000000000000000000000000000000015856c932a0600000000000000000000000000000000000000000000000000001580068a6507000000000000000000000000000000000000000000000000000013801f844408000000000000000000000000000000000000000000000000000012824cb6070900000000000000000000000000000000000000000000000000000f802c8a430a00000000000000000000000000000000000000000000000000000f8477d0400b00000000000000000000000000000000000000000000000000000e8319bf140c00000000000000000000000000000000000000000000000000000d816e9a2c0d00000000000000000000000000000000000000000000000000000d835c886b0e00000000000000000000000000000000000000000000000000000d81709c680f00000000000000000000000000000000000000000000000000000d821f9f161000000000000000000000000000000000000000000000000000000c802582151100000000000000000000000000000000000000000000000000000b84488b0b1200000000000000000000000000000000000000000000000000000b81679e591300000000000000000000000000000000000000000000000000000a8741c4261400000000000000000000000000000000000000000000000000000a805c975b1500000000000000000000000000000000000000000000000000000a7b8946160000000000000000000000000000000000000000000000000000068255820717000000000000000000000000000000000000000000000000000006810b8178180000000000000000000000000000000000000000000000000000068656ac4419000000000000000000000000000000000000000000000000000005810180081a0000000000000000000000000000000000000000000000000000058447a3081b000000000000000000000000000000000000000000000000000004864e960b1c0000000000000000000000000000000000000000000000000000038273a1501d0000000000000000000000000000000000000000000000000000038304a6161e00000000000000000000000000000000000000000000000000000282189d3e1f0000000000000000000000000000000000000000000000000000018338b83820000000000000000000000000000000000000000000000000000000815f92662100000000000000000000000000000000000000000000000000000000"_hex_v_u8, {{4584, 725}, {4364, 762}, {1750, 317}, {4185, 1078}, {1232, 326}, {683, 183}, {408, 114}, {1745, 1029}, {198, 189}, {18555, 18373}, {188, 267}, {96, 292}, {68, 257}, {-196, 469}, {-630, 604}, {-774, 712}, {-203, 165}, {-1478, 974}, {-291, 180}, {-1945, 470}, {-738, 172}, {-3548, 702}, {-755, 134}, {-2029, 359}, {-1206, 186}, {-1582, 220}, {-3524, 460}}); TestOptimalLinearization("6f856d0087059a220172853002813d9a2c038730867604803d820c05842e9b53068066806e07873bb577088146922009847891710a865ba91f0b8018825d0c807e8b550d803789560e810e9c370f8361a271108455c650118440c30b1282068341137f8939148010841515802d917b168736c03217871f801718847ac31819805a211a82569d310000000000000000000000000000000000000000000000000000001b803a916b01000000000000000000000000000000000000000000000000000019836d912a0200000000000000000000000000000000000000000000000000001980348345030000000000000000000000000000000000000000000000000000168124804004000000000000000000000000000000000000000000000000000016843eb63705000000000000000000000000000000000000000000000000000015856c932a0600000000000000000000000000000000000000000000000000001580068a6507000000000000000000000000000000000000000000000000000013801f844408000000000000000000000000000000000000000000000000000012824cb6070900000000000000000000000000000000000000000000000000000f802c8a430a00000000000000000000000000000000000000000000000000000f8477d0400b00000000000000000000000000000000000000000000000000000e8319bf140c00000000000000000000000000000000000000000000000000000d816e9a2c0d00000000000000000000000000000000000000000000000000000d835c886b0e00000000000000000000000000000000000000000000000000000d81709c680f00000000000000000000000000000000000000000000000000000d821f9f161000000000000000000000000000000000000000000000000000000c802582151100000000000000000000000000000000000000000000000000000b84488b0b1200000000000000000000000000000000000000000000000000000b81679e591300000000000000000000000000000000000000000000000000000a8741c4261400000000000000000000000000000000000000000000000000000a805c975b1500000000000000000000000000000000000000000000000000000a7b8946160000000000000000000000000000000000000000000000000000068255820717000000000000000000000000000000000000000000000000000006810b8178180000000000000000000000000000000000000000000000000000068656ac4419000000000000000000000000000000000000000000000000000005810180081a0000000000000000000000000000000000000000000000000000058447a3081b000000000000000000000000000000000000000000000000000004864e960b1c0000000000000000000000000000000000000000000000000000038273a1501d0000000000000000000000000000000000000000000000000000038304a6161e00000000000000000000000000000000000000000000000000000282189d3e1f0000000000000000000000000000000000000000000000000000018338b83820000000000000000000000000000000000000000000000000000000815f92662100000000000000000000000000000000000000000000000000000000"_hex_u8, {39, 56, 6, 51, 18, 30, 5, 2, 10, 14, 7, 54, 58, 41, 23, 19, 46, 13, 20, 25, 16, 35, 1, 42, 40, 32, 49, 26, 24, 59, 43, 29, 31, 55, 57, 27, 53, 37, 60, 50, 47, 17, 4, 12, 45, 9, 48, 44, 28, 34, 33, 52, 8, 0, 22, 11, 15, 36, 3, 38, 21});
TestOptimalLinearization("832a8e4f008160850201854bbe4e0283429e1e0382558b2404872c937d05831593610672801d0780088b0c088708a5330982159d510a865db6010b83618d160c8526b8030d824f89520e813090590f80598d62108637b42a1181348e6d12863eb44a13863bc76d1483329779158543b65816813d9a141781198f4618810d934d00000000000000000000000000000000000000000000000000188319ad1601000000000000000000000000000000000000000000000000188634c8740200000000000000000000000000000000000000000000000017826087340300000000000000000000000000000000000000000000000011830d82050400000000000000000000000000000000000000000000000011860b8356050000000000000000000000000000000000000000000000000e807c9141060000000000000000000000000000000000000000000000000985349100070000000000000000000000000000000000000000000000000100"_hex_v_u8, {{774, 136}, {1738, 317}, {4071, 843}, {945, 217}, {3564, 835}, {1059, 281}, {3413, 951}, {3429, 958}, {1999, 578}, {786, 469}, {907, 609}, {681, 463}, {385, 352}, {-79, 114}, {-14191, 11733}, {-1185, 252}, {-1319, 269}}); TestOptimalLinearization("832a8e4f008160850201854bbe4e0283429e1e0382558b2404872c937d05831593610672801d0780088b0c088708a5330982159d510a865db6010b83618d160c8526b8030d824f89520e813090590f80598d62108637b42a1181348e6d12863eb44a13863bc76d1483329779158543b65816813d9a141781198f4618810d934d00000000000000000000000000000000000000000000000000188319ad1601000000000000000000000000000000000000000000000000188634c8740200000000000000000000000000000000000000000000000017826087340300000000000000000000000000000000000000000000000011830d82050400000000000000000000000000000000000000000000000011860b8356050000000000000000000000000000000000000000000000000e807c9141060000000000000000000000000000000000000000000000000985349100070000000000000000000000000000000000000000000000000100"_hex_u8, {13, 30, 5, 23, 29, 32, 24, 26, 6, 7, 18, 20, 3, 10, 8, 0, 14, 9, 28, 25, 17, 21, 19, 15, 27, 2, 4, 31, 11, 16, 12, 22, 1});
TestOptimalLinearization("806c883b00852cb52d0184028f590285248a01000584149e6d0203872de672040284648f2905028554b02800000b8637b471010006860ca51a0402028405a80706000009842ebb39020307845d814d03030006817da346040300058453a9760700010003835c8f680309804a8f0e070200108739ae4c070200010580588310090002000382738e6f090200000c8559c940040501000d87198e190005188417a5560202040e816e803203010600098112956402031d8450a5700a000000000100188117981f0b00000000010013820ba5100406021a8311b240080201000101188060933d0106011b846dc679050301030b840db86c000b0b83619c26080003000000000e842a93440c0000000000000000068675cf6a070005000000001d817b92730307000000178608ac780401001384158255070301000000128449b62709000000000100108124824f020800001e82059501000201000000002281398258020100000001000e00"_hex_v_u8, {{6043, 1305}, {2111, 1592}, {16829, 16660}, {2522, 3629}, {-232, 292}, {-1546, 885}, {-4578, 1405}, {-1409, 389}}); TestOptimalLinearization("806c883b00852cb52d0184028f590285248a01000584149e6d0203872de672040284648f2905028554b02800000b8637b471010006860ca51a0402028405a80706000009842ebb39020307845d814d03030006817da346040300058453a9760700010003835c8f680309804a8f0e070200108739ae4c070200010580588310090002000382738e6f090200000c8559c940040501000d87198e190005188417a5560202040e816e803203010600098112956402031d8450a5700a000000000100188117981f0b00000000010013820ba5100406021a8311b240080201000101188060933d0106011b846dc679050301030b840db86c000b0b83619c26080003000000000e842a93440c0000000000000000068675cf6a070005000000001d817b92730307000000178608ac780401001384158255070301000000128449b62709000000000100108124824f020800001e82059501000201000000002281398258020100000001000e00"_hex_u8, {15, 25, 31, 9, 41, 12, 33, 40, 30, 3, 36, 38, 22, 16, 39, 34, 19, 11, 32, 17, 4, 20, 1, 2, 37, 18, 23, 35, 13, 5, 8, 0, 26, 29, 28, 10, 7, 21, 14, 24, 27, 6});
TestOptimalLinearization("853d9a0300872ce27c01855dc769028042831b0380268234048670b972058159931a0109815b9c66040782548d5d000b8263ab21020a805f86510401088261ab3b06000204811e816802060a8070805704050a8701ad740501010c852fb83f09000001000880538b4c0305048510c24904000a85479a3b030302128413b0290207078409aa5d060500000480518a4103090a805f8413080500000009841ead02040f80058173001b842d802d0903000002098448a96004030617841aba6a09000012835c950c030b011783099f700211840eb8440502080d810e8f79040a010f81588229020704058040080500050302068619a95d0d0003000000068440a122060a010000068518a070030a04248177957b05090104855cca650802040420830c850508050401010d8348a8690206022e71871f000104020728870ec35d020001000000000200"_hex_v_u8, {{6398, 1068}, {3769, 1008}, {1511, 511}, {6, 7736}, {-2660, 6557}, {-1198, 1987}, {-717, 747}, {-2735, 921}, {-2555, 645}, {-2677, 584}, {-9778, 2011}}); TestOptimalLinearization("853d9a0300872ce27c01855dc769028042831b0380268234048670b972058159931a0109815b9c66040782548d5d000b8263ab21020a805f86510401088261ab3b06000204811e816802060a8070805704050a8701ad740501010c852fb83f09000001000880538b4c0305048510c24904000a85479a3b030302128413b0290207078409aa5d060500000480518a4103090a805f8413080500000009841ead02040f80058173001b842d802d0903000002098448a96004030617841aba6a09000012835c950c030b011783099f700211840eb8440502080d810e8f79040a010f81588229020704058040080500050302068619a95d0d0003000000068440a122060a010000068518a070030a04248177957b05090104855cca650802040420830c850508050401010d8348a8690206022e71871f000104020728870ec35d020001000000000200"_hex_u8, {19, 42, 39, 4, 31, 2, 16, 26, 12, 13, 11, 10, 5, 30, 17, 9, 35, 22, 14, 15, 6, 37, 24, 34, 25, 29, 21, 18, 7, 36, 27, 32, 38, 0, 23, 28, 33, 20, 41, 3, 8, 40, 1});
TestOptimalLinearization("80278170008458b93c01840e9c220284358d1b0377800c04871ca3470580338c00068219a40807861f9b4f088200977309810a847c0a82398b2e0b814e9b760c8177915c0d8657a5360e872ba73a0f81290810847db55111854cae4300000000000000000000000000000000000012852bbb420100000000000000000000000000000000001181168d270200000000000000000000000000000000001186049933030000000000000000000000000000000000118304a5550400000000000000000000000000000000000f8338926b0500000000000000000000000000000000000f853c830e0600000000000000000000000000000000000f8530ba630700000000000000000000000000000000000f853191580800000000000000000000000000000000000e870d85570900000000000000000000000000000000000b827e83180a00000000000000000000000000000000000b874abd420b000000000000000000000000000000000008803689030c000000000000000000000000000000000008826287720d000000000000000000000000000000000007836daf3b0e0000000000000000000000000000000000078678ba550f000000000000000000000000000000000006855e877610000000000000000000000000000000000006815385071100000000000000000000000000000000000681200d120000000000000000000000000000000000058350af75130000000000000000000000000000000000028713db5e140000000000000000000000000000000000008257813b1500000000000000000000000000000000000000"_hex_v_u8, {{2372, 409}, {1851, 334}, {3742, 728}, {832, 179}, {1198, 375}, {1873, 654}, {2459, 983}, {2589, 1067}, {791, 441}, {382, 266}, {184, 167}, {6046, 9350}, {268, 510}, {263, 828}, {-7, 288}, {-158, 471}, {-428, 1037}, {-388, 339}, {-1690, 900}, {-1270, 568}, {-916, 278}, {-642, 182}, {-3042, 844}, {-3819, 1016}, {-3826, 816}, {-2475, 516}, {-3102, 621}, {-3131, 592}}); TestOptimalLinearization("80278170008458b93c01840e9c220284358d1b0377800c04871ca3470580338c00068219a40807861f9b4f088200977309810a847c0a82398b2e0b814e9b760c8177915c0d8657a5360e872ba73a0f81290810847db55111854cae4300000000000000000000000000000000000012852bbb420100000000000000000000000000000000001181168d270200000000000000000000000000000000001186049933030000000000000000000000000000000000118304a5550400000000000000000000000000000000000f8338926b0500000000000000000000000000000000000f853c830e0600000000000000000000000000000000000f8530ba630700000000000000000000000000000000000f853191580800000000000000000000000000000000000e870d85570900000000000000000000000000000000000b827e83180a00000000000000000000000000000000000b874abd420b000000000000000000000000000000000008803689030c000000000000000000000000000000000008826287720d000000000000000000000000000000000007836daf3b0e0000000000000000000000000000000000078678ba550f000000000000000000000000000000000006855e877610000000000000000000000000000000000006815385071100000000000000000000000000000000000681200d120000000000000000000000000000000000058350af75130000000000000000000000000000000000028713db5e140000000000000000000000000000000000008257813b1500000000000000000000000000000000000000"_hex_u8, {18, 30, 5, 15, 32, 6, 33, 34, 26, 23, 1, 13, 36, 11, 19, 14, 20, 37, 38, 2, 21, 12, 24, 28, 17, 9, 31, 39, 16, 29, 4, 8, 3, 22, 0, 27, 10, 7, 25, 35});
TestOptimalLinearization("825a8f49008163894a018617c37e028211980d0380649505048345b34905805f976006864f840e07856bde290885638c5c09866bee300a8171805e0b8735db090c8564c6010d8117947d0e841abf260f81209259108559917811814789531284109f4d138325b5191480528b3a158401bf7616864aae10178554db4318800d856719871cc20b00000000000000000000000000000000000000000000000000001a843a994e01000000000000000000000000000000000000000000000000001981339d580200000000000000000000000000000000000000000000000000198644d25103000000000000000000000000000000000000000000000000001980468724040000000000000000000000000000000000000000000000000019810a8d390500000000000000000000000000000000000000000000000000198446b2120600000000000000000000000000000000000000000000000000188575c56f070000000000000000000000000000000000000000000000000017813a880e080000000000000000000000000000000000000000000000000014811f832409000000000000000000000000000000000000000000000000001481289f620a0000000000000000000000000000000000000000000000000011836ab4600b000000000000000000000000000000000000000000000000001186119c020c00000000000000000000000000000000000000000000000000118673b5060d0000000000000000000000000000000000000000000000000010845c93070e000000000000000000000000000000000000000000000000000d804b856b0f000000000000000000000000000000000000000000000000000d857d835d10000000000000000000000000000000000000000000000000000c81469a5e11000000000000000000000000000000000000000000000000000981548a511200000000000000000000000000000000000000000000000000088661c1371300000000000000000000000000000000000000000000000000088119867b1400000000000000000000000000000000000000000000000000088467cb101500000000000000000000000000000000000000000000000000068526a4451600000000000000000000000000000000000000000000000000068278aa281700000000000000000000000000000000000000000000000000068329973818000000000000000000000000000000000000000000000000000582688425190000000000000000000000000000000000000000000000000005853988131a0000000000000000000000000000000000000000000000000005862098561b00000000000000000000000000000000000000000000000000038222a55c1c00000000000000000000000000000000000000000000000000038166a4101d00000000000000000000000000000000000000000000000000028730ef3b1e000000000000000000000000000000000000000000000000000183798e511f0000000000000000000000000000000000000000000000000001836d907620000000000000000000000000000000000000000000000000000000"_hex_v_u8, {{7128, 1003}, {1584, 223}, {4155, 641}, {4115, 666}, {4415, 919}, {797, 210}, {3016, 970}, {677, 355}, {1212, 857}, {878, 867}, {327, 975}, {111, 369}, {-1440, 17399}, {-303, 893}, {-339, 488}, {-586, 825}, {-1001, 633}, {-1284, 732}, {-510, 281}, {-438, 203}, {-745, 340}, {-2403, 806}, {-925, 266}, {-4294, 1052}, {-4252, 993}, {-4536, 885}, {-5353, 964}, {-7198, 1072}}); TestOptimalLinearization("825a8f49008163894a018617c37e028211980d0380649505048345b34905805f976006864f840e07856bde290885638c5c09866bee300a8171805e0b8735db090c8564c6010d8117947d0e841abf260f81209259108559917811814789531284109f4d138325b5191480528b3a158401bf7616864aae10178554db4318800d856719871cc20b00000000000000000000000000000000000000000000000000001a843a994e01000000000000000000000000000000000000000000000000001981339d580200000000000000000000000000000000000000000000000000198644d25103000000000000000000000000000000000000000000000000001980468724040000000000000000000000000000000000000000000000000019810a8d390500000000000000000000000000000000000000000000000000198446b2120600000000000000000000000000000000000000000000000000188575c56f070000000000000000000000000000000000000000000000000017813a880e080000000000000000000000000000000000000000000000000014811f832409000000000000000000000000000000000000000000000000001481289f620a0000000000000000000000000000000000000000000000000011836ab4600b000000000000000000000000000000000000000000000000001186119c020c00000000000000000000000000000000000000000000000000118673b5060d0000000000000000000000000000000000000000000000000010845c93070e000000000000000000000000000000000000000000000000000d804b856b0f000000000000000000000000000000000000000000000000000d857d835d10000000000000000000000000000000000000000000000000000c81469a5e11000000000000000000000000000000000000000000000000000981548a511200000000000000000000000000000000000000000000000000088661c1371300000000000000000000000000000000000000000000000000088119867b1400000000000000000000000000000000000000000000000000088467cb101500000000000000000000000000000000000000000000000000068526a4451600000000000000000000000000000000000000000000000000068278aa281700000000000000000000000000000000000000000000000000068329973818000000000000000000000000000000000000000000000000000582688425190000000000000000000000000000000000000000000000000005853988131a0000000000000000000000000000000000000000000000000005862098561b00000000000000000000000000000000000000000000000000038222a55c1c00000000000000000000000000000000000000000000000000038166a4101d00000000000000000000000000000000000000000000000000028730ef3b1e000000000000000000000000000000000000000000000000000183798e511f0000000000000000000000000000000000000000000000000001836d907620000000000000000000000000000000000000000000000000000000"_hex_u8, {24, 16, 49, 32, 9, 48, 52, 7, 35, 22, 17, 25, 39, 1, 57, 40, 11, 33, 31, 29, 26, 13, 12, 44, 54, 18, 19, 53, 41, 3, 51, 20, 43, 34, 8, 23, 45, 5, 2, 21, 14, 58, 50, 15, 30, 46, 47, 56, 27, 38, 28, 36, 42, 6, 0, 37, 10, 4, 55});
TestOptimalLinearization("83158670008454b00201853eae2100038357ac07010384369d5c02028429822b0007801e887b010482216f050001800a877a0600008603a0410403800c873105000c8559ab0c040886199159070001038374b0290103108050807c0205010a830cb359040003010e8413926f04030107807c85220703000000058631af6009000001000a8637a46305050185609360070102000110846cc57b08020100000d6587160805000a8240a87007020201158551874806040101128177974c03080d84368c5f060400041a8559905a040204000c8422903002070513850ead0c09000401001d853dbd51070202020101018574d03d060009001c8104885e0c0200010103867b853c050007010b8158803c00090301118019847605060001000100038361ae5807020202000000058566ac5a0401040100010101835b854f07010000030001098237a37c0402010002001986608e5102040102001f855da12f0201000000010000"_hex_v_u8, {{3137, 724}, {1966, 694}, {2184, 1015}, {1077, 671}, {-56, 417}, {-4305, 19152}, {-424, 603}, {-2200, 861}, {-6216, 1876}}); TestOptimalLinearization("83158670008454b00201853eae2100038357ac07010384369d5c02028429822b0007801e887b010482216f050001800a877a0600008603a0410403800c873105000c8559ab0c040886199159070001038374b0290103108050807c0205010a830cb359040003010e8413926f04030107807c85220703000000058631af6009000001000a8637a46305050185609360070102000110846cc57b08020100000d6587160805000a8240a87007020201158551874806040101128177974c03080d84368c5f060400041a8559905a040204000c8422903002070513850ead0c09000401001d853dbd51070202020101018574d03d060009001c8104885e0c0200010103867b853c050007010b8158803c00090301118019847605060001000100038361ae5807020202000000058566ac5a0401040100010101835b854f07010000030001098237a37c0402010002001986608e5102040102001f855da12f0201000000010000"_hex_u8, {32, 20, 23, 26, 16, 33, 29, 10, 37, 7, 14, 18, 27, 13, 30, 24, 6, 8, 11, 2, 21, 40, 0, 25, 1, 28, 19, 38, 17, 22, 36, 12, 4, 5, 15, 34, 35, 39, 31, 41, 3, 9});
TestOptimalLinearization("8711d24400834a8e460180458b4302841fbf3200028025883800068672d2640104841fc210020104856fbd3001078039820e050000018175930b03038174915d070000008469864b011086248a4004098475a8040701000a844e925c080000000d8157a0540302108442c13504020f8162895105020685169902050401128559c2360101020b81568a5207000300028427c340060500001180118d520400000204137a835c0901010001118318ad6606010204000a847c8f39050805835da52600248455cb19050206048400b27b010c048604b97b0302080a842695560024835f96790002158530bc2f030703038365a02f012d807481580800040003001c801e851e01218631a40503050004218535c7030405000413800e82080202040602846ec55f09020002000000000017831fb37904020104000000001f85588150030005010101000885449c3d0600010400000f872e8f3f080101000100000e804a825106000100011e81619a5c03010200000c80118b1301010102002c00"_hex_v_u8, {{5346, 1041}, {12977, 2549}, {3992, 879}, {604, 165}, {9466, 2925}, {10459, 5394}, {1398, 1369}, {-5465, 2673}, {-3270, 1378}, {-25877, 8528}, {-4167, 688}}); TestOptimalLinearization("8711d24400834a8e460180458b4302841fbf3200028025883800068672d2640104841fc210020104856fbd3001078039820e050000018175930b03038174915d070000008469864b011086248a4004098475a8040701000a844e925c080000000d8157a0540302108442c13504020f8162895105020685169902050401128559c2360101020b81568a5207000300028427c340060500001180118d520400000204137a835c0901010001118318ad6606010204000a847c8f39050805835da52600248455cb19050206048400b27b010c048604b97b0302080a842695560024835f96790002158530bc2f030703038365a02f012d807481580800040003001c801e851e01218631a40503050004218535c7030405000413800e82080202040602846ec55f09020002000000000017831fb37904020104000000001f85588150030005010101000885449c3d0600010400000f872e8f3f080101000100000e804a825106000100011e81619a5c03010200000c80118b1301010102002c00"_hex_u8, {15, 28, 36, 20, 26, 22, 3, 24, 18, 4, 35, 11, 27, 0, 42, 6, 14, 12, 45, 40, 25, 30, 37, 7, 17, 9, 8, 33, 13, 32, 1, 21, 46, 41, 44, 29, 43, 5, 23, 38, 16, 19, 39, 34, 31, 10, 2});
TestOptimalLinearization("845c9571008502c1220180458c6002822dae760381738272048546dc02058710ac1606826c9a240780108c6d088563b973098261b34a0a8625b4170b8532b2110c8376813d0d8424c34c0e8031911a0f81179d031081308c0911872abb6b128670a65813853ab85c148678f60a158672f17316843ba46617865d8214000000000000000000000000000000000000000000000000188537bd66010000000000000000000000000000000000000000000000188669c638020000000000000000000000000000000000000000000000188343b60c03000000000000000000000000000000000000000000000018835bb632040000000000000000000000000000000000000000000000188303b4090500000000000000000000000000000000000000000000001783039c2e060000000000000000000000000000000000000000000000178455c17207000000000000000000000000000000000000000000000016802f8b16080000000000000000000000000000000000000000000000158619a50309000000000000000000000000000000000000000000000014837db56e0a000000000000000000000000000000000000000000000014866897370b000000000000000000000000000000000000000000000014843f87570c0000000000000000000000000000000000000000000000148651ca440d000000000000000000000000000000000000000000000014863cde0f0e000000000000000000000000000000000000000000000014820990560f000000000000000000000000000000000000000000000014820a826710000000000000000000000000000000000000000000000013798c281100000000000000000000000000000000000000000000001182039f0212000000000000000000000000000000000000000000000010833dbc42130000000000000000000000000000000000000000000000108377a51b1400000000000000000000000000000000000000000000000e83649e3a1500000000000000000000000000000000000000000000000d870beb4f1600000000000000000000000000000000000000000000000b83008d401700000000000000000000000000000000000000000000000b842dc51c1800000000000000000000000000000000000000000000000b8359c5141900000000000000000000000000000000000000000000000b835bbe521a00000000000000000000000000000000000000000000000a8255876b1b000000000000000000000000000000000000000000000007824b97161c000000000000000000000000000000000000000000000007834ca4411d0000000000000000000000000000000000000000000000058673a6301e00000000000000000000000000000000000000000000000287218e731f000000000000000000000000000000000000000000000001835e8d622000000000000000000000000000000000000000000000000000"_hex_v_u8, {{7621, 1016}, {3067, 429}, {5953, 838}, {3365, 481}, {1165, 177}, {4390, 676}, {4241, 770}, {3694, 826}, {880, 197}, {1746, 492}, {2419, 699}, {2891, 1040}, {2540, 1008}, {32264, 19146}, {945, 606}, {202, 989}, {-244, 394}, {-556, 703}, {-1018, 1057}, {-566, 469}, {-1564, 1000}, {-2434, 921}, {-2446, 631}, {-2401, 588}, {-6088, 956}, {-3397, 515}, {-6952, 1035}}); TestOptimalLinearization("845c9571008502c1220180458c6002822dae760381738272048546dc02058710ac1606826c9a240780108c6d088563b973098261b34a0a8625b4170b8532b2110c8376813d0d8424c34c0e8031911a0f81179d031081308c0911872abb6b128670a65813853ab85c148678f60a158672f17316843ba46617865d8214000000000000000000000000000000000000000000000000188537bd66010000000000000000000000000000000000000000000000188669c638020000000000000000000000000000000000000000000000188343b60c03000000000000000000000000000000000000000000000018835bb632040000000000000000000000000000000000000000000000188303b4090500000000000000000000000000000000000000000000001783039c2e060000000000000000000000000000000000000000000000178455c17207000000000000000000000000000000000000000000000016802f8b16080000000000000000000000000000000000000000000000158619a50309000000000000000000000000000000000000000000000014837db56e0a000000000000000000000000000000000000000000000014866897370b000000000000000000000000000000000000000000000014843f87570c0000000000000000000000000000000000000000000000148651ca440d000000000000000000000000000000000000000000000014863cde0f0e000000000000000000000000000000000000000000000014820990560f000000000000000000000000000000000000000000000014820a826710000000000000000000000000000000000000000000000013798c281100000000000000000000000000000000000000000000001182039f0212000000000000000000000000000000000000000000000010833dbc42130000000000000000000000000000000000000000000000108377a51b1400000000000000000000000000000000000000000000000e83649e3a1500000000000000000000000000000000000000000000000d870beb4f1600000000000000000000000000000000000000000000000b83008d401700000000000000000000000000000000000000000000000b842dc51c1800000000000000000000000000000000000000000000000b8359c5141900000000000000000000000000000000000000000000000b835bbe521a00000000000000000000000000000000000000000000000a8255876b1b000000000000000000000000000000000000000000000007824b97161c000000000000000000000000000000000000000000000007834ca4411d0000000000000000000000000000000000000000000000058673a6301e00000000000000000000000000000000000000000000000287218e731f000000000000000000000000000000000000000000000001835e8d622000000000000000000000000000000000000000000000000000"_hex_u8, {51, 12, 22, 31, 42, 41, 8, 50, 10, 25, 55, 23, 49, 20, 39, 5, 46, 33, 47, 34, 29, 28, 43, 53, 38, 24, 27, 40, 37, 3, 9, 4, 14, 26, 17, 1, 2, 11, 7, 45, 32, 19, 52, 36, 56, 0, 21, 16, 54, 44, 15, 13, 30, 48, 18, 6, 35});
TestOptimalLinearization("805683130081759877018501ac560282608b1e038703b72f048554861d058445a50606856db672078359a70f08864abd4f097e86010a806d82030b82048b470000000000000000000000000c8712ce7e0100000000000000000000000c8470947b0200000000000000000000000c840e9d100300000000000000000000000b84539e0e0400000000000000000000000a8613b00b0500000000000000000000000a8346863906000000000000000000000009863ac27507000000000000000000000006870ebe7f08000000000000000000000005860d842109000000000000000000000005845589030a000000000000000000000002845588460b00000000000000000000000180198b490c000000000000000000000001812b972b0d0000000000000000000000008328a3770e000000000000000000000000872fa0700f00000000000000000000000000"_hex_v_u8, {{3577, 877}, {2923, 769}, {2435, 709}, {783, 480}, {-1399, 8615}, {-337, 909}, {-477, 582}, {-642, 725}, {-1406, 752}, {-804, 388}, {-3142, 915}, {-4096, 1038}, {-2364, 552}, {-4347, 954}, {-1558, 299}, {-805, 153}}); TestOptimalLinearization("805683130081759877018501ac560282608b1e038703b72f048554861d058445a50606856db672078359a70f08864abd4f097e86010a806d82030b82048b470000000000000000000000000c8712ce7e0100000000000000000000000c8470947b0200000000000000000000000c840e9d100300000000000000000000000b84539e0e0400000000000000000000000a8613b00b0500000000000000000000000a8346863906000000000000000000000009863ac27507000000000000000000000006870ebe7f08000000000000000000000005860d842109000000000000000000000005845589030a000000000000000000000002845588460b00000000000000000000000180198b490c000000000000000000000001812b972b0d0000000000000000000000008328a3770e000000000000000000000000872fa0700f00000000000000000000000000"_hex_u8, {17, 8, 14, 10, 12, 24, 3, 11, 21, 19, 18, 5, 1, 4, 6, 27, 22, 16, 9, 20, 2, 0, 7, 15, 26, 13, 25, 23});
TestOptimalLinearization("8327982d0080608f67000085299d2a0100847b8207020082769438030082479f0b0202822a996a01000887298a350100098432a61f010883029b5b04000006870ec96a03048172812b03010008824d916f010102000c833aa8040110801a847f0402000002832c862104000000000a873d9c060202010383208e7803010110815d1101041268870f050001851254010e8124804a020411822c9028060001000e866d8a77030105836ba27e001a8503890804030116857b8f620110850ba7510008188704b103010201001c857cc54f000001000000"_hex_v_u8, {{8000, 4089}, {-935, 11933}, {-3202, 1028}, {-2601, 779}, {-4520, 892}}); TestOptimalLinearization("8327982d0080608f67000085299d2a0100847b8207020082769438030082479f0b0202822a996a01000887298a350100098432a61f010883029b5b04000006870ec96a03048172812b03010008824d916f010102000c833aa8040110801a847f0402000002832c862104000000000a873d9c060202010383208e7803010110815d1101041268870f050001851254010e8124804a020411822c9028060001000e866d8a77030105836ba27e001a8503890804030116857b8f620110850ba7510008188704b103010201001c857cc54f000001000000"_hex_u8, {11, 26, 19, 21, 10, 25, 16, 15, 22, 8, 18, 14, 6, 3, 23, 1, 7, 17, 13, 24, 5, 2, 12, 28, 27, 9, 20, 0, 4, 29});
TestOptimalLinearization("8678e51700857aca3901844ab2170282049f5f038003895f048638b6740405861f7e0208804491420206842e83130301078100901e02010b852bac6104030281759b31030301058533a67d02098275aa0108000000028178865107010001098336942a02050f841d99450305010e8501ba150304010a820b853205040a836eb53c060501057a83340904000004815e846b050416820d852b03090e845ebb310b020100000b8702835d0212815f9044000d09867ea171001e80359138020705178106880e09010000050f864fc97c040504011683109034030b010b824c8737080202000300000e847d8045090202000101000d835587720507030018862c9d00060500050b820587090608030000008461a5000103020003208601ab780106010102000183069130010305058734844f050200010100000004872fdb12050000000102000100078313ab200203020000248404a92503000101000100"_hex_v_u8, {{497, 327}, {-4592, 24583}, {-360, 1076}, {-2707, 644}}); TestOptimalLinearization("8678e51700857aca3901844ab2170282049f5f038003895f048638b6740405861f7e0208804491420206842e83130301078100901e02010b852bac6104030281759b31030301058533a67d02098275aa0108000000028178865107010001098336942a02050f841d99450305010e8501ba150304010a820b853205040a836eb53c060501057a83340904000004815e846b050416820d852b03090e845ebb310b020100000b8702835d0212815f9044000d09867ea171001e80359138020705178106880e09010000050f864fc97c040504011683109034030b010b824c8737080202000300000e847d8045090202000101000d835587720507030018862c9d00060500050b820587090608030000008461a5000103020003208601ab780106010102000183069130010305058734844f050200010100000004872fdb12050000000102000100078313ab200203020000248404a92503000101000100"_hex_u8, {39, 27, 26, 12, 36, 8, 1, 30, 7, 3, 31, 16, 28, 15, 38, 18, 10, 29, 9, 0, 24, 21, 14, 13, 4, 25, 11, 20, 2, 17, 33, 32, 42, 23, 40, 22, 19, 34, 6, 35, 5, 37, 41});
TestOptimalLinearization("87139152008053853701864db30c0280338815038544b2040486788f4f05841e841e06862ea22907823d8f150886706f09837b872e0a830e9f7f0b8465c07b0c831eab0b0d810d825d0e832b81100f8435a76a108602b63811810f897c000000000000000000000000000000000000118445b63d01000000000000000000000000000000000011847fc24c0200000000000000000000000000000000001080558c3f03000000000000000000000000000000000010861fbd0304000000000000000000000000000000000010871fde1805000000000000000000000000000000000010815c93240600000000000000000000000000000000000f8726b74c0700000000000000000000000000000000000e817c823b0800000000000000000000000000000000000e865e8c220900000000000000000000000000000000000c8309833a0a00000000000000000000000000000000000b8000854d0b00000000000000000000000000000000000b83049e620c00000000000000000000000000000000000a82619d510d00000000000000000000000000000000000a870899120e00000000000000000000000000000000000a7d670f00000000000000000000000000000000000a8354a83c1000000000000000000000000000000000000a8159941111000000000000000000000000000000000008821da75e12000000000000000000000000000000000007807c8f6013000000000000000000000000000000000007835d840f140000000000000000000000000000000000038212a00a1500000000000000000000000000000000000383039a0c160000000000000000000000000000000000018605c2501700000000000000000000000000000000000100"_hex_v_u8, {{3548, 898}, {3266, 836}, {2613, 693}, {3334, 973}, {21647, 16912}, {849, 990}, {285, 521}, {-52, 125}, {-328, 605}, {-222, 380}, {-423, 128}, {-1353, 345}, {-864, 213}, {-1961, 481}, {-3970, 927}, {-3551, 709}}); TestOptimalLinearization("87139152008053853701864db30c0280338815038544b2040486788f4f05841e841e06862ea22907823d8f150886706f09837b872e0a830e9f7f0b8465c07b0c831eab0b0d810d825d0e832b81100f8435a76a108602b63811810f897c000000000000000000000000000000000000118445b63d01000000000000000000000000000000000011847fc24c0200000000000000000000000000000000001080558c3f03000000000000000000000000000000000010861fbd0304000000000000000000000000000000000010871fde1805000000000000000000000000000000000010815c93240600000000000000000000000000000000000f8726b74c0700000000000000000000000000000000000e817c823b0800000000000000000000000000000000000e865e8c220900000000000000000000000000000000000c8309833a0a00000000000000000000000000000000000b8000854d0b00000000000000000000000000000000000b83049e620c00000000000000000000000000000000000a82619d510d00000000000000000000000000000000000a870899120e00000000000000000000000000000000000a7d670f00000000000000000000000000000000000a8354a83c1000000000000000000000000000000000000a8159941111000000000000000000000000000000000008821da75e12000000000000000000000000000000000007807c8f6013000000000000000000000000000000000007835d840f140000000000000000000000000000000000038212a00a1500000000000000000000000000000000000383039a0c160000000000000000000000000000000000018605c2501700000000000000000000000000000000000100"_hex_u8, {41, 13, 38, 8, 0, 28, 16, 37, 26, 34, 14, 3, 25, 19, 10, 31, 33, 32, 29, 7, 4, 36, 40, 24, 30, 20, 9, 11, 39, 1, 22, 15, 17, 23, 35, 12, 18, 27, 5, 21, 6, 2});
TestOptimalLinearization("8225830d00801c874a01832393380281088e7c038600d033048639927a0581249631068324b3150782649f4c08816840098527b34b0a802c816c0b850a8f040c866cc57e0d811b90350e801a8d5e0f80308c2710810f917011800b835f00000000000000000000000000000000000012836ebc6d0100000000000000000000000000000000001281659b6c020000000000000000000000000000000000128375980a030000000000000000000000000000000000128746857a040000000000000000000000000000000000128170960d050000000000000000000000000000000000118025825f0600000000000000000000000000000000000d810098330700000000000000000000000000000000000c8572b06c0800000000000000000000000000000000000b852da800090000000000000000000000000000000000098427a87c0a000000000000000000000000000000000009806c83380b0000000000000000000000000000000000098470bd020c000000000000000000000000000000000008852b845c0d000000000000000000000000000000000008825f6d0e0000000000000000000000000000000000078151902b0f00000000000000000000000000000000000382369d1d10000000000000000000000000000000000003835f8a7e11000000000000000000000000000000000003855f864c120000000000000000000000000000000000038640bc4013000000000000000000000000000000000003861fa83e140000000000000000000000000000000000038447ba3e15000000000000000000000000000000000003802c8e54160000000000000000000000000000000000018653d11b170000000000000000000000000000000000018638cb2518000000000000000000000000000000000000866fbb471900000000000000000000000000000000000000"_hex_v_u8, {{943, 154}, {4543, 1004}, {1208, 271}, {2086, 484}, {1022, 264}, {549, 156}, {1308, 547}, {1277, 953}, {1026, 778}, {12943, 11680}, {486, 863}, {366, 811}, {445, 1094}, {-55, 479}, {-240, 165}, {-304, 139}, {-1110, 337}, {-3876, 1007}, {-1479, 368}, {-1935, 438}, {-4883, 952}, {-5262, 979}, {-1626, 256}, {-3959, 622}}); TestOptimalLinearization("8225830d00801c874a01832393380281088e7c038600d033048639927a0581249631068324b3150782649f4c08816840098527b34b0a802c816c0b850a8f040c866cc57e0d811b90350e801a8d5e0f80308c2710810f917011800b835f00000000000000000000000000000000000012836ebc6d0100000000000000000000000000000000001281659b6c020000000000000000000000000000000000128375980a030000000000000000000000000000000000128746857a040000000000000000000000000000000000128170960d050000000000000000000000000000000000118025825f0600000000000000000000000000000000000d810098330700000000000000000000000000000000000c8572b06c0800000000000000000000000000000000000b852da800090000000000000000000000000000000000098427a87c0a000000000000000000000000000000000009806c83380b0000000000000000000000000000000000098470bd020c000000000000000000000000000000000008852b845c0d000000000000000000000000000000000008825f6d0e0000000000000000000000000000000000078151902b0f00000000000000000000000000000000000382369d1d10000000000000000000000000000000000003835f8a7e11000000000000000000000000000000000003855f864c120000000000000000000000000000000000038640bc4013000000000000000000000000000000000003861fa83e140000000000000000000000000000000000038447ba3e15000000000000000000000000000000000003802c8e54160000000000000000000000000000000000018653d11b170000000000000000000000000000000000018638cb2518000000000000000000000000000000000000866fbb471900000000000000000000000000000000000000"_hex_u8, {37, 28, 41, 17, 9, 7, 8, 12, 27, 26, 21, 5, 29, 24, 38, 14, 10, 16, 39, 36, 22, 2, 34, 19, 15, 18, 35, 3, 32, 20, 33, 23, 4, 25, 11, 0, 30, 43, 6, 31, 42, 40, 13, 1});
TestOptimalLinearization("813c865a0080178a6f0183449e0202836ca622038446c40d0485028e6e0405816fa17203026c865604028419c03b000e82148c0f0500098351997a070103861b9f0405020a8542a07b07010002861383700111832e89530111860a830c000c8342b138020b810e97660704000006821ba6330803000008855fc612050401000d8028915e03040308832cb03c0a020000000000048509c97d0605000100118167820f07040200086586710703010000000b85762804080104851dcd4105050217854acb3a0a0301000000000f8514976b04080c83449a100808000009874485630b000102010c85799c750d00020001001b80368d0f07030005098259a0700c00000002010a8056876b050b0000001581328a660e0000000100001b807f800405060600098569850a0307050012860a933506040003000200058463b22f09020004000000000021805188430401020602188052853305010203020204824b9e150c0001000101000000248114842c0501030101030a851d944c0503010300238449a2560a0201000000000000000023844ea548070700000000000f8277ae15020700011981479a7e070500000000000000000d81339c5a070003020000000000000016867395490702000200000100001080278938030302000100007a81150400020001318457b11200010201000002827fb116010000010000002300"_hex_v_u8, {{4709, 1055}, {2513, 620}, {2218, 909}, {6605, 3186}, {6218, 3702}, {703, 1507}, {20, 886}, {-2372, 6067}, {-10262, 12450}}); TestOptimalLinearization("813c865a0080178a6f0183449e0202836ca622038446c40d0485028e6e0405816fa17203026c865604028419c03b000e82148c0f0500098351997a070103861b9f0405020a8542a07b07010002861383700111832e89530111860a830c000c8342b138020b810e97660704000006821ba6330803000008855fc612050401000d8028915e03040308832cb03c0a020000000000048509c97d0605000100118167820f07040200086586710703010000000b85762804080104851dcd4105050217854acb3a0a0301000000000f8514976b04080c83449a100808000009874485630b000102010c85799c750d00020001001b80368d0f07030005098259a0700c00000002010a8056876b050b0000001581328a660e0000000100001b807f800405060600098569850a0307050012860a933506040003000200058463b22f09020004000000000021805188430401020602188052853305010203020204824b9e150c0001000101000000248114842c0501030101030a851d944c0503010300238449a2560a0201000000000000000023844ea548070700000000000f8277ae15020700011981479a7e070500000000000000000d81339c5a070003020000000000000016867395490702000200000100001080278938030302000100007a81150400020001318457b11200010201000002827fb116010000010000002300"_hex_u8, {18, 44, 53, 23, 13, 26, 1, 2, 9, 50, 3, 17, 43, 30, 41, 45, 16, 34, 0, 22, 47, 51, 15, 49, 31, 24, 38, 14, 28, 32, 40, 33, 4, 20, 21, 27, 37, 12, 6, 39, 11, 42, 46, 35, 10, 48, 29, 7, 8, 36, 25, 54, 5, 19, 52});
TestOptimalLinearization("803a8f330086548209018265ac21028521bf2e0104800b844d02018321a05d0006835e933e040003835792230400048047865703068201a07d04068662a16d0308865ad476000e8431bb620200020b8264841503010c8625ba5704000209837d9d52021686378e68020e837b8174020e840e80590301060383329a4007020100118262885c0305010a834d8d2a02128133964d0600040d8437ac2a0503040005816b810705020419840cb2440d00000100000b865ad07005030003118419ae21060201030586748076060005000c80068a0e050103030006870dc31208020000020010863bc91f060100020301000a80218b4f0400020d817c8e6f080100020201000880108c4f010d1b834db0320607000017841ca15c0500040000020478853200020100000000001300"_hex_v_u8, {{3922, 1781}, {3529, 2772}, {16566, 14073}, {579, 1338}, {-1016, 380}, {-7368, 1740}, {-808, 161}, {-872, 144}}); TestOptimalLinearization("803a8f330086548209018265ac21028521bf2e0104800b844d02018321a05d0006835e933e040003835792230400048047865703068201a07d04068662a16d0308865ad476000e8431bb620200020b8264841503010c8625ba5704000209837d9d52021686378e68020e837b8174020e840e80590301060383329a4007020100118262885c0305010a834d8d2a02128133964d0600040d8437ac2a0503040005816b810705020419840cb2440d00000100000b865ad07005030003118419ae21060201030586748076060005000c80068a0e050103030006870dc31208020000020010863bc91f060100020301000a80218b4f0400020d817c8e6f080100020201000880108c4f010d1b834db0320607000017841ca15c0500040000020478853200020100000000001300"_hex_u8, {35, 2, 4, 6, 26, 10, 37, 23, 5, 27, 8, 0, 14, 25, 34, 22, 36, 19, 30, 13, 29, 3, 9, 17, 16, 21, 11, 20, 12, 1, 15, 33, 28, 32, 24, 18, 31, 7});
TestOptimalLinearization("83049f4a0083539553018011896b02843fae55000583309e310201841ba76701028628b504010204850ea4570009820c846d030000078451a60303010006802c8877030203857a9e280304805e857005010c83798c7001050c8441811d0403018550bd5f0305008636c9210701000e846d9e1d010311821d933c06020006847e961a0503000a7a8945060200148610bf4d0115842fa97b0402040476841c010716872d28040201058631a10a0104001a81579d3a060001000100001681078c43020401011b8438844406000001000000000f83678264070000000000000c820c8800040101010017814c9103030300000011840c912200000000001200"_hex_v_u8, {{2085, 516}, {-1, 2091}, {-214, 2450}, {-2803, 3167}, {-16800, 11295}}); TestOptimalLinearization("83049f4a0083539553018011896b02843fae55000583309e310201841ba76701028628b504010204850ea4570009820c846d030000078451a60303010006802c8877030203857a9e280304805e857005010c83798c7001050c8441811d0403018550bd5f0305008636c9210701000e846d9e1d010311821d933c06020006847e961a0503000a7a8945060200148610bf4d0115842fa97b0402040476841c010716872d28040201058631a10a0104001a81579d3a060001000100001681078c43020401011b8438844406000001000000000f83678264070000000000000c820c8800040101010017814c9103030300000011840c912200000000001200"_hex_u8, {18, 22, 26, 21, 12, 28, 25, 6, 9, 2, 11, 31, 24, 19, 17, 30, 23, 13, 4, 32, 10, 27, 8, 5, 3, 7, 29, 0, 1, 16, 20, 15, 14});
TestOptimalLinearization("8600ce6f00678071018613875102865ed14301000384579a0c010103854cbe730201028376900f03010278810703068355833202058354ab7e03000b844b9a370402098269a4780303068300a66e020001010c8519a4670300020a84319c090600000007698027030204872ac12f05010100000782369e5106010000000f82549d5006000100000f845b9a7b0601010c8536a42e0601000b8325b33a0503010006826498040400050d80488e5702158206906e0702020b6b86170b000100088745ad1703108406aa3b03090e823b9117010b01821394500107148626c44e0b00000001000f82019f2a0103030001128153900a040401000000000d866bde1c03060000000d80548e180503020001068455a7100604010000001e867fd30e0a00020000000000058505891f060101000000000004840b9d3a0303010000000000268631bc12050100020000000500"_hex_v_u8, {{9901, 20654}, {1369, 3124}, {-656, 773}}); TestOptimalLinearization("8600ce6f00678071018613875102865ed14301000384579a0c010103854cbe730201028376900f03010278810703068355833202058354ab7e03000b844b9a370402098269a4780303068300a66e020001010c8519a4670300020a84319c090600000007698027030204872ac12f05010100000782369e5106010000000f82549d5006000100000f845b9a7b0601010c8536a42e0601000b8325b33a0503010006826498040400050d80488e5702158206906e0702020b6b86170b000100088745ad1703108406aa3b03090e823b9117010b01821394500107148626c44e0b00000001000f82019f2a0103030001128153900a040401000000000d866bde1c03060000000d80548e180503020001068455a7100604010000001e867fd30e0a00020000000000058505891f060101000000000004840b9d3a0303010000000000268631bc12050100020000000500"_hex_u8, {39, 37, 26, 10, 31, 29, 2, 33, 1, 5, 8, 13, 22, 4, 36, 28, 9, 20, 7, 14, 24, 19, 25, 3, 32, 18, 11, 12, 17, 16, 23, 15, 34, 21, 27, 38, 30, 6, 0, 35});
TestOptimalLinearization("851a8e58008454b44d01841a8c2902856eb42e0380314404841bbf4b0582368b3a068067897407823ca94d088420823a098555be160a823a87700b835086700c8350845e0d8747984d0e8137870c0f810f8006108417ab0911842fae6c1280358071138571c674148734d83f158327aa76168228892a178706d45018821e97001983479b591a826ca46b1b856daf59000000000000000000000000000000000000000000000000000000001b8428b309010000000000000000000000000000000000000000000000000000001a826f9021020000000000000000000000000000000000000000000000000000001a86729e61030000000000000000000000000000000000000000000000000000001a8643880604000000000000000000000000000000000000000000000000000000158646cc0e0500000000000000000000000000000000000000000000000000000012846e935e06000000000000000000000000000000000000000000000000000000128551884f0700000000000000000000000000000000000000000000000000000012811e9836080000000000000000000000000000000000000000000000000000000f82308c66090000000000000000000000000000000000000000000000000000000d865ea4640a0000000000000000000000000000000000000000000000000000000884269c770b00000000000000000000000000000000000000000000000000000008831d80570c000000000000000000000000000000000000000000000000000000068531b4620d00000000000000000000000000000000000000000000000000000005865e92390e00000000000000000000000000000000000000000000000000000004855f892d0f00000000000000000000000000000000000000000000000000000003863c8b0110000000000000000000000000000000000000000000000000000000038374aa22110000000000000000000000000000000000000000000000000000000381078e2712000000000000000000000000000000000000000000000000000000038153932c13000000000000000000000000000000000000000000000000000000018321ad5814000000000000000000000000000000000000000000000000000000018318ba1b15000000000000000000000000000000000000000000000000000000018469a57516000000000000000000000000000000000000000000000000000000018310854e17000000000000000000000000000000000000000000000000000000018543a57e180000000000000000000000000000000000000000000000000000000000"_hex_v_u8, {{5480, 1030}, {4602, 881}, {2811, 551}, {4043, 853}, {3062, 687}, {3415, 878}, {1536, 414}, {698, 231}, {797, 438}, {518, 311}, {661, 424}, {568, 442}, {1004, 794}, {504, 592}, {367, 592}, {221, 672}, {67, 271}, {34, 177}, {-526, 14670}, {-108, 541}, {-616, 849}, {-663, 863}, {-769, 956}, {-1245, 990}, {-2033, 1010}, {-1105, 495}, {-1916, 678}, {-2491, 745}, {-3117, 877}, {-980, 263}, {-3333, 680}, {-3790, 536}}); TestOptimalLinearization("851a8e58008454b44d01841a8c2902856eb42e0380314404841bbf4b0582368b3a068067897407823ca94d088420823a098555be160a823a87700b835086700c8350845e0d8747984d0e8137870c0f810f8006108417ab0911842fae6c1280358071138571c674148734d83f158327aa76168228892a178706d45018821e97001983479b591a826ca46b1b856daf59000000000000000000000000000000000000000000000000000000001b8428b309010000000000000000000000000000000000000000000000000000001a826f9021020000000000000000000000000000000000000000000000000000001a86729e61030000000000000000000000000000000000000000000000000000001a8643880604000000000000000000000000000000000000000000000000000000158646cc0e0500000000000000000000000000000000000000000000000000000012846e935e06000000000000000000000000000000000000000000000000000000128551884f0700000000000000000000000000000000000000000000000000000012811e9836080000000000000000000000000000000000000000000000000000000f82308c66090000000000000000000000000000000000000000000000000000000d865ea4640a0000000000000000000000000000000000000000000000000000000884269c770b00000000000000000000000000000000000000000000000000000008831d80570c000000000000000000000000000000000000000000000000000000068531b4620d00000000000000000000000000000000000000000000000000000005865e92390e00000000000000000000000000000000000000000000000000000004855f892d0f00000000000000000000000000000000000000000000000000000003863c8b0110000000000000000000000000000000000000000000000000000000038374aa22110000000000000000000000000000000000000000000000000000000381078e2712000000000000000000000000000000000000000000000000000000038153932c13000000000000000000000000000000000000000000000000000000018321ad5814000000000000000000000000000000000000000000000000000000018318ba1b15000000000000000000000000000000000000000000000000000000018469a57516000000000000000000000000000000000000000000000000000000018310854e17000000000000000000000000000000000000000000000000000000018543a57e180000000000000000000000000000000000000000000000000000000000"_hex_u8, {39, 32, 35, 18, 28, 7, 44, 12, 10, 25, 37, 19, 0, 20, 22, 14, 26, 8, 29, 6, 23, 45, 27, 2, 51, 33, 13, 9, 21, 47, 15, 42, 36, 46, 52, 30, 24, 16, 50, 11, 34, 17, 40, 41, 38, 5, 4, 31, 49, 1, 43, 3, 48});
TestOptimalLinearization("82549265008464d27c01866ab47902837da12a0380368f74048738dc4d05842e8b3b06853dc84a078661ab22088454a16b09865f957f0a8279ab2b0b837b84050c837dc31a0d837db5180e7b816f0f8346ac4310800b883d1180148709128349a63c1380629800148638ae3f15802c8b59168223ae4117801d8e1718812f893319853bdc3b1a841caa5b1b8354aa55000000000000000000000000000000000000000000000000000000001c870abd4d010000000000000000000000000000000000000000000000000000001b85768103020000000000000000000000000000000000000000000000000000001a801c8861030000000000000000000000000000000000000000000000000000001980658e150400000000000000000000000000000000000000000000000000000019826da47005000000000000000000000000000000000000000000000000000000198100884506000000000000000000000000000000000000000000000000000000188528d056070000000000000000000000000000000000000000000000000000001880718a5d08000000000000000000000000000000000000000000000000000000178677ba060900000000000000000000000000000000000000000000000000000017815889110a00000000000000000000000000000000000000000000000000000016813187200b00000000000000000000000000000000000000000000000000000015804a800a0c00000000000000000000000000000000000000000000000000000015847a81550d0000000000000000000000000000000000000000000000000000001486799e420e00000000000000000000000000000000000000000000000000000013835cb8120f00000000000000000000000000000000000000000000000000000012865ff84910000000000000000000000000000000000000000000000000000000118403ac6111000000000000000000000000000000000000000000000000000000108656db361200000000000000000000000000000000000000000000000000000010815da06013000000000000000000000000000000000000000000000000000000108740f30c1400000000000000000000000000000000000000000000000000000010843ad1361500000000000000000000000000000000000000000000000000000010806a92421600000000000000000000000000000000000000000000000000000010874acc3017000000000000000000000000000000000000000000000000000000108001897218000000000000000000000000000000000000000000000000000000108213a100190000000000000000000000000000000000000000000000000000001085159f141a0000000000000000000000000000000000000000000000000000000e806288681b0000000000000000000000000000000000000000000000000000000c842d86401c0000000000000000000000000000000000000000000000000000000b860bb3081d00000000000000000000000000000000000000000000000000000008814ca17f1e0000000000000000000000000000000000000000000000000000000680418c4e1f00000000000000000000000000000000000000000000000000000006820e98212000000000000000000000000000000000000000000000000000000006856db851210000000000000000000000000000000000000000000000000000000300"_hex_v_u8, {{5374, 740}, {1600, 226}, {4365, 637}, {1082, 182}, {4709, 829}, {3468, 637}, {2526, 585}, {2197, 637}, {2833, 993}, {14949, 22604}, {69, 202}, {-130, 886}, {-171, 762}, {-649, 344}, {-611, 256}, {-751, 241}, {-4007, 1034}, {-625, 156}, {-1617, 398}, {-3689, 877}, {-971, 229}, {-2929, 643}, {-2795, 596}, {-2240, 332}, {-7781, 991}}); TestOptimalLinearization("82549265008464d27c01866ab47902837da12a0380368f74048738dc4d05842e8b3b06853dc84a078661ab22088454a16b09865f957f0a8279ab2b0b837b84050c837dc31a0d837db5180e7b816f0f8346ac4310800b883d1180148709128349a63c1380629800148638ae3f15802c8b59168223ae4117801d8e1718812f893319853bdc3b1a841caa5b1b8354aa55000000000000000000000000000000000000000000000000000000001c870abd4d010000000000000000000000000000000000000000000000000000001b85768103020000000000000000000000000000000000000000000000000000001a801c8861030000000000000000000000000000000000000000000000000000001980658e150400000000000000000000000000000000000000000000000000000019826da47005000000000000000000000000000000000000000000000000000000198100884506000000000000000000000000000000000000000000000000000000188528d056070000000000000000000000000000000000000000000000000000001880718a5d08000000000000000000000000000000000000000000000000000000178677ba060900000000000000000000000000000000000000000000000000000017815889110a00000000000000000000000000000000000000000000000000000016813187200b00000000000000000000000000000000000000000000000000000015804a800a0c00000000000000000000000000000000000000000000000000000015847a81550d0000000000000000000000000000000000000000000000000000001486799e420e00000000000000000000000000000000000000000000000000000013835cb8120f00000000000000000000000000000000000000000000000000000012865ff84910000000000000000000000000000000000000000000000000000000118403ac6111000000000000000000000000000000000000000000000000000000108656db361200000000000000000000000000000000000000000000000000000010815da06013000000000000000000000000000000000000000000000000000000108740f30c1400000000000000000000000000000000000000000000000000000010843ad1361500000000000000000000000000000000000000000000000000000010806a92421600000000000000000000000000000000000000000000000000000010874acc3017000000000000000000000000000000000000000000000000000000108001897218000000000000000000000000000000000000000000000000000000108213a100190000000000000000000000000000000000000000000000000000001085159f141a0000000000000000000000000000000000000000000000000000000e806288681b0000000000000000000000000000000000000000000000000000000c842d86401c0000000000000000000000000000000000000000000000000000000b860bb3081d00000000000000000000000000000000000000000000000000000008814ca17f1e0000000000000000000000000000000000000000000000000000000680418c4e1f00000000000000000000000000000000000000000000000000000006820e98212000000000000000000000000000000000000000000000000000000006856db851210000000000000000000000000000000000000000000000000000000300"_hex_u8, {3, 50, 39, 12, 20, 41, 48, 9, 22, 38, 17, 26, 42, 59, 1, 24, 51, 5, 47, 61, 46, 55, 44, 15, 28, 57, 60, 56, 33, 32, 11, 31, 25, 30, 36, 37, 34, 8, 53, 35, 14, 49, 43, 40, 23, 18, 45, 19, 4, 21, 16, 10, 13, 2, 6, 54, 58, 7, 29, 0, 52, 27});
TestOptimalLinearization("863e9b20008701a22e0182579614010281579c03010381008737030180078e2603028345911504028417a101030981318d650508867b9a11070006823c924f0105058647a60b050101058579a75b07010001861bdf4c060001010c834e841d0700010106855dca03070102008633dc7f03060d8654bf39090000020c854bc4370802000103846aac180c000100018058811e03138727b30b0a0200010a845a902206050104804191120703010108844cc60f030b00188530b810090000030d8434be3403070d833fad1b00298038953206051d801a520606000f8216a05a030b218007891e020911815b9716030b0b867ab553050709802391740f030000010007817896370d010003000200168041880803080518816ea42a050902040e872d8a09080200050302000e8576960e050b010400098330bb6e0c06020200098418ad6a1002000300000000148704c07008020405030011851f8657060d040e8619be7016000101000000088559d32c0213078307891a08040a00011e8313b627010c0104001e853ad64004070300051b815d834205030c038423aa3904040701030001128155a3390f000000000500308262a43b0a000107010b8136861d0505000701010f82359b1307010005000401001e8028841605000603010200002981679d16030705000300298710cd6c080601010000000101308055803e0802040100010002001681758e2a090400010100000100258741ac0d0a00030001030000000680738e2c06020500000001001783629a68020703000001098707dd08000001030000001000"_hex_v_u8, {{3242, 1160}, {9343, 4022}, {7247, 25626}, {-574, 1753}, {-2604, 5019}, {-2887, 1089}}); TestOptimalLinearization("863e9b20008701a22e0182579614010281579c03010381008737030180078e2603028345911504028417a101030981318d650508867b9a11070006823c924f0105058647a60b050101058579a75b07010001861bdf4c060001010c834e841d0700010106855dca03070102008633dc7f03060d8654bf39090000020c854bc4370802000103846aac180c000100018058811e03138727b30b0a0200010a845a902206050104804191120703010108844cc60f030b00188530b810090000030d8434be3403070d833fad1b00298038953206051d801a520606000f8216a05a030b218007891e020911815b9716030b0b867ab553050709802391740f030000010007817896370d010003000200168041880803080518816ea42a050902040e872d8a09080200050302000e8576960e050b010400098330bb6e0c06020200098418ad6a1002000300000000148704c07008020405030011851f8657060d040e8619be7016000101000000088559d32c0213078307891a08040a00011e8313b627010c0104001e853ad64004070300051b815d834205030c038423aa3904040701030001128155a3390f000000000500308262a43b0a000107010b8136861d0505000701010f82359b1307010005000401001e8028841605000603010200002981679d16030705000300298710cd6c080601010000000101308055803e0802040100010002001681758e2a090400010100000100258741ac0d0a00030001030000000680738e2c06020500000001001783629a68020703000001098707dd08000001030000001000"_hex_u8, {58, 32, 26, 8, 42, 13, 5, 60, 21, 12, 31, 18, 53, 6, 14, 23, 2, 11, 55, 52, 17, 63, 7, 44, 36, 33, 27, 49, 59, 43, 1, 19, 39, 41, 35, 4, 48, 29, 62, 34, 56, 46, 10, 9, 20, 61, 25, 50, 15, 37, 0, 30, 22, 40, 28, 51, 16, 24, 45, 3, 38, 54, 47, 57});
TestOptimalLinearization("83638b0300845bac6801871ac51d028278937a036a5004855494040405814883580405872dd30f030203816f9009030301856bb80f0501000684008658030406805380100400068632a8520500010b80658e2f0403010580068a340702000002845cae500802000000806b8c350400040584319f5a0900000000086f827c09000100000184627b06000004038341844d0603000000001181208d070502000102048043760600000200000010862fad260603000000000a817786690402000003000e84059e410305020004861eb63a0401020001138016862600080486419756020500010008833ca46f04040000001182019658020000000200000800"_hex_v_u8, {{2932, 731}, {1341, 504}, {3541, 2737}, {492, 640}, {40, 106}, {72, 211}, {-779, 2654}, {-2914, 8443}, {-359, 577}, {-2424, 572}}); TestOptimalLinearization("83638b0300845bac6801871ac51d028278937a036a5004855494040405814883580405872dd30f030203816f9009030301856bb80f0501000684008658030406805380100400068632a8520500010b80658e2f0403010580068a340702000002845cae500802000000806b8c350400040584319f5a0900000000086f827c09000100000184627b06000004038341844d0603000000001181208d070502000102048043760600000200000010862fad260603000000000a817786690402000003000e84059e410305020004861eb63a0401020001138016862600080486419756020500010008833ca46f04040000001182019658020000000200000800"_hex_u8, {9, 18, 4, 1, 0, 2, 7, 28, 17, 15, 20, 30, 27, 23, 19, 5, 24, 8, 13, 10, 16, 26, 14, 29, 6, 11, 25, 22, 21, 3, 12});
TestOptimalLinearization("8015812700866ade5401811c8f7b028442ac3003866fc73d00058220984901048676c4440204813194740500057b8b1b060005845fa71e050106837bb34d060003853abd55070001008519ab1102030e824f94580602000a8405b15c0403020b806a8b78040303088724be690603020380708230080003000d851f9b5d05050000008674dc540401050011864f9652060200020110841c8a61090001000101832c8819060303000005814b9c160601010400068109885a06050002018304b203050001061686419e69020b00128638c97d0a010100000000000018856dc2060302080000028419b54c0307030781568573090300000000000000028428a7150702000100001d864db25f020207000a85409403000700000018822f920c0300010201001483409a1a0501000100000013856ac8200400010000010011803e8f620500000000000019836692540302000000208548895a00000000000c867ecc2801000000000a00"_hex_v_u8, {{6122, 1002}, {7354, 1720}, {2575, 735}, {1254, 454}, {1609, 1061}, {302, 747}, {-6224, 20869}}); TestOptimalLinearization("8015812700866ade5401811c8f7b028442ac3003866fc73d00058220984901048676c4440204813194740500057b8b1b060005845fa71e050106837bb34d060003853abd55070001008519ab1102030e824f94580602000a8405b15c0403020b806a8b78040303088724be690603020380708230080003000d851f9b5d05050000008674dc540401050011864f9652060200020110841c8a61090001000101832c8819060303000005814b9c160601010400068109885a06050002018304b203050001061686419e69020b00128638c97d0a010100000000000018856dc2060302080000028419b54c0307030781568573090300000000000000028428a7150702000100001d864db25f020207000a85409403000700000018822f920c0300010201001483409a1a0501000100000013856ac8200400010000010011803e8f620500000000000019836692540302000000208548895a00000000000c867ecc2801000000000a00"_hex_u8, {7, 34, 25, 20, 0, 14, 24, 9, 23, 15, 1, 26, 22, 3, 31, 12, 36, 35, 33, 19, 8, 28, 5, 32, 17, 11, 40, 39, 37, 38, 29, 10, 2, 4, 13, 21, 18, 16, 6, 30, 27});
TestOptimalLinearization("8677a44400823d9b1101847c893e0102831ea2130201865b944502028560ac640301856cc01101088644cc2c0302867ea77d0008843d8949040202843a9d0307000081528f5707000005804e8c5b0403000585169c7e06000201834e8e0d0503000d835e96250500000f8628a9550104078018847d0302000201821f90780301000002000681648442030103028433976b070000000000000e844a9116040202000d82349016000880158b240600010100108006831101060001850bb04e0101010100088723835a010002010c830593360203000003811a8e150400000000001c7f8168010000001300"_hex_v_u8, {{2402, 1015}, {2700, 1506}, {671, 764}, {1129, 1309}, {-7302, 12461}, {-1410, 818}, {-971, 282}}); TestOptimalLinearization("8677a44400823d9b1101847c893e0102831ea2130201865b944502028560ac640301856cc01101088644cc2c0302867ea77d0008843d8949040202843a9d0307000081528f5707000005804e8c5b0403000585169c7e06000201834e8e0d0503000d835e96250500000f8628a9550104078018847d0302000201821f90780301000002000681648442030103028433976b070000000000000e844a9116040202000d82349016000880158b240600010100108006831101060001850bb04e0101010100088723835a010002010c830593360203000003811a8e150400000000001c7f8168010000001300"_hex_u8, {5, 6, 22, 1, 15, 21, 9, 19, 12, 2, 27, 17, 13, 14, 18, 4, 23, 11, 29, 28, 3, 8, 24, 16, 25, 20, 26, 7, 10, 0});
TestOptimalLinearization("8744ad0c008552be55018377a07f02844ec32802038655a103020482109b72020006867ee92c030006847fb879040003867cc5770301098620c77d06000001834e9c6b050102831ea745070000048736e7040309854bb64e04000a82129d600303068327847c03060c81749e6a0604000c8616af13070400008062915d08010200078007880206030301823e815106000609862ab9220502178451b018080000010c82469e2a0803000001058579c33c090000020116852f8b210704000001068168a05d04070001148616c21d0801020001000e8327991f05000f8025860a0b000002010003862f8a250c00010100000b8002480a00010002000b801f877005000600011e8539be10010b011c8341b558060302000001001a83758b0c09030000000000038738d71b070500000000010000088527c943070005000001001d81789e5204060300001c850eb12a0b03000100000000058676d84b0602010103000b834aaa310202020001000100001c8425af0c0302020001000100000d8107942e02010201000200001c830f9f330000000002000012830ea4700200000000000000000d00"_hex_v_u8, {{7322, 1810}, {2404, 2903}, {8842, 11211}, {4511, 6807}, {764, 2139}, {-1680, 551}, {-4367, 1277}, {-10769, 2999}, {-2074, 527}}); TestOptimalLinearization("8744ad0c008552be55018377a07f02844ec32802038655a103020482109b72020006867ee92c030006847fb879040003867cc5770301098620c77d06000001834e9c6b050102831ea745070000048736e7040309854bb64e04000a82129d600303068327847c03060c81749e6a0604000c8616af13070400008062915d08010200078007880206030301823e815106000609862ab9220502178451b018080000010c82469e2a0803000001058579c33c090000020116852f8b210704000001068168a05d04070001148616c21d0801020001000e8327991f05000f8025860a0b000002010003862f8a250c00010100000b8002480a00010002000b801f877005000600011e8539be10010b011c8341b558060302000001001a83758b0c09030000000000038738d71b070500000000010000088527c943070005000001001d81789e5204060300001c850eb12a0b03000100000000058676d84b0602010103000b834aaa310202020001000100001c8425af0c0302020001000100000d8107942e02010201000200001c830f9f330000000002000012830ea4700200000000000000000d00"_hex_u8, {17, 14, 41, 27, 4, 1, 16, 39, 29, 0, 25, 20, 7, 5, 18, 44, 19, 2, 38, 10, 33, 22, 23, 45, 42, 30, 6, 37, 24, 11, 43, 21, 9, 40, 28, 12, 31, 3, 34, 35, 15, 13, 36, 8, 32, 26});
TestOptimalLinearization("82159935008379b66e01830bae7202803d87690203826ea53b0302821a993303038408b52a0502864de64005028326bc7b050106827a9b050508842ace1c010f836f966204020865810a080106816ba5640703018270844306010301851f8e69050201000d8500866c0505000b8357ac7d040500098542881e040109822f8451050303048257985708010400028555bd29020e8116875e0603010211865c9f0906010408846db41b0206050786259654050503000011855ac662080300010100068655c91b020910830bb7540d0000020000000d8563da4d0e0000010000001481148d1f0e010000010012831193360a000004010a860ece440807000100068402b614060404020e8712da6e06080001028377997c070401040000018224a23c040800041e805f976e0c0201000200018655e22305060501088656a83c0801000401011e8248a140010a02002385633903010703011c80528207080302000200002780038e130c01000300000000268421330701020103010b800682590a0102020000001f863ca66005050202012b831fb146070300000202000024834c9f5d060003000100010d840dc01a040201010319857a8a2606010101000001000009824f814701040301136e876d05000202010000000c871cad4d0107002c803d884203000402008446cd4e0000010000000d00"_hex_v_u8, {{10199, 1606}, {3065, 523}, {1786, 1053}, {1089, 913}, {792, 773}, {1104, 1232}, {13868, 19409}, {-4512, 8170}, {-567, 110}}); TestOptimalLinearization("82159935008379b66e01830bae7202803d87690203826ea53b0302821a993303038408b52a0502864de64005028326bc7b050106827a9b050508842ace1c010f836f966204020865810a080106816ba5640703018270844306010301851f8e69050201000d8500866c0505000b8357ac7d040500098542881e040109822f8451050303048257985708010400028555bd29020e8116875e0603010211865c9f0906010408846db41b0206050786259654050503000011855ac662080300010100068655c91b020910830bb7540d0000020000000d8563da4d0e0000010000001481148d1f0e010000010012831193360a000004010a860ece440807000100068402b614060404020e8712da6e06080001028377997c070401040000018224a23c040800041e805f976e0c0201000200018655e22305060501088656a83c0801000401011e8248a140010a02002385633903010703011c80528207080302000200002780038e130c01000300000000268421330701020103010b800682590a0102020000001f863ca66005050202012b831fb146070300000202000024834c9f5d060003000100010d840dc01a040201010319857a8a2606010101000001000009824f814701040301136e876d05000202010000000c871cad4d0107002c803d884203000402008446cd4e0000010000000d00"_hex_u8, {31, 32, 54, 2, 29, 0, 20, 21, 26, 47, 7, 1, 37, 13, 51, 34, 14, 49, 48, 36, 27, 24, 23, 53, 28, 43, 44, 30, 52, 39, 35, 16, 19, 5, 50, 8, 11, 22, 15, 40, 25, 46, 10, 18, 12, 3, 4, 17, 38, 6, 45, 55, 33, 9, 42, 41});
TestOptimalLinearization("8673c728008004810c01805e967802866fb254038536a93f048712a43d0584498d14068610c30a07822dac46088401a72f09860082450a8279a0490b6a853e0c817c991e0d815795060e8349c2490f7e8972108438b610118616b67f12807485361382058940148739c34615847ea91016805f8421178662d04718805b835019852b97491a857aaf401b832090231c810991491d802184130000000000000000000000000000000000000000000000000000000000001e855fb371010000000000000000000000000000000000000000000000000000000000198563b31d0200000000000000000000000000000000000000000000000000000000001980178c10030000000000000000000000000000000000000000000000000000000000198201867404000000000000000000000000000000000000000000000000000000000018873b86670500000000000000000000000000000000000000000000000000000000001382279e3e060000000000000000000000000000000000000000000000000000000000118442ae4d070000000000000000000000000000000000000000000000000000000000118707c3000800000000000000000000000000000000000000000000000000000000000f8533b9360900000000000000000000000000000000000000000000000000000000000e833d94160a00000000000000000000000000000000000000000000000000000000000e843381770b00000000000000000000000000000000000000000000000000000000000e811590520c00000000000000000000000000000000000000000000000000000000000d8729993f0d00000000000000000000000000000000000000000000000000000000000c82149f050e00000000000000000000000000000000000000000000000000000000000c8648c6740f00000000000000000000000000000000000000000000000000000000000c832fa20e1000000000000000000000000000000000000000000000000000000000000b860e862711000000000000000000000000000000000000000000000000000000000009842f923212000000000000000000000000000000000000000000000000000000000009815c967613000000000000000000000000000000000000000000000000000000000008824aad4714000000000000000000000000000000000000000000000000000000000008854c844715000000000000000000000000000000000000000000000000000000000008851da76b1600000000000000000000000000000000000000000000000000000000000781449e7517000000000000000000000000000000000000000000000000000000000002832e8d051800000000000000000000000000000000000000000000000000000000000000"_hex_v_u8, {{1532, 222}, {2915, 429}, {697, 126}, {3528, 696}, {4357, 912}, {4628, 1011}, {1679, 380}, {1411, 343}, {4387, 1081}, {415, 106}, {2696, 766}, {3104, 890}, {3306, 1007}, {672, 389}, {411, 244}, {296, 219}, {906, 713}, {134, 132}, {-227, 896}, {-3629, 13571}, {-188, 691}, {-356, 844}, {-500, 1083}, {-468, 910}, {-1696, 1065}, {-899, 558}, {-330, 161}, {-2614, 797}, {-3343, 867}, {-3385, 863}, {-3047, 706}, {-2051, 404}, {-2043, 324}, {-2980, 458}}); TestOptimalLinearization("8673c728008004810c01805e967802866fb254038536a93f048712a43d0584498d14068610c30a07822dac46088401a72f09860082450a8279a0490b6a853e0c817c991e0d815795060e8349c2490f7e8972108438b610118616b67f12807485361382058940148739c34615847ea91016805f8421178662d04718805b835019852b97491a857aaf401b832090231c810991491d802184130000000000000000000000000000000000000000000000000000000000001e855fb371010000000000000000000000000000000000000000000000000000000000198563b31d0200000000000000000000000000000000000000000000000000000000001980178c10030000000000000000000000000000000000000000000000000000000000198201867404000000000000000000000000000000000000000000000000000000000018873b86670500000000000000000000000000000000000000000000000000000000001382279e3e060000000000000000000000000000000000000000000000000000000000118442ae4d070000000000000000000000000000000000000000000000000000000000118707c3000800000000000000000000000000000000000000000000000000000000000f8533b9360900000000000000000000000000000000000000000000000000000000000e833d94160a00000000000000000000000000000000000000000000000000000000000e843381770b00000000000000000000000000000000000000000000000000000000000e811590520c00000000000000000000000000000000000000000000000000000000000d8729993f0d00000000000000000000000000000000000000000000000000000000000c82149f050e00000000000000000000000000000000000000000000000000000000000c8648c6740f00000000000000000000000000000000000000000000000000000000000c832fa20e1000000000000000000000000000000000000000000000000000000000000b860e862711000000000000000000000000000000000000000000000000000000000009842f923212000000000000000000000000000000000000000000000000000000000009815c967613000000000000000000000000000000000000000000000000000000000008824aad4714000000000000000000000000000000000000000000000000000000000008854c844715000000000000000000000000000000000000000000000000000000000008851da76b1600000000000000000000000000000000000000000000000000000000000781449e7517000000000000000000000000000000000000000000000000000000000002832e8d051800000000000000000000000000000000000000000000000000000000000000"_hex_u8, {3, 13, 28, 30, 12, 1, 21, 22, 40, 18, 44, 50, 4, 37, 36, 48, 11, 2, 15, 46, 49, 52, 9, 5, 34, 14, 17, 53, 47, 24, 8, 19, 33, 25, 41, 23, 29, 35, 26, 39, 10, 27, 43, 16, 38, 31, 54, 0, 45, 7, 6, 20, 32, 51, 42});
TestOptimalLinearization("8063850a0084718e1f018627d96c028369c06503842ec7070480158a0505853fbf200683719c3e07806f906a088611df4e09816fa0570a863e94760b800485030c8307b4590d8642e7400e8459bf1d0f803461108259aa03118671ad171280708651138257907e14821986091582203b168527c013178315aa081880558e67198664c5511a872afc330000000000000000000000000000000000000000000000000000001b863b8d480100000000000000000000000000000000000000000000000000001b847f81610200000000000000000000000000000000000000000000000000001b8526852d03000000000000000000000000000000000000000000000000000018857d901b0400000000000000000000000000000000000000000000000000001884238e240500000000000000000000000000000000000000000000000000001885049c610600000000000000000000000000000000000000000000000000001880401a070000000000000000000000000000000000000000000000000000168349a2100800000000000000000000000000000000000000000000000000001581539c5f09000000000000000000000000000000000000000000000000000015810f96030a0000000000000000000000000000000000000000000000000000148406b8190b0000000000000000000000000000000000000000000000000000138005801a0c000000000000000000000000000000000000000000000000000013863c99570d000000000000000000000000000000000000000000000000000013842ea1130e000000000000000000000000000000000000000000000000000012810b8a5e0f000000000000000000000000000000000000000000000000000011861c8474100000000000000000000000000000000000000000000000000000118117903911000000000000000000000000000000000000000000000000000010850b981d12000000000000000000000000000000000000000000000000000010822d9d73130000000000000000000000000000000000000000000000000000108655c73614000000000000000000000000000000000000000000000000000010862baf0c15000000000000000000000000000000000000000000000000000010758c001600000000000000000000000000000000000000000000000000000f80739a7f1700000000000000000000000000000000000000000000000000000f8070856b1800000000000000000000000000000000000000000000000000000f837c8d4e1900000000000000000000000000000000000000000000000000000e806888691a00000000000000000000000000000000000000000000000000000b8570de661b0000000000000000000000000000000000000000000000000000098332bb0b1c0000000000000000000000000000000000000000000000000000098240ae6b1d000000000000000000000000000000000000000000000000000008861599711e000000000000000000000000000000000000000000000000000006821da71e1f0000000000000000000000000000000000000000000000000000038334af692000000000000000000000000000000000000000000000000000000200"_hex_v_u8, {{6688, 962}, {6183, 913}, {5814, 935}, {2756, 533}, {4112, 831}, {1141, 239}, {1887, 625}, {1151, 471}, {389, 227}, {1403, 958}, {-30, 416}, {-49, 180}, {-13972, 17369}, {-1102, 893}, {-1708, 956}, {-438, 240}, {-1721, 917}, {-1615, 779}, {-1905, 772}, {-629, 232}, {-2186, 686}, {-1117, 279}, {-1978, 429}, {-1474, 271}, {-3125, 564}, {-1904, 339}, {-3661, 646}, {-3062, 448}, {-3846, 562}, {-1792, 243}, {-8026, 1066}}); TestOptimalLinearization("8063850a0084718e1f018627d96c028369c06503842ec7070480158a0505853fbf200683719c3e07806f906a088611df4e09816fa0570a863e94760b800485030c8307b4590d8642e7400e8459bf1d0f803461108259aa03118671ad171280708651138257907e14821986091582203b168527c013178315aa081880558e67198664c5511a872afc330000000000000000000000000000000000000000000000000000001b863b8d480100000000000000000000000000000000000000000000000000001b847f81610200000000000000000000000000000000000000000000000000001b8526852d03000000000000000000000000000000000000000000000000000018857d901b0400000000000000000000000000000000000000000000000000001884238e240500000000000000000000000000000000000000000000000000001885049c610600000000000000000000000000000000000000000000000000001880401a070000000000000000000000000000000000000000000000000000168349a2100800000000000000000000000000000000000000000000000000001581539c5f09000000000000000000000000000000000000000000000000000015810f96030a0000000000000000000000000000000000000000000000000000148406b8190b0000000000000000000000000000000000000000000000000000138005801a0c000000000000000000000000000000000000000000000000000013863c99570d000000000000000000000000000000000000000000000000000013842ea1130e000000000000000000000000000000000000000000000000000012810b8a5e0f000000000000000000000000000000000000000000000000000011861c8474100000000000000000000000000000000000000000000000000000118117903911000000000000000000000000000000000000000000000000000010850b981d12000000000000000000000000000000000000000000000000000010822d9d73130000000000000000000000000000000000000000000000000000108655c73614000000000000000000000000000000000000000000000000000010862baf0c15000000000000000000000000000000000000000000000000000010758c001600000000000000000000000000000000000000000000000000000f80739a7f1700000000000000000000000000000000000000000000000000000f8070856b1800000000000000000000000000000000000000000000000000000f837c8d4e1900000000000000000000000000000000000000000000000000000e806888691a00000000000000000000000000000000000000000000000000000b8570de661b0000000000000000000000000000000000000000000000000000098332bb0b1c0000000000000000000000000000000000000000000000000000098240ae6b1d000000000000000000000000000000000000000000000000000008861599711e000000000000000000000000000000000000000000000000000006821da71e1f0000000000000000000000000000000000000000000000000000038334af692000000000000000000000000000000000000000000000000000000200"_hex_u8, {40, 24, 5, 56, 16, 22, 18, 50, 3, 33, 53, 43, 52, 4, 49, 37, 47, 59, 13, 58, 54, 41, 44, 27, 39, 11, 10, 34, 45, 55, 31, 14, 32, 25, 38, 8, 1, 20, 26, 12, 2, 6, 7, 21, 36, 51, 29, 9, 42, 23, 28, 30, 17, 57, 15, 19, 48, 46, 35, 0});
TestOptimalLinearization("822f8a1500813c8e2c01812b92570280708513038608a92804835ca704058668d931068417a738078402a65b08853f9749098176994f0a81438c730b8261827e0c816c816f0d831d8a450e825a901f0f8105852600000000000000000000000000000000108338ab330100000000000000000000000000000010852dbe30020000000000000000000000000000000e82419630030000000000000000000000000000000d813c867c040000000000000000000000000000000b831b9d1a050000000000000000000000000000000b84069108060000000000000000000000000000000b854b967b070000000000000000000000000000000b8031820b080000000000000000000000000000000b81518a2e090000000000000000000000000000000b83208e010a0000000000000000000000000000000a8670d4660b0000000000000000000000000000000a860dce2a0c0000000000000000000000000000000a8451c1270d000000000000000000000000000000098543b1490e0000000000000000000000000000000883609b660f00000000000000000000000000000006843da97210000000000000000000000000000000068028897f1100000000000000000000000000000000842ab52d120000000000000000000000000000000000"_hex_v_u8, {{2562, 604}, {2588, 663}, {982, 316}, {2708, 904}, {8802, 12587}, {-198, 177}, {-961, 544}, {-1534, 843}, {-3237, 835}, {-704, 168}, {-2842, 568}, {-3479, 682}, {-4244, 721}}); TestOptimalLinearization("822f8a1500813c8e2c01812b92570280708513038608a92804835ca704058668d931068417a738078402a65b08853f9749098176994f0a81438c730b8261827e0c816c816f0d831d8a450e825a901f0f8105852600000000000000000000000000000000108338ab330100000000000000000000000000000010852dbe30020000000000000000000000000000000e82419630030000000000000000000000000000000d813c867c040000000000000000000000000000000b831b9d1a050000000000000000000000000000000b84069108060000000000000000000000000000000b854b967b070000000000000000000000000000000b8031820b080000000000000000000000000000000b81518a2e090000000000000000000000000000000b83208e010a0000000000000000000000000000000a8670d4660b0000000000000000000000000000000a860dce2a0c0000000000000000000000000000000a8451c1270d000000000000000000000000000000098543b1490e0000000000000000000000000000000883609b660f00000000000000000000000000000006843da97210000000000000000000000000000000068028897f1100000000000000000000000000000000842ab52d120000000000000000000000000000000000"_hex_u8, {15, 21, 3, 8, 29, 30, 31, 7, 2, 24, 32, 28, 23, 5, 27, 19, 18, 17, 4, 26, 10, 6, 25, 14, 11, 9, 0, 13, 16, 12, 22, 33, 1, 34, 20});
TestOptimalLinearization("8333b0280080278a4701831688680002870ecd590102866f74010581298e1203000280238a42030006648603040006850aac5b05000680048845020c8314866b000f8355b84a06000005856d814a070000058172823103020f8409b86904020c8664e05502050b824eab0501030681708f410014847dc92c090000000000018511993e0302010681548c17001a8276a87b050201000012816b933e0401030d853fa06b020604857ec0300901000000000b872dde14020700000f8252851c04000313813a8d0305000500088051816a04070000018228913a02081b8323854d002183458170050501000b8517ca10050201020015802f89210204178509c61503041682529401050102010686269150010003031a806e821c000002010204856798430100000101020e845498700104002000"_hex_v_u8, {{3156, 563}, {1594, 1161}, {3115, 10582}, {-3684, 5344}, {-423, 547}, {-4401, 3628}, {-1634, 871}}); TestOptimalLinearization("8333b0280080278a4701831688680002870ecd590102866f74010581298e1203000280238a42030006648603040006850aac5b05000680048845020c8314866b000f8355b84a06000005856d814a070000058172823103020f8409b86904020c8664e05502050b824eab0501030681708f410014847dc92c090000000000018511993e0302010681548c17001a8276a87b050201000012816b933e0401030d853fa06b020604857ec0300901000000000b872dde14020700000f8252851c04000313813a8d0305000500088051816a04070000018228913a02081b8323854d002183458170050501000b8517ca10050201020015802f89210204178509c61503041682529401050102010686269150010003031a806e821c000002010204856798430100000101020e845498700104002000"_hex_u8, {27, 39, 30, 29, 6, 21, 18, 15, 3, 0, 1, 33, 37, 23, 24, 9, 22, 31, 10, 20, 16, 26, 11, 32, 4, 34, 38, 5, 13, 12, 2, 8, 28, 35, 17, 19, 14, 36, 7, 25});
TestOptimalLinearization("810c8e3d008316881a01863fa11b02831dad01038049881804873d9a410203822e9f420302822299290204842d32040208874a8734020b80278a6b020b6884100408803b812505000e857ba64a0801000a874bc7760604088600aa69060980618e7a05060a8472a23a010b0b873bcf000604000e816d97620a01020f86409a730215872c8e22010c04801b8963010a18855c8b3f0a00010200000015864c98150701000401000a81428f60080005098458c254040601020d837cae5c04010a0c8273a56209050101000000058507b07b080200061080519068090003010100118310a0050503020000010000148727d92f0502020200001785599e740207000201000b8421905004010102010124854d8b0f00050003002200"_hex_v_u8, {{588, 201}, {3571, 2051}, {6111, 4552}, {5853, 5439}, {4559, 5181}, {-800, 860}, {-4457, 3265}, {-2115, 528}, {-5784, 1063}}); TestOptimalLinearization("810c8e3d008316881a01863fa11b02831dad01038049881804873d9a410203822e9f420302822299290204842d32040208874a8734020b80278a6b020b6884100408803b812505000e857ba64a0801000a874bc7760604088600aa69060980618e7a05060a8472a23a010b0b873bcf000604000e816d97620a01020f86409a730215872c8e22010c04801b8963010a18855c8b3f0a00010200000015864c98150701000401000a81428f60080005098458c254040601020d837cae5c04010a0c8273a56209050101000000058507b07b080200061080519068090003010100118310a0050503020000010000148727d92f0502020200001785599e740207000201000b8421905004010102010124854d8b0f00050003002200"_hex_u8, {33, 7, 35, 23, 15, 34, 29, 9, 28, 13, 10, 6, 5, 27, 30, 3, 8, 31, 20, 32, 12, 19, 18, 2, 21, 25, 16, 26, 24, 4, 22, 17, 0, 1, 14, 11});
TestOptimalLinearization("850c8f35008651ce2f0165807a028725d844038227a4150481378e1c058729b702068279a853076f8878088239a3380981228d300a805c85710b86559b420c8653a67a0d860eac270e823d8c0a0f82539142000000000000000000000000000000000f80068543010000000000000000000000000000000f825f8156020000000000000000000000000000000d83459166030000000000000000000000000000000b84209c0a040000000000000000000000000000000b807e9509050000000000000000000000000000000a80709452060000000000000000000000000000000a70823d070000000000000000000000000000000a8301a000080000000000000000000000000000000a8168806c090000000000000000000000000000000a8120865e0a00000000000000000000000000000009801583190b00000000000000000000000000000009857ed1480c00000000000000000000000000000006806082300d00000000000000000000000000000004801f89590e000000000000000000000000000000038103965a0f00000000000000000000000000000003801d822d10000000000000000000000000000000038459a3031100000000000000000000000000000002872eaf7f1200000000000000000000000000000002854b9658130000000000000000000000000000000100"_hex_v_u8, {{636, 111}, {5730, 1061}, {2332, 441}, {3585, 1065}, {920, 290}, {974, 311}, {2557, 979}, {837, 445}, {1825, 981}, {125, 101}, {2546, 9635}, {-215, 157}, {-269, 149}, {-223, 112}, {-3136, 1070}, {-418, 134}, {-2306, 729}, {-685, 159}, {-1413, 254}}); TestOptimalLinearization("850c8f35008651ce2f0165807a028725d844038227a4150481378e1c058729b702068279a853076f8878088239a3380981228d300a805c85710b86559b420c8653a67a0d860eac270e823d8c0a0f82539142000000000000000000000000000000000f80068543010000000000000000000000000000000f825f8156020000000000000000000000000000000d83459166030000000000000000000000000000000b84209c0a040000000000000000000000000000000b807e9509050000000000000000000000000000000a80709452060000000000000000000000000000000a70823d070000000000000000000000000000000a8301a000080000000000000000000000000000000a8168806c090000000000000000000000000000000a8120865e0a00000000000000000000000000000009801583190b00000000000000000000000000000009857ed1480c00000000000000000000000000000006806082300d00000000000000000000000000000004801f89590e000000000000000000000000000000038103965a0f00000000000000000000000000000003801d822d10000000000000000000000000000000038459a3031100000000000000000000000000000002872eaf7f1200000000000000000000000000000002854b9658130000000000000000000000000000000100"_hex_u8, {20, 6, 21, 16, 23, 10, 30, 35, 26, 4, 0, 24, 33, 3, 19, 7, 22, 28, 12, 14, 9, 1, 8, 34, 17, 25, 5, 15, 29, 18, 13, 32, 2, 31, 27, 11});
TestOptimalLinearization("844f8835008631d1440183318e0a02801b896803863dc83402048525bb440304811a937e04000581669911040006872aaa100600058452b04607000480208c7005020681319777060200852dcc3c0701000b821ea3640801000481168f0808000201860c843204088715df6f0c00000000870ebd7b07030013816f9831021a82778d4200188018854a0c01000103825093730601011684298a2b0402070011832dad31030603098571cc760c00000001000000058704dd7b0b0000000000000000000b8257845005050000000000000000178630c00e04060000000001108435c159090101000000000100078474ba01050004068447ba4506030102000200028408490901030000000111850db1610a00020100000000001a8557c6570307000000011d8275ab4706000000010217648325010303188419801d04000600010012837ebd2202091785548e2f050000000103108028852702030001030383689059040300020102862aa26c010003000000002086199a08020003000000001300"_hex_v_u8, {{5282, 945}, {4698, 957}, {3874, 805}, {692, 155}, {14104, 3949}, {6151, 2252}, {345, 908}, {-589, 2663}, {-696, 870}, {-892, 981}, {-1375, 1112}, {-32657, 11825}}); TestOptimalLinearization("844f8835008631d1440183318e0a02801b896803863dc83402048525bb440304811a937e04000581669911040006872aaa100600058452b04607000480208c7005020681319777060200852dcc3c0701000b821ea3640801000481168f0808000201860c843204088715df6f0c00000000870ebd7b07030013816f9831021a82778d4200188018854a0c01000103825093730601011684298a2b0402070011832dad31030603098571cc760c00000001000000058704dd7b0b0000000000000000000b8257845005050000000000000000178630c00e04060000000001108435c159090101000000000100078474ba01050004068447ba4506030102000200028408490901030000000111850db1610a00020100000000001a8557c6570307000000011d8275ab4706000000010217648325010303188419801d04000600010012837ebd2202091785548e2f050000000103108028852702030001030383689059040300020102862aa26c010003000000002086199a08020003000000001300"_hex_u8, {28, 19, 25, 32, 30, 1, 2, 27, 14, 10, 22, 34, 12, 41, 33, 36, 0, 8, 17, 5, 18, 11, 35, 3, 6, 21, 7, 29, 37, 39, 20, 26, 42, 24, 38, 4, 13, 15, 31, 9, 23, 16, 40});
TestOptimalLinearization("824b8e1200805c8610018129801f028373a87d0380767f0486319546058649b858068623a50f07871ca14908805c9121098637af790a8668d1220b6480290c801e827d0d845eb6420e857ec3680f8600c332108517857f118126880100000000000000000000000000000000000012806b917101000000000000000000000000000000000011815e8069020000000000000000000000000000000000118468a40e0300000000000000000000000000000000000d8355ae150400000000000000000000000000000000000b832c99610500000000000000000000000000000000000a8720cb11060000000000000000000000000000000000098623b37c0700000000000000000000000000000000000880668f1b08000000000000000000000000000000000008835b9813090000000000000000000000000000000000088279892f0a000000000000000000000000000000000006802488110b0000000000000000000000000000000000038337a31a0c0000000000000000000000000000000000038574aa730d00000000000000000000000000000000000100"_hex_v_u8, {{5265, 1000}, {4404, 894}, {4377, 896}, {3553, 734}, {3692, 969}, {969, 459}, {456, 220}, {1443, 945}, {-64, 246}, {-80, 297}, {-448, 791}, {-4017, 6631}, {-664, 505}, {-577, 294}, {-1610, 603}, {-1713, 556}, {-2810, 884}, {-585, 164}, {-1038, 230}, {-4873, 1056}, {-3019, 597}, {-1209, 235}}); TestOptimalLinearization("824b8e1200805c8610018129801f028373a87d0380767f0486319546058649b858068623a50f07871ca14908805c9121098637af790a8668d1220b6480290c801e827d0d845eb6420e857ec3680f8600c332108517857f118126880100000000000000000000000000000000000012806b917101000000000000000000000000000000000011815e8069020000000000000000000000000000000000118468a40e0300000000000000000000000000000000000d8355ae150400000000000000000000000000000000000b832c99610500000000000000000000000000000000000a8720cb11060000000000000000000000000000000000098623b37c0700000000000000000000000000000000000880668f1b08000000000000000000000000000000000008835b9813090000000000000000000000000000000000088279892f0a000000000000000000000000000000000006802488110b0000000000000000000000000000000000038337a31a0c0000000000000000000000000000000000038574aa730d00000000000000000000000000000000000100"_hex_u8, {21, 28, 29, 25, 10, 1, 4, 9, 7, 5, 31, 23, 24, 14, 12, 20, 6, 16, 27, 17, 8, 3, 22, 0, 19, 13, 30, 26, 18, 15, 11, 2});
TestOptimalLinearization("866db148008305944a018340810400038721c963010282528f4802028532a1260301852e954c030685778653050002668530010c806a4a020c8451aa0f030102866c8e250202000b812e9071060000000009852f875105010000000d834e98750400020003814b8b63040000020007840fa646050000020001812c891d0203021082428c7606000001000d822e875d01118502bf170701000006840a8e6c050002010a820c9b1c0204107c871f030100031682259a480401000300188676815a0107128034845b03030002138458a24205000000000013861ca528050000000001048560b41e0200000101000e80618757020200001300"_hex_v_u8, {{3236, 1005}, {3576, 1335}, {1060, 466}, {1984, 1492}, {37, 234}, {-3095, 13613}, {-556, 225}}); TestOptimalLinearization("866db148008305944a018340810400038721c963010282528f4802028532a1260301852e954c030685778653050002668530010c806a4a020c8451aa0f030102866c8e250202000b812e9071060000000009852f875105010000000d834e98750400020003814b8b63040000020007840fa646050000020001812c891d0203021082428c7606000001000d822e875d01118502bf170701000006840a8e6c050002010a820c9b1c0204107c871f030100031682259a480401000300188676815a0107128034845b03030002138458a24205000000000013861ca528050000000001048560b41e0200000101000e80618757020200001300"_hex_u8, {18, 25, 28, 22, 13, 15, 4, 6, 23, 30, 21, 29, 1, 5, 10, 20, 27, 19, 2, 17, 0, 12, 14, 7, 3, 9, 24, 16, 8, 26, 11});
TestOptimalLinearization("8260991f008662892d0001837fa91b01008401a85d0001870cad1f0101810c8658010681356a0206846b824c0400058661c47805000183058c7104028609914d06000a864fc143070004852fb7020601078132943c03040008845eb202040201048626a67f02000682358c18040004000384249049050000030781428c4c02020c8361962f030204028078873307000001010008821b986c0205010005853b8a0e070001000000000c8260956c0301040c862ca078030000010200186b825d010401000c807d930100040101821196590500000000000000088235880e020000001300"_hex_v_u8, {{1910, 8479}, {-3111, 8308}, {-1517, 401}, {-1281, 253}}); TestOptimalLinearization("8260991f008662892d0001837fa91b01008401a85d0001870cad1f0101810c8658010681356a0206846b824c0400058661c47805000183058c7104028609914d06000a864fc143070004852fb7020601078132943c03040008845eb202040201048626a67f02000682358c18040004000384249049050000030781428c4c02020c8361962f030204028078873307000001010008821b986c0205010005853b8a0e070001000000000c8260956c0301040c862ca078030000010200186b825d010401000c807d930100040101821196590500000000000000088235880e020000001300"_hex_u8, {8, 5, 10, 21, 4, 24, 26, 19, 6, 2, 7, 3, 18, 1, 11, 23, 12, 13, 17, 28, 16, 22, 25, 14, 0, 15, 9, 20, 27});
TestOptimalLinearization("842ba05d0083138d6d018720e40a0268816b038548bc49000684269a620105840dab78030007850cc00c010009835486260200088667873a0300078065811006000103865b943f050303836db67905078749c8200700010b8742c257080001000d8351a3460500098604a67e060000108355896d0407000c8712b40005050004832e854607000400128421a30704060f8416944b020a01804e8d5207020100001081598f290209088422862b0700030306867cb04a06030100128733c8370005050e840a884d020105031b8477ba4404050100020886669d270203051886378d2e04030100020000000d8745db65020700000000198465845e0205001382059f3a07020001000000001c843ca06304060100001c854d8f670208000b81519352000004000f84598017000001000200"_hex_v_u8, {{6469, 1056}, {1595, 782}, {12744, 6989}, {-189, 1663}, {-1826, 9149}, {-470, 674}, {-615, 650}, {-8266, 5425}, {-5939, 1093}}); TestOptimalLinearization("842ba05d0083138d6d018720e40a0268816b038548bc49000684269a620105840dab78030007850cc00c010009835486260200088667873a0300078065811006000103865b943f050303836db67905078749c8200700010b8742c257080001000d8351a3460500098604a67e060000108355896d0407000c8712b40005050004832e854607000400128421a30704060f8416944b020a01804e8d5207020100001081598f290209088422862b0700030306867cb04a06030100128733c8370005050e840a884d020105031b8477ba4404050100020886669d270203051886378d2e04030100020000000d8745db65020700000000198465845e0205001382059f3a07020001000000001c843ca06304060100001c854d8f670208000b81519352000004000f84598017000001000200"_hex_u8, {34, 37, 33, 23, 1, 17, 4, 14, 16, 20, 29, 10, 31, 32, 7, 24, 12, 26, 2, 36, 11, 27, 28, 3, 13, 15, 5, 22, 30, 0, 19, 9, 18, 25, 6, 21, 35, 8});
TestOptimalLinearization("810e982400840a9a7e018619dc02028157a542038640a10b04844ec93a058055805f06872eb8660783718a1f08874bcc070980477a0a820194780b8345a66d0c8310a0420d8437b4660e8672af300f8225957310801a826f11807b877e128558d32c136e87581483299c7a00000000000000000000000000000000000000000015805f904d01000000000000000000000000000000000000000015831f922a020000000000000000000000000000000000000000158570be5d03000000000000000000000000000000000000000015863c88160400000000000000000000000000000000000000001480178919050000000000000000000000000000000000000000128563816406000000000000000000000000000000000000000012864bc86307000000000000000000000000000000000000000012841c9a7b0800000000000000000000000000000000000000001182029c6e0900000000000000000000000000000000000000000f8234922d0a00000000000000000000000000000000000000000d800582520b00000000000000000000000000000000000000000d8570cb7d0c00000000000000000000000000000000000000000c8471c94d0d00000000000000000000000000000000000000000c8013865b0e00000000000000000000000000000000000000000c83348a680f00000000000000000000000000000000000000000b811496721000000000000000000000000000000000000000000b850cd3641100000000000000000000000000000000000000000b8738905f1200000000000000000000000000000000000000000b6d812e1300000000000000000000000000000000000000000a7a81501400000000000000000000000000000000000000000a836ba6171500000000000000000000000000000000000000000a8736e1381600000000000000000000000000000000000000000a834a833c170000000000000000000000000000000000000000078340af00180000000000000000000000000000000000000000068460cd141900000000000000000000000000000000000000000686429d651a00000000000000000000000000000000000000000382179f3d1b0000000000000000000000000000000000000000038651b36c1c0000000000000000000000000000000000000000038405c04b1d000000000000000000000000000000000000000002874182401e0000000000000000000000000000000000000000028127827d1f00000000000000000000000000000000000000000100"_hex_v_u8, {{2465, 343}, {4765, 718}, {5953, 921}, {5398, 856}, {1618, 270}, {556, 110}, {3443, 695}, {2145, 528}, {1404, 385}, {3699, 1070}, {3096, 1010}, {1791, 650}, {575, 251}, {17859, 10290}, {151, 109}, {168, 122}, {756, 564}, {587, 956}, {286, 586}, {224, 1089}, {178, 867}, {-255, 295}, {-1136, 1080}, {-1971, 962}, {-1790, 668}, {-1239, 436}, {-494, 147}, {-2508, 619}, {-653, 151}, {-4079, 880}, {-4722, 971}, {-1127, 223}, {-2079, 407}, {-4927, 880}, {-4775, 753}, {-4198, 645}}); TestOptimalLinearization("810e982400840a9a7e018619dc02028157a542038640a10b04844ec93a058055805f06872eb8660783718a1f08874bcc070980477a0a820194780b8345a66d0c8310a0420d8437b4660e8672af300f8225957310801a826f11807b877e128558d32c136e87581483299c7a00000000000000000000000000000000000000000015805f904d01000000000000000000000000000000000000000015831f922a020000000000000000000000000000000000000000158570be5d03000000000000000000000000000000000000000015863c88160400000000000000000000000000000000000000001480178919050000000000000000000000000000000000000000128563816406000000000000000000000000000000000000000012864bc86307000000000000000000000000000000000000000012841c9a7b0800000000000000000000000000000000000000001182029c6e0900000000000000000000000000000000000000000f8234922d0a00000000000000000000000000000000000000000d800582520b00000000000000000000000000000000000000000d8570cb7d0c00000000000000000000000000000000000000000c8471c94d0d00000000000000000000000000000000000000000c8013865b0e00000000000000000000000000000000000000000c83348a680f00000000000000000000000000000000000000000b811496721000000000000000000000000000000000000000000b850cd3641100000000000000000000000000000000000000000b8738905f1200000000000000000000000000000000000000000b6d812e1300000000000000000000000000000000000000000a7a81501400000000000000000000000000000000000000000a836ba6171500000000000000000000000000000000000000000a8736e1381600000000000000000000000000000000000000000a834a833c170000000000000000000000000000000000000000078340af00180000000000000000000000000000000000000000068460cd141900000000000000000000000000000000000000000686429d651a00000000000000000000000000000000000000000382179f3d1b0000000000000000000000000000000000000000038651b36c1c0000000000000000000000000000000000000000038405c04b1d000000000000000000000000000000000000000002874182401e0000000000000000000000000000000000000000028127827d1f00000000000000000000000000000000000000000100"_hex_u8, {11, 14, 7, 50, 4, 52, 38, 36, 34, 17, 41, 6, 47, 29, 16, 20, 43, 13, 42, 35, 24, 27, 40, 33, 26, 39, 15, 0, 46, 2, 19, 30, 31, 25, 5, 37, 49, 9, 51, 28, 44, 12, 18, 23, 32, 8, 3, 10, 1, 45, 21, 22, 48});
TestOptimalLinearization("852dbb7700865eeb7601817ca676028220a65e000580368e660204850932030281369816030106872caf420208861bdc08020209861eba7403020880378d6703020b8253965b040209823f95360013826ab4040402048713bd3606010101817f88540009837cb26c060003000d81628e4e07000300058009811605000511817a9c10090002000005821e9379040700048656d7620500060b850e8d6803080008841a9f44040700138239a535060005010f842e81630605000114822a8f73040800000a8539b3580b010000028407c670020a0e811f0b050702058616cb1303081c8315ae6406040301001c806f9921020c16860fe23e040c038563cf050a0001040f8023842d020e16803f885c050700040182109c010206080d8242ae6702042c813ca3320209041f843ec61401030a1082659641080201020223864cbc42010e1e8442a279012980608866010b0010836c991e0106010f8637903f09010002001e820998050a0500000000108328b41c0200050a825a8d63000b0f827bb9030009108152923704020300020080298155060201020000048023802102093283758a2c000600010035805a8403030203218516c7410300010000000200"_hex_v_u8, {{6971, 990}, {2555, 380}, {2543, 416}, {1011, 182}, {9375, 2190}, {3834, 926}, {7100, 2111}, {24543, 8471}, {999, 354}, {948, 782}, {3401, 2813}, {599, 974}, {-2440, 4852}, {-946, 474}, {-9312, 3117}, {-3594, 1125}, {-1603, 393}, {-4641, 790}}); TestOptimalLinearization("852dbb7700865eeb7601817ca676028220a65e000580368e660204850932030281369816030106872caf420208861bdc08020209861eba7403020880378d6703020b8253965b040209823f95360013826ab4040402048713bd3606010101817f88540009837cb26c060003000d81628e4e07000300058009811605000511817a9c10090002000005821e9379040700048656d7620500060b850e8d6803080008841a9f44040700138239a535060005010f842e81630605000114822a8f73040800000a8539b3580b010000028407c670020a0e811f0b050702058616cb1303081c8315ae6406040301001c806f9921020c16860fe23e040c038563cf050a0001040f8023842d020e16803f885c050700040182109c010206080d8242ae6702042c813ca3320209041f843ec61401030a1082659641080201020223864cbc42010e1e8442a279012980608866010b0010836c991e0106010f8637903f09010002001e820998050a0500000000108328b41c0200050a825a8d63000b0f827bb9030009108152923704020300020080298155060201020000048023802102093283758a2c000600010035805a8403030203218516c7410300010000000200"_hex_u8, {33, 47, 24, 27, 46, 7, 42, 18, 25, 50, 55, 29, 26, 13, 15, 41, 16, 0, 3, 52, 2, 9, 12, 28, 49, 40, 39, 45, 17, 21, 6, 32, 14, 23, 5, 31, 43, 35, 8, 19, 44, 10, 48, 53, 11, 37, 30, 20, 38, 4, 1, 36, 51, 56, 22, 34, 54});
TestOptimalLinearization("803894000087239a23018325873d02812fa0580100028315a2570200027c8a3f0300028608b21b030102870aeb0c05000283728121060000853fcb4d070000856ddb50020b802c927803030b8361c41105030a874af55b050209814d825101168319b7420600040e752f0601030e8054947c0700000d841ca56f0409817a26080501827cb2340108020c83239b340301060d8155a0020a0000000207867cea37010b06836bc00905060101000001836abc570a0300000000001680228f7d0703030000108400ac050703000002168302853b08000103000100068418c6790602010002020017865793550603001c803d84280d00000001000011850c812901168671af190a01010004000783159302060029850a6102081f8718ee2b010703218544d150040b0008835680790607020200804c8d43010f27870b9069030d00218168a83f0117857fe51c06080102001c80248c6b070604001c8526a136060308188607ad41030d010c8576ca010d03000102088545b84a050d0000002e805e934e020a0500078539a877040003092a825e977203040102348342bc010408020101000000198622e778010d000017801582190300000802822b833a07020003000000000000338702ca070108000000002c806c957307000001000100000000028350c36105000200000200002b8315a53205020000000001002000"_hex_v_u8, {{1344, 184}, {14532, 3445}, {2929, 1712}, {19, 378}, {-2610, 2705}, {-19575, 18795}, {-12674, 4996}, {-2889, 974}, {-4804, 1026}, {-1466, 236}, {-3905, 578}, {-4401, 592}}); TestOptimalLinearization("803894000087239a23018325873d02812fa0580100028315a2570200027c8a3f0300028608b21b030102870aeb0c05000283728121060000853fcb4d070000856ddb50020b802c927803030b8361c41105030a874af55b050209814d825101168319b7420600040e752f0601030e8054947c0700000d841ca56f0409817a26080501827cb2340108020c83239b340301060d8155a0020a0000000207867cea37010b06836bc00905060101000001836abc570a0300000000001680228f7d0703030000108400ac050703000002168302853b08000103000100068418c6790602010002020017865793550603001c803d84280d00000001000011850c812901168671af190a01010004000783159302060029850a6102081f8718ee2b010703218544d150040b0008835680790607020200804c8d43010f27870b9069030d00218168a83f0117857fe51c06080102001c80248c6b070604001c8526a136060308188607ad41030d010c8576ca010d03000102088545b84a050d0000002e805e934e020a0500078539a877040003092a825e977203040102348342bc010408020101000000198622e778010d000017801582190300000802822b833a07020003000000000000338702ca070108000000002c806c957307000001000100000000028350c36105000200000200002b8315a53205020000000001002000"_hex_u8, {6, 42, 23, 38, 18, 36, 51, 50, 4, 55, 24, 52, 34, 39, 10, 25, 32, 37, 40, 35, 53, 29, 46, 17, 41, 19, 44, 54, 20, 22, 45, 2, 27, 31, 57, 13, 0, 8, 28, 7, 47, 48, 1, 5, 33, 43, 21, 15, 12, 16, 49, 26, 3, 9, 58, 11, 56, 30, 14});
TestOptimalLinearization("8705ca08008231997201826b964d02872adf1b03807f994d0303861d9d0d01000584008f3502000281029c0703000283678c2804000104860ad4540500010480308a0e030580028e0d00108266a15d070000048134826d06010e8576806b0600000f82098f6a0a0000000c821e95270506088535826c060303865ca8310104147e8c3b06000e832090420600020311861d995305020202018330901f05000100148511bf1d050202030002833d92660801000200028337805606060000001380528f6206020301000007830cac650406000117813698660a00020000000000000683688f1c04020006000011814b8e63020614857592200c010000000007810f872e05080000028634ac16020c1980148e2800288309893f09050001000000028704af74012a8546a0300c010201000381658c090401288068905e0201278135956303070100010026855aab5109020200000000000016813d933d030402041d874bb051030a0000158577650501040300000009817f9c1e0205030c84419f6c0502040001000d8457d22c03030600001c8033883c0205041e80698b0e080202010000000c84058726010801278222876e0c0000000100000001871c820001080100208747e02f030100000117864585210003001084789b5a0002002200"_hex_v_u8, {{4804, 1029}, {1721, 433}, {-813, 15413}, {-1617, 12598}, {-7653, 3678}}); TestOptimalLinearization("8705ca08008231997201826b964d02872adf1b03807f994d0303861d9d0d01000584008f3502000281029c0703000283678c2804000104860ad4540500010480308a0e030580028e0d00108266a15d070000048134826d06010e8576806b0600000f82098f6a0a0000000c821e95270506088535826c060303865ca8310104147e8c3b06000e832090420600020311861d995305020202018330901f05000100148511bf1d050202030002833d92660801000200028337805606060000001380528f6206020301000007830cac650406000117813698660a00020000000000000683688f1c04020006000011814b8e63020614857592200c010000000007810f872e05080000028634ac16020c1980148e2800288309893f09050001000000028704af74012a8546a0300c010201000381658c090401288068905e0201278135956303070100010026855aab5109020200000000000016813d933d030402041d874bb051030a0000158577650501040300000009817f9c1e0205030c84419f6c0502040001000d8457d22c03030600001c8033883c0205041e80698b0e080202010000000c84058726010801278222876e0c0000000100000001871c820001080100208747e02f030100000117864585210003001084789b5a0002002200"_hex_u8, {1, 26, 34, 35, 33, 31, 38, 46, 19, 49, 27, 8, 5, 0, 36, 55, 4, 17, 47, 3, 18, 41, 6, 30, 37, 51, 53, 29, 15, 11, 10, 12, 50, 24, 7, 43, 16, 52, 9, 44, 28, 14, 45, 2, 48, 22, 23, 42, 39, 54, 13, 20, 25, 32, 40, 21});
TestOptimalLinearization("873b94550082209e2201835ac664028740b35703806d82630480568177056e83670683069c77078058920108855a974909871cf6520a821c912d0b820595650c8560864a0d844f86290e801790420f843280631080799b7e11812b9209128742a66c138674d41214807e281583309615168444881917844fd17c188356c12b19810681070000000000000000000000000000000000000000000000000000198240a9580100000000000000000000000000000000000000000000000000188707ea160200000000000000000000000000000000000000000000000000188471931b030000000000000000000000000000000000000000000000000014788a6d040000000000000000000000000000000000000000000000000014864a98300500000000000000000000000000000000000000000000000000128733ca0206000000000000000000000000000000000000000000000000001284099c5b07000000000000000000000000000000000000000000000000001283499319080000000000000000000000000000000000000000000000000012805487620900000000000000000000000000000000000000000000000000128051820c0a0000000000000000000000000000000000000000000000000010823f87730b00000000000000000000000000000000000000000000000000108366ae390c0000000000000000000000000000000000000000000000000010815180370d0000000000000000000000000000000000000000000000000010810692790e000000000000000000000000000000000000000000000000000c855ec0220f000000000000000000000000000000000000000000000000000c82269f2010000000000000000000000000000000000000000000000000000c824ab42811000000000000000000000000000000000000000000000000000c853f825b12000000000000000000000000000000000000000000000000000c833db84713000000000000000000000000000000000000000000000000000c81028c6214000000000000000000000000000000000000000000000000000c8272943b150000000000000000000000000000000000000000000000000008821191781600000000000000000000000000000000000000000000000000068057963317000000000000000000000000000000000000000000000000000684768176180000000000000000000000000000000000000000000000000005807182601900000000000000000000000000000000000000000000000000058309ac2a1a0000000000000000000000000000000000000000000000000005846acb461b00000000000000000000000000000000000000000000000000058564a1251c00000000000000000000000000000000000000000000000000058446a5791d00000000000000000000000000000000000000000000000000048142917a1e0000000000000000000000000000000000000000000000000004830898781f00000000000000000000000000000000000000000000000000048150a17120000000000000000000000000000000000000000000000000000100"_hex_v_u8, {{4594, 602}, {1855, 249}, {1121, 151}, {5310, 719}, {7657, 1052}, {5449, 1012}, {2001, 416}, {2550, 1090}, {18542, 18063}, {240, 241}, {198, 209}, {187, 758}, {-92, 337}, {-238, 831}, {-132, 262}, {-570, 447}, {-1294, 753}, {-1293, 585}, {-2195, 868}, {-1374, 498}, {-1902, 649}, {-2493, 710}, {-1277, 262}, {-3037, 614}, {-759, 120}, {-3684, 573}, {-2233, 336}, {-1498, 215}}); TestOptimalLinearization("873b94550082209e2201835ac664028740b35703806d82630480568177056e83670683069c77078058920108855a974909871cf6520a821c912d0b820595650c8560864a0d844f86290e801790420f843280631080799b7e11812b9209128742a66c138674d41214807e281583309615168444881917844fd17c188356c12b19810681070000000000000000000000000000000000000000000000000000198240a9580100000000000000000000000000000000000000000000000000188707ea160200000000000000000000000000000000000000000000000000188471931b030000000000000000000000000000000000000000000000000014788a6d040000000000000000000000000000000000000000000000000014864a98300500000000000000000000000000000000000000000000000000128733ca0206000000000000000000000000000000000000000000000000001284099c5b07000000000000000000000000000000000000000000000000001283499319080000000000000000000000000000000000000000000000000012805487620900000000000000000000000000000000000000000000000000128051820c0a0000000000000000000000000000000000000000000000000010823f87730b00000000000000000000000000000000000000000000000000108366ae390c0000000000000000000000000000000000000000000000000010815180370d0000000000000000000000000000000000000000000000000010810692790e000000000000000000000000000000000000000000000000000c855ec0220f000000000000000000000000000000000000000000000000000c82269f2010000000000000000000000000000000000000000000000000000c824ab42811000000000000000000000000000000000000000000000000000c853f825b12000000000000000000000000000000000000000000000000000c833db84713000000000000000000000000000000000000000000000000000c81028c6214000000000000000000000000000000000000000000000000000c8272943b150000000000000000000000000000000000000000000000000008821191781600000000000000000000000000000000000000000000000000068057963317000000000000000000000000000000000000000000000000000684768176180000000000000000000000000000000000000000000000000005807182601900000000000000000000000000000000000000000000000000058309ac2a1a0000000000000000000000000000000000000000000000000005846acb461b00000000000000000000000000000000000000000000000000058564a1251c00000000000000000000000000000000000000000000000000058446a5791d00000000000000000000000000000000000000000000000000048142917a1e0000000000000000000000000000000000000000000000000004830898781f00000000000000000000000000000000000000000000000000048150a17120000000000000000000000000000000000000000000000000000100"_hex_u8, {5, 38, 36, 56, 24, 44, 2, 41, 27, 50, 37, 35, 55, 8, 7, 0, 19, 54, 11, 25, 6, 12, 26, 40, 18, 58, 31, 4, 48, 3, 47, 30, 29, 14, 52, 34, 53, 42, 17, 13, 46, 20, 45, 23, 32, 1, 21, 9, 16, 49, 39, 15, 51, 28, 22, 10, 33, 57, 43});
// Clusters which admit repeated states in SFL. // Clusters which admit repeated states in SFL.
TestOptimalLinearization("862ea341008713833c018745817502827a814f0382528b6704813381280581308548010005815a8e7a0100010684019f0005000003802783720500000009856cae0005000001028601ac0e050000000475811a0601000000008135834c070000000000088007863e0800000000000284299b710900000000000200"_hex_v_u8, {{7533, 8149}, {-1849, 681}}); TestOptimalLinearization("862ea341008713833c018745817502827a814f0382528b6704813381280581308548010005815a8e7a0100010684019f0005000003802783720500000009856cae0005000001028601ac0e050000000475811a0601000000008135834c070000000000088007863e0800000000000284299b710900000000000200"_hex_u8, {14, 2, 3, 6, 11, 10, 4, 8, 1, 12, 9, 7, 0, 15, 5, 13});
TestOptimalLinearization("82759235008069896c0186438e3d028244912600000003851ba405010000038214845c0200000183018a4b03000001807f841f00000000078573823a0100000007820f8a65020000000164805703000000018622ab5804000000018412936600000000000c82749c04010000000008832b977602000000000700"_hex_v_u8, {{694, 233}, {2856, 7908}}); TestOptimalLinearization("82759235008069896c0186438e3d028244912600000003851ba405010000038214845c0200000183018a4b03000001807f841f00000000078573823a0100000007820f8a65020000000164805703000000018622ab5804000000018412936600000000000c82749c04010000000008832b977602000000000700"_hex_u8, {8, 14, 6, 3, 9, 10, 4, 13, 2, 12, 1, 11, 5, 7, 0});
TestOptimalLinearization("85478e3b00823c904101820c893f0283179c5903814c893104854282530583429f140100000103830d8509010001000284409a70020100000181168c190300000001088718b06a0400000001058553ac2c0500000000000b8506a22e060000000000008552803a0000000008800f861e020000010008817c844802000100010700"_hex_v_u8, {{6613, 7335}, {-322, 2176}}); TestOptimalLinearization("85478e3b00823c904101820c893f0283179c5903814c893104854282530583429f140100000103830d8509010001000284409a70020100000181168c190300000001088718b06a0400000001058553ac2c0500000000000b8506a22e060000000000008552803a0000000008800f861e020000010008817c844802000100010700"_hex_u8, {13, 1, 4, 11, 3, 9, 5, 0, 7, 15, 14, 12, 2, 6, 8, 10});
TestOptimalLinearization("8146845100804b890d0186768b55028406a32f03863ca23104832f8e3b05810a892b0680358253078502ac5d08872d96700983718004000100000002018273952801010001000100097b3c02020000000100058562a14203010000000000010d8718817804000000010000000c862f956c050000000000000000000900"_hex_v_u8, {{1528, 1069}, {-5842, 9025}}); TestOptimalLinearization("8146845100804b890d0186768b55028406a32f03863ca23104832f8e3b05810a892b0680358253078502ac5d08872d96700983718004000100000002018273952801010001000100097b3c02020000000100058562a14203010000000000010d8718817804000000010000000c862f956c050000000000000000000900"_hex_u8, {14, 5, 1, 12, 9, 8, 11, 2, 15, 7, 4, 0, 10, 13, 6, 3});
TestOptimalLinearization("8460992400872dbd1901867fb07f02852a817d00000003852d87540100000181348f60020000018435942b03000000837f8943000000000681608e730100000005857da67f0200000005843794080300000004658217040000000086628a1500000000000b8708805401000000000a847fa32402000000000700"_hex_v_u8, {{1682, 736}, {-8507, 10189}}); TestOptimalLinearization("8460992400872dbd1901867fb07f02852a817d00000003852d87540100000181348f60020000018435942b03000000837f8943000000000681608e730100000005857da67f0200000005843794080300000004658217040000000086628a1500000000000b8708805401000000000a847fa32402000000000700"_hex_u8, {4, 12, 8, 11, 10, 0, 13, 9, 2, 14, 6, 5, 7, 3, 1});
TestOptimalLinearization("81668e3500804e844f018435927302861f9d5f03846ea342010000018261897a010000018165831102000100863e895003000000078232985e04000000018606823f000001000986318a570200000009804300020100000981408323040000000885179a260400000000068510af7800000000000b8360966f01000000000000"_hex_v_u8, {{4144, 9101}, {-1528, 608}}); TestOptimalLinearization("81668e3500804e844f018435927302861f9d5f03846ea342010000018261897a010000018165831102000100863e895003000000078232985e04000000018606823f000001000986318a570200000009804300020100000981408323040000000885179a260400000000068510af7800000000000b8360966f01000000000000"_hex_u8, {7, 9, 11, 12, 6, 13, 10, 4, 0, 14, 8, 2, 1, 5, 3, 15});
TestOptimalLinearization("861e862e00851aa57f018060816b02831ba009038628b818048576b3010580072a068478911d07854fa8600003000007816d86560200000000048576b11403000000010009850aa7100300000100010782178f040400010000010280758a22050100000000000d860eb344060000000000010c8501975a070000000001000500"_hex_v_u8, {{3660, 936}, {6832, 9471}}); TestOptimalLinearization("861e862e00851aa57f018060816b02831ba009038628b818048576b3010580072a068478911d07854fa8600003000007816d86560200000000048576b11403000000010009850aa7100300000100010782178f040400010000010280758a22050100000000000d860eb344060000000000010c8501975a070000000001000500"_hex_u8, {9, 1, 14, 7, 15, 4, 11, 8, 2, 3, 6, 5, 0, 13, 10, 12});
TestOptimalLinearization("802e7300824b95370000821c8a5e0002827a89580102813185560201867ba17f0301810e83580000000000835d9a0c010000000087218c1602000000008458905a03000000008319937d00000000068216900801000000068677ab2a0200000005826f91710300000004864f4404000000038702ac3c00000000000900"_hex_v_u8, {{6067, 6956}, {392, 3033}}); TestOptimalLinearization("802e7300824b95370000821c8a5e0002827a89580102813185560201867ba17f0301810e83580000000000835d9a0c010000000087218c1602000000008458905a03000000008319937d00000000068216900801000000068677ab2a0200000005826f91710300000004864f4404000000038702ac3c00000000000900"_hex_u8, {2, 9, 0, 3, 1, 7, 13, 15, 11, 14, 8, 5, 12, 10, 4, 6});
TestOptimalLinearization("8151801500823e835201842ba81902837b881e038674b461048676897a058369894306873e8511078514a802010001010001833a8f51010001000100078236885502000101000003872cab780300000101000381035605000000000000038123825305010000000000018152847106000000000000000100"_hex_v_u8, {{5948, 5991}, {-8330, 3591}}); TestOptimalLinearization("8151801500823e835201842ba81902837b881e038674b461048676897a058369894306873e8511078514a802010001010001833a8f51010001000100078236885502000101000003872cab780300000101000381035605000000000000038123825305010000000000018152847106000000000000000100"_hex_u8, {4, 6, 1, 0, 14, 10, 11, 8, 5, 2, 3, 9, 12, 13, 7});
TestOptimalLinearization("6f845f008472960a01842084330286779f7903800786310481588d0505865994390683449e480100000000000387218e3a02000000000000811d22020000000100008500812a0300000000000003825e970e04000000000000028436815a05000000000000027c812e060000000000000000"_hex_v_u8, {{1477, 754}, {-526, 7248}}); TestOptimalLinearization("6f845f008472960a01842084330286779f7903800786310481588d0505865994390683449e480100000000000387218e3a02000000000000811d22020000000100008500812a0300000000000003825e970e04000000000000028436815a05000000000000027c812e060000000000000000"_hex_u8, {1, 2, 8, 3, 6, 0, 5, 4, 9, 13, 11, 10, 7, 12});
TestOptimalLinearization("83419a7b00860e9172000183289a1901018157824f020183209e53030085398e5a040081458e2d00010000068334a04c010000000005840d8f1d02000000000281398b70030000000000872f8f5a040000000000816a8070010000000b843ba5140100000109823a91680200000000078267903303000000000700"_hex_v_u8, {{2212, 8180}, {-1114, 487}}); TestOptimalLinearization("83419a7b00860e9172000183289a1901018157824f020183209e53030085398e5a040081458e2d00010000068334a04c010000000005840d8f1d02000000000281398b70030000000000872f8f5a040000000000816a8070010000000b843ba5140100000109823a91680200000000078267903303000000000700"_hex_u8, {9, 2, 12, 8, 5, 1, 11, 4, 13, 14, 10, 3, 6, 0, 7});
TestOptimalLinearization("867e816800827e9a7101811c8f470000018613905501000080708c0e020000865c963a030000873a834e0400008267921900000000000486238a5a0100000000028614914a020000000002823083560300000000008652993e040000000000813c8e03010000000a803c817601010000028507990402000000000a00"_hex_v_u8, {{3395, 9748}, {-962, 316}}); TestOptimalLinearization("867e816800827e9a7101811c8f470000018613905501000080708c0e020000865c963a030000873a834e0400008267921900000000000486238a5a0100000000028614914a020000000002823083560300000000008652993e040000000000813c8e03010000000a803c817601010000028507990402000000000a00"_hex_u8, {0, 3, 7, 10, 11, 6, 1, 14, 9, 8, 13, 5, 4, 12, 2});
TestOptimalLinearization("856d9d530083029d1d0186429d3f02866b927b038234947a000201835389400101028460895c0201000582128f5303000100803183290400000184358f790500010082779924060000000682416d0700000006867b9a4003000000000a83149b200100010100000482488f62020100000000000b00"_hex_v_u8, {{-524, 9354}}); TestOptimalLinearization("856d9d530083029d1d0186429d3f02866b927b038234947a000201835389400101028460895c0201000582128f5303000100803183290400000184358f790500010082779924060000000682416d0700000006867b9a4003000000000a83149b200100010100000482488f62020100000000000b00"_hex_u8, {11, 5, 0, 8, 14, 12, 4, 6, 9, 1, 7, 13, 10, 3, 2});
TestOptimalLinearization("8748865d0082558d3d01825d8f7a0281678623000003815e8b750100000277831e02000001873d8f3a03000000805b841f0001000682548f0b010000018376891e0200000007826d8320030000000482288b71040000000282078b0c000000000d82288e26010000000d872994040200010009800e800a03000000000b00"_hex_v_u8, {{1085, 477}, {513, 7734}}); TestOptimalLinearization("8748865d0082558d3d01825d8f7a0281678623000003815e8b750100000277831e02000001873d8f3a03000000805b841f0001000682548f0b010000018376891e0200000007826d8320030000000482288b71040000000282078b0c000000000d82288e26010000000d872994040200010009800e800a03000000000b00"_hex_u8, {12, 2, 9, 11, 14, 7, 8, 5, 10, 3, 13, 15, 1, 0, 6, 4});
TestOptimalLinearization("817b8f1100832c965701811b8a4400000281418f16010002804f86370200028573941d0300028179820f04000280238743000000000006845291470100000000037f826c0200000000018602a563030000000001850d902000000000058652826301000000058673a03602000000028379970d030000000200"_hex_v_u8, {{-3780, 7686}, {-1543, 633}}); TestOptimalLinearization("817b8f1100832c965701811b8a4400000281418f16010002804f86370200028573941d0300028179820f04000280238743000000000006845291470100000000037f826c0200000000018602a563030000000001850d902000000000058652826301000000058673a03602000000028379970d030000000200"_hex_u8, {9, 14, 2, 0, 8, 4, 3, 10, 5, 13, 1, 11, 6, 7, 12});
TestOptimalLinearization("85179c690081659269018635831a02866289680385438d3704867eae70058726b035068009856307816e926001000100048742b83801000000010a822190360201000001098721b05603000000000108861db2580401000001000080758a30050000010000000d8354a334060100000000000d8629a87c070000010000000a00"_hex_v_u8, {{3064, 1022}, {11548, 10758}}); TestOptimalLinearization("85179c690081659269018635831a02866289680385438d3704867eae70058726b035068009856307816e926001000100048742b83801000000010a822190360201000001098721b05603000000000108861db2580401000001000080758a30050000010000000d8354a334060100000000000d8629a87c070000010000000a00"_hex_u8, {11, 9, 8, 10, 2, 13, 12, 14, 3, 6, 1, 15, 7, 0, 5, 4});
TestOptimalLinearization("813d894b008263966701802d827f028375997a00000003861891180100000387219a68020000018462827503000001821a924504000001833a9d16000000000003810e8d2d01000000000284299632020000000001820993160300000000008656b4780000000009845c8f03010000000300"_hex_v_u8, {{7961, 7623}, {-1026, 732}}); TestOptimalLinearization("813d894b008263966701802d827f028375997a00000003861891180100000387219a68020000018462827503000001821a924504000001833a9d16000000000003810e8d2d01000000000284299632020000000001820993160300000000008656b4780000000009845c8f03010000000300"_hex_u8, {12, 2, 4, 0, 5, 1, 7, 9, 6, 13, 11, 8, 3, 10});
TestOptimalLinearization("86639b0b0084139655018156830f000002872895040100028567862f02000280468504030001830c8427040000870b987900000000000680527801000000000280148635020000000001860c952a0300000000018216867600000000098426a04c010000000481658d55020000000100"_hex_v_u8, {{-583, 8038}, {-939, 357}}); TestOptimalLinearization("86639b0b0084139655018156830f000002872895040100028567862f02000280468504030001830c8427040000870b987900000000000680527801000000000280148635020000000001860c952a0300000000018216867600000000098426a04c010000000481658d55020000000100"_hex_u8, {5, 9, 6, 3, 4, 13, 0, 11, 7, 1, 10, 8, 2, 12});
TestOptimalLinearization("8718a9310084369903018666a2270000018207936e0100018470800102000084609c240300008324985c04000086418d2100000000000285708d7c0100000000028362875802000000000182519504030000000001854fa01a000000000b851fa3120100000008834d8b47020000000300"_hex_v_u8, {{4600, 9729}, {-804, 589}}); TestOptimalLinearization("8718a9310084369903018666a2270000018207936e0100018470800102000084609c240300008324985c04000086418d2100000000000285708d7c0100000000028362875802000000000182519504030000000001854fa01a000000000b851fa3120100000008834d8b47020000000300"_hex_u8, {5, 1, 3, 13, 9, 6, 2, 12, 8, 11, 7, 4, 0, 10});
// Clusters which have lots of potential SFL states/transitions. // Clusters which have lots of potential SFL states/transitions.
TestOptimalLinearization("84559211008539851b01825098430285268d1e00010181008e700100028425a22e02000005860a9c1403000005830b924004000005810d87040500000483768808060000038731854007000003862b9066000001010a83799a540100020104850c9a5702010000020482098c0003000002000002826897580400010000010000"_hex_v_u8, {{10878, 9607}, {-1772, 780}}); TestOptimalLinearization("84559211008539851b01825098430285268d1e00010181008e700100028425a22e02000005860a9c1403000005830b924004000005810d87040500000483768808060000038731854007000003862b9066000001010a83799a540100020104850c9a5702010000020482098c0003000002000002826897580400010000010000"_hex_u8, {6, 4, 14, 13, 0, 2, 1, 5, 11, 7, 8, 15, 10, 12, 3, 9});
TestOptimalLinearization("8657833900865d887e018043894b0287338377038624880100010001851fa82401000000038421990e02000000038723af560300000003866dae0a04000000028265860005000000028031863800000001088353a12c0101000000088630b51a02000000000003866ba1650300000000000300"_hex_v_u8, {{15815, 9911}, {-2227, 1003}}); TestOptimalLinearization("8657833900865d887e018043894b0287338377038624880100010001851fa82401000000038421990e02000000038723af560300000003866dae0a04000000028265860005000000028031863800000001088353a12c0101000000088630b51a02000000000003866ba1650300000000000300"_hex_u8, {1, 0, 13, 12, 7, 2, 8, 6, 5, 11, 3, 9, 4, 10});
TestOptimalLinearization("852a9d7d008350920901825193330280691201000181428c25010001823d8d1f020000018355460300000182448c0f040000008608994d05000000843ea14a01000100078511a07001000200058737ad5802000200058569ae3f04010000026e80520401000000058509ac7605000000010400"_hex_v_u8, {{1641, 8273}, {-3040, 873}}); TestOptimalLinearization("852a9d7d008350920901825193330280691201000181428c25010001823d8d1f020000018355460300000182448c0f040000008608994d05000000843ea14a01000100078511a07001000200058737ad5802000200058569ae3f04010000026e80520401000000058509ac7605000000010400"_hex_u8, {1, 0, 3, 4, 9, 13, 14, 7, 10, 11, 2, 6, 5, 8, 12});
TestOptimalLinearization("803a88570078825101806a88390282048777038430920a000003811b841f010000038003801c0200000006822092420300000002821a96380400000001820280110500000001806d8834000001000006871aaf2b01000000000003806a8a2a02000000000001864c9e600300000000000100"_hex_v_u8, {{4968, 4685}, {-3094, 1050}}); TestOptimalLinearization("803a88570078825101806a88390282048777038430920a000003811b841f010000038003801c0200000006822092420300000002821a96380400000001820280110500000001806d8834000001000006871aaf2b01000000000003806a8a2a02000000000001864c9e600300000000000100"_hex_u8, {13, 2, 3, 7, 5, 1, 9, 6, 0, 10, 11, 4, 12, 8});
TestOptimalLinearization("8437801e00845d833f01816b907800000286438821010002867cac720200028202895e030000861db23d00000000068419a47301000000048404966b0200000002812a817c000000058438824b01000004822c980e0200000286168f4c03000002860c8a5b040000008542997a00000000000a8247815101000000000800"_hex_v_u8, {{4563, 3197}, {-4405, 7734}}); TestOptimalLinearization("8437801e00845d833f01816b907800000286438821010002867cac720200028202895e030000861db23d00000000068419a47301000000048404966b0200000002812a817c000000058438824b01000004822c980e0200000286168f4c03000002860c8a5b040000008542997a00000000000a8247815101000000000800"_hex_u8, {9, 13, 1, 6, 14, 2, 10, 0, 3, 11, 12, 5, 8, 15, 4, 7});
TestOptimalLinearization("8556877f0081658a7b01803865028412813e03810e816d048743b56e0581398d070680378048010100000001812e85280100000100000780018226020001000000078370891403000000000100824a994a05000000000000822c835a050000000000000980608376060000000000000100"_hex_v_u8, {{3511, 1091}, {1365, 4984}}); TestOptimalLinearization("8556877f0081658a7b01803865028412813e03810e816d048743b56e0581398d070680378048010100000001812e85280100000100000780018226020001000000078370891403000000000100824a994a05000000000000822c835a050000000000000980608376060000000000000100"_hex_u8, {8, 6, 5, 0, 7, 4, 13, 9, 10, 2, 12, 1, 11, 3});
TestOptimalLinearization("66844f008651aa61018409810902816f814d03823084080000000004843b8144010000000483528d16020000000082758c5403000000008342927f000000000886780c01000000088656802302000000088637b649000004855f8f4001000009815a8c5002000009814b8d240300000900"_hex_v_u8, {{292, 8437}, {-3557, 951}}); TestOptimalLinearization("66844f008651aa61018409810902816f814d03823084080000000004843b8144010000000483528d16020000000082758c5403000000008342927f000000000886780c01000000088656802302000000088637b649000004855f8f4001000009815a8c5002000009814b8d240300000900"_hex_u8, {10, 12, 9, 8, 14, 13, 6, 7, 1, 2, 0, 5, 4, 3, 11});
TestOptimalLinearization("825d842900824a800401864bb0360281598d13038039835f04834a80310585568663068555862e00000000000000078552935e010000000000000785738c5c02000000000000058163864403000000000000058069837e040000000000000480708610050000000000000000"_hex_v_u8, {{3163, 971}, {1861, 6319}}); TestOptimalLinearization("825d842900824a800401864bb0360281598d13038039835f04834a80310585568663068555862e00000000000000078552935e010000000000000785738c5c02000000000000058163864403000000000000058069837e040000000000000480708610050000000000000000"_hex_u8, {6, 3, 10, 11, 2, 9, 8, 12, 1, 7, 5, 4, 0});
TestOptimalLinearization("83249365008149926b01817a925202874bba1f038631ab2b0484788e55058613992d06857aa671078367883600000100000001844f916e010100010000008179867002000100000100847a90600300000000000007842c902a0500000000000004825e856b0500000000000000068016831206000000000000000200"_hex_v_u8, {{1257, 378}, {-10088, 9271}}); TestOptimalLinearization("83249365008149926b01817a925202874bba1f038631ab2b0484788e55058613992d06857aa671078367883600000100000001844f916e010100010000008179867002000100000100847a90600300000000000007842c902a0500000000000004825e856b0500000000000000068016831206000000000000000200"_hex_u8, {2, 6, 8, 0, 10, 4, 3, 14, 1, 12, 13, 9, 5, 11, 7});
TestOptimalLinearization("802488410085669221018528aa5b02800a8539038278921601000382338719010103802b8744030102842b8404050002857b886a040102864d9317050100088267920006000001806b813407000100863a5d080000000182529b23000000010000010884259254010000010100000781739540030000000000000600"_hex_v_u8, {{-125, 8361}, {-1810, 466}}); TestOptimalLinearization("802488410085669221018528aa5b02800a8539038278921601000382338719010103802b8744030102842b8404050002857b886a040102864d9317050100088267920006000001806b813407000100863a5d080000000182529b23000000010000010884259254010000010100000781739540030000000000000600"_hex_u8, {2, 12, 11, 4, 9, 13, 3, 0, 6, 15, 8, 14, 7, 1, 10, 5});
TestOptimalLinearization("81528b45008715a71201834c8c090102802f85320202866a89320301812985680001068120817301010005837a836a020000000581448a060300000005846e6b0400000001814c9355000100000582758c5a0101000002833b872d02000000000884539c000300000000068459a140000000000b83098f5a010000000300"_hex_v_u8, {{2569, 1045}, {4798, 7773}}); TestOptimalLinearization("81528b45008715a71201834c8c090102802f85320202866a89320301812985680001068120817301010005837a836a020000000581448a060300000005846e6b0400000001814c9355000100000582758c5a0101000002833b872d02000000000884539c000300000000068459a140000000000b83098f5a010000000300"_hex_u8, {15, 10, 9, 11, 6, 4, 0, 2, 14, 1, 8, 13, 5, 7, 3, 12});
TestOptimalLinearization("8635a94d00866f9a5901847ea66802821c81640203856694370101018713b00d030001813b8b3603000000811980480400000086108960000100000881068b4301000001028033866202000001008556b22f030000000003835ba028040000000001815789540100000006823d903e01010000058629b01202000000000500"_hex_v_u8, {{2548, 766}, {-3769, 9412}}); TestOptimalLinearization("8635a94d00866f9a5901847ea66802821c81640203856694370101018713b00d030001813b8b3603000000811980480400000086108960000100000881068b4301000001028033866202000001008556b22f030000000003835ba028040000000001815789540100000006823d903e01010000058629b01202000000000500"_hex_u8, {6, 3, 2, 12, 1, 13, 4, 5, 14, 15, 0, 8, 9, 11, 10, 7});
TestOptimalLinearization("81188d5500822c855b01821c3a02863a9117038425930d048207906f057243068235804f07853f8b16000002000108822a8a5601000100010880738e07020001000008850d8c4605010000000681038c2205010000010681628b4a050001000007840a8d440600000002000a8538986a070000000001000000"_hex_v_u8, {{1557, 7818}, {-964, 243}}); TestOptimalLinearization("81188d5500822c855b01821c3a02863a9117038425930d048207906f057243068235804f07853f8b16000002000108822a8a5601000100010880738e07020001000008850d8c4605010000000681038c2205010000010681628b4a050001000007840a8d440600000002000a8538986a070000000001000000"_hex_u8, {8, 14, 13, 3, 10, 11, 9, 2, 12, 1, 7, 15, 4, 6, 0, 5});
TestOptimalLinearization("8522934b00812a8b15018610b44e0285789a1f0386509173048233901705840f914906857a924f07831d8e58020000000107860b806502000000010380328724030200000000824b5f0301010000000181518964040000010000000c816e8b24060000000000000b853f45070000000000000400"_hex_v_u8, {{3431, 912}, {-5784, 8563}}); TestOptimalLinearization("8522934b00812a8b15018610b44e0285789a1f0386509173048233901705840f914906857a924f07831d8e58020000000107860b806502000000010380328724030200000000824b5f0301010000000181518964040000010000000c816e8b24060000000000000b853f45070000000000000400"_hex_u8, {5, 7, 12, 1, 11, 6, 8, 3, 4, 14, 2, 0, 10, 13, 9});
TestOptimalLinearization("832f8f59008730831a018022822b02801239038275987b048520a0590582448b6506826398500001010007854b971a0100020000088105894c0201000001068737992603000101000387249424040001010003815b82220500000001028706934a0600000100000d8602ae3d0701000000000c844789560801000000000100"_hex_v_u8, {{3440, 9506}, {-3039, 898}}); TestOptimalLinearization("832f8f59008730831a018022822b02801239038275987b048520a0590582448b6506826398500001010007854b971a0100020000088105894c0201000001068737992603000101000387249424040001010003815b82220500000001028706934a0600000100000d8602ae3d0701000000000c844789560801000000000100"_hex_u8, {6, 8, 7, 15, 3, 12, 1, 9, 10, 11, 4, 5, 0, 14, 13, 2});
TestOptimalLinearization("8458a65900850aac29018201855f02854fab75038461877504821e86330584328d3706861b8d7107844e9d2808847c9250000000030004836d8d3e040000000000098179916402020000010005825b95700400000100000000867dae5e04000000000001000a8162941e05000000000100000682628a4e06000000010000000600"_hex_v_u8, {{1940, 718}, {-1665, 9596}}); TestOptimalLinearization("8458a65900850aac29018201855f02854fab75038461877504821e86330584328d3706861b8d7107844e9d2808847c9250000000030004836d8d3e040000000000098179916402020000010005825b95700400000100000000867dae5e04000000000001000a8162941e05000000000100000682628a4e06000000010000000600"_hex_u8, {14, 6, 13, 4, 10, 12, 5, 0, 2, 8, 7, 15, 3, 11, 9, 1});
TestOptimalLinearization("8147814100805389410185059d29028045833103850834048073883f05803580330000000106832b9f6c0101000105821c0b020000000000068519a8600300000000000484759a66010000018339a07201000001854ea048020000018730ba160400000086409d3c040000000c00"_hex_v_u8, {{12873, 8672}}); TestOptimalLinearization("8147814100805389410185059d29028045833103850834048073883f05803580330000000106832b9f6c0101000105821c0b020000000000068519a8600300000000000484759a66010000018339a07201000001854ea048020000018730ba160400000086409d3c040000000c00"_hex_u8, {9, 0, 8, 11, 7, 4, 5, 6, 3, 12, 13, 1, 14, 10, 2});
TestOptimalLinearization("8219866f008118842f01854ba30b0283058a1f038614921b04866a807005840f9b140000000000000584339d1601000000000004834d925402000000000004811d8b3403000000000003844f8552040000000000038217821e0500000000000100"_hex_v_u8, {{1429, 7313}}); TestOptimalLinearization("8219866f008118842f01854ba30b0283058a1f038614921b04866a807005840f9b140000000000000584339d1601000000000004834d925402000000000004811d8b3403000000000003844f8552040000000000038217821e0500000000000100"_hex_u8, {11, 2, 0, 9, 8, 5, 3, 6, 1, 4, 7, 10});
TestOptimalLinearization("8177892100831b9b490181418f05027d803603872c8040048438837805852ea30200000000000006871e956c01000000000005824c9036020000000000018471972203000000000001865d8e28040000000000008566a4100500000000000000"_hex_v_u8, {{6781, 8064}}); TestOptimalLinearization("8177892100831b9b490181418f05027d803603872c8040048438837805852ea30200000000000006871e956c01000000000005824c9036020000000000018471972203000000000001865d8e28040000000000008566a4100500000000000000"_hex_u8, {5, 9, 6, 1, 4, 3, 0, 11, 7, 8, 2, 10});
TestOptimalLinearization("8534a80f008374901f018379995e000002807a8c4201000285438d340200028019856403000282178b22040001830b930605000080608b06000000000000048621ad3601000000000001842ba10a02000000000000825494320300000000000000"_hex_v_u8, {{9556, 6553}}); TestOptimalLinearization("8534a80f008374901f018379995e000002807a8c4201000285438d340200028019856403000282178b22040001830b930605000080608b06000000000000048621ad3601000000000001842ba10a02000000000000825494320300000000000000"_hex_u8, {7, 5, 1, 3, 0, 9, 6, 2, 4, 8, 10, 11});
TestOptimalLinearization("81398a1700805f84750183639f61028032835f0387498f1b048526992b0581688f4e0000000000000480028348010000000000038005821c02000000000003864fad6803000000000003816c9156040000000000038715b5320500000000000000"_hex_v_u8, {{3013, 6235}}); TestOptimalLinearization("81398a1700805f84750183639f61028032835f0387498f1b048526992b0581688f4e0000000000000480028348010000000000038005821c02000000000003864fad6803000000000003816c9156040000000000038715b5320500000000000000"_hex_u8, {9, 1, 8, 10, 0, 3, 11, 7, 6, 2, 4, 5});
TestOptimalLinearization("83799c23008671ad4901815c896b02854fab3303810481680000000004803181130100000003845f8743020000000383258862030000000381658f6d0400000002802384590000000000058318876701000000000380758d020000038618951201000366812a02000200"_hex_v_u8, {{-7815, 6881}}); TestOptimalLinearization("83799c23008671ad4901815c896b02854fab3303810481680000000004803181130100000003845f8743020000000383258862030000000381658f6d0400000002802384590000000000058318876701000000000380758d020000038618951201000366812a02000200"_hex_u8, {12, 6, 1, 13, 5, 0, 3, 2, 10, 7, 4, 8, 9, 11});
TestOptimalLinearization("8225945300815931018413962f02836a9635038720b46d04842b840f058659974a0000000000000587179118010000000000058710a5540200000000000187169242030000000000018620ac6c04000000000001844182700500000000000000"_hex_v_u8, {{1461, 9533}}); TestOptimalLinearization("8225945300815931018413962f02836a9635038720b46d04842b840f058659974a0000000000000587179118010000000000058710a5540200000000000187169242030000000000018620ac6c04000000000001844182700500000000000000"_hex_u8, {3, 10, 4, 5, 6, 0, 9, 7, 1, 8, 2, 11});
TestOptimalLinearization("806e801500871ca421018125845d02841a9c3703845da477048528997d058510a820000000000000068745946e01000000000004840f9b1202000000000004822d8e280300000000000484599f0004000000000004807d81050500000000000200"_hex_v_u8, {{2, 7480}, {-131, 253}}); TestOptimalLinearization("806e801500871ca421018125845d02841a9c3703845da477048528997d058510a820000000000000068745946e01000000000004840f9b1202000000000004822d8e280300000000000484599f0004000000000004807d81050500000000000200"_hex_u8, {1, 7, 11, 2, 8, 10, 0, 6, 4, 5, 3, 9});
TestOptimalLinearization("84098a0d008000811f01812f831902867a843a038124890f04821e821905870b9e4400000000000004840aa00601000000000002852e97020200000000000284769b18030000000000018042847604000000000001853290160500000000000100"_hex_v_u8, {{7324, 7073}}); TestOptimalLinearization("84098a0d008000811f01812f831902867a843a038124890f04821e821905870b9e4400000000000004840aa00601000000000002852e97020200000000000284769b18030000000000018042847604000000000001853290160500000000000100"_hex_u8, {4, 11, 3, 0, 1, 7, 5, 8, 9, 2, 6, 10});
TestOptimalLinearization("834a9b5f00820a89790180598b3f0273815703816e807004805683370580308062068417a42c0000000000000002865098610100000000000000831a93590200000000000000801981000000000a856eb5520100000786409000020000058336903803000005836b9a020400000583599c0c0500000500"_hex_v_u8, {{5272, 8022}}); TestOptimalLinearization("834a9b5f00820a89790180598b3f0273815703816e807004805683370580308062068417a42c0000000000000002865098610100000000000000831a93590200000000000000801981000000000a856eb5520100000786409000020000058336903803000005836b9a020400000583599c0c0500000500"_hex_u8, {13, 6, 12, 5, 2, 1, 3, 11, 14, 15, 4, 10, 9, 8, 7, 0});
TestOptimalLinearization("85268b4c0082748120018068802102807986310381428d770480268659058340994e00000000000004806b8a3e01000000000004811f8c3c02000000000002840a8d6c030000000000018608af5604000000000001822492100500000000000000"_hex_v_u8, {{7536, 5347}}); TestOptimalLinearization("85268b4c0082748120018068802102807986310381428d770480268659058340994e00000000000004806b8a3e01000000000004811f8c3c02000000000002840a8d6c030000000000018608af5604000000000001822492100500000000000000"_hex_u8, {0, 1, 4, 5, 7, 10, 9, 3, 6, 2, 11, 8});
TestOptimalLinearization("83718f5300862d9663018700ae190281338d3303825c865104832c916705851b9c64000000000000068419a256010000000000028510a35802000000000001816b861a030000000000018564ad6804000000000001832e85480500000000000100"_hex_v_u8, {{2190, 7962}}); TestOptimalLinearization("83718f5300862d9663018700ae190281338d3303825c865104832c916705851b9c64000000000000068419a256010000000000028510a35802000000000001816b861a030000000000018564ad6804000000000001832e85480500000000000100"_hex_u8, {6, 2, 1, 11, 3, 4, 9, 5, 7, 0, 8, 10});
TestOptimalLinearization("842a980f008356951f01805c82570282308f4303802d8317048415a13705863e51000000000000058530a15201000000000004827c865402000000000004845e93260300000000000281638e68040000000000028121832e0500000000000100"_hex_v_u8, {{-1542, 6426}}); TestOptimalLinearization("842a980f008356951f01805c82570282308f4303802d8317048415a13705863e51000000000000058530a15201000000000004827c865402000000000004845e93260300000000000281638e68040000000000028121832e0500000000000100"_hex_u8, {5, 9, 0, 2, 6, 11, 8, 3, 7, 10, 4, 1});
TestOptimalLinearization("855f8024008024816501807c81020284629b030383078631048044895c000002048078100100000000068315856a020000000004800784130300000000028167800c04000000000281758a14010000000885249a1a0100010004852ca63e020000010300"_hex_v_u8, {{3618, 5996}}); TestOptimalLinearization("855f8024008024816501807c81020284629b030383078631048044895c000002048078100100000000068315856a020000000004800784130300000000028167800c04000000000281758a14010000000885249a1a0100010004852ca63e020000010300"_hex_u8, {6, 1, 12, 5, 11, 3, 4, 10, 0, 8, 9, 7, 2});
TestOptimalLinearization("855f97230080678a4f018210925d02856113038105892b04854e996105805a8a480000000000000283028b7a01000000000002846d9f080200000000000283189656030000000000018277862e0400000000000185508d200500000000000000"_hex_v_u8, {{573, 6834}}); TestOptimalLinearization("855f97230080678a4f018210925d02856113038105892b04854e996105805a8a480000000000000283028b7a01000000000002846d9f080200000000000283189656030000000000018277862e0400000000000185508d200500000000000000"_hex_u8, {3, 0, 10, 7, 2, 1, 4, 8, 6, 5, 11, 9});
TestOptimalLinearization("866faa23008646b71501851f96130282588f1103804d851c0000000003822097600100000003850a8f310200000003856e9201000000038656935f01000003855b8f5f020000018743923a0000000a812b810b010000098403a328020000068712970203000005833e98400400000200"_hex_v_u8, {{-4960, 11011}}); TestOptimalLinearization("866faa23008646b71501851f96130282588f1103804d851c0000000003822097600100000003850a8f310200000003856e9201000000038656935f01000003855b8f5f020000018743923a0000000a812b810b010000098403a328020000068712970203000005833e98400400000200"_hex_u8, {11, 14, 1, 10, 4, 3, 5, 13, 9, 7, 6, 12, 8, 0, 2});
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
+69 -3
View File
@@ -925,7 +925,7 @@ FUZZ_TARGET(clusterlin_sfl)
if (rng.randbits(4) == 0) { if (rng.randbits(4) == 0) {
// Verify that the diagram of GetLinearization() is at least as good as GetDiagram(), // Verify that the diagram of GetLinearization() is at least as good as GetDiagram(),
// from time to time. // from time to time.
auto lin = sfl.GetLinearization(); auto lin = sfl.GetLinearization(IndexTxOrder{});
auto lin_diagram = ChunkLinearization(depgraph, lin); auto lin_diagram = ChunkLinearization(depgraph, lin);
auto cmp_lin = CompareChunks(lin_diagram, diagram); auto cmp_lin = CompareChunks(lin_diagram, diagram);
assert(cmp_lin >= 0); assert(cmp_lin >= 0);
@@ -1044,7 +1044,7 @@ FUZZ_TARGET(clusterlin_linearize)
// Invoke Linearize(). // Invoke Linearize().
iter_count &= 0x7ffff; iter_count &= 0x7ffff;
auto [linearization, optimal, cost] = Linearize(depgraph, iter_count, rng_seed, old_linearization, /*is_topological=*/claim_topological_input); auto [linearization, optimal, cost] = Linearize(depgraph, iter_count, rng_seed, IndexTxOrder{}, old_linearization, /*is_topological=*/claim_topological_input);
SanityCheck(depgraph, linearization); SanityCheck(depgraph, linearization);
auto chunking = ChunkLinearization(depgraph, linearization); auto chunking = ChunkLinearization(depgraph, linearization);
@@ -1082,6 +1082,72 @@ FUZZ_TARGET(clusterlin_linearize)
auto read_chunking = ChunkLinearization(depgraph, read); auto read_chunking = ChunkLinearization(depgraph, read);
auto cmp_read = CompareChunks(chunking, read_chunking); auto cmp_read = CompareChunks(chunking, read_chunking);
assert(cmp_read >= 0); assert(cmp_read >= 0);
// Verify that within every chunk, the transactions are in a valid order. For any pair of
// transactions, it should not be possible to swap them; either due to a missing
// dependency, or because the order would be inconsistent with decreasing feerate,
// increasing size, and fallback order (just DepGraphIndex value here).
auto chunking_info = ChunkLinearizationInfo(depgraph, linearization);
/** The set of all transactions (strictly) before tx1 (see below), or (strictly) before
* chunk1 (see even further below). */
TestBitSet done;
unsigned pos{0};
for (const auto& chunk : chunking_info) {
auto chunk_start = pos;
auto chunk_end = pos + chunk.transactions.Count() - 1;
// Go over all pairs of transactions. done is the set of transactions seen before pos1.
for (unsigned pos1 = chunk_start; pos1 <= chunk_end; ++pos1) {
auto tx1 = linearization[pos1];
for (unsigned pos2 = pos1 + 1; pos2 <= chunk_end; ++pos2) {
auto tx2 = linearization[pos2];
// Check whether tx2 only depends on transactions that precede tx1.
if ((depgraph.Ancestors(tx2) - done).Count() == 1) {
// tx2 could take position pos1.
// Verify that individual transaction feerate is decreasing (note that >=
// tie-breaks by size).
assert(depgraph.FeeRate(tx1) >= depgraph.FeeRate(tx2));
// If feerate and size are equal, compare by DepGraphIndex.
if (depgraph.FeeRate(tx1) == depgraph.FeeRate(tx2)) {
assert(tx1 < tx2);
}
}
}
done.Set(tx1);
}
pos += chunk.transactions.Count();
}
// Verify that chunks themselves are in a valid order. For any pair of chunks, it should
// not be possible to swap them; either due to a missing dependency, or because the order
// would be inconsistent with decreasing chunk feerate, increasing chunk size, and order
// of maximum fallback-ordered element (just maximum DepGraphIndex element here).
done = {};
// Go over all pairs of chunks. done is the set of transactions seen before chunk_num1.
for (unsigned chunk_num1 = 0; chunk_num1 < chunking_info.size(); ++chunk_num1) {
const auto& chunk1 = chunking_info[chunk_num1];
for (unsigned chunk_num2 = chunk_num1 + 1; chunk_num2 < chunking_info.size(); ++chunk_num2) {
const auto& chunk2 = chunking_info[chunk_num2];
TestBitSet chunk2_ancestors;
for (auto tx : chunk2.transactions) chunk2_ancestors |= depgraph.Ancestors(tx);
// Check whether chunk2 only depends on transactions that precede chunk1.
if ((chunk2_ancestors - done).IsSubsetOf(chunk2.transactions)) {
// chunk2 could take position chunk_num1.
// Verify that chunk feerate is decreasing (note that >= tie-breaks by size).
assert(chunk1.feerate >= chunk2.feerate);
// If feerate and size are equal, compare by maximum DepGraphIndex element.
if (chunk1.feerate == chunk2.feerate) {
assert(chunk1.transactions.Last() < chunk2.transactions.Last());
}
}
}
done |= chunk1.transactions;
}
// Redo from scratch with a different rng_seed. The resulting linearization should be
// deterministic, if both are optimal.
auto [linearization2, optimal2, cost2] = Linearize(depgraph, MaxOptimalLinearizationIters(depgraph.TxCount()) + 1, rng_seed ^ 0x1337, IndexTxOrder{});
assert(optimal2);
assert(linearization2 == linearization);
} }
} }
@@ -1170,7 +1236,7 @@ FUZZ_TARGET(clusterlin_postlinearize_tree)
// Try to find an even better linearization directly. This must not change the diagram for the // Try to find an even better linearization directly. This must not change the diagram for the
// same reason. // same reason.
auto [opt_linearization, _optimal, _cost] = Linearize(depgraph_tree, 100000, rng_seed, post_linearization); auto [opt_linearization, _optimal, _cost] = Linearize(depgraph_tree, 100000, rng_seed, IndexTxOrder{}, post_linearization);
auto opt_chunking = ChunkLinearization(depgraph_tree, opt_linearization); auto opt_chunking = ChunkLinearization(depgraph_tree, opt_linearization);
auto cmp_opt = CompareChunks(opt_chunking, post_chunking); auto cmp_opt = CompareChunks(opt_chunking, post_chunking);
assert(cmp_opt == 0); assert(cmp_opt == 0);
+153 -20
View File
@@ -23,6 +23,14 @@ using namespace cluster_linearize;
namespace { namespace {
struct SimTxObject : public TxGraph::Ref
{
// Use random uint64_t as txids for this simulation (0 = empty object).
const uint64_t m_txid{0};
SimTxObject() noexcept = default;
explicit SimTxObject(uint64_t txid) noexcept : m_txid(txid) {}
};
/** Data type representing a naive simulated TxGraph, keeping all transactions (even from /** Data type representing a naive simulated TxGraph, keeping all transactions (even from
* disconnected components) in a single DepGraph. Unlike the real TxGraph, this only models * disconnected components) in a single DepGraph. Unlike the real TxGraph, this only models
* a single graph, and multiple instances are used to simulate main/staging. */ * a single graph, and multiple instances are used to simulate main/staging. */
@@ -42,14 +50,14 @@ struct SimTxGraph
/** The dependency graph (for all transactions in the simulation, regardless of /** The dependency graph (for all transactions in the simulation, regardless of
* connectivity/clustering). */ * connectivity/clustering). */
DepGraph<SetType> graph; DepGraph<SetType> graph;
/** For each position in graph, which TxGraph::Ref it corresponds with (if any). Use shared_ptr /** For each position in graph, which SimTxObject it corresponds with (if any). Use shared_ptr
* so that a SimTxGraph can be copied to create a staging one, while sharing Refs with * so that a SimTxGraph can be copied to create a staging one, while sharing Refs with
* the main graph. */ * the main graph. */
std::array<std::shared_ptr<TxGraph::Ref>, MAX_TRANSACTIONS> simmap; std::array<std::shared_ptr<SimTxObject>, MAX_TRANSACTIONS> simmap;
/** For each TxGraph::Ref in graph, the position it corresponds with. */ /** For each TxGraph::Ref in graph, the position it corresponds with. */
std::map<const TxGraph::Ref*, Pos> simrevmap; std::map<const TxGraph::Ref*, Pos> simrevmap;
/** The set of TxGraph::Ref entries that have been removed, but not yet destroyed. */ /** The set of SimTxObject entries that have been removed, but not yet destroyed. */
std::vector<std::shared_ptr<TxGraph::Ref>> removed; std::vector<std::shared_ptr<SimTxObject>> removed;
/** Whether the graph is oversized (true = yes, false = no, std::nullopt = unknown). */ /** Whether the graph is oversized (true = yes, false = no, std::nullopt = unknown). */
std::optional<bool> oversized; std::optional<bool> oversized;
/** The configured maximum number of transactions per cluster. */ /** The configured maximum number of transactions per cluster. */
@@ -129,23 +137,24 @@ struct SimTxGraph
return MISSING; return MISSING;
} }
/** Given a position in this simulated graph, get the corresponding TxGraph::Ref. */ /** Given a position in this simulated graph, get the corresponding SimTxObject. */
TxGraph::Ref* GetRef(Pos pos) SimTxObject* GetRef(Pos pos)
{ {
assert(graph.Positions()[pos]); assert(graph.Positions()[pos]);
assert(simmap[pos]); assert(simmap[pos]);
return simmap[pos].get(); return simmap[pos].get();
} }
/** Add a new transaction to the simulation. */ /** Add a new transaction to the simulation and the specified real graph. */
void AddTransaction(TxGraph::Ref&& ref, const FeePerWeight& feerate) void AddTransaction(TxGraph& txgraph, const FeePerWeight& feerate, uint64_t txid)
{ {
assert(graph.TxCount() < MAX_TRANSACTIONS); assert(graph.TxCount() < MAX_TRANSACTIONS);
auto simpos = graph.AddTransaction(feerate); auto simpos = graph.AddTransaction(feerate);
real_is_optimal = false; real_is_optimal = false;
MakeModified(simpos); MakeModified(simpos);
assert(graph.Positions()[simpos]); assert(graph.Positions()[simpos]);
simmap[simpos] = std::make_shared<TxGraph::Ref>(std::move(ref)); simmap[simpos] = std::make_shared<SimTxObject>(txid);
txgraph.AddTransaction(*simmap[simpos], feerate);
auto ptr = simmap[simpos].get(); auto ptr = simmap[simpos].get();
simrevmap[ptr] = simpos; simrevmap[ptr] = simpos;
// This may invalidate our cached oversized value. // This may invalidate our cached oversized value.
@@ -308,8 +317,8 @@ FUZZ_TARGET(txgraph)
* specialized test cases that are hard to perform more generically. */ * specialized test cases that are hard to perform more generically. */
InsecureRandomContext rng(provider.ConsumeIntegral<uint64_t>()); InsecureRandomContext rng(provider.ConsumeIntegral<uint64_t>());
/** Variable used whenever an empty TxGraph::Ref is needed. */ /** Variable used whenever an empty SimTxObject is needed. */
TxGraph::Ref empty_ref; SimTxObject empty_ref;
/** The maximum number of transactions per (non-oversized) cluster we will use in this /** The maximum number of transactions per (non-oversized) cluster we will use in this
* simulation. */ * simulation. */
@@ -319,8 +328,23 @@ FUZZ_TARGET(txgraph)
/** The number of iterations to consider a cluster acceptably linearized. */ /** The number of iterations to consider a cluster acceptably linearized. */
auto acceptable_iters = provider.ConsumeIntegralInRange<uint64_t>(0, 10000); auto acceptable_iters = provider.ConsumeIntegralInRange<uint64_t>(0, 10000);
/** The set of uint64_t "txid"s that have been assigned before. */
std::set<uint64_t> assigned_txids;
// Construct a real graph, and a vector of simulated graphs (main, and possibly staging). // Construct a real graph, and a vector of simulated graphs (main, and possibly staging).
auto real = MakeTxGraph(max_cluster_count, max_cluster_size, acceptable_iters); auto fallback_order = [&](const TxGraph::Ref& a, const TxGraph::Ref& b) noexcept {
uint64_t txid_a = static_cast<const SimTxObject&>(a).m_txid;
uint64_t txid_b = static_cast<const SimTxObject&>(b).m_txid;
assert(assigned_txids.contains(txid_a));
assert(assigned_txids.contains(txid_b));
return txid_a <=> txid_b;
};
auto real = MakeTxGraph(
/*max_cluster_count=*/max_cluster_count,
/*max_cluster_size=*/max_cluster_size,
/*acceptable_iters=*/acceptable_iters,
/*fallback_order=*/fallback_order);
std::vector<SimTxGraph> sims; std::vector<SimTxGraph> sims;
sims.reserve(2); sims.reserve(2);
sims.emplace_back(max_cluster_count, max_cluster_size); sims.emplace_back(max_cluster_count, max_cluster_size);
@@ -343,9 +367,9 @@ FUZZ_TARGET(txgraph)
/** Currently active block builders. */ /** Currently active block builders. */
std::vector<BlockBuilderData> block_builders; std::vector<BlockBuilderData> block_builders;
/** Function to pick any Ref (for either sim in sims: from sim.simmap or sim.removed, or the /** Function to pick any SimTxObject (for either sim in sims: from sim.simmap or sim.removed, or the
* empty Ref). */ * empty one). */
auto pick_fn = [&]() noexcept -> TxGraph::Ref* { auto pick_fn = [&]() noexcept -> SimTxObject* {
size_t tx_count[2] = {sims[0].GetTransactionCount(), 0}; size_t tx_count[2] = {sims[0].GetTransactionCount(), 0};
/** The number of possible choices. */ /** The number of possible choices. */
size_t choices = tx_count[0] + sims[0].removed.size() + 1; size_t choices = tx_count[0] + sims[0].removed.size() + 1;
@@ -455,10 +479,14 @@ FUZZ_TARGET(txgraph)
size = provider.ConsumeIntegralInRange<uint32_t>(1, 0xff); size = provider.ConsumeIntegralInRange<uint32_t>(1, 0xff);
} }
FeePerWeight feerate{fee, size}; FeePerWeight feerate{fee, size};
// Create a real TxGraph::Ref. // Pick a novel txid (and not 0, which is reserved for empty_ref).
auto ref = real->AddTransaction(feerate); uint64_t txid;
// Create a shared_ptr place in the simulation to put the Ref in. do {
top_sim.AddTransaction(std::move(ref), feerate); txid = rng.rand64();
} while (txid == 0 || assigned_txids.contains(txid));
assigned_txids.insert(txid);
// Create the transaction in the simulation and the real graph.
top_sim.AddTransaction(*real, feerate, txid);
break; break;
} else if ((block_builders.empty() || sims.size() > 1) && top_sim.GetTransactionCount() + top_sim.removed.size() > 1 && command-- == 0) { } else if ((block_builders.empty() || sims.size() > 1) && top_sim.GetTransactionCount() + top_sim.removed.size() > 1 && command-- == 0) {
// AddDependency. // AddDependency.
@@ -1066,10 +1094,115 @@ FUZZ_TARGET(txgraph)
// that calling Linearize on it does not improve it further. // that calling Linearize on it does not improve it further.
if (sims[0].real_is_optimal) { if (sims[0].real_is_optimal) {
auto real_diagram = ChunkLinearization(sims[0].graph, vec1); auto real_diagram = ChunkLinearization(sims[0].graph, vec1);
auto [sim_lin, _optimal, _cost] = Linearize(sims[0].graph, 300000, rng.rand64(), vec1); auto fallback_order_sim = [&](DepGraphIndex a, DepGraphIndex b) noexcept {
auto txid_a = sims[0].GetRef(a)->m_txid;
auto txid_b = sims[0].GetRef(b)->m_txid;
return txid_a <=> txid_b;
};
auto [sim_lin, sim_optimal, _cost] = Linearize(sims[0].graph, 300000, rng.rand64(), fallback_order_sim, vec1);
PostLinearize(sims[0].graph, sim_lin);
auto sim_diagram = ChunkLinearization(sims[0].graph, sim_lin); auto sim_diagram = ChunkLinearization(sims[0].graph, sim_lin);
auto cmp = CompareChunks(real_diagram, sim_diagram); auto cmp = CompareChunks(real_diagram, sim_diagram);
assert(cmp == 0); assert(cmp == 0);
// Verify consistency of cross-cluster chunk ordering with tie-break (equal-feerate
// prefix size).
auto real_chunking = ChunkLinearizationInfo(sims[0].graph, vec1);
/** Map with one entry per component of the sim main graph. Key is the first Pos of the
* component. Value is the sum of all chunk sizes from that component seen
* already, at the current chunk feerate. */
std::map<SimTxGraph::Pos, int32_t> comp_prefix_sizes;
/** Current chunk feerate. */
FeeFrac last_chunk_feerate;
/** Largest seen (equal-feerate chunk prefix size, max txid). */
std::pair<int32_t, uint64_t> max_chunk_tiebreak{0, 0};
for (const auto& chunk : real_chunking) {
// If this is the first chunk with a strictly lower feerate, reset.
if (chunk.feerate << last_chunk_feerate) {
comp_prefix_sizes.clear();
max_chunk_tiebreak = {0, 0};
}
last_chunk_feerate = chunk.feerate;
// Find which sim component this chunk belongs to.
auto component = sims[0].graph.GetConnectedComponent(sims[0].graph.Positions(), chunk.transactions.First());
assert(chunk.transactions.IsSubsetOf(component));
auto comp_key = component.First();
auto& comp_prefix_size = comp_prefix_sizes[comp_key];
comp_prefix_size += chunk.feerate.size;
// Determine the chunk's max txid.
uint64_t chunk_max_txid{0};
for (auto tx : chunk.transactions) {
auto txid = sims[0].GetRef(tx)->m_txid;
chunk_max_txid = std::max(txid, chunk_max_txid);
}
// Verify consistency: within each group of equal-feerate chunks, the
// (equal-feerate chunk prefix size, max txid) must be increasing.
std::pair<int32_t, uint64_t> chunk_tiebreak{comp_prefix_size, chunk_max_txid};
assert(chunk_tiebreak > max_chunk_tiebreak);
max_chunk_tiebreak = chunk_tiebreak;
}
// Verify that within each cluster, the internal ordering matches that of the
// simulation if that is optimal too, since per-cluster optimal orderings are
// deterministic. Note that both have been PostLinearize()'ed.
if (sim_optimal) {
for (const auto& component : sims[0].GetComponents()) {
std::vector<DepGraphIndex> sim_chunk_lin, real_chunk_lin;
for (auto i : sim_lin) {
if (component[i]) sim_chunk_lin.push_back(i);
}
for (auto i : vec1) {
if (component[i]) real_chunk_lin.push_back(i);
}
assert(sim_chunk_lin == real_chunk_lin);
}
}
// Verify that a fresh TxGraph, with the same transactions and txids, but constructed
// in a different order, and with a different RNG state, recreates the exact same
// ordering, showing that for optimal graphs, the full mempool ordering is
// deterministic.
auto real_redo = MakeTxGraph(
/*max_cluster_count=*/max_cluster_count,
/*max_cluster_size=*/max_cluster_size,
/*acceptable_iters=*/acceptable_iters,
/*fallback_order=*/fallback_order);
/** Vector (indexed by SimTxGraph::Pos) of TxObjects in real_redo). */
std::vector<std::optional<SimTxObject>> txobjects_redo;
txobjects_redo.resize(sims[0].graph.PositionRange());
// Recreate the graph's transactions with same feerate and txid.
std::vector<DepGraphIndex> positions;
for (auto i : sims[0].graph.Positions()) positions.push_back(i);
std::shuffle(positions.begin(), positions.end(), rng);
for (auto i : positions) {
txobjects_redo[i].emplace(sims[0].GetRef(i)->m_txid);
real_redo->AddTransaction(*txobjects_redo[i], FeePerWeight::FromFeeFrac(sims[0].graph.FeeRate(i)));
}
// Recreate the graph's dependencies.
std::vector<std::pair<DepGraphIndex, DepGraphIndex>> deps;
for (auto i : sims[0].graph.Positions()) {
for (auto j : sims[0].graph.GetReducedParents(i)) {
deps.emplace_back(j, i);
}
}
std::shuffle(deps.begin(), deps.end(), rng);
for (auto [parent, child] : deps) {
real_redo->AddDependency(*txobjects_redo[parent], *txobjects_redo[child]);
}
// Do work to reach optimality.
if (real_redo->DoWork(300000)) {
// Start from a random permutation.
auto vec_redo = vec1;
std::shuffle(vec_redo.begin(), vec_redo.end(), rng);
if (vec_redo == vec1) std::next_permutation(vec_redo.begin(), vec_redo.end());
// Sort it according to the main graph order in real_redo.
auto cmp_redo = [&](SimTxGraph::Pos a, SimTxGraph::Pos b) noexcept {
return real_redo->CompareMainOrder(*txobjects_redo[a], *txobjects_redo[b]) < 0;
};
std::sort(vec_redo.begin(), vec_redo.end(), cmp_redo);
// Compare with the ordering we got from real.
assert(vec1 == vec_redo);
}
} }
// For every transaction in the total ordering, find a random one before it and after it, // For every transaction in the total ordering, find a random one before it and after it,
+1 -1
View File
@@ -27,5 +27,5 @@ CTxMemPoolEntry ConsumeTxMemPoolEntry(FuzzedDataProvider& fuzzed_data_provider,
const auto entry_height{fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(0, max_height)}; const auto entry_height{fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(0, max_height)};
const bool spends_coinbase = fuzzed_data_provider.ConsumeBool(); const bool spends_coinbase = fuzzed_data_provider.ConsumeBool();
const unsigned int sig_op_cost = fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(0, MAX_BLOCK_SIGOPS_COST); const unsigned int sig_op_cost = fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(0, MAX_BLOCK_SIGOPS_COST);
return CTxMemPoolEntry{TxGraph::Ref(), MakeTransactionRef(tx), fee, time, entry_height, entry_sequence, spends_coinbase, sig_op_cost, {}}; return CTxMemPoolEntry{MakeTransactionRef(tx), fee, time, entry_height, entry_sequence, spends_coinbase, sig_op_cost, {}};
} }
+31 -21
View File
@@ -13,9 +13,18 @@
BOOST_AUTO_TEST_SUITE(txgraph_tests) BOOST_AUTO_TEST_SUITE(txgraph_tests)
namespace {
/** The number used as acceptable_iters argument in these tests. High enough that everything /** The number used as acceptable_iters argument in these tests. High enough that everything
* should be optimal, always. */ * should be optimal, always. */
static constexpr uint64_t NUM_ACCEPTABLE_ITERS = 100'000'000; constexpr uint64_t NUM_ACCEPTABLE_ITERS = 100'000'000;
std::strong_ordering PointerComparator(const TxGraph::Ref& a, const TxGraph::Ref& b) noexcept
{
return (&a) <=> (&b);
}
} // namespace
BOOST_AUTO_TEST_CASE(txgraph_trim_zigzag) BOOST_AUTO_TEST_CASE(txgraph_trim_zigzag)
{ {
@@ -39,18 +48,18 @@ BOOST_AUTO_TEST_CASE(txgraph_trim_zigzag)
static constexpr int32_t MAX_CLUSTER_SIZE = 100'000 * 100; static constexpr int32_t MAX_CLUSTER_SIZE = 100'000 * 100;
// Create a new graph for the test. // Create a new graph for the test.
auto graph = MakeTxGraph(MAX_CLUSTER_COUNT, MAX_CLUSTER_SIZE, NUM_ACCEPTABLE_ITERS); auto graph = MakeTxGraph(MAX_CLUSTER_COUNT, MAX_CLUSTER_SIZE, NUM_ACCEPTABLE_ITERS, PointerComparator);
// Add all transactions and store their Refs. // Add all transactions and store their Refs.
std::vector<TxGraph::Ref> refs; std::vector<TxGraph::Ref> refs;
refs.reserve(NUM_TOTAL_TX); refs.reserve(NUM_TOTAL_TX);
// First all bottom transactions: the i'th bottom transaction is at position i. // First all bottom transactions: the i'th bottom transaction is at position i.
for (unsigned int i = 0; i < NUM_BOTTOM_TX; ++i) { for (unsigned int i = 0; i < NUM_BOTTOM_TX; ++i) {
refs.push_back(graph->AddTransaction(FeePerWeight{200 - i, 100})); graph->AddTransaction(refs.emplace_back(), FeePerWeight{200 - i, 100});
} }
// Then all top transactions: the i'th top transaction is at position NUM_BOTTOM_TX + i. // Then all top transactions: the i'th top transaction is at position NUM_BOTTOM_TX + i.
for (unsigned int i = 0; i < NUM_TOP_TX; ++i) { for (unsigned int i = 0; i < NUM_TOP_TX; ++i) {
refs.push_back(graph->AddTransaction(FeePerWeight{100 - i, 100})); graph->AddTransaction(refs.emplace_back(), FeePerWeight{100 - i, 100});
} }
// Create the zigzag dependency structure. // Create the zigzag dependency structure.
@@ -102,16 +111,16 @@ BOOST_AUTO_TEST_CASE(txgraph_trim_flower)
/** Set a very large cluster size limit so that only the count limit is triggered. */ /** Set a very large cluster size limit so that only the count limit is triggered. */
static constexpr int32_t MAX_CLUSTER_SIZE = 100'000 * 100; static constexpr int32_t MAX_CLUSTER_SIZE = 100'000 * 100;
auto graph = MakeTxGraph(MAX_CLUSTER_COUNT, MAX_CLUSTER_SIZE, NUM_ACCEPTABLE_ITERS); auto graph = MakeTxGraph(MAX_CLUSTER_COUNT, MAX_CLUSTER_SIZE, NUM_ACCEPTABLE_ITERS, PointerComparator);
// Add all transactions and store their Refs. // Add all transactions and store their Refs.
std::vector<TxGraph::Ref> refs; std::vector<TxGraph::Ref> refs;
refs.reserve(NUM_TOTAL_TX); refs.reserve(NUM_TOTAL_TX);
// Add all transactions. They are in individual clusters. // Add all transactions. They are in individual clusters.
refs.push_back(graph->AddTransaction({1, 100})); graph->AddTransaction(refs.emplace_back(), {1, 100});
for (unsigned int i = 0; i < NUM_TOP_TX; ++i) { for (unsigned int i = 0; i < NUM_TOP_TX; ++i) {
refs.push_back(graph->AddTransaction(FeePerWeight{500 + i, 100})); graph->AddTransaction(refs.emplace_back(), FeePerWeight{500 + i, 100});
} }
graph->SanityCheck(); graph->SanityCheck();
@@ -188,7 +197,7 @@ BOOST_AUTO_TEST_CASE(txgraph_trim_huge)
std::vector<size_t> top_components; std::vector<size_t> top_components;
FastRandomContext rng; FastRandomContext rng;
auto graph = MakeTxGraph(MAX_CLUSTER_COUNT, MAX_CLUSTER_SIZE, NUM_ACCEPTABLE_ITERS); auto graph = MakeTxGraph(MAX_CLUSTER_COUNT, MAX_CLUSTER_SIZE, NUM_ACCEPTABLE_ITERS, PointerComparator);
// Construct the top chains. // Construct the top chains.
for (int chain = 0; chain < NUM_TOP_CHAINS; ++chain) { for (int chain = 0; chain < NUM_TOP_CHAINS; ++chain) {
@@ -196,8 +205,8 @@ BOOST_AUTO_TEST_CASE(txgraph_trim_huge)
// Use random fees, size 1. // Use random fees, size 1.
int64_t fee = rng.randbits<27>() + 100; int64_t fee = rng.randbits<27>() + 100;
FeePerWeight feerate{fee, 1}; FeePerWeight feerate{fee, 1};
top_refs.push_back(graph->AddTransaction(feerate)); graph->AddTransaction(top_refs.emplace_back(), feerate);
// Add internal dependencies linked the chain transactions together. // Add internal dependencies linking the chain transactions together.
if (chaintx > 0) { if (chaintx > 0) {
graph->AddDependency(*(top_refs.rbegin()), *(top_refs.rbegin() + 1)); graph->AddDependency(*(top_refs.rbegin()), *(top_refs.rbegin() + 1));
} }
@@ -215,7 +224,8 @@ BOOST_AUTO_TEST_CASE(txgraph_trim_huge)
// Construct the transaction. // Construct the transaction.
int64_t fee = rng.randbits<27>() + 100; int64_t fee = rng.randbits<27>() + 100;
FeePerWeight feerate{fee, 1}; FeePerWeight feerate{fee, 1};
auto bottom_tx = graph->AddTransaction(feerate); TxGraph::Ref bottom_tx;
graph->AddTransaction(bottom_tx, feerate);
// Determine the number of dependencies this transaction will have. // Determine the number of dependencies this transaction will have.
int deps = std::min<int>(NUM_DEPS_PER_BOTTOM_TX, top_components.size()); int deps = std::min<int>(NUM_DEPS_PER_BOTTOM_TX, top_components.size());
for (int dep = 0; dep < deps; ++dep) { for (int dep = 0; dep < deps; ++dep) {
@@ -260,7 +270,7 @@ BOOST_AUTO_TEST_CASE(txgraph_trim_big_singletons)
static constexpr int NUM_TOTAL_TX = 100; static constexpr int NUM_TOTAL_TX = 100;
// Create a new graph for the test. // Create a new graph for the test.
auto graph = MakeTxGraph(MAX_CLUSTER_COUNT, MAX_CLUSTER_SIZE, NUM_ACCEPTABLE_ITERS); auto graph = MakeTxGraph(MAX_CLUSTER_COUNT, MAX_CLUSTER_SIZE, NUM_ACCEPTABLE_ITERS, PointerComparator);
// Add all transactions and store their Refs. // Add all transactions and store their Refs.
std::vector<TxGraph::Ref> refs; std::vector<TxGraph::Ref> refs;
@@ -271,7 +281,7 @@ BOOST_AUTO_TEST_CASE(txgraph_trim_big_singletons)
// The 88th transaction is oversized. // The 88th transaction is oversized.
// Every 20th transaction is oversized. // Every 20th transaction is oversized.
const FeePerWeight feerate{500 + i, (i == 88 || i % 20 == 0) ? MAX_CLUSTER_SIZE + 1 : 100}; const FeePerWeight feerate{500 + i, (i == 88 || i % 20 == 0) ? MAX_CLUSTER_SIZE + 1 : 100};
refs.push_back(graph->AddTransaction(feerate)); graph->AddTransaction(refs.emplace_back(), feerate);
} }
graph->SanityCheck(); graph->SanityCheck();
@@ -294,7 +304,7 @@ BOOST_AUTO_TEST_CASE(txgraph_trim_big_singletons)
BOOST_AUTO_TEST_CASE(txgraph_chunk_chain) BOOST_AUTO_TEST_CASE(txgraph_chunk_chain)
{ {
// Create a new graph for the test. // Create a new graph for the test.
auto graph = MakeTxGraph(50, 1000, NUM_ACCEPTABLE_ITERS); auto graph = MakeTxGraph(50, 1000, NUM_ACCEPTABLE_ITERS, PointerComparator);
auto block_builder_checker = [&graph](std::vector<std::vector<TxGraph::Ref*>> expected_chunks) { auto block_builder_checker = [&graph](std::vector<std::vector<TxGraph::Ref*>> expected_chunks) {
std::vector<std::vector<TxGraph::Ref*>> chunks; std::vector<std::vector<TxGraph::Ref*>> chunks;
@@ -334,23 +344,23 @@ BOOST_AUTO_TEST_CASE(txgraph_chunk_chain)
// everytime adding a transaction, test the chunk status // everytime adding a transaction, test the chunk status
// [A] // [A]
refs.push_back(graph->AddTransaction(feerateA)); graph->AddTransaction(refs.emplace_back(), feerateA);
BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 1); BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 1);
block_builder_checker({{&refs[0]}}); block_builder_checker({{&refs[0]}});
// [A, B] // [A, B]
refs.push_back(graph->AddTransaction(feerateB)); graph->AddTransaction(refs.emplace_back(), feerateB);
graph->AddDependency(/*parent=*/refs[0], /*child=*/refs[1]); graph->AddDependency(/*parent=*/refs[0], /*child=*/refs[1]);
BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 2); BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 2);
block_builder_checker({{&refs[0]}, {&refs[1]}}); block_builder_checker({{&refs[0]}, {&refs[1]}});
// [A, BC] // [A, BC]
refs.push_back(graph->AddTransaction(feerateC)); graph->AddTransaction(refs.emplace_back(), feerateC);
graph->AddDependency(/*parent=*/refs[1], /*child=*/refs[2]); graph->AddDependency(/*parent=*/refs[1], /*child=*/refs[2]);
BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 3); BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 3);
block_builder_checker({{&refs[0]}, {&refs[1], &refs[2]}}); block_builder_checker({{&refs[0]}, {&refs[1], &refs[2]}});
// [ABCD] // [ABCD]
refs.push_back(graph->AddTransaction(feerateD)); graph->AddTransaction(refs.emplace_back(), feerateD);
graph->AddDependency(/*parent=*/refs[2], /*child=*/refs[3]); graph->AddDependency(/*parent=*/refs[2], /*child=*/refs[3]);
BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 4); BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 4);
block_builder_checker({{&refs[0], &refs[1], &refs[2], &refs[3]}}); block_builder_checker({{&refs[0], &refs[1], &refs[2], &refs[3]}});
@@ -373,7 +383,7 @@ BOOST_AUTO_TEST_CASE(txgraph_staging)
/* Create a new graph for the test. /* Create a new graph for the test.
* The parameters are max_cluster_count, max_cluster_size, acceptable_iters * The parameters are max_cluster_count, max_cluster_size, acceptable_iters
*/ */
auto graph = MakeTxGraph(10, 1000, NUM_ACCEPTABLE_ITERS); auto graph = MakeTxGraph(10, 1000, NUM_ACCEPTABLE_ITERS, PointerComparator);
std::vector<TxGraph::Ref> refs; std::vector<TxGraph::Ref> refs;
refs.reserve(2); refs.reserve(2);
@@ -383,7 +393,7 @@ BOOST_AUTO_TEST_CASE(txgraph_staging)
// everytime adding a transaction, test the chunk status // everytime adding a transaction, test the chunk status
// [A] // [A]
refs.push_back(graph->AddTransaction(feerateA)); graph->AddTransaction(refs.emplace_back(), feerateA);
BOOST_CHECK_EQUAL(graph->HaveStaging(), false); BOOST_CHECK_EQUAL(graph->HaveStaging(), false);
BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 1); BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 1);
@@ -392,7 +402,7 @@ BOOST_AUTO_TEST_CASE(txgraph_staging)
BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 1); BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 1);
// [A, B] // [A, B]
refs.push_back(graph->AddTransaction(feerateB)); graph->AddTransaction(refs.emplace_back(), feerateB);
BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::MAIN), 1); BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::MAIN), 1);
BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 2); BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 2);
BOOST_CHECK_EQUAL(graph->Exists(refs[0], TxGraph::Level::TOP), true); BOOST_CHECK_EQUAL(graph->Exists(refs[0], TxGraph::Level::TOP), true);
+1 -1
View File
@@ -38,7 +38,7 @@ CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CMutableTransaction& tx) co
CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CTransactionRef& tx) const CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CTransactionRef& tx) const
{ {
return CTxMemPoolEntry{TxGraph::Ref(), tx, nFee, TicksSinceEpoch<std::chrono::seconds>(time), nHeight, m_sequence, spendsCoinbase, sigOpCost, lp}; return CTxMemPoolEntry{tx, nFee, TicksSinceEpoch<std::chrono::seconds>(time), nHeight, m_sequence, spendsCoinbase, sigOpCost, lp};
} }
std::optional<std::string> CheckPackageMempoolAcceptResult(const Package& txns, std::optional<std::string> CheckPackageMempoolAcceptResult(const Package& txns,
+175 -47
View File
@@ -182,8 +182,13 @@ public:
virtual int GetLevel(const TxGraphImpl& graph) const noexcept = 0; virtual int GetLevel(const TxGraphImpl& graph) const noexcept = 0;
/** Only called by TxGraphImpl::SwapIndexes. */ /** Only called by TxGraphImpl::SwapIndexes. */
virtual void UpdateMapping(DepGraphIndex cluster_idx, GraphIndex graph_idx) noexcept = 0; virtual void UpdateMapping(DepGraphIndex cluster_idx, GraphIndex graph_idx) noexcept = 0;
/** Push changes to Cluster and its linearization to the TxGraphImpl Entry objects. */ /** Push changes to Cluster and its linearization to the TxGraphImpl Entry objects. Main chunk
virtual void Updated(TxGraphImpl& graph, int level) noexcept = 0; * information is computed if the cluster is acceptable, or when rename is set. Rename is used
* when called from Compact, to recompute after GraphIndexes may have changed; in this case,
* no chunk index objects are removed or created either. */
virtual void Updated(TxGraphImpl& graph, int level, bool rename) noexcept = 0;
/** Remove all chunk index entries for this cluster (level=0 only). */
virtual void RemoveChunkData(TxGraphImpl& graph) noexcept = 0;
/** Create a copy of this Cluster in staging, returning a pointer to it (used by PullIn). */ /** Create a copy of this Cluster in staging, returning a pointer to it (used by PullIn). */
virtual Cluster* CopyToStaging(TxGraphImpl& graph) const noexcept = 0; virtual Cluster* CopyToStaging(TxGraphImpl& graph) const noexcept = 0;
/** Get the list of Clusters in main that conflict with this one (which is assumed to be in staging). */ /** Get the list of Clusters in main that conflict with this one (which is assumed to be in staging). */
@@ -279,7 +284,8 @@ public:
void ExtractTransactions(const std::function<void (DepGraphIndex, GraphIndex, FeePerWeight)>& visit1_fn, const std::function<void (DepGraphIndex, GraphIndex, SetType)>& visit2_fn) noexcept final; void ExtractTransactions(const std::function<void (DepGraphIndex, GraphIndex, FeePerWeight)>& visit1_fn, const std::function<void (DepGraphIndex, GraphIndex, SetType)>& visit2_fn) noexcept final;
int GetLevel(const TxGraphImpl& graph) const noexcept final; int GetLevel(const TxGraphImpl& graph) const noexcept final;
void UpdateMapping(DepGraphIndex cluster_idx, GraphIndex graph_idx) noexcept final { m_mapping[cluster_idx] = graph_idx; } void UpdateMapping(DepGraphIndex cluster_idx, GraphIndex graph_idx) noexcept final { m_mapping[cluster_idx] = graph_idx; }
void Updated(TxGraphImpl& graph, int level) noexcept final; void Updated(TxGraphImpl& graph, int level, bool rename) noexcept final;
void RemoveChunkData(TxGraphImpl& graph) noexcept final;
Cluster* CopyToStaging(TxGraphImpl& graph) const noexcept final; Cluster* CopyToStaging(TxGraphImpl& graph) const noexcept final;
void GetConflicts(const TxGraphImpl& graph, std::vector<Cluster*>& out) const noexcept final; void GetConflicts(const TxGraphImpl& graph, std::vector<Cluster*>& out) const noexcept final;
void MakeStagingTransactionsMissing(TxGraphImpl& graph) noexcept final; void MakeStagingTransactionsMissing(TxGraphImpl& graph) noexcept final;
@@ -335,7 +341,8 @@ public:
void ExtractTransactions(const std::function<void (DepGraphIndex, GraphIndex, FeePerWeight)>& visit1_fn, const std::function<void (DepGraphIndex, GraphIndex, SetType)>& visit2_fn) noexcept final; void ExtractTransactions(const std::function<void (DepGraphIndex, GraphIndex, FeePerWeight)>& visit1_fn, const std::function<void (DepGraphIndex, GraphIndex, SetType)>& visit2_fn) noexcept final;
int GetLevel(const TxGraphImpl& graph) const noexcept final; int GetLevel(const TxGraphImpl& graph) const noexcept final;
void UpdateMapping(DepGraphIndex cluster_idx, GraphIndex graph_idx) noexcept final { Assume(cluster_idx == 0); m_graph_index = graph_idx; } void UpdateMapping(DepGraphIndex cluster_idx, GraphIndex graph_idx) noexcept final { Assume(cluster_idx == 0); m_graph_index = graph_idx; }
void Updated(TxGraphImpl& graph, int level) noexcept final; void Updated(TxGraphImpl& graph, int level, bool rename) noexcept final;
void RemoveChunkData(TxGraphImpl& graph) noexcept final;
Cluster* CopyToStaging(TxGraphImpl& graph) const noexcept final; Cluster* CopyToStaging(TxGraphImpl& graph) const noexcept final;
void GetConflicts(const TxGraphImpl& graph, std::vector<Cluster*>& out) const noexcept final; void GetConflicts(const TxGraphImpl& graph, std::vector<Cluster*>& out) const noexcept final;
void MakeStagingTransactionsMissing(TxGraphImpl& graph) noexcept final; void MakeStagingTransactionsMissing(TxGraphImpl& graph) noexcept final;
@@ -396,6 +403,8 @@ private:
/** The number of linearization improvement steps needed per cluster to be considered /** The number of linearization improvement steps needed per cluster to be considered
* acceptable. */ * acceptable. */
const uint64_t m_acceptable_iters; const uint64_t m_acceptable_iters;
/** Fallback ordering for transactions. */
const std::function<std::strong_ordering(const TxGraph::Ref&, const TxGraph::Ref&)> m_fallback_order;
/** Information about one group of Clusters to be merged. */ /** Information about one group of Clusters to be merged. */
struct GroupEntry struct GroupEntry
@@ -483,6 +492,7 @@ private:
/** Compare two entries (which must both exist within the main graph). */ /** Compare two entries (which must both exist within the main graph). */
std::strong_ordering CompareMainTransactions(GraphIndex a, GraphIndex b) const noexcept std::strong_ordering CompareMainTransactions(GraphIndex a, GraphIndex b) const noexcept
{ {
if (a == b) return std::strong_ordering::equal;
Assume(a < m_entries.size() && b < m_entries.size()); Assume(a < m_entries.size() && b < m_entries.size());
const auto& entry_a = m_entries[a]; const auto& entry_a = m_entries[a];
const auto& entry_b = m_entries[b]; const auto& entry_b = m_entries[b];
@@ -490,14 +500,27 @@ private:
auto feerate_cmp = FeeRateCompare(entry_b.m_main_chunk_feerate, entry_a.m_main_chunk_feerate); auto feerate_cmp = FeeRateCompare(entry_b.m_main_chunk_feerate, entry_a.m_main_chunk_feerate);
if (feerate_cmp < 0) return std::strong_ordering::less; if (feerate_cmp < 0) return std::strong_ordering::less;
if (feerate_cmp > 0) return std::strong_ordering::greater; if (feerate_cmp > 0) return std::strong_ordering::greater;
// Compare Cluster m_sequence as tie-break for equal chunk feerates. // Compare equal-feerate chunk prefix size for comparing equal chunk feerates. This does two
// things: it distinguishes equal-feerate chunks within the same cluster (because later
// ones will always have a higher prefix size), and it may distinguish equal-feerate chunks
// from distinct clusters.
if (entry_a.m_main_equal_feerate_chunk_prefix_size != entry_b.m_main_equal_feerate_chunk_prefix_size) {
return entry_a.m_main_equal_feerate_chunk_prefix_size <=> entry_b.m_main_equal_feerate_chunk_prefix_size;
}
// Compare by maximum m_fallback_order element to order equal-feerate chunks in distinct
// clusters, when the equal-feerate-prefix size is also the same.
const auto& locator_a = entry_a.m_locator[0]; const auto& locator_a = entry_a.m_locator[0];
const auto& locator_b = entry_b.m_locator[0]; const auto& locator_b = entry_b.m_locator[0];
Assume(locator_a.IsPresent() && locator_b.IsPresent()); Assume(locator_a.IsPresent() && locator_b.IsPresent());
if (locator_a.cluster != locator_b.cluster) { if (locator_a.cluster != locator_b.cluster) {
auto fallback_cmp = m_fallback_order(*m_entries[entry_a.m_main_max_chunk_fallback].m_ref,
*m_entries[entry_b.m_main_max_chunk_fallback].m_ref);
if (fallback_cmp != 0) return fallback_cmp;
// This shouldn't be reachable as m_fallback_order defines a strong ordering.
Assume(false);
return CompareClusters(locator_a.cluster, locator_b.cluster); return CompareClusters(locator_a.cluster, locator_b.cluster);
} }
// As final tie-break, compare position within cluster linearization. // Within a single chunk, sort by position within cluster linearization.
return entry_a.m_main_lin_index <=> entry_b.m_main_lin_index; return entry_a.m_main_lin_index <=> entry_b.m_main_lin_index;
} }
@@ -588,8 +611,18 @@ private:
Locator m_locator[MAX_LEVELS]; Locator m_locator[MAX_LEVELS];
/** The chunk feerate of this transaction in main (if present in m_locator[0]). */ /** The chunk feerate of this transaction in main (if present in m_locator[0]). */
FeePerWeight m_main_chunk_feerate; FeePerWeight m_main_chunk_feerate;
/** The equal-feerate chunk prefix size of this transaction in main. If the transaction is
* part of chunk C in main, then this gives the sum of the sizes of all chunks in C's
* cluster, whose feerate is equal to that of C, which do not appear after C itself in
* the cluster's linearization.
* This provides a way to sort equal-feerate chunks across clusters, in a way that agrees
* with the within-cluster chunk ordering. */
int32_t m_main_equal_feerate_chunk_prefix_size;
/** The position this transaction has in the main linearization (if present). */ /** The position this transaction has in the main linearization (if present). */
LinearizationIndex m_main_lin_index; LinearizationIndex m_main_lin_index;
/** Of all transactions within this transaction's chunk in main (if present there), the
* maximal one according to m_fallback_order. */
GraphIndex m_main_max_chunk_fallback = GraphIndex(-1);
}; };
/** The set of all transactions (in all levels combined). GraphIndex values index into this. */ /** The set of all transactions (in all levels combined). GraphIndex values index into this. */
@@ -599,11 +632,17 @@ private:
std::vector<GraphIndex> m_unlinked; std::vector<GraphIndex> m_unlinked;
public: public:
/** Construct a new TxGraphImpl with the specified limits. */ /** Construct a new TxGraphImpl with the specified limits and fallback order. */
explicit TxGraphImpl(DepGraphIndex max_cluster_count, uint64_t max_cluster_size, uint64_t acceptable_iters) noexcept : explicit TxGraphImpl(
DepGraphIndex max_cluster_count,
uint64_t max_cluster_size,
uint64_t acceptable_iters,
const std::function<std::strong_ordering(const TxGraph::Ref&, const TxGraph::Ref&)>& fallback_order
) noexcept :
m_max_cluster_count(max_cluster_count), m_max_cluster_count(max_cluster_count),
m_max_cluster_size(max_cluster_size), m_max_cluster_size(max_cluster_size),
m_acceptable_iters(acceptable_iters), m_acceptable_iters(acceptable_iters),
m_fallback_order(fallback_order),
m_main_chunkindex(ChunkOrder(this)) m_main_chunkindex(ChunkOrder(this))
{ {
Assume(max_cluster_count >= 1); Assume(max_cluster_count >= 1);
@@ -621,8 +660,9 @@ public:
// Simple helper functions. // Simple helper functions.
/** Swap the Entry referred to by a and the one referred to by b. */ /** Swap the Entry referred to by a and the one referred to by b. Gather main clusters to
void SwapIndexes(GraphIndex a, GraphIndex b) noexcept; * update afterwards. */
void SwapIndexes(GraphIndex a, GraphIndex b, std::vector<Cluster*>& affected_main) noexcept;
/** If idx exists in the specified level ClusterSet (explicitly, or in the level below and not /** If idx exists in the specified level ClusterSet (explicitly, or in the level below and not
* removed), return the Cluster it is in. Otherwise, return nullptr. */ * removed), return the Cluster it is in. Otherwise, return nullptr. */
Cluster* FindCluster(GraphIndex idx, int level) const noexcept { return FindClusterAndLevel(idx, level).first; } Cluster* FindCluster(GraphIndex idx, int level) const noexcept { return FindClusterAndLevel(idx, level).first; }
@@ -693,6 +733,11 @@ public:
auto& entry = m_entries[idx]; auto& entry = m_entries[idx];
Assume(entry.m_ref != nullptr); Assume(entry.m_ref != nullptr);
Assume(m_main_chunkindex_observers == 0 || !entry.m_locator[0].IsPresent()); Assume(m_main_chunkindex_observers == 0 || !entry.m_locator[0].IsPresent());
// Remove all chunk index entries for the affected cluster, to avoid any chunk indexes
// referencing unlinked/destroyed Refs.
if (entry.m_locator[0].IsPresent()) {
entry.m_locator[0].cluster->RemoveChunkData(*this);
}
entry.m_ref = nullptr; entry.m_ref = nullptr;
// Mark the transaction as to be removed in all levels where it explicitly or implicitly // Mark the transaction as to be removed in all levels where it explicitly or implicitly
// exists. // exists.
@@ -753,7 +798,7 @@ public:
// Implementations for the public TxGraph interface. // Implementations for the public TxGraph interface.
Ref AddTransaction(const FeePerWeight& feerate) noexcept final; void AddTransaction(Ref& arg, const FeePerWeight& feerate) noexcept final;
void RemoveTransaction(const Ref& arg) noexcept final; void RemoveTransaction(const Ref& arg) noexcept final;
void AddDependency(const Ref& parent, const Ref& child) noexcept final; void AddDependency(const Ref& parent, const Ref& child) noexcept final;
void SetTransactionFee(const Ref&, int64_t fee) noexcept final; void SetTransactionFee(const Ref&, int64_t fee) noexcept final;
@@ -848,6 +893,9 @@ void TxGraphImpl::ClearChunkData(Entry& entry) noexcept
void TxGraphImpl::CreateChunkData(GraphIndex idx, LinearizationIndex chunk_count) noexcept void TxGraphImpl::CreateChunkData(GraphIndex idx, LinearizationIndex chunk_count) noexcept
{ {
auto& entry = m_entries[idx]; auto& entry = m_entries[idx];
// Make sure to not create chunk data for unlinked entries, which would make invoking
// m_fallback_order on them impossible.
Assume(entry.m_ref != nullptr);
if (!m_main_chunkindex_discarded.empty()) { if (!m_main_chunkindex_discarded.empty()) {
// Reuse an discarded node handle. // Reuse an discarded node handle.
auto& node = m_main_chunkindex_discarded.back().value(); auto& node = m_main_chunkindex_discarded.back().value();
@@ -1007,14 +1055,29 @@ void TxGraphImpl::ClearLocator(int level, GraphIndex idx, bool oversized_tx) noe
if (level == 0) ClearChunkData(entry); if (level == 0) ClearChunkData(entry);
} }
void GenericClusterImpl::Updated(TxGraphImpl& graph, int level) noexcept void GenericClusterImpl::RemoveChunkData(TxGraphImpl& graph) noexcept
{
for (DepGraphIndex idx : m_linearization) {
auto& entry = graph.m_entries[m_mapping[idx]];
graph.ClearChunkData(entry);
}
}
void SingletonClusterImpl::RemoveChunkData(TxGraphImpl& graph) noexcept
{
if (GetTxCount() == 0) return;
auto& entry = graph.m_entries[m_graph_index];
graph.ClearChunkData(entry);
}
void GenericClusterImpl::Updated(TxGraphImpl& graph, int level, bool rename) noexcept
{ {
// Update all the Locators for this Cluster's Entry objects. // Update all the Locators for this Cluster's Entry objects.
for (DepGraphIndex idx : m_linearization) { for (DepGraphIndex idx : m_linearization) {
auto& entry = graph.m_entries[m_mapping[idx]]; auto& entry = graph.m_entries[m_mapping[idx]];
// Discard any potential ChunkData prior to modifying the Cluster (as that could // Discard any potential ChunkData prior to modifying the Cluster (as that could
// invalidate its ordering). // invalidate its ordering).
if (level == 0) graph.ClearChunkData(entry); if (level == 0 && !rename) graph.ClearChunkData(entry);
entry.m_locator[level].SetPresent(this, idx); entry.m_locator[level].SetPresent(this, idx);
} }
// If this is for the main graph (level = 0), and the Cluster's quality is ACCEPTABLE or // If this is for the main graph (level = 0), and the Cluster's quality is ACCEPTABLE or
@@ -1022,14 +1085,40 @@ void GenericClusterImpl::Updated(TxGraphImpl& graph, int level) noexcept
// and m_main_chunk_feerate. These fields are only accessed after making the entire graph // and m_main_chunk_feerate. These fields are only accessed after making the entire graph
// ACCEPTABLE, so it is pointless to compute these if we haven't reached that quality level // ACCEPTABLE, so it is pointless to compute these if we haven't reached that quality level
// yet. // yet.
if (level == 0 && IsAcceptable()) { // When rename=true, this is always performed for level 0, to make sure the values inside the
// entries remain consistent with the chunk index (otherwise unrelated chunk index operations
// could cause the index to become corrupted, by inserting elements in the wrong place).
if (level == 0 && (rename || IsAcceptable())) {
auto chunking = ChunkLinearizationInfo(m_depgraph, m_linearization); auto chunking = ChunkLinearizationInfo(m_depgraph, m_linearization);
LinearizationIndex lin_idx{0}; LinearizationIndex lin_idx{0};
/** The sum of all chunk feerate FeeFracs with the same feerate as the current chunk,
* up to and including the current chunk. */
FeeFrac equal_feerate_chunk_feerate;
// Iterate over the chunks. // Iterate over the chunks.
for (unsigned chunk_idx = 0; chunk_idx < chunking.size(); ++chunk_idx) { for (unsigned chunk_idx = 0; chunk_idx < chunking.size(); ++chunk_idx) {
auto& chunk = chunking[chunk_idx]; auto& chunk = chunking[chunk_idx];
auto chunk_count = chunk.transactions.Count(); auto chunk_count = chunk.transactions.Count();
Assume(chunk_count > 0); Assume(chunk_count > 0);
// Update equal_feerate_chunk_feerate to include this chunk, starting over when the
// feerate changed.
if (chunk.feerate << equal_feerate_chunk_feerate) {
equal_feerate_chunk_feerate = chunk.feerate;
} else {
// Note that this is adding fees to fees, and sizes to sizes, so the overall
// ratio remains the same; it's just accounting for the size of the added chunk.
equal_feerate_chunk_feerate += chunk.feerate;
}
// Determine the m_fallback_order maximum transaction in the chunk.
auto it = chunk.transactions.begin();
GraphIndex max_element = m_mapping[*it];
++it;
while (it != chunk.transactions.end()) {
GraphIndex this_element = m_mapping[*it];
if (graph.m_fallback_order(*graph.m_entries[this_element].m_ref, *graph.m_entries[max_element].m_ref) > 0) {
max_element = this_element;
}
++it;
}
// Iterate over the transactions in the linearization, which must match those in chunk. // Iterate over the transactions in the linearization, which must match those in chunk.
while (true) { while (true) {
DepGraphIndex idx = m_linearization[lin_idx]; DepGraphIndex idx = m_linearization[lin_idx];
@@ -1037,6 +1126,8 @@ void GenericClusterImpl::Updated(TxGraphImpl& graph, int level) noexcept
auto& entry = graph.m_entries[graph_idx]; auto& entry = graph.m_entries[graph_idx];
entry.m_main_lin_index = lin_idx++; entry.m_main_lin_index = lin_idx++;
entry.m_main_chunk_feerate = FeePerWeight::FromFeeFrac(chunk.feerate); entry.m_main_chunk_feerate = FeePerWeight::FromFeeFrac(chunk.feerate);
entry.m_main_equal_feerate_chunk_prefix_size = equal_feerate_chunk_feerate.size;
entry.m_main_max_chunk_fallback = max_element;
Assume(chunk.transactions[idx]); Assume(chunk.transactions[idx]);
chunk.transactions.Reset(idx); chunk.transactions.Reset(idx);
if (chunk.transactions.None()) { if (chunk.transactions.None()) {
@@ -1047,7 +1138,7 @@ void GenericClusterImpl::Updated(TxGraphImpl& graph, int level) noexcept
// clusters), store the special value -1 as chunk count. // clusters), store the special value -1 as chunk count.
chunk_count = LinearizationIndex(-1); chunk_count = LinearizationIndex(-1);
} }
graph.CreateChunkData(graph_idx, chunk_count); if (!rename) graph.CreateChunkData(graph_idx, chunk_count);
break; break;
} }
} }
@@ -1055,7 +1146,7 @@ void GenericClusterImpl::Updated(TxGraphImpl& graph, int level) noexcept
} }
} }
void SingletonClusterImpl::Updated(TxGraphImpl& graph, int level) noexcept void SingletonClusterImpl::Updated(TxGraphImpl& graph, int level, bool rename) noexcept
{ {
// Don't do anything if this is empty. // Don't do anything if this is empty.
if (GetTxCount() == 0) return; if (GetTxCount() == 0) return;
@@ -1063,16 +1154,18 @@ void SingletonClusterImpl::Updated(TxGraphImpl& graph, int level) noexcept
auto& entry = graph.m_entries[m_graph_index]; auto& entry = graph.m_entries[m_graph_index];
// Discard any potential ChunkData prior to modifying the Cluster (as that could // Discard any potential ChunkData prior to modifying the Cluster (as that could
// invalidate its ordering). // invalidate its ordering).
if (level == 0) graph.ClearChunkData(entry); if (level == 0 && !rename) graph.ClearChunkData(entry);
entry.m_locator[level].SetPresent(this, 0); entry.m_locator[level].SetPresent(this, 0);
// If this is for the main graph (level = 0), compute its chunking and store its information in // If this is for the main graph (level = 0), compute its chunking and store its information in
// the Entry's m_main_lin_index and m_main_chunk_feerate. // the Entry's m_main_lin_index and m_main_chunk_feerate.
if (level == 0 && IsAcceptable()) { if (level == 0 && (rename || IsAcceptable())) {
entry.m_main_lin_index = 0; entry.m_main_lin_index = 0;
entry.m_main_chunk_feerate = m_feerate; entry.m_main_chunk_feerate = m_feerate;
entry.m_main_equal_feerate_chunk_prefix_size = m_feerate.size;
entry.m_main_max_chunk_fallback = m_graph_index;
// Always use the special LinearizationIndex(-1), indicating singleton chunk at end of // Always use the special LinearizationIndex(-1), indicating singleton chunk at end of
// Cluster, here. // Cluster, here.
graph.CreateChunkData(m_graph_index, LinearizationIndex(-1)); if (!rename) graph.CreateChunkData(m_graph_index, LinearizationIndex(-1));
} }
} }
@@ -1138,7 +1231,7 @@ Cluster* GenericClusterImpl::CopyToStaging(TxGraphImpl& graph) const noexcept
// Insert the new Cluster into the graph. // Insert the new Cluster into the graph.
graph.InsertCluster(/*level=*/1, std::move(ret), m_quality); graph.InsertCluster(/*level=*/1, std::move(ret), m_quality);
// Update its Locators. // Update its Locators.
ptr->Updated(graph, /*level=*/1); ptr->Updated(graph, /*level=*/1, /*rename=*/false);
// Update memory usage. // Update memory usage.
graph.GetClusterSet(/*level=*/1).m_cluster_usage += ptr->TotalMemoryUsage(); graph.GetClusterSet(/*level=*/1).m_cluster_usage += ptr->TotalMemoryUsage();
return ptr; return ptr;
@@ -1155,7 +1248,7 @@ Cluster* SingletonClusterImpl::CopyToStaging(TxGraphImpl& graph) const noexcept
// Insert the new Cluster into the graph. // Insert the new Cluster into the graph.
graph.InsertCluster(/*level=*/1, std::move(ret), m_quality); graph.InsertCluster(/*level=*/1, std::move(ret), m_quality);
// Update its Locators. // Update its Locators.
ptr->Updated(graph, /*level=*/1); ptr->Updated(graph, /*level=*/1, /*rename=*/false);
// Update memory usage. // Update memory usage.
graph.GetClusterSet(/*level=*/1).m_cluster_usage += ptr->TotalMemoryUsage(); graph.GetClusterSet(/*level=*/1).m_cluster_usage += ptr->TotalMemoryUsage();
return ptr; return ptr;
@@ -1204,7 +1297,7 @@ void GenericClusterImpl::ApplyRemovals(TxGraphImpl& graph, int level, std::span<
graph.GetClusterSet(level).m_cluster_usage += TotalMemoryUsage(); graph.GetClusterSet(level).m_cluster_usage += TotalMemoryUsage();
auto new_quality = IsTopological() ? QualityLevel::NEEDS_SPLIT : QualityLevel::NEEDS_SPLIT_FIX; auto new_quality = IsTopological() ? QualityLevel::NEEDS_SPLIT : QualityLevel::NEEDS_SPLIT_FIX;
graph.SetClusterQuality(level, m_quality, m_setindex, new_quality); graph.SetClusterQuality(level, m_quality, m_setindex, new_quality);
Updated(graph, level); Updated(graph, /*level=*/level, /*rename=*/false);
} }
void SingletonClusterImpl::ApplyRemovals(TxGraphImpl& graph, int level, std::span<GraphIndex>& to_remove) noexcept void SingletonClusterImpl::ApplyRemovals(TxGraphImpl& graph, int level, std::span<GraphIndex>& to_remove) noexcept
@@ -1260,7 +1353,7 @@ void GenericClusterImpl::MoveToMain(TxGraphImpl& graph) noexcept
// Remove cluster itself from staging and add it to main. // Remove cluster itself from staging and add it to main.
auto cluster = graph.ExtractCluster(1, quality, m_setindex); auto cluster = graph.ExtractCluster(1, quality, m_setindex);
graph.InsertCluster(/*level=*/0, std::move(cluster), quality); graph.InsertCluster(/*level=*/0, std::move(cluster), quality);
Updated(graph, /*level=*/0); Updated(graph, /*level=*/0, /*rename=*/false);
} }
void SingletonClusterImpl::MoveToMain(TxGraphImpl& graph) noexcept void SingletonClusterImpl::MoveToMain(TxGraphImpl& graph) noexcept
@@ -1274,7 +1367,7 @@ void SingletonClusterImpl::MoveToMain(TxGraphImpl& graph) noexcept
auto cluster = graph.ExtractCluster(/*level=*/1, quality, m_setindex); auto cluster = graph.ExtractCluster(/*level=*/1, quality, m_setindex);
graph.InsertCluster(/*level=*/0, std::move(cluster), quality); graph.InsertCluster(/*level=*/0, std::move(cluster), quality);
graph.GetClusterSet(/*level=*/0).m_cluster_usage += TotalMemoryUsage(); graph.GetClusterSet(/*level=*/0).m_cluster_usage += TotalMemoryUsage();
Updated(graph, /*level=*/0); Updated(graph, /*level=*/0, /*rename=*/false);
} }
void GenericClusterImpl::Compact() noexcept void GenericClusterImpl::Compact() noexcept
@@ -1372,7 +1465,7 @@ bool GenericClusterImpl::Split(TxGraphImpl& graph, int level) noexcept
graph.SetClusterQuality(level, m_quality, m_setindex, split_quality); graph.SetClusterQuality(level, m_quality, m_setindex, split_quality);
// If this made the quality ACCEPTABLE or OPTIMAL, we need to compute and cache its // If this made the quality ACCEPTABLE or OPTIMAL, we need to compute and cache its
// chunking. // chunking.
Updated(graph, level); Updated(graph, /*level=*/level, /*rename=*/false);
return false; return false;
} }
first = false; first = false;
@@ -1407,7 +1500,7 @@ bool GenericClusterImpl::Split(TxGraphImpl& graph, int level) noexcept
} }
// Update all the Locators of moved transactions, and memory usage. // Update all the Locators of moved transactions, and memory usage.
for (Cluster* new_cluster : new_clusters) { for (Cluster* new_cluster : new_clusters) {
new_cluster->Updated(graph, level); new_cluster->Updated(graph, /*level=*/level, /*rename=*/false);
new_cluster->Compact(); new_cluster->Compact();
graph.GetClusterSet(level).m_cluster_usage += new_cluster->TotalMemoryUsage(); graph.GetClusterSet(level).m_cluster_usage += new_cluster->TotalMemoryUsage();
} }
@@ -1497,7 +1590,7 @@ void GenericClusterImpl::ApplyDependencies(TxGraphImpl& graph, int level, std::s
graph.SetClusterQuality(level, m_quality, m_setindex, QualityLevel::NEEDS_FIX); graph.SetClusterQuality(level, m_quality, m_setindex, QualityLevel::NEEDS_FIX);
// Finally push the changes to graph.m_entries. // Finally push the changes to graph.m_entries.
Updated(graph, level); Updated(graph, /*level=*/level, /*rename=*/false);
} }
void SingletonClusterImpl::ApplyDependencies(TxGraphImpl&, int, std::span<std::pair<GraphIndex, GraphIndex>>) noexcept void SingletonClusterImpl::ApplyDependencies(TxGraphImpl&, int, std::span<std::pair<GraphIndex, GraphIndex>>) noexcept
@@ -1653,7 +1746,7 @@ void TxGraphImpl::ApplyRemovals(int up_to_level) noexcept
Compact(); Compact();
} }
void TxGraphImpl::SwapIndexes(GraphIndex a, GraphIndex b) noexcept void TxGraphImpl::SwapIndexes(GraphIndex a, GraphIndex b, std::vector<Cluster*>& affected_main) noexcept
{ {
Assume(a < m_entries.size()); Assume(a < m_entries.size());
Assume(b < m_entries.size()); Assume(b < m_entries.size());
@@ -1669,12 +1762,12 @@ void TxGraphImpl::SwapIndexes(GraphIndex a, GraphIndex b) noexcept
if (entry.m_main_chunkindex_iterator != m_main_chunkindex.end()) { if (entry.m_main_chunkindex_iterator != m_main_chunkindex.end()) {
entry.m_main_chunkindex_iterator->m_graph_index = idx; entry.m_main_chunkindex_iterator->m_graph_index = idx;
} }
// Update the locators for both levels. The rest of the Entry information will not change, // Update the locators for both levels.
// so no need to invoke Cluster::Updated().
for (int level = 0; level < MAX_LEVELS; ++level) { for (int level = 0; level < MAX_LEVELS; ++level) {
Locator& locator = entry.m_locator[level]; Locator& locator = entry.m_locator[level];
if (locator.IsPresent()) { if (locator.IsPresent()) {
locator.cluster->UpdateMapping(locator.index, idx); locator.cluster->UpdateMapping(locator.index, idx);
if (level == 0) affected_main.push_back(locator.cluster);
} }
} }
} }
@@ -1702,6 +1795,7 @@ void TxGraphImpl::Compact() noexcept
// invalidate them). // invalidate them).
std::sort(m_unlinked.begin(), m_unlinked.end(), std::greater{}); std::sort(m_unlinked.begin(), m_unlinked.end(), std::greater{});
std::vector<Cluster*> affected_main;
auto last = GraphIndex(-1); auto last = GraphIndex(-1);
for (GraphIndex idx : m_unlinked) { for (GraphIndex idx : m_unlinked) {
// m_unlinked should never contain the same GraphIndex twice (the code below would fail // m_unlinked should never contain the same GraphIndex twice (the code below would fail
@@ -1718,10 +1812,18 @@ void TxGraphImpl::Compact() noexcept
} }
// Move the entry to the end. // Move the entry to the end.
if (idx != m_entries.size() - 1) SwapIndexes(idx, m_entries.size() - 1); if (idx != m_entries.size() - 1) SwapIndexes(idx, m_entries.size() - 1, affected_main);
// Drop the entry for idx, now that it is at the end. // Drop the entry for idx, now that it is at the end.
m_entries.pop_back(); m_entries.pop_back();
} }
// Update the affected clusters, to fixup Entry::m_main_max_chunk_fallback values which may
// have become outdated due to the compaction above.
std::sort(affected_main.begin(), affected_main.end());
affected_main.erase(std::unique(affected_main.begin(), affected_main.end()), affected_main.end());
for (Cluster* cluster : affected_main) {
cluster->Updated(*this, /*level=*/0, /*rename=*/true);
}
m_unlinked.clear(); m_unlinked.clear();
} }
@@ -2061,8 +2163,13 @@ std::pair<uint64_t, bool> GenericClusterImpl::Relinearize(TxGraphImpl& graph, in
if (IsOptimal()) return {0, false}; if (IsOptimal()) return {0, false};
// Invoke the actual linearization algorithm (passing in the existing one). // Invoke the actual linearization algorithm (passing in the existing one).
uint64_t rng_seed = graph.m_rng.rand64(); uint64_t rng_seed = graph.m_rng.rand64();
auto [linearization, optimal, cost] = Linearize(m_depgraph, max_iters, rng_seed, m_linearization, /*is_topological=*/IsTopological()); const auto fallback_order = [&](DepGraphIndex a, DepGraphIndex b) noexcept {
// Postlinearize to undo some of the non-determinism caused by randomizing the linearization. const auto ref_a = graph.m_entries[m_mapping[a]].m_ref;
const auto ref_b = graph.m_entries[m_mapping[b]].m_ref;
return graph.m_fallback_order(*ref_a, *ref_b);
};
auto [linearization, optimal, cost] = Linearize(m_depgraph, max_iters, rng_seed, fallback_order, m_linearization, /*is_topological=*/IsTopological());
// Postlinearize to improve the linearization (if optimal, only the sub-chunk order).
// This also guarantees that all chunks are connected (even when non-optimal). // This also guarantees that all chunks are connected (even when non-optimal).
PostLinearize(m_depgraph, linearization); PostLinearize(m_depgraph, linearization);
// Update the linearization. // Update the linearization.
@@ -2080,7 +2187,7 @@ std::pair<uint64_t, bool> GenericClusterImpl::Relinearize(TxGraphImpl& graph, in
improved = true; improved = true;
} }
// Update the Entry objects. // Update the Entry objects.
Updated(graph, level); Updated(graph, /*level=*/level, /*rename=*/false);
return {cost, improved}; return {cost, improved};
} }
@@ -2115,20 +2222,19 @@ void TxGraphImpl::MakeAllAcceptable(int level) noexcept
GenericClusterImpl::GenericClusterImpl(uint64_t sequence) noexcept : Cluster{sequence} {} GenericClusterImpl::GenericClusterImpl(uint64_t sequence) noexcept : Cluster{sequence} {}
TxGraph::Ref TxGraphImpl::AddTransaction(const FeePerWeight& feerate) noexcept void TxGraphImpl::AddTransaction(Ref& arg, const FeePerWeight& feerate) noexcept
{ {
Assume(m_main_chunkindex_observers == 0 || GetTopLevel() != 0); Assume(m_main_chunkindex_observers == 0 || GetTopLevel() != 0);
Assume(feerate.size > 0); Assume(feerate.size > 0);
// Construct a new Ref. Assume(GetRefGraph(arg) == nullptr);
Ref ret;
// Construct a new Entry, and link it with the Ref. // Construct a new Entry, and link it with the Ref.
auto idx = m_entries.size(); auto idx = m_entries.size();
m_entries.emplace_back(); m_entries.emplace_back();
auto& entry = m_entries.back(); auto& entry = m_entries.back();
entry.m_main_chunkindex_iterator = m_main_chunkindex.end(); entry.m_main_chunkindex_iterator = m_main_chunkindex.end();
entry.m_ref = &ret; entry.m_ref = &arg;
GetRefGraph(ret) = this; GetRefGraph(arg) = this;
GetRefIndex(ret) = idx; GetRefIndex(arg) = idx;
// Construct a new singleton Cluster (which is necessarily optimally linearized). // Construct a new singleton Cluster (which is necessarily optimally linearized).
bool oversized = uint64_t(feerate.size) > m_max_cluster_size; bool oversized = uint64_t(feerate.size) > m_max_cluster_size;
auto cluster = CreateEmptyCluster(1); auto cluster = CreateEmptyCluster(1);
@@ -2137,7 +2243,7 @@ TxGraph::Ref TxGraphImpl::AddTransaction(const FeePerWeight& feerate) noexcept
int level = GetTopLevel(); int level = GetTopLevel();
auto& clusterset = GetClusterSet(level); auto& clusterset = GetClusterSet(level);
InsertCluster(level, std::move(cluster), oversized ? QualityLevel::OVERSIZED_SINGLETON : QualityLevel::OPTIMAL); InsertCluster(level, std::move(cluster), oversized ? QualityLevel::OVERSIZED_SINGLETON : QualityLevel::OPTIMAL);
cluster_ptr->Updated(*this, level); cluster_ptr->Updated(*this, /*level=*/level, /*rename=*/false);
clusterset.m_cluster_usage += cluster_ptr->TotalMemoryUsage(); clusterset.m_cluster_usage += cluster_ptr->TotalMemoryUsage();
++clusterset.m_txcount; ++clusterset.m_txcount;
// Deal with individually oversized transactions. // Deal with individually oversized transactions.
@@ -2146,8 +2252,6 @@ TxGraph::Ref TxGraphImpl::AddTransaction(const FeePerWeight& feerate) noexcept
clusterset.m_oversized = true; clusterset.m_oversized = true;
clusterset.m_group_data = std::nullopt; clusterset.m_group_data = std::nullopt;
} }
// Return the Ref.
return ret;
} }
void TxGraphImpl::RemoveTransaction(const Ref& arg) noexcept void TxGraphImpl::RemoveTransaction(const Ref& arg) noexcept
@@ -2574,6 +2678,10 @@ void TxGraphImpl::CommitStaging() noexcept
// Staging must exist. // Staging must exist.
Assume(m_staging_clusterset.has_value()); Assume(m_staging_clusterset.has_value());
Assume(m_main_chunkindex_observers == 0); Assume(m_main_chunkindex_observers == 0);
// Get rid of removed transactions in staging before moving to main, so they do not need to be
// added to the chunk index there. Doing so is impossible if they were unlinked, and thus have
// no Ref anymore to pass to the fallback comparator.
ApplyRemovals(/*up_to_level=*/1);
// Delete all conflicting Clusters in main, to make place for moving the staging ones // Delete all conflicting Clusters in main, to make place for moving the staging ones
// there. All of these have been copied to staging in PullIn(). // there. All of these have been copied to staging in PullIn().
auto conflicts = GetConflicts(); auto conflicts = GetConflicts();
@@ -2619,7 +2727,7 @@ void GenericClusterImpl::SetFee(TxGraphImpl& graph, int level, DepGraphIndex idx
} else if (IsAcceptable()) { } else if (IsAcceptable()) {
graph.SetClusterQuality(level, m_quality, m_setindex, QualityLevel::NEEDS_RELINEARIZE); graph.SetClusterQuality(level, m_quality, m_setindex, QualityLevel::NEEDS_RELINEARIZE);
} }
Updated(graph, level); Updated(graph, /*level=*/level, /*rename=*/false);
} }
void SingletonClusterImpl::SetFee(TxGraphImpl& graph, int level, DepGraphIndex idx, int64_t fee) noexcept void SingletonClusterImpl::SetFee(TxGraphImpl& graph, int level, DepGraphIndex idx, int64_t fee) noexcept
@@ -2627,7 +2735,7 @@ void SingletonClusterImpl::SetFee(TxGraphImpl& graph, int level, DepGraphIndex i
Assume(GetTxCount()); Assume(GetTxCount());
Assume(idx == 0); Assume(idx == 0);
m_feerate.fee = fee; m_feerate.fee = fee;
Updated(graph, level); Updated(graph, /*level=*/level, /*rename=*/false);
} }
void TxGraphImpl::SetTransactionFee(const Ref& ref, int64_t fee) noexcept void TxGraphImpl::SetTransactionFee(const Ref& ref, int64_t fee) noexcept
@@ -2740,6 +2848,8 @@ void GenericClusterImpl::SanityCheck(const TxGraphImpl& graph, int level) const
LinearizationIndex linindex{0}; LinearizationIndex linindex{0};
DepGraphIndex chunk_pos{0}; //!< position within the current chunk DepGraphIndex chunk_pos{0}; //!< position within the current chunk
assert(m_depgraph.IsAcyclic()); assert(m_depgraph.IsAcyclic());
if (m_linearization.empty()) return;
FeeFrac equal_feerate_prefix = linchunking[chunk_num].feerate;
for (auto lin_pos : m_linearization) { for (auto lin_pos : m_linearization) {
assert(lin_pos < m_mapping.size()); assert(lin_pos < m_mapping.size());
const auto& entry = graph.m_entries[m_mapping[lin_pos]]; const auto& entry = graph.m_entries[m_mapping[lin_pos]];
@@ -2756,12 +2866,22 @@ void GenericClusterImpl::SanityCheck(const TxGraphImpl& graph, int level) const
assert(entry.m_main_lin_index == linindex); assert(entry.m_main_lin_index == linindex);
++linindex; ++linindex;
if (!linchunking[chunk_num].transactions[lin_pos]) { if (!linchunking[chunk_num].transactions[lin_pos]) {
// First transaction of a new chunk.
++chunk_num; ++chunk_num;
assert(chunk_num < linchunking.size());
chunk_pos = 0; chunk_pos = 0;
if (linchunking[chunk_num].feerate << equal_feerate_prefix) {
equal_feerate_prefix = linchunking[chunk_num].feerate;
} else {
assert(!(linchunking[chunk_num].feerate >> equal_feerate_prefix));
equal_feerate_prefix += linchunking[chunk_num].feerate;
}
} }
assert(entry.m_main_chunk_feerate == linchunking[chunk_num].feerate); assert(entry.m_main_chunk_feerate == linchunking[chunk_num].feerate);
assert(entry.m_main_equal_feerate_chunk_prefix_size == equal_feerate_prefix.size);
// Verify that an entry in the chunk index exists for every chunk-ending transaction. // Verify that an entry in the chunk index exists for every chunk-ending transaction.
++chunk_pos; ++chunk_pos;
if (graph.m_main_clusterset.m_to_remove.empty()) {
bool is_chunk_end = (chunk_pos == linchunking[chunk_num].transactions.Count()); bool is_chunk_end = (chunk_pos == linchunking[chunk_num].transactions.Count());
assert((entry.m_main_chunkindex_iterator != graph.m_main_chunkindex.end()) == is_chunk_end); assert((entry.m_main_chunkindex_iterator != graph.m_main_chunkindex.end()) == is_chunk_end);
if (is_chunk_end) { if (is_chunk_end) {
@@ -2772,6 +2892,7 @@ void GenericClusterImpl::SanityCheck(const TxGraphImpl& graph, int level) const
assert(chunk_data.m_chunk_count == chunk_pos); assert(chunk_data.m_chunk_count == chunk_pos);
} }
} }
}
// If this Cluster has an acceptable quality level, its chunks must be connected. // If this Cluster has an acceptable quality level, its chunks must be connected.
assert(m_depgraph.IsConnected(linchunking[chunk_num].transactions)); assert(m_depgraph.IsConnected(linchunking[chunk_num].transactions));
} }
@@ -2793,12 +2914,15 @@ void SingletonClusterImpl::SanityCheck(const TxGraphImpl& graph, int level) cons
if (level == 0 && IsAcceptable()) { if (level == 0 && IsAcceptable()) {
assert(entry.m_main_lin_index == 0); assert(entry.m_main_lin_index == 0);
assert(entry.m_main_chunk_feerate == m_feerate); assert(entry.m_main_chunk_feerate == m_feerate);
assert(entry.m_main_equal_feerate_chunk_prefix_size == m_feerate.size);
if (graph.m_main_clusterset.m_to_remove.empty()) {
assert(entry.m_main_chunkindex_iterator != graph.m_main_chunkindex.end()); assert(entry.m_main_chunkindex_iterator != graph.m_main_chunkindex.end());
auto& chunk_data = *entry.m_main_chunkindex_iterator; auto& chunk_data = *entry.m_main_chunkindex_iterator;
assert(chunk_data.m_chunk_count == LinearizationIndex(-1)); assert(chunk_data.m_chunk_count == LinearizationIndex(-1));
} }
} }
} }
}
void TxGraphImpl::SanityCheck() const void TxGraphImpl::SanityCheck() const
{ {
@@ -3438,7 +3562,11 @@ TxGraph::Ref::Ref(Ref&& other) noexcept
std::swap(m_index, other.m_index); std::swap(m_index, other.m_index);
} }
std::unique_ptr<TxGraph> MakeTxGraph(unsigned max_cluster_count, uint64_t max_cluster_size, uint64_t acceptable_iters) noexcept std::unique_ptr<TxGraph> MakeTxGraph(
unsigned max_cluster_count,
uint64_t max_cluster_size,
uint64_t acceptable_iters,
const std::function<std::strong_ordering(const TxGraph::Ref&, const TxGraph::Ref&)>& fallback_order) noexcept
{ {
return std::make_unique<TxGraphImpl>(max_cluster_count, max_cluster_size, acceptable_iters); return std::make_unique<TxGraphImpl>(max_cluster_count, max_cluster_size, acceptable_iters, fallback_order);
} }
+23 -10
View File
@@ -4,6 +4,7 @@
#include <compare> #include <compare>
#include <cstdint> #include <cstdint>
#include <functional>
#include <memory> #include <memory>
#include <optional> #include <optional>
#include <utility> #include <utility>
@@ -67,12 +68,14 @@ public:
/** Virtual destructor, so inheriting is safe. */ /** Virtual destructor, so inheriting is safe. */
virtual ~TxGraph() = default; virtual ~TxGraph() = default;
/** Construct a new transaction with the specified feerate, and return a Ref to it. /** Initialize arg (which must be an empty Ref) to refer to a new transaction in this graph
* with the specified feerate.
*
* If a staging graph exists, the new transaction is only created there. feerate.size must be * If a staging graph exists, the new transaction is only created there. feerate.size must be
* strictly positive. In all further calls, only Refs created by AddTransaction() are allowed * strictly positive. In all further calls, only Refs passed to AddTransaction() are allowed
* to be passed to this TxGraph object (or empty Ref objects). Ref objects may outlive the * to be passed to this TxGraph object (or empty Ref objects). Ref objects may outlive the
* TxGraph they were created for. */ * TxGraph they were added to. */
[[nodiscard]] virtual Ref AddTransaction(const FeePerWeight& feerate) noexcept = 0; virtual void AddTransaction(Ref& arg, const FeePerWeight& feerate) noexcept = 0;
/** Remove the specified transaction. If a staging graph exists, the removal only happens /** Remove the specified transaction. If a staging graph exists, the removal only happens
* there. This is a no-op if the transaction was already removed. * there. This is a no-op if the transaction was already removed.
* *
@@ -235,8 +238,7 @@ public:
/** Index into the Graph's m_entries. Only used if m_graph != nullptr. */ /** Index into the Graph's m_entries. Only used if m_graph != nullptr. */
GraphIndex m_index = GraphIndex(-1); GraphIndex m_index = GraphIndex(-1);
public: public:
/** Construct an empty Ref. Non-empty Refs can only be created using /** Construct an empty Ref. It can be initialized through TxGraph::AddTransaction. */
* TxGraph::AddTransaction. */
Ref() noexcept = default; Ref() noexcept = default;
/** Destroy this Ref. If it is not empty, the corresponding transaction is removed (in both /** Destroy this Ref. If it is not empty, the corresponding transaction is removed (in both
* main and staging, if it exists). */ * main and staging, if it exists). */
@@ -252,9 +254,20 @@ public:
}; };
/** Construct a new TxGraph with the specified limit on the number of transactions within a cluster, /** Construct a new TxGraph with the specified limit on the number of transactions within a cluster,
* and on the sum of transaction sizes within a cluster. max_cluster_count cannot exceed * and on the sum of transaction sizes within a cluster.
* MAX_CLUSTER_COUNT_LIMIT. acceptable_iters controls how many linearization optimization *
* steps will be performed per cluster before they are considered to be of acceptable quality. */ * - max_cluster_count cannot exceed MAX_CLUSTER_COUNT_LIMIT.
std::unique_ptr<TxGraph> MakeTxGraph(unsigned max_cluster_count, uint64_t max_cluster_size, uint64_t acceptable_iters) noexcept; * - acceptable_iters controls how many linearization optimization steps will be performed per
* cluster before they are considered to be of acceptable quality.
* - fallback_order determines how to break tie-breaks between transactions:
* fallback_order(a, b) < 0 means a is "better" than b, and will (in case of ties) be placed
* first. This ordering must be stable over the transactions' lifetimes.
*/
std::unique_ptr<TxGraph> MakeTxGraph(
unsigned max_cluster_count,
uint64_t max_cluster_size,
uint64_t acceptable_iters,
const std::function<std::strong_ordering(const TxGraph::Ref&, const TxGraph::Ref&)>& fallback_order
) noexcept;
#endif // BITCOIN_TXGRAPH_H #endif // BITCOIN_TXGRAPH_H
+12 -3
View File
@@ -176,7 +176,15 @@ static CTxMemPool::Options&& Flatten(CTxMemPool::Options&& opts, bilingual_str&
CTxMemPool::CTxMemPool(Options opts, bilingual_str& error) CTxMemPool::CTxMemPool(Options opts, bilingual_str& error)
: m_opts{Flatten(std::move(opts), error)} : m_opts{Flatten(std::move(opts), error)}
{ {
m_txgraph = MakeTxGraph(m_opts.limits.cluster_count, m_opts.limits.cluster_size_vbytes * WITNESS_SCALE_FACTOR, ACCEPTABLE_ITERS); m_txgraph = MakeTxGraph(
/*max_cluster_count=*/m_opts.limits.cluster_count,
/*max_cluster_size=*/m_opts.limits.cluster_size_vbytes * WITNESS_SCALE_FACTOR,
/*acceptable_iters=*/ACCEPTABLE_ITERS,
/*fallback_order=*/[&](const TxGraph::Ref& a, const TxGraph::Ref& b) noexcept {
const Txid& txid_a = static_cast<const CTxMemPoolEntry&>(a).GetTx().GetHash();
const Txid& txid_b = static_cast<const CTxMemPoolEntry&>(b).GetTx().GetHash();
return txid_a <=> txid_b;
});
} }
bool CTxMemPool::isSpent(const COutPoint& outpoint) const bool CTxMemPool::isSpent(const COutPoint& outpoint) const
@@ -1000,8 +1008,9 @@ CTxMemPool::ChangeSet::TxHandle CTxMemPool::ChangeSet::StageAddition(const CTran
CAmount delta{0}; CAmount delta{0};
m_pool->ApplyDelta(tx->GetHash(), delta); m_pool->ApplyDelta(tx->GetHash(), delta);
TxGraph::Ref ref(m_pool->m_txgraph->AddTransaction(FeePerWeight(fee, GetSigOpsAdjustedWeight(GetTransactionWeight(*tx), sigops_cost, ::nBytesPerSigOp)))); FeePerWeight feerate(fee, GetSigOpsAdjustedWeight(GetTransactionWeight(*tx), sigops_cost, ::nBytesPerSigOp));
auto newit = m_to_add.emplace(std::move(ref), tx, fee, time, entry_height, entry_sequence, spends_coinbase, sigops_cost, lp).first; auto newit = m_to_add.emplace(tx, fee, time, entry_height, entry_sequence, spends_coinbase, sigops_cost, lp).first;
m_pool->m_txgraph->AddTransaction(const_cast<CTxMemPoolEntry&>(*newit), feerate);
if (delta) { if (delta) {
newit->UpdateModifiedFee(delta); newit->UpdateModifiedFee(delta);
m_pool->m_txgraph->SetTransactionFee(*newit, newit->GetModifiedFee()); m_pool->m_txgraph->SetTransactionFee(*newit, newit->GetModifiedFee());
+3 -3
View File
@@ -239,9 +239,9 @@ class MempoolPackagesTest(BitcoinTestFramework):
self.generate(self.nodes[0], 1) self.generate(self.nodes[0], 1)
self.trigger_reorg(fork_blocks, self.nodes[0]) self.trigger_reorg(fork_blocks, self.nodes[0])
# Check if the txs are returned to the mempool (though the transaction ordering may # Check that the txs are returned to the mempool, and that transaction ordering is
# change as it is non-deterministic). # unchanged, as it is deterministic.
assert_equal(set(self.nodes[0].getrawmempool()), set(mempool0)) assert_equal(self.nodes[0].getrawmempool(), mempool0)
# Clean-up the mempool # Clean-up the mempool
self.generate(self.nodes[0], 1) self.generate(self.nodes[0], 1)