/root/bitcoin/src/util/feefrac.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | #include <algorithm> |
7 | | #include <array> |
8 | | #include <vector> |
9 | | |
10 | | std::partial_ordering CompareChunks(Span<const FeeFrac> chunks0, Span<const FeeFrac> chunks1) |
11 | 0 | { |
12 | | /** Array to allow indexed access to input diagrams. */ |
13 | 0 | const std::array<Span<const FeeFrac>, 2> chunk = {chunks0, chunks1}; |
14 | | /** How many elements we have processed in each input. */ |
15 | 0 | size_t next_index[2] = {0, 0}; |
16 | | /** Accumulated fee/sizes in diagrams, up to next_index[i] - 1. */ |
17 | 0 | FeeFrac accum[2]; |
18 | | /** Whether the corresponding input is strictly better than the other at least in one place. */ |
19 | 0 | bool better_somewhere[2] = {false, false}; |
20 | | /** Get the first unprocessed point in diagram number dia. */ |
21 | 0 | const auto next_point = [&](int dia) { return chunk[dia][next_index[dia]] + accum[dia]; }; |
22 | | /** Get the last processed point in diagram number dia. */ |
23 | 0 | const auto prev_point = [&](int dia) { return accum[dia]; }; |
24 | | /** Move to the next point in diagram number dia. */ |
25 | 0 | const auto advance = [&](int dia) { accum[dia] += chunk[dia][next_index[dia]++]; }; |
26 | |
|
27 | 0 | do { |
28 | 0 | bool done_0 = next_index[0] == chunk[0].size(); |
29 | 0 | bool done_1 = next_index[1] == chunk[1].size(); |
30 | 0 | if (done_0 && done_1) break; |
31 | | |
32 | | // Determine which diagram has the first unprocessed point. If a single side is finished, use the |
33 | | // other one. Only up to one can be done due to check above. |
34 | 0 | const int unproc_side = (done_0 || done_1) ? done_0 : next_point(0).size > next_point(1).size; |
35 | | |
36 | | // Let `P` be the next point on diagram unproc_side, and `A` and `B` the previous and next points |
37 | | // on the other diagram. We want to know if P lies above or below the line AB. To determine this, we |
38 | | // compute the slopes of line AB and of line AP, and compare them. These slopes are fee per size, |
39 | | // and can thus be expressed as FeeFracs. |
40 | 0 | const FeeFrac& point_p = next_point(unproc_side); |
41 | 0 | const FeeFrac& point_a = prev_point(!unproc_side); |
42 | |
|
43 | 0 | const auto slope_ap = point_p - point_a; |
44 | 0 | Assume(slope_ap.size > 0); |
45 | 0 | std::weak_ordering cmp = std::weak_ordering::equivalent; |
46 | 0 | if (done_0 || done_1) { |
47 | | // If a single side has no points left, act as if AB has slope tail_feerate(of 0). |
48 | 0 | Assume(!(done_0 && done_1)); |
49 | 0 | cmp = FeeRateCompare(slope_ap, FeeFrac(0, 1)); |
50 | 0 | } else { |
51 | | // If both sides have points left, compute B, and the slope of AB explicitly. |
52 | 0 | const FeeFrac& point_b = next_point(!unproc_side); |
53 | 0 | const auto slope_ab = point_b - point_a; |
54 | 0 | Assume(slope_ab.size >= slope_ap.size); |
55 | 0 | cmp = FeeRateCompare(slope_ap, slope_ab); |
56 | | |
57 | | // If B and P have the same size, B can be marked as processed (in addition to P, see |
58 | | // below), as we've already performed a comparison at this size. |
59 | 0 | if (point_b.size == point_p.size) advance(!unproc_side); |
60 | 0 | } |
61 | | // If P lies above AB, unproc_side is better in P. If P lies below AB, then !unproc_side is |
62 | | // better in P. |
63 | 0 | if (std::is_gt(cmp)) better_somewhere[unproc_side] = true; |
64 | 0 | if (std::is_lt(cmp)) better_somewhere[!unproc_side] = true; |
65 | 0 | advance(unproc_side); |
66 | | |
67 | | // If both diagrams are better somewhere, they are incomparable. |
68 | 0 | if (better_somewhere[0] && better_somewhere[1]) return std::partial_ordering::unordered; |
69 | 0 | } while(true); |
70 | | |
71 | | // Otherwise compare the better_somewhere values. |
72 | 0 | return better_somewhere[0] <=> better_somewhere[1]; |
73 | 0 | } |