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

daisytuner / sdfglib / 20585279183

29 Dec 2025 11:48PM UTC coverage: 39.581% (-0.8%) from 40.359%
20585279183

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%)

41 existing lines in 1 file 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

0.0
/src/data_flow/library_nodes/math/tensor/broadcast_node.cpp
1
#include "sdfg/data_flow/library_nodes/math/tensor/broadcast_node.h"
2
#include "sdfg/analysis/scope_analysis.h"
3
#include "sdfg/builder/structured_sdfg_builder.h"
4
#include "sdfg/structured_control_flow/for.h"
5

6
namespace sdfg {
7
namespace math {
8
namespace tensor {
9

NEW
10
BroadcastNode::BroadcastNode(
×
11
    size_t element_id,
12
    const DebugInfo& debug_info,
13
    const graph::Vertex vertex,
14
    data_flow::DataFlowGraph& parent,
15
    const std::vector<symbolic::Expression>& input_shape,
16
    const std::vector<symbolic::Expression>& output_shape
17
)
NEW
18
    : MathNode(
×
NEW
19
          element_id,
×
NEW
20
          debug_info,
×
NEW
21
          vertex,
×
NEW
22
          parent,
×
23
          LibraryNodeType_Broadcast,
NEW
24
          {"Y"},
×
NEW
25
          {"X"},
×
26
          data_flow::ImplementationType_NONE
27
      ),
NEW
28
      input_shape_(input_shape), output_shape_(output_shape) {}
×
29

NEW
30
symbolic::SymbolSet BroadcastNode::symbols() const {
×
NEW
31
    symbolic::SymbolSet syms;
×
NEW
32
    for (const auto& dim : input_shape_) {
×
NEW
33
        for (auto& atom : symbolic::atoms(dim)) {
×
NEW
34
            syms.insert(atom);
×
35
        }
36
    }
NEW
37
    for (const auto& dim : output_shape_) {
×
NEW
38
        for (auto& atom : symbolic::atoms(dim)) {
×
NEW
39
            syms.insert(atom);
×
40
        }
41
    }
NEW
42
    return syms;
×
NEW
43
}
×
44

NEW
45
void BroadcastNode::replace(const symbolic::Expression old_expression, const symbolic::Expression new_expression) {
×
NEW
46
    for (auto& dim : input_shape_) {
×
NEW
47
        dim = symbolic::subs(dim, old_expression, new_expression);
×
48
    }
NEW
49
    for (auto& dim : output_shape_) {
×
NEW
50
        dim = symbolic::subs(dim, old_expression, new_expression);
×
51
    }
NEW
52
}
×
53

NEW
54
void BroadcastNode::validate(const Function& function) const {}
×
55

NEW
56
bool BroadcastNode::expand(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
×
NEW
57
    auto& dataflow = this->get_parent();
×
NEW
58
    auto& block = static_cast<structured_control_flow::Block&>(*dataflow.get_parent());
×
59

NEW
60
    if (dataflow.in_degree(*this) != 1 || dataflow.out_degree(*this) != 1) {
×
NEW
61
        return false;
×
62
    }
63

NEW
64
    auto& scope_analysis = analysis_manager.get<analysis::ScopeAnalysis>();
×
NEW
65
    auto& parent = static_cast<structured_control_flow::Sequence&>(*scope_analysis.parent_scope(&block));
×
66

NEW
67
    auto& in_edge = *dataflow.in_edges(*this).begin();
×
NEW
68
    auto& out_edge = *dataflow.out_edges(*this).begin();
×
NEW
69
    auto& in_node = static_cast<data_flow::AccessNode&>(in_edge.src());
×
NEW
70
    auto& out_node = static_cast<data_flow::AccessNode&>(out_edge.dst());
×
71

NEW
72
    symbolic::SymbolVec loop_vars;
×
NEW
73
    structured_control_flow::Sequence* inner_scope = nullptr;
×
74

NEW
75
    for (size_t i = 0; i < output_shape_.size(); ++i) {
×
NEW
76
        std::string var_name = builder.find_new_name("_i" + std::to_string(i));
×
NEW
77
        builder.add_container(var_name, types::Scalar(types::PrimitiveType::Int64));
×
78

NEW
79
        auto sym_var = symbolic::symbol(var_name);
×
NEW
80
        auto condition = symbolic::Lt(sym_var, output_shape_[i]);
×
NEW
81
        auto init = symbolic::zero();
×
NEW
82
        auto update = symbolic::add(sym_var, symbolic::one());
×
83

NEW
84
        if (i == 0) {
×
NEW
85
            auto& loop = builder.add_map_before(
×
NEW
86
                parent,
×
NEW
87
                block,
×
NEW
88
                sym_var,
×
NEW
89
                condition,
×
NEW
90
                init,
×
NEW
91
                update,
×
NEW
92
                structured_control_flow::ScheduleType_Sequential::create(),
×
NEW
93
                {},
×
NEW
94
                this->debug_info()
×
95
            );
NEW
96
            inner_scope = &loop.root();
×
NEW
97
        } else {
×
NEW
98
            auto& loop = builder.add_map(
×
NEW
99
                *inner_scope,
×
NEW
100
                sym_var,
×
NEW
101
                condition,
×
NEW
102
                init,
×
NEW
103
                update,
×
NEW
104
                structured_control_flow::ScheduleType_Sequential::create(),
×
NEW
105
                {},
×
NEW
106
                this->debug_info()
×
107
            );
NEW
108
            inner_scope = &loop.root();
×
109
        }
NEW
110
        loop_vars.push_back(sym_var);
×
NEW
111
    }
×
112

NEW
113
    auto& tasklet_block = builder.add_block(*inner_scope, {}, this->debug_info());
×
114

NEW
115
    auto& in_acc = builder.add_access(tasklet_block, in_node.data());
×
NEW
116
    auto& out_acc = builder.add_access(tasklet_block, out_node.data());
×
117

NEW
118
    auto& tasklet =
×
NEW
119
        builder.add_tasklet(tasklet_block, data_flow::TaskletCode::assign, "_out", {"_in"}, this->debug_info());
×
120

NEW
121
    symbolic::Expression input_linear_index = symbolic::zero();
×
NEW
122
    for (size_t i = 0; i < input_shape_.size(); ++i) {
×
NEW
123
        if (!symbolic::eq(input_shape_[i], symbolic::one())) {
×
NEW
124
            input_linear_index = symbolic::add(symbolic::mul(input_linear_index, input_shape_[i]), loop_vars[i]);
×
NEW
125
        }
×
NEW
126
    }
×
127

NEW
128
    symbolic::Expression output_linear_index = symbolic::zero();
×
NEW
129
    for (size_t i = 0; i < output_shape_.size(); ++i) {
×
NEW
130
        output_linear_index = symbolic::add(symbolic::mul(output_linear_index, output_shape_[i]), loop_vars[i]);
×
NEW
131
    }
×
132

NEW
133
    data_flow::Subset input_subset;
×
NEW
134
    if (in_edge.base_type().type_id() != types::TypeID::Scalar) {
×
NEW
135
        input_subset = {input_linear_index};
×
NEW
136
    }
×
NEW
137
    data_flow::Subset output_subset;
×
NEW
138
    if (out_edge.base_type().type_id() != types::TypeID::Scalar) {
×
NEW
139
        output_subset = {output_linear_index};
×
NEW
140
    }
×
NEW
141
    builder.add_computational_memlet(
×
NEW
142
        tasklet_block, in_acc, tasklet, "_in", input_subset, in_edge.base_type(), this->debug_info()
×
143
    );
NEW
144
    builder.add_computational_memlet(
×
NEW
145
        tasklet_block, tasklet, "_out", out_acc, output_subset, out_edge.base_type(), this->debug_info()
×
146
    );
147

NEW
148
    builder.remove_memlet(block, in_edge);
×
NEW
149
    builder.remove_memlet(block, out_edge);
×
NEW
150
    builder.remove_node(block, in_node);
×
NEW
151
    builder.remove_node(block, out_node);
×
NEW
152
    builder.remove_node(block, *this);
×
153

NEW
154
    int index = parent.index(block);
×
NEW
155
    builder.remove_child(parent, index);
×
156

NEW
157
    return true;
×
NEW
158
}
×
159

160
std::unique_ptr<data_flow::DataFlowNode> BroadcastNode::
NEW
161
    clone(size_t element_id, const graph::Vertex vertex, data_flow::DataFlowGraph& parent) const {
×
NEW
162
    return std::unique_ptr<data_flow::DataFlowNode>(
×
NEW
163
        new BroadcastNode(element_id, this->debug_info(), vertex, parent, input_shape_, output_shape_)
×
164
    );
NEW
165
}
×
166

167
} // namespace tensor
168
} // namespace math
169
} // 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