fn propagate_counts()

in src/reader.rs [1165:1216]


    fn propagate_counts(
        blocks: &SmallVec<[GcovBlock; 16]>,
        edges: &mut SmallVec<[GcovEdge; 16]>,
        block_no: usize,
        pred_arc: Option<usize>,
        visited: &mut FxHashSet<usize>,
    ) -> u64 {
        // For each basic block, the sum of incoming edge counts equals the sum of
        // outgoing edge counts by Kirchoff's circuit law. If the unmeasured arcs form a
        // spanning tree, the count for each unmeasured arc (GCOV_ARC_ON_TREE) can be
        // uniquely identified.

        // Prevent infinite recursion
        if !visited.insert(block_no) {
            return 0;
        }
        let mut positive_excess = 0;
        let mut negative_excess = 0;
        let block = &blocks[block_no];
        for edge_id in block.source.iter() {
            if pred_arc != Some(*edge_id) {
                let edge = &edges[*edge_id];
                positive_excess += if edge.is_on_tree() {
                    let source = edge.source;
                    Self::propagate_counts(blocks, edges, source, Some(*edge_id), visited)
                } else {
                    edge.counter
                };
            }
        }
        for edge_id in block.destination.iter() {
            if pred_arc != Some(*edge_id) {
                let edge = &edges[*edge_id];
                negative_excess += if edge.is_on_tree() {
                    let destination = edge.destination;
                    Self::propagate_counts(blocks, edges, destination, Some(*edge_id), visited)
                } else {
                    edge.counter
                };
            }
        }
        let excess = if positive_excess >= negative_excess {
            positive_excess - negative_excess
        } else {
            negative_excess - positive_excess
        };
        if let Some(id) = pred_arc {
            let edge = &mut edges[id];
            edge.counter = excess;
        }
        excess
    }