/bitcoin/src/util/feefrac.cpp
Line | Count | Source |
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(std::span<const FeeFrac> chunks0, std::span<const FeeFrac> chunks1) |
11 | 231 | { |
12 | | /** Array to allow indexed access to input diagrams. */ |
13 | 231 | const std::array<std::span<const FeeFrac>, 2> chunk = {chunks0, chunks1}; |
14 | | /** How many elements we have processed in each input. */ |
15 | 231 | size_t next_index[2] = {0, 0}; |
16 | | /** Accumulated fee/sizes in diagrams, up to next_index[i] - 1. */ |
17 | 231 | FeeFrac accum[2]; |
18 | | /** Whether the corresponding input is strictly better than the other at least in one place. */ |
19 | 231 | bool better_somewhere[2] = {false, false}; |
20 | | /** Get the first unprocessed point in diagram number dia. */ |
21 | 2.91k | 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 | 883 | const auto prev_point = [&](int dia) { return accum[dia]; }; |
24 | | /** Move to the next point in diagram number dia. */ |
25 | 897 | const auto advance = [&](int dia) { accum[dia] += chunk[dia][next_index[dia]++]; }; |
26 | | |
27 | 918 | do { |
28 | 918 | bool done_0 = next_index[0] == chunk[0].size(); |
29 | 918 | bool done_1 = next_index[1] == chunk[1].size(); |
30 | 918 | if (done_0 && done_1) break; Branch (30:13): [True: 77, False: 841]
Branch (30:23): [True: 35, False: 42]
|
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 | 883 | const int unproc_side = (done_0 || done_1) ? done_0 : next_point(0).size > next_point(1).size; Branch (34:34): [True: 42, False: 841]
Branch (34:44): [True: 163, False: 678]
|
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 | 883 | const FeeFrac& point_p = next_point(unproc_side); |
41 | 883 | const FeeFrac& point_a = prev_point(!unproc_side); |
42 | | |
43 | 883 | const auto slope_ap = point_p - point_a; |
44 | 883 | Assume(slope_ap.size > 0); |
45 | 883 | std::weak_ordering cmp = std::weak_ordering::equivalent; |
46 | 883 | if (done_0 || done_1) { Branch (46:13): [True: 42, False: 841]
Branch (46:23): [True: 163, False: 678]
|
47 | | // If a single side has no points left, act as if AB has slope tail_feerate(of 0). |
48 | 205 | Assume(!(done_0 && done_1)); |
49 | 205 | cmp = FeeRateCompare(slope_ap, FeeFrac(0, 1)); |
50 | 678 | } else { |
51 | | // If both sides have points left, compute B, and the slope of AB explicitly. |
52 | 678 | const FeeFrac& point_b = next_point(!unproc_side); |
53 | 678 | const auto slope_ab = point_b - point_a; |
54 | 678 | Assume(slope_ab.size >= slope_ap.size); |
55 | 678 | 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 | 678 | if (point_b.size == point_p.size) advance(!unproc_side); Branch (59:17): [True: 14, False: 664]
|
60 | 678 | } |
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 | 883 | if (std::is_gt(cmp)) better_somewhere[unproc_side] = true; Branch (63:13): [True: 734, False: 149]
|
64 | 883 | if (std::is_lt(cmp)) better_somewhere[!unproc_side] = true; Branch (64:13): [True: 139, False: 744]
|
65 | 883 | advance(unproc_side); |
66 | | |
67 | | // If both diagrams are better somewhere, they are incomparable. |
68 | 883 | if (better_somewhere[0] && better_somewhere[1]) return std::partial_ordering::unordered; Branch (68:13): [True: 301, False: 582]
Branch (68:36): [True: 196, False: 105]
|
69 | 883 | } while(true); Branch (69:13): [Folded - Ignored]
|
70 | | |
71 | | // Otherwise compare the better_somewhere values. |
72 | 35 | return better_somewhere[0] <=> better_somewhere[1]; |
73 | 231 | } |