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

daisytuner / sdfglib / 20764569418

06 Jan 2026 10:50PM UTC coverage: 62.168% (+21.4%) from 40.764%
20764569418

push

github

web-flow
Merge pull request #433 from daisytuner/clang-coverage

updates clang coverage flags

14988 of 24109 relevant lines covered (62.17%)

88.57 hits per line

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

72.07
/src/data_flow/library_nodes/math/tensor/reduce_ops/std_node.cpp
1
#include "sdfg/data_flow/library_nodes/math/tensor/reduce_ops/std_node.h"
2
#include "sdfg/analysis/scope_analysis.h"
3
#include "sdfg/builder/structured_sdfg_builder.h"
4
#include "sdfg/data_flow/library_nodes/math/tensor/elementwise_ops/mul_node.h"
5
#include "sdfg/data_flow/library_nodes/math/tensor/elementwise_ops/sqrt_node.h"
6
#include "sdfg/data_flow/library_nodes/math/tensor/elementwise_ops/sub_node.h"
7
#include "sdfg/data_flow/library_nodes/math/tensor/reduce_ops/mean_node.h"
8
#include "sdfg/data_flow/library_nodes/stdlib/malloc.h"
9
#include "sdfg/structured_control_flow/block.h"
10
#include "sdfg/types/scalar.h"
11
#include "sdfg/types/utils.h"
12

