/root/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 | 0 | { | 
| 12 |  |     /** Array to allow indexed access to input diagrams. */ | 
| 13 | 0 |     const std::array<std::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 | } |