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

daisytuner / sdfglib / 20623330469

31 Dec 2025 04:51PM UTC coverage: 39.635% (-0.08%) from 39.712%
20623330469

Pull #421

github

web-flow
Merge 6f97fcd37 into 3b72c335e
Pull Request #421: Extend tensor library nodes with primitive type support and refactor CMathNode to use enums

14997 of 49248 branches covered (30.45%)

Branch coverage included in aggregate %.

247 of 620 new or added lines in 52 files covered. (39.84%)

37 existing lines in 4 files now uncovered.

12875 of 21074 relevant lines covered (61.09%)

89.41 hits per line

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

6.71
/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

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

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

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

196
CMathNode::CMathNode(
108✔
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(
108!
205
          element_id, debug_info, vertex, parent, LibraryNodeType_CMath, {"_out"}, {}, data_flow::ImplementationType_NONE
108!
206
      ),
207
      function_(function), primitive_type_(primitive_type) {
108✔
208
    for (size_t i = 0; i < cmath_function_to_arity(function); i++) {
253!
209
        this->inputs_.push_back("_in" + std::to_string(i + 1));
145!
210
    }
145✔
211
}
108✔
212

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

NEW
215
types::PrimitiveType CMathNode::primitive_type() const { return this->primitive_type_; }
×
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 {}; }
2✔
220

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

225

226
void CMathNode::validate(const Function& function) const {
54✔
227
    if (!types::is_floating_point(this->primitive_type_)) {
54✔
228
        throw InvalidSDFGException("CMathNode: Primitive type must be a floating point type");
1!
229
    }
230

231
    auto& dataflow = this->get_parent();
53✔
232
    if (this->inputs_.size() != dataflow.in_degree(*this)) {
53!
NEW
233
        throw InvalidSDFGException("CMathNode: Mismatch between number of inputs and in-degree of the node");
×
234
    }
235
    if (this->outputs_.size() != dataflow.out_degree(*this)) {
53!
NEW
236
        throw InvalidSDFGException("CMathNode: Mismatch between number of outputs and out-degree of the node");
×
237
    }
238
    for (const auto& iedge : dataflow.in_edges(*this)) {
119✔
239
        auto& inferred_type = types::infer_type(function, iedge.base_type(), iedge.subset());
66✔
240
        if (inferred_type.type_id() != types::TypeID::Scalar) {
66!
NEW
241
            throw InvalidSDFGException("CMathNode: Input type must be scalar");
×
242
        }
243
        auto& scalar_type = static_cast<const types::Scalar&>(inferred_type);
66✔
244
        if (scalar_type.primitive_type() != this->primitive_type_) {
66!
NEW
245
            std::string input_primitive_type_str = types::primitive_type_to_string(scalar_type.primitive_type());
×
NEW
246
            std::string node_primitive_type_str = types::primitive_type_to_string(this->primitive_type_);
×
NEW
247
            throw InvalidSDFGException(
×
NEW
248
                "CMathNode: Input primitive type " + input_primitive_type_str + " does not match node primitive type " +
×
NEW
249
                node_primitive_type_str + " for function " + cmath_function_to_stem(this->function_)
×
250
            );
NEW
251
        }
×
252
    }
253
    for (const auto& oedge : dataflow.out_edges(*this)) {
106✔
254
        auto& inferred_type = types::infer_type(function, oedge.base_type(), oedge.subset());
53✔
255
        if (inferred_type.type_id() != types::TypeID::Scalar) {
53!
NEW
256
            throw InvalidSDFGException("CMathNode: Output type must be scalar");
×
257
        }
258
        auto& scalar_type = static_cast<const types::Scalar&>(inferred_type);
53✔
259
        if (this->function_ == CMathFunction::lrint || this->function_ == CMathFunction::llrint ||
106!
260
            this->function_ == CMathFunction::lround || this->function_ == CMathFunction::llround) {
53!
NEW
261
            if (!types::is_integer(scalar_type.primitive_type())) {
×
NEW
262
                std::string output_primitive_type_str = types::primitive_type_to_string(scalar_type.primitive_type());
×
NEW
263
                throw InvalidSDFGException(
×
264
                    "CMathNode: Output primitive type must be an integer type for lrint, llrint, lround, llround "
NEW
265
                    "functions. Found: " +
×
266
                    output_primitive_type_str
267
                );
NEW
268
            }
×
269
        } else if (scalar_type.primitive_type() != this->primitive_type_) {
53!
NEW
270
            std::string output_primitive_type_str = types::primitive_type_to_string(scalar_type.primitive_type());
×
NEW
271
            std::string node_primitive_type_str = types::primitive_type_to_string(this->primitive_type_);
×
NEW
272
            throw InvalidSDFGException(
×
NEW
273
                "CMathNode: Output primitive type " + output_primitive_type_str +
×
NEW
274
                " does not match node primitive type " + node_primitive_type_str
×
275
            );
NEW
276
        }
×
277
    }
278
}
54✔
279