13
namespace sdfg {
14
namespace math {
15
namespace tensor {
16

17
StdNode::StdNode(
18
    size_t element_id,
19
    const DebugInfo& debug_info,
20
    const graph::Vertex vertex,
21
    data_flow::DataFlowGraph& parent,
22
    const std::vector<symbolic::Expression>& shape,
23
    const std::vector<int64_t>& axes,
24
    bool keepdims
25
)
26
    : ReduceNode(element_id, debug_info, vertex, parent, LibraryNodeType_Std, shape, axes, keepdims) {}
2✔
27

28
bool StdNode::expand(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
2✔
29
    auto& dataflow = this->get_parent();
2✔
30
    auto& block = static_cast<structured_control_flow::Block&>(*dataflow.get_parent());
2✔
31

32
    if (dataflow.in_degree(*this) != 1 || dataflow.out_degree(*this) != 1) {
2✔
33
        return false;
×
34
    }
×
35

36
    auto& scope_analysis = analysis_manager.get<analysis::ScopeAnalysis>();
2✔
37
    auto& parent = static_cast<structured_control_flow::Sequence&>(*scope_analysis.parent_scope(&block));
2✔
38
    int index = parent.index(block);
2✔
39
    auto& transition = parent.at(index).second;
2✔
40

41
    auto& in_edge = *dataflow.in_edges(*this).begin();
2✔
42
    auto& out_edge = *dataflow.out_edges(*this).begin();
2✔
43
    auto& in_node = static_cast<data_flow::AccessNode&>(in_edge.src());
2✔
44
    auto& out_node = static_cast<data_flow::AccessNode&>(out_edge.dst());
2✔
45

46
    // Calculate output shape
47
    std::vector<symbolic::Expression> output_shape;
2✔
48
    std::vector<int64_t> sorted_axes = axes_;
2✔
49
    std::sort(sorted_axes.begin(), sorted_axes.end());
2✔
50

51
    for (size_t i = 0; i < shape_.size(); ++i) {
4✔
52
        bool is_axis = false;
2✔
53
        for (auto axis : sorted_axes) {
2✔
54
            if (axis == (int64_t) i) {
2✔
55
                is_axis = true;
2✔
56
                break;
2✔
57
            }
2✔
58
        }
2✔
59

60
        if (is_axis) {
2✔
61
            if (keepdims_) {
2✔
62
                output_shape.push_back(symbolic::one());
×
63
            }
×
64
        } else {
2✔
65
            output_shape.push_back(shape_[i]);
×
66
        }
×
67
    }
2✔
68

69
    types::Scalar element_type(this->primitive_type(dataflow));
2✔
70
    types::Pointer pointer_type(element_type);
2✔
71

72
    std::string tmp_x2_name = builder.find_new_name("_std_x2");
2✔
73
    builder.add_container(tmp_x2_name, in_edge.base_type());
2✔
74
    std::string tmp_mean_x2_name = builder.find_new_name("_std_mean_x2");
2✔
75
    builder.add_container(tmp_mean_x2_name, out_edge.base_type());
2✔
76
    std::string tmp_mean_x_name = builder.find_new_name("_std_mean_x");
2✔
77
    builder.add_container(tmp_mean_x_name, out_edge.base_type());
2✔
78

79
    if (in_edge.base_type().type_id() == types::TypeID::Pointer) {
2✔
80
        symbolic::Expression bytes_in = types::get_type_size(element_type, false);
2✔
81
        for (auto& dim : this->shape_) {
2✔
82
            bytes_in = symbolic::mul(dim, bytes_in);
2✔
83
        }
2✔
84

85
        {
2✔
86
            auto& alloc_block = builder.add_block_before(parent, block, {}, this->debug_info());
2✔
87
            auto& tmp_x2_name_access = builder.add_access(alloc_block, tmp_x2_name);
2✔
88
            auto& tmp_x2_name_malloc_node =
2✔
89
                builder.add_library_node<stdlib::MallocNode>(alloc_block, this->debug_info(), bytes_in);
2✔
90
            builder.add_computational_memlet(
2✔
91
                alloc_block,
2✔
92
                tmp_x2_name_malloc_node,
2✔
93
                "_ret",
2✔
94
                tmp_x2_name_access,
2✔
95
                {},
2✔
96
                in_edge.base_type(),
2✔
97
                this->debug_info()
2✔
98
            );
2✔
99
        }
2✔
100
    }
2✔
101

102
    if (out_edge.base_type().type_id() == types::TypeID::Pointer) {
2✔
103
        auto& pointee_type = static_cast<const types::Pointer&>(out_edge.base_type()).pointee_type();
×
104
        symbolic::Expression bytes_out = types::get_type_size(pointee_type, false);
×
105
        for (auto& dim : output_shape) {
×
106
            bytes_out = symbolic::mul(dim, bytes_out);
×
107
        }
×
108

109
        {
×
110
            auto& alloc_block = builder.add_block_before(parent, block, {}, this->debug_info());
×
111
            auto& tmp_mean_x2_name_access = builder.add_access(alloc_block, tmp_mean_x2_name);
×
112
            auto& tmp_mean_x2_name_malloc_node =
×
113
                builder.add_library_node<stdlib::MallocNode>(alloc_block, this->debug_info(), bytes_out);
×
114
            builder.add_computational_memlet(
×
115
                alloc_block,
×
116
                tmp_mean_x2_name_malloc_node,
×
117
                "_ret",
×
118
                tmp_mean_x2_name_access,
×
119
                {},
×
120
                in_edge.base_type(),
×
121
                this->debug_info()
×
122
            );
×
123
        }
×
124

125
        {
×
126
            auto& alloc_block = builder.add_block_before(parent, block, {}, this->debug_info());
×
127
            auto& tmp_mean_x_name_access = builder.add_access(alloc_block, tmp_mean_x_name);
×
128
            auto& tmp_mean_x_name_malloc_node =
×
129
                builder.add_library_node<stdlib::MallocNode>(alloc_block, this->debug_info(), bytes_out);
×
130
            builder.add_computational_memlet(
×
131
                alloc_block,
×
132
                tmp_mean_x_name_malloc_node,
×
133
                "_ret",
×
134
                tmp_mean_x_name_access,
×
135
                {},
×
136
                in_edge.base_type(),
×
137
                this->debug_info()
×
138
            );
×
139
        }
×
140
    }
×
141

142
    // 1. X^2
143
    auto& pow_block = builder.add_block_before(parent, block, {}, this->debug_info());
2✔
144
    auto& pow_in_node = builder.add_access(pow_block, in_node.data(), this->debug_info());
2✔
145
    auto& pow_out_node = builder.add_access(pow_block, tmp_x2_name, this->debug_info());
2✔
146

147
    auto& pow_node_1 = builder.add_library_node<MulNode>(pow_block, this->debug_info(), shape_);
2✔
148
    builder
2✔
149
        .add_computational_memlet(pow_block, pow_in_node, pow_node_1, "A", {}, in_edge.base_type(), this->debug_info());
2✔
150
    builder
2✔
151
        .add_computational_memlet(pow_block, pow_in_node, pow_node_1, "B", {}, in_edge.base_type(), this->debug_info());
2✔
152
    builder
2✔
153
        .add_computational_memlet(pow_block, pow_node_1, "C", pow_out_node, {}, in_edge.base_type(), this->debug_info());
2✔
154

155
    // 2. Mean(X^2)
156
    auto& mean_x2_block = builder.add_block_before(parent, block, {}, this->debug_info());
2✔
157
    auto& mean_x2_in_node = builder.add_access(mean_x2_block, tmp_x2_name, this->debug_info());
2✔
158
    auto& mean_x2_out_node = builder.add_access(mean_x2_block, tmp_mean_x2_name, this->debug_info());
2✔
159

160
    auto& mean_node_1 = builder.add_library_node<MeanNode>(mean_x2_block, this->debug_info(), shape_, axes_, keepdims_);
2✔
161
    builder.add_computational_memlet(
2✔
162
        mean_x2_block, mean_x2_in_node, mean_node_1, "X", {}, in_edge.base_type(), this->debug_info()
2✔
163
    );
2✔
164
    builder.add_computational_memlet(
2✔
165
        mean_x2_block, mean_node_1, "Y", mean_x2_out_node, {}, out_edge.base_type(), this->debug_info()
2✔
166
    );
2✔
167

168
    // 3. Mean(X)
169
    auto& mean_x_block = builder.add_block_before(parent, block, {}, this->debug_info());
2✔
170
    auto& mean_x_in_node = builder.add_access(mean_x_block, in_node.data(), this->debug_info());
2✔
171
    auto& mean_x_out_node = builder.add_access(mean_x_block, tmp_mean_x_name, this->debug_info());
2✔
172

173
    auto& mean_node_2 = builder.add_library_node<MeanNode>(mean_x_block, this->debug_info(), shape_, axes_, keepdims_);
2✔
174
    builder.add_computational_memlet(
2✔
175
        mean_x_block, mean_x_in_node, mean_node_2, "X", {}, in_edge.base_type(), this->debug_info()
2✔
176
    );
2✔
177
    builder.add_computational_memlet(
2✔
178
        mean_x_block, mean_node_2, "Y", mean_x_out_node, {}, out_edge.base_type(), this->debug_info()
2✔
179
    );
2✔
180

181
    // 4. Mean(X)^2
182
    auto& pow_mean_x_block = builder.add_block_before(parent, block, {}, this->debug_info());
2✔
183
    auto& pow_mean_x_in_node = builder.add_access(pow_mean_x_block, tmp_mean_x_name, this->debug_info());
2✔
184
    auto& pow_mean_x_out_node = builder.add_access(pow_mean_x_block, tmp_mean_x_name, this->debug_info());
2✔
185

186
    auto& pow_node_2 = builder.add_library_node<MulNode>(pow_mean_x_block, this->debug_info(), output_shape);
2✔
187

188
    builder.add_computational_memlet(
2✔
189
        pow_mean_x_block, pow_mean_x_in_node, pow_node_2, "A", {}, out_edge.base_type(), this->debug_info()
2✔
190
    );
2✔
191
    builder.add_computational_memlet(
2✔
192
        pow_mean_x_block, pow_mean_x_in_node, pow_node_2, "B", {}, out_edge.base_type(), this->debug_info()
2✔
193
    );
2✔
194
    builder.add_computational_memlet(
2✔
195
        pow_mean_x_block, pow_node_2, "C", pow_mean_x_out_node, {}, out_edge.base_type(), this->debug_info()
2✔
196
    );
2✔
197

198
    // 5. Mean(X^2) - Mean(X)^2
199
    auto& sub_block = builder.add_block_before(parent, block, {}, this->debug_info());
2✔
200
    auto& sub_in1_node = builder.add_access(sub_block, tmp_mean_x2_name, this->debug_info());
2✔
201
    auto& sub_in2_node = builder.add_access(sub_block, tmp_mean_x_name, this->debug_info());
2✔
202
    auto& sub_out_node = builder.add_access(sub_block, out_node.data(), this->debug_info());
2✔
203

204
    auto& sub_node = builder.add_library_node<SubNode>(sub_block, this->debug_info(), output_shape);
2✔
205
    builder
2✔
206
        .add_computational_memlet(sub_block, sub_in1_node, sub_node, "A", {}, out_edge.base_type(), this->debug_info());
2✔
207
    builder
2✔
208
        .add_computational_memlet(sub_block, sub_in2_node, sub_node, "B", {}, out_edge.base_type(), this->debug_info());
2✔
209
    builder
2✔
210
        .add_computational_memlet(sub_block, sub_node, "C", sub_out_node, {}, out_edge.base_type(), this->debug_info());
2✔
211

212
    // 6. Sqrt(...)
213
    auto& sqrt_block = builder.add_block_before(parent, block, transition.assignments(), this->debug_info());
2✔
214
    auto& sqrt_in_node = builder.add_access(sqrt_block, out_node.data(), this->debug_info());
2✔
215
    auto& sqrt_out_node = builder.add_access(sqrt_block, out_node.data(), this->debug_info());
2✔
216

217
    auto& sqrt_node = builder.add_library_node<SqrtNode>(sqrt_block, this->debug_info(), output_shape);
2✔
218
    builder
2✔
219
        .add_computational_memlet(sqrt_block, sqrt_in_node, sqrt_node, "X", {}, out_edge.base_type(), this->debug_info());
2✔
220
    builder
2✔
221
        .add_computational_memlet(sqrt_block, sqrt_node, "Y", sqrt_out_node, {}, out_edge.base_type(), this->debug_info());
2✔
222

223
    // Cleanup
224
    builder.remove_memlet(block, in_edge);
2✔
225
    builder.remove_memlet(block, out_edge);
2✔
226
    builder.remove_node(block, in_node);
2✔
227
    builder.remove_node(block, out_node);
2✔
228
    builder.remove_node(block, *this);
2✔
229

230
    int last_index = parent.index(block);
2✔
231
    builder.remove_child(parent, last_index);
2✔
232

233
    return true;
2✔
234
}
2✔
235

236
bool StdNode::expand_reduction(
237
    builder::StructuredSDFGBuilder& builder,
238
    analysis::AnalysisManager& analysis_manager,
239
    structured_control_flow::Sequence& body,
240
    const std::string& input_name,
241
    const std::string& output_name,
242
    const types::IType& input_type,
243
    const types::IType& output_type,
244
    const data_flow::Subset& input_subset,
245
    const data_flow::Subset& output_subset
246
) {
×
247
    throw std::runtime_error("StdNode::expand_reduction should not be called");
×
248
}
×
249

250
std::string StdNode::identity() const { return "0"; }
×
251

252
std::unique_ptr<data_flow::DataFlowNode> StdNode::
253
    clone(size_t element_id, const graph::Vertex vertex, data_flow::DataFlowGraph& parent) const {
×
254
    return std::unique_ptr<
×
255
        data_flow::DataFlowNode>(new StdNode(element_id, debug_info_, vertex, parent, shape_, axes_, keepdims_));
×
256
}
×
257

258
} // namespace tensor
259
} // namespace math
260
} // 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