• 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

10.68
/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(
108✔
205
          element_id, debug_info, vertex, parent, LibraryNodeType_CMath, {"_out"}, {}, data_flow::ImplementationType_NONE
108✔
206
      ),
108✔
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

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

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
    }
1✔
230

231
    auto& dataflow = this->get_parent();
53✔
232
    if (this->inputs_.size() != dataflow.in_degree(*this)) {
53✔
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✔
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)) {
66✔
239
        auto& inferred_type = types::infer_type(function, iedge.base_type(), iedge.subset());
66✔
240
        if (inferred_type.type_id() != types::TypeID::Scalar) {
66✔
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✔
245
            std::string input_primitive_type_str = types::primitive_type_to_string(scalar_type.primitive_type());
×
246
            std::string node_primitive_type_str = types::primitive_type_to_string(this->primitive_type_);
×
247
            throw InvalidSDFGException(
×
248
                "CMathNode: Input primitive type " + input_primitive_type_str + " does not match node primitive type " +
×
249
                node_primitive_type_str + " for function " + cmath_function_to_stem(this->function_)
×
250
            );
×
251
        }
×
252
    }
66✔
253
    for (const auto& oedge : dataflow.out_edges(*this)) {
53✔
254
        auto& inferred_type = types::infer_type(function, oedge.base_type(), oedge.subset());
53✔
255
        if (inferred_type.type_id() != types::TypeID::Scalar) {
53✔
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 ||
53✔
260
            this->function_ == CMathFunction::lround || this->function_ == CMathFunction::llround) {
53✔
261
            if (!types::is_integer(scalar_type.primitive_type())) {
×
262
                std::string output_primitive_type_str = types::primitive_type_to_string(scalar_type.primitive_type());
×
263
                throw InvalidSDFGException(
×
264
                    "CMathNode: Output primitive type must be an integer type for lrint, llrint, lround, llround "
×
265
                    "functions. Found: " +
×
266
                    output_primitive_type_str
×
267
                );
×
268
            }
×
269
        } else if (scalar_type.primitive_type() != this->primitive_type_) {
53✔
270
            std::string output_primitive_type_str = types::primitive_type_to_string(scalar_type.primitive_type());
×
271
            std::string node_primitive_type_str = types::primitive_type_to_string(this->primitive_type_);
×
272
            throw InvalidSDFGException(
×
273
                "CMathNode: Output primitive type " + output_primitive_type_str +
×
274
                " does not match node primitive type " + node_primitive_type_str
×
275
            );
×
276
        }
×
277
    }
53✔
278
}
53✔
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<
×
283
        CMathNode>(new CMathNode(element_id, this->debug_info(), vertex, parent, this->function_, this->primitive_type_)
×
284
    );
×
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();
×
296
    j["function_stem"] = cmath_function_to_stem(node.function());
×
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

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

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