Bitcoin Core 31.99.0
P2P Digital Currency
feefrac.cpp
Go to the documentation of this file.
1// Copyright (c) The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#include <util/feefrac.h>
6
7#include <util/check.h>
8
9#include <array>
10#include <cstddef>
11
12std::partial_ordering CompareChunks(std::span<const FeeFrac> chunks0, std::span<const FeeFrac> chunks1)
13{
15 const std::array<std::span<const FeeFrac>, 2> chunk = {chunks0, chunks1};
17 size_t next_index[2] = {0, 0};
19 FeeFrac accum[2];
21 bool better_somewhere[2] = {false, false};
23 const auto next_point = [&](int dia) { return chunk[dia][next_index[dia]] + accum[dia]; };
25 const auto prev_point = [&](int dia) { return accum[dia]; };
27 const auto advance = [&](int dia) { accum[dia] += chunk[dia][next_index[dia]++]; };
28
29 do {
30 bool done_0 = next_index[0] == chunk[0].size();
31 bool done_1 = next_index[1] == chunk[1].size();
32 if (done_0 && done_1) break;
33
34 // Determine which diagram has the first unprocessed point. If a single side is finished, use the
35 // other one. Only up to one can be done due to check above.
36 const int unproc_side = (done_0 || done_1) ? done_0 : next_point(0).size > next_point(1).size;
37
38 // Let `P` be the next point on diagram unproc_side, and `A` and `B` the previous and next points
39 // on the other diagram. We want to know if P lies above or below the line AB. To determine this, we
40 // compute the slopes of line AB and of line AP, and compare them. These slopes are fee per size,
41 // and can thus be expressed as FeeFracs.
42 const FeeFrac& point_p = next_point(unproc_side);
43 const FeeFrac& point_a = prev_point(!unproc_side);
44
45 const auto slope_ap = point_p - point_a;
46 Assume(slope_ap.size > 0);
47 std::weak_ordering cmp = std::weak_ordering::equivalent;
48 if (done_0 || done_1) {
49 // If a single side has no points left, act as if AB has slope tail_feerate(of 0).
50 Assume(!(done_0 && done_1));
51 cmp = FeeRateCompare(slope_ap, FeeFrac(0, 1));
52 } else {
53 // If both sides have points left, compute B, and the slope of AB explicitly.
54 const FeeFrac& point_b = next_point(!unproc_side);
55 const auto slope_ab = point_b - point_a;
56 Assume(slope_ab.size >= slope_ap.size);
57 cmp = FeeRateCompare(slope_ap, slope_ab);
58
59 // If B and P have the same size, B can be marked as processed (in addition to P, see
60 // below), as we've already performed a comparison at this size.
61 if (point_b.size == point_p.size) advance(!unproc_side);
62 }
63 // If P lies above AB, unproc_side is better in P. If P lies below AB, then !unproc_side is
64 // better in P.
65 if (std::is_gt(cmp)) better_somewhere[unproc_side] = true;
66 if (std::is_lt(cmp)) better_somewhere[!unproc_side] = true;
67 advance(unproc_side);
68
69 // If both diagrams are better somewhere, they are incomparable.
70 if (better_somewhere[0] && better_somewhere[1]) return std::partial_ordering::unordered;
71 } while(true);
72
73 // Otherwise compare the better_somewhere values.
74 return better_somewhere[0] <=> better_somewhere[1];
75}
#define Assume(val)
Assume is the identity function.
Definition: check.h:128
Data structure storing a fee and size, ordered by increasing fee/size.
Definition: feefrac.h:41
int32_t size
Definition: feefrac.h:109
std::partial_ordering CompareChunks(std::span< const FeeFrac > chunks0, std::span< const FeeFrac > chunks1)
Compare the feerate diagrams implied by the provided sorted chunks data.
Definition: feefrac.cpp:12