280
std::unique_ptr<data_flow::DataFlowNode> CMathNode::
281
    clone(size_t element_id, const graph::Vertex vertex, data_flow::DataFlowGraph& parent) const {
×
282
    return std::unique_ptr<
×
NEW
283
        CMathNode>(new CMathNode(element_id, this->debug_info(), vertex, parent, this->function_, this->primitive_type_)
×
284
    );
UNCOV
285
}
×
286

287
symbolic::Expression CMathNode::flop() const { return symbolic::one(); }
1✔
288

289
nlohmann::json CMathNodeSerializer::serialize(const data_flow::LibraryNode& library_node) {
×
290
    const CMathNode& node = static_cast<const CMathNode&>(library_node);
×
291
    nlohmann::json j;
×
292

293
    serializer::JSONSerializer serializer;
×
294
    j["code"] = node.code().value();
×
295
    j["name"] = node.name();
×
NEW
296
    j["function_stem"] = cmath_function_to_stem(node.function());
×
NEW
297
    j["primitive_type"] = static_cast<int>(node.primitive_type());
×
298

299
    return j;
×
300
}
×
301

302
data_flow::LibraryNode& CMathNodeSerializer::deserialize(
×
303
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Block& parent
304
) {
305
    // Assertions for required fields
306
    assert(j.contains("element_id"));
×
307
    assert(j.contains("code"));
×
308
    assert(j.contains("debug_info"));
×
309

310
    auto code = j["code"].get<std::string>();
×
311
    // Backward compatibility
312
    if (code != LibraryNodeType_CMath.value() && code != LibraryNodeType_CMath_Deprecated.value()) {
×
313
        throw std::runtime_error("Invalid library node code");
×
314
    }
315

316
    // Extract debug info using JSONSerializer
317
    sdfg::serializer::JSONSerializer serializer;
×
318
    DebugInfo debug_info = serializer.json_to_debug_info(j["debug_info"]);
×
319

320
    // Try new format first (with function_stem and primitive_type)
321
    CMathFunction function;
322
    types::PrimitiveType prim_type;
323

NEW
324
    if (j.contains("function_stem") && j.contains("primitive_type")) {
×
325
        // New format
NEW
326
        auto stem = j["function_stem"].get<std::string>();
×
NEW
327
        function = string_to_cmath_function(stem);
×
NEW
328
        prim_type = static_cast<types::PrimitiveType>(j["primitive_type"].get<int>());
×
NEW
329
    } else {
×
330
        // Backward compatibility: old format with just "name"
NEW
331
        auto name = j["name"].get<std::string>();
×
NEW
332
        function = string_to_cmath_function(name);
×
333
        // Infer primitive type from the suffix
NEW
334
        if (name.back() == 'f') {
×
NEW
335
            prim_type = types::PrimitiveType::Float;
×
NEW
336
        } else if (name.back() == 'l') {
×
NEW
337
            prim_type = types::PrimitiveType::X86_FP80; // Assuming long double
×
NEW
338
        } else {
×
NEW
339
            prim_type = types::PrimitiveType::Double;
×
340
        }
NEW
341
    }
×
342

NEW
343
    return builder.add_library_node<CMathNode>(parent, debug_info, function, prim_type);
×
344
}
×
345

346
CMathNodeDispatcher::CMathNodeDispatcher(
×
347
    codegen::LanguageExtension& language_extension,
348
    const Function& function,
349
    const data_flow::DataFlowGraph& data_flow_graph,
350
    const CMathNode& node
351
)
352
    : codegen::LibraryNodeDispatcher(language_extension, function, data_flow_graph, node) {}
×
353

354
void CMathNodeDispatcher::dispatch_code(
×
355
    codegen::PrettyPrinter& stream,
356
    codegen::PrettyPrinter& globals_stream,
357
    codegen::CodeSnippetFactory& library_snippet_factory
358
) {
359
    stream << "{" << std::endl;
×
360
    stream.setIndent(stream.indent() + 4);
×
361

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

364
    stream << node.outputs().at(0) << " = ";
×
365
    stream << node.name() << "(";
×
366
    for (size_t i = 0; i < node.inputs().size(); i++) {
×
367
        stream << node.inputs().at(i);
×
368
        if (i < node.inputs().size() - 1) {
×
369
            stream << ", ";
×
370
        }
×
371
    }
×
372
    stream << ");" << std::endl;
×
373

374
    stream.setIndent(stream.indent() - 4);
×
375
    stream << "}" << std::endl;
×
376
}
×
377

378
} // namespace cmath
379
} // namespace math
380
} // 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