Coverage Report

Created: 2025-06-10 13:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}