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

daisytuner / docc / 22023884668

14 Feb 2026 08:36PM UTC coverage: 64.903% (-1.4%) from 66.315%
22023884668

Pull #525

github

web-flow
Merge 1d47f8bf2 into 9d01cacd5
Pull Request #525: Step 3 (Native Tensor Support): Refactor Python Frontend

2522 of 3435 new or added lines in 32 files covered. (73.42%)

320 existing lines in 15 files now uncovered.

23204 of 35752 relevant lines covered (64.9%)

370.03 hits per line

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

81.32
/sdfg/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(
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✔
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
    // Normalize negative axes
45
    for (auto& axis : sorted_axes) {
3✔
46
        if (axis < 0) {
3✔
47
            axis = static_cast<int64_t>(shape_.size()) + axis;
2✔
48
        }
2✔
49
        // Validate axis is in bounds
50
        if (axis < 0 || axis >= static_cast<int64_t>(shape_.size())) {
3✔
NEW
51
            throw InvalidSDFGException(
×
NEW
52
                "Library Node: Axis value out of bounds. Axis: " + std::to_string(axis) +
×
NEW
53
                " Shape size: " + std::to_string(shape_.size())
×
NEW
54
            );
×
NEW
55
        }
×
56
    }
3✔
57
    std::sort(sorted_axes.begin(), sorted_axes.end());
3✔
58

59
    for (size_t i = 0; i < shape_.size(); ++i) {
8✔
60
        bool is_axis = false;
5✔
61
        for (auto axis : sorted_axes) {
5✔
62
            if (axis == (int64_t) i) {
5✔
63
                is_axis = true;
3✔
64
                break;
3✔
65
            }
3✔
66
        }
5✔
67

68
        if (is_axis) {
5✔
69
            if (keepdims_) {
3✔
70
                output_shape.push_back(symbolic::one());
×
71
            }
×
72
        } else {
3✔
73
            output_shape.push_back(shape_[i]);
2✔
74
        }
2✔
75
    }
5✔
76

77
    // Create SumNode
78
    auto& sum_block = builder.add_block_before(parent, block, {}, this->debug_info());
3✔
79
    auto& sum_node = builder.add_library_node<SumNode>(sum_block, this->debug_info(), shape_, axes_, keepdims_);
3✔
80

81
    // Create intermediate buffer for Sum result
82
    auto& sum_in_node = builder.add_access(sum_block, in_node.data(), this->debug_info());
3✔
83
    auto& sum_out_node = builder.add_access(sum_block, out_node.data(), this->debug_info());
3✔
84

85
    // Connect Input -> Sum -> Tmp
86
    builder.add_computational_memlet(sum_block, sum_in_node, sum_node, "X", {}, in_edge.base_type(), this->debug_info());
3✔
87
    builder
3✔
88
        .add_computational_memlet(sum_block, sum_node, "Y", sum_out_node, {}, out_edge.base_type(), this->debug_info());
3✔
89

90
    // Create Count (symbolically)
91
    auto count_container = builder.find_new_name("_mean_count");
3✔
92
    builder.add_container(count_container, types::Scalar(types::PrimitiveType::Int64));
3✔
93

94
    symbolic::Expression count_expr = symbolic::one();
3✔
95
    for (auto axis : axes_) {
3✔
96
        int64_t ax = axis;
3✔
97
        if (ax < 0) ax += shape_.size();
3✔
98
        symbolic::Expression dim = shape_[ax];
3✔
99
        count_expr = symbolic::mul(count_expr, dim);
3✔
100
    }
3✔
101
    auto& count_block =
3✔
102
        builder.add_block_before(parent, block, {{symbolic::symbol(count_container), count_expr}}, this->debug_info());
3✔
103

104
    // Create DivNode
105
    auto& div_block = builder.add_block_before(parent, block, transition.assignments(), this->debug_info());
3✔
106
    auto& div_node = builder.add_library_node<DivNode>(div_block, this->debug_info(), output_shape);
3✔
107

108
    // Connect Tmp -> Div (A)
109
    auto& div_in_node = builder.add_access(div_block, out_node.data(), this->debug_info());
3✔
110
    builder
3✔
111
        .add_computational_memlet(div_block, div_in_node, div_node, "A", {}, out_edge.base_type(), this->debug_info());
3✔
112

113
    // Connect Count -> Div (B)
114
    types::Tensor scalar_tensor(out_edge.base_type().primitive_type(), {});
3✔
115
    auto& div_count_node = builder.add_access(div_block, count_container, this->debug_info());
3✔
116
    builder.add_computational_memlet(div_block, div_count_node, div_node, "B", {}, scalar_tensor, this->debug_info());
3✔
117

118
    // Connect Div -> Output (C)
119
    auto& div_out_node = builder.add_access(div_block, out_node.data(), this->debug_info());
3✔
120
    builder
3✔
121
        .add_computational_memlet(div_block, div_node, "C", div_out_node, {}, out_edge.base_type(), this->debug_info());
3✔
122

123

124
    // Cleanup
125
    builder.remove_memlet(block, in_edge);
3✔
126
    builder.remove_memlet(block, out_edge);
3✔
127
    builder.remove_node(block, in_node);
3✔
128
    builder.remove_node(block, out_node);
3✔
129
    builder.remove_node(block, *this);
3✔
130

131
    int last_index = parent.index(block);
3✔
132
    builder.remove_child(parent, last_index);
3✔
133

134
    return true;
3✔
135
}
3✔
136

137
bool MeanNode::expand_reduction(
138
    builder::StructuredSDFGBuilder& builder,
139
    analysis::AnalysisManager& analysis_manager,
140
    structured_control_flow::Sequence& body,
141
    const std::string& input_name,
142
    const std::string& output_name,
143
    const types::Tensor& input_type,
144
    const types::Tensor& output_type,
145
    const data_flow::Subset& input_subset,
146
    const data_flow::Subset& output_subset
147
) {
×
148
    throw std::runtime_error("MeanNode::expand_reduction should not be called");
×
149
}
×
150

151
std::string MeanNode::identity() const { return "0"; }
×
152

153
std::unique_ptr<data_flow::DataFlowNode> MeanNode::
154
    clone(size_t element_id, const graph::Vertex vertex, data_flow::DataFlowGraph& parent) const {
×
155
    return std::unique_ptr<
×
156
        data_flow::DataFlowNode>(new MeanNode(element_id, debug_info_, vertex, parent, shape_, axes_, keepdims_));
×
157
}
×
158

159
} // namespace tensor
160
} // namespace math
161
} // 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