• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

daisytuner / sdfglib / 20588702450

29 Dec 2025 11:48PM UTC coverage: 39.581%. Remained the same
20588702450

push

github

web-flow
Merge pull request #412 from daisytuner/mean-std-nodes

adds mean/std library nodes

14647 of 48066 branches covered (30.47%)

Branch coverage included in aggregate %.

225 of 622 new or added lines in 14 files covered. (36.17%)

17 existing lines in 2 files now uncovered.

12489 of 20493 relevant lines covered (60.94%)

87.19 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

60.87
/src/data_flow/library_nodes/math/tensor/reduce_ops/mean_node.cpp
1
#include "sdfg/data_flow/library_nodes/math/tensor/reduce_ops/mean_node.h"
2

3
#include "sdfg/analysis/scope_analysis.h"
4
#include "sdfg/builder/structured_sdfg_builder.h"
5
#include "sdfg/data_flow/library_nodes/math/tensor/elementwise_ops/div_node.h"
6
#include "sdfg/data_flow/library_nodes/math/tensor/reduce_ops/sum_node.h"
7

8
namespace sdfg {
9
namespace math {
10
namespace tensor {
11

12
MeanNode::MeanNode(
7✔
13
    size_t element_id,
14
    const DebugInfo& debug_info,
15
    const graph::Vertex vertex,
16
    data_flow::DataFlowGraph& parent,
17
    const std::vector<symbolic::Expression>& shape,
18
    const std::vector<int64_t>& axes,
19
    bool keepdims
20
)
21
    : ReduceNode(element_id, debug_info, vertex, parent, LibraryNodeType_Mean, shape, axes, keepdims) {}
7✔
22

23
bool MeanNode::expand(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
3✔
24
    auto& dataflow = this->get_parent();
3✔
25
    auto& block = static_cast<structured_control_flow::Block&>(*dataflow.get_parent());
3✔
26

27
    if (dataflow.in_degree(*this) != 1 || dataflow.out_degree(*this) != 1) {
3!
NEW
28
        return false;
×
29
    }
30

31
    auto& scope_analysis = analysis_manager.get<analysis::ScopeAnalysis>();
3✔
32
    auto& parent = static_cast<structured_control_flow::Sequence&>(*scope_analysis.parent_scope(&block));
3✔
33
    int index = parent.index(block);
3✔
34
    auto& transition = parent.at(index).second;
3✔
35

36
    auto& in_edge = *dataflow.in_edges(*this).begin();
3✔
37
    auto& out_edge = *dataflow.out_edges(*this).begin();
3✔
38
    auto& in_node = static_cast<data_flow::AccessNode&>(in_edge.src());
3✔
39
    auto& out_node = static_cast<data_flow::AccessNode&>(out_edge.dst());
3✔
40

41
    // Calculate output shape
42
    std::vector<symbolic::Expression> output_shape;
3✔
43
    std::vector<int64_t> sorted_axes = axes_;
3!
44
    std::sort(sorted_axes.begin(), sorted_axes.end());
3!
45

46
    for (size_t i = 0; i < shape_.size(); ++i) {
8✔
47
        bool is_axis = false;
5✔
48
        for (auto axis : sorted_axes) {
9✔
49
            if (axis == (int64_t) i) {
5✔
50
                is_axis = true;
1✔
51
                break;
1✔
52
            }
53
        }
54

55
        if (is_axis) {
5✔
56
            if (keepdims_) {
1!
NEW
57
                output_shape.push_back(symbolic::one());
×
NEW
58
            }
×
59
        } else {
1✔
60
            output_shape.push_back(shape_[i]);
4!
61
        }
62
    }
5✔
63
    sdfg::types::Scalar element_type(out_edge.base_type().primitive_type());
3!
64

65
    // Create SumNode
66
    auto& sum_block = builder.add_block_before(parent, block, {}, this->debug_info());
3!
67
    auto& sum_node = builder.add_library_node<SumNode>(sum_block, this->debug_info(), shape_, axes_, keepdims_);
3!
68

69
    // Create intermediate buffer for Sum result
70
    auto& sum_in_node = builder.add_access(sum_block, in_node.data(), this->debug_info());
3!
71
    auto& sum_out_node = builder.add_access(sum_block, out_node.data(), this->debug_info());
3!
72

73
    // Connect Input -> Sum -> Tmp
74
    builder.add_computational_memlet(sum_block, sum_in_node, sum_node, "X", {}, in_edge.base_type(), this->debug_info());
3!
75
    builder
6✔
76
        .add_computational_memlet(sum_block, sum_node, "Y", sum_out_node, {}, out_edge.base_type(), this->debug_info());
3!
77

78
    // Create Count (symbolically)
79
    auto count_container = builder.find_new_name("_mean_count");
3!
80
    builder.add_container(count_container, types::Scalar(types::PrimitiveType::Int64));
3!
81

82
    symbolic::Expression count_expr = symbolic::one();
3!
83
    for (auto axis : axes_) {
6✔
84
        int64_t ax = axis;
3✔
85
        if (ax < 0) ax += shape_.size();
3✔
86
        symbolic::Expression dim = shape_[ax];
3!
87
        count_expr = symbolic::mul(count_expr, dim);
3!
88
    }
3✔
89
    auto& count_block =
3✔
90
        builder.add_block_before(parent, block, {{symbolic::symbol(count_container), count_expr}}, this->debug_info());
3!
91

92
    // Create DivNode
93
    auto& div_block = builder.add_block_before(parent, block, transition.assignments(), this->debug_info());
3!
94
    auto& div_node = builder.add_library_node<DivNode>(div_block, this->debug_info(), output_shape);
3!
95

96
    // Connect Tmp -> Div (A)
97
    auto& div_in_node = builder.add_access(div_block, out_node.data(), this->debug_info());
3!
98
    builder
6✔
99
        .add_computational_memlet(div_block, div_in_node, div_node, "A", {}, out_edge.base_type(), this->debug_info());
3!
100

101
    // Connect Count -> Div (B)
102
    auto& div_count_node = builder.add_access(div_block, count_container, this->debug_info());
3!
103
    builder.add_computational_memlet(div_block, div_count_node, div_node, "B", {}, element_type, this->debug_info());
3!
104

105
    // Connect Div -> Output (C)
106
    auto& div_out_node = builder.add_access(div_block, out_node.data(), this->debug_info());
3!
107
    builder
6✔
108
        .add_computational_memlet(div_block, div_node, "C", div_out_node, {}, out_edge.base_type(), this->debug_info());
3!
109

110

111
    // Cleanup
112
    builder.remove_memlet(block, in_edge);
3!
113
    builder.remove_memlet(block, out_edge);
3!
114
    builder.remove_node(block, in_node);
3!
115
    builder.remove_node(block, out_node);
3!
116
    builder.remove_node(block, *this);
3!
117

118
    int last_index = parent.index(block);
3!
119
    builder.remove_child(parent, last_index);
3!
120

121
    return true;
3✔
122
}
3✔
123

NEW
124
bool MeanNode::expand_reduction(
×
125
    builder::StructuredSDFGBuilder& builder,
126
    analysis::AnalysisManager& analysis_manager,
127
    structured_control_flow::Sequence& body,
128
    const std::string& input_name,
129
    const std::string& output_name,
130
    const types::IType& input_type,
131
    const types::IType& output_type,
132
    const data_flow::Subset& input_subset,
133
    const data_flow::Subset& output_subset
134
) {
NEW
135
    throw std::runtime_error("MeanNode::expand_reduction should not be called");
×
NEW
136
}
×
137

NEW
138
std::string MeanNode::identity() const { return "0"; }
×
139

140
std::unique_ptr<data_flow::DataFlowNode> MeanNode::
NEW
141
    clone(size_t element_id, const graph::Vertex vertex, data_flow::DataFlowGraph& parent) const {
×
NEW
142
    return std::unique_ptr<
×
NEW
143
        data_flow::DataFlowNode>(new MeanNode(element_id, debug_info_, vertex, parent, shape_, axes_, keepdims_));
×
NEW
144
}
×
145

146
} // namespace tensor
147
} // namespace math
148
} // namespace sdfg
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc