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

daisytuner / docc / 23087278095

14 Mar 2026 11:44AM UTC coverage: 63.927% (+0.3%) from 63.617%
23087278095

push

github

web-flow
Merge pull request #568 from daisytuner/dead-data-elimination

Working on memory ownership & escape analysis

475 of 637 new or added lines in 28 files covered. (74.57%)

6 existing lines in 3 files now uncovered.

26010 of 40687 relevant lines covered (63.93%)

402.05 hits per line

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

13.99
/sdfg/src/data_flow/library_nodes/math/cmath/cmath_node.cpp
1
#include "sdfg/data_flow/library_nodes/math/cmath/cmath_node.h"
2
#include "sdfg/symbolic/symbolic.h"
3

4
#include <string>
5
#include <unordered_map>
6

7
#include "sdfg/types/utils.h"
8

9
namespace sdfg {
10
namespace math {
11
namespace cmath {
12

13
CMathFunction string_to_cmath_function(const std::string& name) {
×
14
    static const std::unordered_map<std::string, CMathFunction> function_map = {
×
15
        {"sin", CMathFunction::sin},
×
16
        {"sinf", CMathFunction::sin},
×
17
        {"sinl", CMathFunction::sin},
×
18
        {"cos", CMathFunction::cos},
×
19
        {"cosf", CMathFunction::cos},
×
20
        {"cosl", CMathFunction::cos},
×
21
        {"tan", CMathFunction::tan},
×
22
        {"tanf", CMathFunction::tan},
×
23
        {"tanl", CMathFunction::tan},
×
24
        {"asin", CMathFunction::asin},
×
25
        {"asinf", CMathFunction::asin},
×
26
        {"asinl", CMathFunction::asin},
×
27
        {"acos", CMathFunction::acos},
×
28
        {"acosf", CMathFunction::acos},
×
29
        {"acosl", CMathFunction::acos},
×
30
        {"atan", CMathFunction::atan},
×
31
        {"atanf", CMathFunction::atan},
×
32
        {"atanl", CMathFunction::atan},
×
33
        {"atan2", CMathFunction::atan2},
×
34
        {"atan2f", CMathFunction::atan2},
×
35
        {"atan2l", CMathFunction::atan2},
×
36
        {"sinh", CMathFunction::sinh},
×
37
        {"sinhf", CMathFunction::sinh},
×
38
        {"sinhl", CMathFunction::sinh},
×
39
        {"cosh", CMathFunction::cosh},
×
40
        {"coshf", CMathFunction::cosh},
×
41
        {"coshl", CMathFunction::cosh},
×
42
        {"tanh", CMathFunction::tanh},
×
43
        {"tanhf", CMathFunction::tanh},
×
44
        {"tanhl", CMathFunction::tanh},
×
45
        {"asinh", CMathFunction::asinh},
×
46
        {"asinhf", CMathFunction::asinh},
×
47
        {"asinhl", CMathFunction::asinh},
×
48
        {"acosh", CMathFunction::acosh},
×
49
        {"acoshf", CMathFunction::acosh},
×
50
        {"acoshl", CMathFunction::acosh},
×
51
        {"atanh", CMathFunction::atanh},
×
52
        {"atanhf", CMathFunction::atanh},
×
53
        {"atanhl", CMathFunction::atanh},
×
54
        {"exp", CMathFunction::exp},
×
55
        {"expf", CMathFunction::exp},
×
56
        {"expl", CMathFunction::exp},
×
57
        {"exp2", CMathFunction::exp2},
×
58
        {"exp2f", CMathFunction::exp2},
×
59
        {"exp2l", CMathFunction::exp2},
×
60
        {"exp10", CMathFunction::exp10},
×
61
        {"exp10f", CMathFunction::exp10},
×
62
        {"exp10l", CMathFunction::exp10},
×
63
        {"expm1", CMathFunction::expm1},
×
64
        {"expm1f", CMathFunction::expm1},
×
65
        {"expm1l", CMathFunction::expm1},
×
66
        {"log", CMathFunction::log},
×
67
        {"logf", CMathFunction::log},
×
68
        {"logl", CMathFunction::log},
×
69
        {"log10", CMathFunction::log10},
×
70
        {"log10f", CMathFunction::log10},
×
71
        {"log10l", CMathFunction::log10},
×
72
        {"log2", CMathFunction::log2},
×
73
        {"log2f", CMathFunction::log2},
×
74
        {"log2l", CMathFunction::log2},
×
75
        {"log1p", CMathFunction::log1p},
×
76
        {"log1pf", CMathFunction::log1p},
×
77
        {"log1pl", CMathFunction::log1p},
×
78
        {"pow", CMathFunction::pow},
×
79
        {"powf", CMathFunction::pow},
×
80
        {"powl", CMathFunction::pow},
×
81
        {"sqrt", CMathFunction::sqrt},
×
82
        {"sqrtf", CMathFunction::sqrt},
×
83
        {"sqrtl", CMathFunction::sqrt},
×
84
        {"cbrt", CMathFunction::cbrt},
×
85
        {"cbrtf", CMathFunction::cbrt},
×
86
        {"cbrtl", CMathFunction::cbrt},
×
87
        {"hypot", CMathFunction::hypot},
×
88
        {"hypotf", CMathFunction::hypot},
×
89
        {"hypotl", CMathFunction::hypot},
×
90
        {"erf", CMathFunction::erf},
×
91
        {"erff", CMathFunction::erf},
×
92
        {"erfl", CMathFunction::erf},
×
93
        {"erfc", CMathFunction::erfc},
×
94
        {"erfcf", CMathFunction::erfc},
×
95
        {"erfcl", CMathFunction::erfc},
×
96
        {"tgamma", CMathFunction::tgamma},
×
97
        {"tgammaf", CMathFunction::tgamma},
×
98
        {"tgammal", CMathFunction::tgamma},
×
99
        {"lgamma", CMathFunction::lgamma},
×
100
        {"lgammaf", CMathFunction::lgamma},
×
101
        {"lgammal", CMathFunction::lgamma},
×
102
        {"fabs", CMathFunction::fabs},
×
103
        {"fabsf", CMathFunction::fabs},
×
104
        {"fabsl", CMathFunction::fabs},
×
105
        {"ceil", CMathFunction::ceil},
×
106
        {"ceilf", CMathFunction::ceil},
×
107
        {"ceill", CMathFunction::ceil},
×
108
        {"floor", CMathFunction::floor},
×
109
        {"floorf", CMathFunction::floor},
×
110
        {"floorl", CMathFunction::floor},
×
111
        {"trunc", CMathFunction::trunc},
×
112
        {"truncf", CMathFunction::trunc},
×
113
        {"truncl", CMathFunction::trunc},
×
114
        {"round", CMathFunction::round},
×
115
        {"roundf", CMathFunction::round},
×
116
        {"roundl", CMathFunction::round},
×
117
        {"lround", CMathFunction::lround},
×
118
        {"lroundf", CMathFunction::lround},
×
119
        {"lroundl", CMathFunction::lround},
×
120
        {"llround", CMathFunction::llround},
×
121
        {"llroundf", CMathFunction::llround},
×
122
        {"llroundl", CMathFunction::llround},
×
123
        {"roundeven", CMathFunction::roundeven},
×
124
        {"roundevenf", CMathFunction::roundeven},
×
125
        {"roundevenl", CMathFunction::roundeven},
×
126
        {"nearbyint", CMathFunction::nearbyint},
×
127
        {"nearbyintf", CMathFunction::nearbyint},
×
128
        {"nearbyintl", CMathFunction::nearbyint},
×
129
        {"rint", CMathFunction::rint},
×
130
        {"rintf", CMathFunction::rint},
×
131
        {"rintl", CMathFunction::rint},
×
132
        {"lrint", CMathFunction::lrint},
×
133
        {"lrintf", CMathFunction::lrint},
×
134
        {"lrintl", CMathFunction::lrint},
×
135
        {"llrint", CMathFunction::llrint},
×
136
        {"llrintf", CMathFunction::llrint},
×
137
        {"llrintl", CMathFunction::llrint},
×
138
        {"fmod", CMathFunction::fmod},
×
139
        {"fmodf", CMathFunction::fmod},
×
140
        {"fmodl", CMathFunction::fmod},
×
141
        {"remainder", CMathFunction::remainder},
×
142
        {"remainderf", CMathFunction::remainder},
×
143
        {"remainderl", CMathFunction::remainder},
×
144
        {"frexp", CMathFunction::frexp},
×
145
        {"frexpf", CMathFunction::frexp},
×
146
        {"frexpl", CMathFunction::frexp},
×
147
        {"ldexp", CMathFunction::ldexp},
×
148
        {"ldexpf", CMathFunction::ldexp},
×
149
        {"ldexpl", CMathFunction::ldexp},
×
150
        {"modf", CMathFunction::modf},
×
151
        {"modff", CMathFunction::modf},
×
152
        {"modfl", CMathFunction::modf},
×
153
        {"scalbn", CMathFunction::scalbn},
×
154
        {"scalbnf", CMathFunction::scalbn},
×
155
        {"scalbnl", CMathFunction::scalbn},
×
156
        {"scalbln", CMathFunction::scalbln},
×
157
        {"scalblnf", CMathFunction::scalbln},
×
158
        {"scalblnl", CMathFunction::scalbln},
×
159
        {"ilogb", CMathFunction::ilogb},
×
160
        {"ilogbf", CMathFunction::ilogb},
×
161
        {"ilogbl", CMathFunction::ilogb},
×
162
        {"logb", CMathFunction::logb},
×
163
        {"logbf", CMathFunction::logb},
×
164
        {"logbl", CMathFunction::logb},
×
165
        {"nextafter", CMathFunction::nextafter},
×
166
        {"nextafterf", CMathFunction::nextafter},
×
167
        {"nextafterl", CMathFunction::nextafter},
×
168
        {"nexttoward", CMathFunction::nexttoward},
×
169
        {"nexttowardf", CMathFunction::nexttoward},
×
170
        {"nexttowardl", CMathFunction::nexttoward},
×
171
        {"copysign", CMathFunction::copysign},
×
172
        {"copysignf", CMathFunction::copysign},
×
173
        {"copysignl", CMathFunction::copysign},
×
174
        {"fmax", CMathFunction::fmax},
×
175
        {"fmaxf", CMathFunction::fmax},
×
176
        {"fmaxl", CMathFunction::fmax},
×
177
        {"fmin", CMathFunction::fmin},
×
178
        {"fminf", CMathFunction::fmin},
×
179
        {"fminl", CMathFunction::fmin},
×
180
        {"fdim", CMathFunction::fdim},
×
181
        {"fdimf", CMathFunction::fdim},
×
182
        {"fdiml", CMathFunction::fdim},
×
183
        {"fma", CMathFunction::fma},
×
184
        {"fmaf", CMathFunction::fma},
×
185
        {"fmal", CMathFunction::fma},
×
186
    };
×
187

188
    auto it = function_map.find(name);
×
189
    if (it != function_map.end()) {
×
190
        return it->second;
×
191
    }
×
192

193
    throw std::runtime_error("Unknown CMath function: " + name);
×
194
}
×
195

196
CMathNode::CMathNode(
197
    size_t element_id,
198
    const DebugInfo& debug_info,
199
    const graph::Vertex vertex,
200
    data_flow::DataFlowGraph& parent,
201
    CMathFunction function,
202
    types::PrimitiveType primitive_type
203
)
204
    : MathNode(
356✔
205
          element_id, debug_info, vertex, parent, LibraryNodeType_CMath, {"_out"}, {}, data_flow::ImplementationType_NONE
356✔
206
      ),
356✔
207
      function_(function), primitive_type_(primitive_type) {
356✔
208
    for (size_t i = 0; i < cmath_function_to_arity(function); i++) {
815✔
209
        this->inputs_.push_back("_in" + std::to_string(i + 1));
459✔
210
    }
459✔
211
}
356✔
212

213
CMathFunction CMathNode::function() const { return this->function_; }
240✔
214

215
types::PrimitiveType CMathNode::primitive_type() const { return this->primitive_type_; }
12✔
216

217
std::string CMathNode::name() const { return get_cmath_intrinsic_name(this->function_, this->primitive_type_); }
3✔
218

219
symbolic::SymbolSet CMathNode::symbols() const { return {}; }
13✔
220

221
void CMathNode::replace(const symbolic::Expression old_expression, const symbolic::Expression new_expression) {
×
222
    return;
×
223
}
×
224

225
void CMathNode::validate(const Function& function) const {
292✔
226
    MathNode::validate(function);
292✔
227

228
    if (!types::is_floating_point(this->primitive_type_)) {
292✔
229
        throw InvalidSDFGException("CMathNode: Primitive type must be a floating point type");
1✔
230
    }
1✔
231

232
    auto& dataflow = this->get_parent();
291✔
233
    if (this->inputs_.size() != dataflow.in_degree(*this)) {
291✔
234
        throw InvalidSDFGException("CMathNode: Mismatch between number of inputs and in-degree of the node");
×
235
    }
×
236
    if (this->outputs_.size() != dataflow.out_degree(*this)) {
291✔
237
        throw InvalidSDFGException("CMathNode: Mismatch between number of outputs and out-degree of the node");
×
238
    }
×
239
    for (const auto& iedge : dataflow.in_edges(*this)) {
364✔
240
        auto inferred_type = types::infer_type(function, iedge.base_type(), iedge.subset());
364✔
241
        auto type_id = inferred_type->type_id();
364✔
242
        bool type_ok = false;
364✔
243
        if (type_id == types::TypeID::Scalar) {
364✔
244
            type_ok = true;
364✔
245
        } else if (type_id == types::TypeID::Tensor) {
364✔
NEW
246
            auto& tensor = dynamic_cast<types::Tensor&>(*inferred_type);
×
NEW
247
            if (tensor.is_scalar()) {
×
NEW
248
                type_ok = true;
×
NEW
249
            }
×
NEW
250
        }
×
251
        if (!type_ok) {
364✔
NEW
252
            throw InvalidSDFGException(
×
NEW
253
                "CMathNode: Input type on " + std::to_string(this->element_id()) + ":" + iedge.dst_conn() +
×
NEW
254
                " must be scalar, but was " + std::to_string(static_cast<int>(type_id))
×
NEW
255
            );
×
UNCOV
256
        }
×
257
        auto& scalar_type = static_cast<const types::Scalar&>(*inferred_type);
364✔
258
        if (scalar_type.primitive_type() != this->primitive_type_) {
364✔
259
            std::string input_primitive_type_str = types::primitive_type_to_string(scalar_type.primitive_type());
×
260
            std::string node_primitive_type_str = types::primitive_type_to_string(this->primitive_type_);
×
261
            throw InvalidSDFGException(
×
262
                "CMathNode: Input primitive type " + input_primitive_type_str + " does not match node primitive type " +
×
263
                node_primitive_type_str + " for function " + cmath_function_to_stem(this->function_)
×
264
            );
×
265
        }
×
266
    }
364✔
267
    for (const auto& oedge : dataflow.out_edges(*this)) {
291✔
268
        auto inferred_type = types::infer_type(function, oedge.base_type(), oedge.subset());
291✔
269
        auto type_id = inferred_type->type_id();
291✔
270
        bool type_ok = false;
291✔
271
        if (type_id == types::TypeID::Scalar) {
291✔
272
            type_ok = true;
291✔
273
        } else if (type_id == types::TypeID::Tensor) {
291✔
NEW
274
            auto& tensor = dynamic_cast<types::Tensor&>(*inferred_type);
×
NEW
275
            if (tensor.is_scalar()) {
×
NEW
276
                type_ok = true;
×
NEW
277
            }
×
NEW
278
        }
×
279
        if (!type_ok) {
291✔
NEW
280
            throw InvalidSDFGException(
×
NEW
281
                "Output: Input type in " + std::to_string(this->element_id()) + " must be scalar, but was " +
×
NEW
282
                std::to_string(static_cast<int>(type_id))
×
NEW
283
            );
×
UNCOV
284
        }
×
285
        auto& scalar_type = static_cast<const types::Scalar&>(*inferred_type);
291✔
286
        if (this->function_ == CMathFunction::lrint || this->function_ == CMathFunction::llrint ||
291✔
287
            this->function_ == CMathFunction::lround || this->function_ == CMathFunction::llround) {
291✔
288
            if (!types::is_integer(scalar_type.primitive_type())) {
16✔
289
                std::string output_primitive_type_str = types::primitive_type_to_string(scalar_type.primitive_type());
×
290
                throw InvalidSDFGException(
×
291
                    "CMathNode: Output primitive type must be an integer type for lrint, llrint, lround, llround "
×
292
                    "functions. Found: " +
×
293
                    output_primitive_type_str
×
294
                );
×
295
            }
×
296
        } else if (scalar_type.primitive_type() != this->primitive_type_) {
275✔
297
            std::string output_primitive_type_str = types::primitive_type_to_string(scalar_type.primitive_type());
×
298
            std::string node_primitive_type_str = types::primitive_type_to_string(this->primitive_type_);
×
299
            throw InvalidSDFGException(
×
300
                "CMathNode: Output primitive type " + output_primitive_type_str +
×
301
                " does not match node primitive type " + node_primitive_type_str
×
302
            );
×
303
        }
×
304
    }
291✔
305
}
291✔
306

307
std::unique_ptr<data_flow::DataFlowNode> CMathNode::
308
    clone(size_t element_id, const graph::Vertex vertex, data_flow::DataFlowGraph& parent) const {
×
309
    return std::unique_ptr<
×
310
        CMathNode>(new CMathNode(element_id, this->debug_info(), vertex, parent, this->function_, this->primitive_type_)
×
311
    );
×
312
}
×
313

314
symbolic::Expression CMathNode::flop() const { return symbolic::one(); }
1✔
315

316
nlohmann::json CMathNodeSerializer::serialize(const data_flow::LibraryNode& library_node) {
×
317
    const CMathNode& node = static_cast<const CMathNode&>(library_node);
×
318
    nlohmann::json j;
×
319

320
    serializer::JSONSerializer serializer;
×
321
    j["code"] = node.code().value();
×
322
    j["name"] = node.name();
×
323
    j["function_stem"] = cmath_function_to_stem(node.function());
×
324
    j["primitive_type"] = static_cast<int>(node.primitive_type());
×
325

326
    return j;
×
327
}
×
328

329
data_flow::LibraryNode& CMathNodeSerializer::deserialize(
330
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Block& parent
331
) {
×
332
    // Assertions for required fields
333
    assert(j.contains("element_id"));
×
334
    assert(j.contains("code"));
×
335
    assert(j.contains("debug_info"));
×
336

337
    auto code = j["code"].get<std::string>();
×
338
    // Backward compatibility
339
    if (code != LibraryNodeType_CMath.value() && code != LibraryNodeType_CMath_Deprecated.value()) {
×
340
        throw std::runtime_error("Invalid library node code");
×
341
    }
×
342

343
    // Extract debug info using JSONSerializer
344
    sdfg::serializer::JSONSerializer serializer;
×
345
    DebugInfo debug_info = serializer.json_to_debug_info(j["debug_info"]);
×
346

347
    // Try new format first (with function_stem and primitive_type)
348
    CMathFunction function;
×
349
    types::PrimitiveType prim_type;
×
350

351
    if (j.contains("function_stem") && j.contains("primitive_type")) {
×
352
        // New format
353
        auto stem = j["function_stem"].get<std::string>();
×
354
        function = string_to_cmath_function(stem);
×
355
        prim_type = static_cast<types::PrimitiveType>(j["primitive_type"].get<int>());
×
356
    } else {
×
357
        // Backward compatibility: old format with just "name"
358
        auto name = j["name"].get<std::string>();
×
359
        function = string_to_cmath_function(name);
×
360
        // Infer primitive type from the suffix
361
        if (name.back() == 'f') {
×
362
            prim_type = types::PrimitiveType::Float;
×
363
        } else if (name.back() == 'l') {
×
364
            prim_type = types::PrimitiveType::X86_FP80; // Assuming long double
×
365
        } else {
×
366
            prim_type = types::PrimitiveType::Double;
×
367
        }
×
368
    }
×
369

370
    return builder.add_library_node<CMathNode>(parent, debug_info, function, prim_type);
×
371
}
×
372

373
CMathNodeDispatcher::CMathNodeDispatcher(
374
    codegen::LanguageExtension& language_extension,
375
    const Function& function,
376
    const data_flow::DataFlowGraph& data_flow_graph,
377
    const CMathNode& node
378
)
379
    : codegen::LibraryNodeDispatcher(language_extension, function, data_flow_graph, node) {}
×
380

381
void CMathNodeDispatcher::dispatch_code(
382
    codegen::PrettyPrinter& stream,
383
    codegen::PrettyPrinter& globals_stream,
384
    codegen::CodeSnippetFactory& library_snippet_factory
385
) {
×
386
    stream << "{" << std::endl;
×
387
    stream.setIndent(stream.indent() + 4);
×
388

389
    auto& node = static_cast<const CMathNode&>(this->node_);
×
390

391
    stream << node.outputs().at(0) << " = ";
×
392
    stream << node.name() << "(";
×
393
    for (size_t i = 0; i < node.inputs().size(); i++) {
×
394
        stream << node.inputs().at(i);
×
395
        if (i < node.inputs().size() - 1) {
×
396
            stream << ", ";
×
397
        }
×
398
    }
×
399
    stream << ");" << std::endl;
×
400

401
    stream.setIndent(stream.indent() - 4);
×
402
    stream << "}" << std::endl;
×
403
}
×
404

405
} // namespace cmath
406
} // namespace math
407
} // 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