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

daisytuner / docc / 29992851043

23 Jul 2026 08:52AM UTC coverage: 64.1% (+0.3%) from 63.787%
29992851043

Pull #866

github

web-flow
Merge f4354fb28 into 2e568810b
Pull Request #866: Add Support for Complex Types

188 of 296 new or added lines in 12 files covered. (63.51%)

272 existing lines in 10 files now uncovered.

42854 of 66855 relevant lines covered (64.1%)

737.97 hits per line

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

32.83
/sdfg/src/codegen/language_extensions/cpp_language_extension.cpp
1
#include "sdfg/codegen/language_extensions/cpp_language_extension.h"
2

3
#include "sdfg/codegen/utils.h"
4
#include "sdfg/data_flow/tasklet.h"
5

6
namespace sdfg {
7
namespace codegen {
8

9
std::string CPPLanguageExtension::primitive_type(const types::PrimitiveType prim_type) {
50✔
10
    switch (prim_type) {
50✔
11
        case types::PrimitiveType::Void:
3✔
12
            return "void";
3✔
13
        case types::PrimitiveType::Bool:
1✔
14
            return "bool";
1✔
15
        case types::PrimitiveType::Int8:
1✔
16
            return "int8_t";
1✔
17
        case types::PrimitiveType::Int16:
1✔
18
            return "int16_t";
1✔
19
        case types::PrimitiveType::Int32:
6✔
20
            return "int32_t";
6✔
21
        case types::PrimitiveType::Int64:
1✔
22
            return "int64_t";
1✔
23
        case types::PrimitiveType::Int128:
×
24
            return "__int128";
×
25
        case types::PrimitiveType::UInt8:
4✔
26
            return "uint8_t";
4✔
27
        case types::PrimitiveType::UInt16:
1✔
28
            return "uint16_t";
1✔
29
        case types::PrimitiveType::UInt32:
1✔
30
            return "uint32_t";
1✔
31
        case types::PrimitiveType::UInt64:
4✔
32
            return "uint64_t";
4✔
33
        case types::PrimitiveType::UInt128:
×
34
            return "unsigned __int128";
×
35
        case types::PrimitiveType::Half:
×
36
            return "_Float16";
×
37
        case types::PrimitiveType::BFloat:
×
38
            return "__bf16";
×
39
        case types::PrimitiveType::Float:
21✔
40
            return "float";
21✔
41
        case types::PrimitiveType::Double:
1✔
42
            return "double";
1✔
43
        case types::PrimitiveType::X86_FP80:
×
44
            return "long double";
×
45
        case types::PrimitiveType::FP128:
×
46
            return "__float128";
×
47
        case types::PrimitiveType::PPC_FP128:
×
48
            return "__float128";
×
49
        case types::PrimitiveType::CHalf:
1✔
50
        case types::PrimitiveType::CBFloat:
2✔
51
        case types::PrimitiveType::CFloat:
3✔
52
        case types::PrimitiveType::CDouble:
4✔
53
        case types::PrimitiveType::CFP128:
5✔
54
            return complex_type_name(prim_type);
5✔
55
    }
50✔
56

57
    throw std::runtime_error("Unknown primitive type");
×
58
};
50✔
59

60
std::string CPPLanguageExtension::
61
    declaration(const std::string& name, const types::IType& type, bool use_initializer, bool use_alignment) {
67✔
62
    std::stringstream val;
67✔
63

64
    if (auto scalar_type = dynamic_cast<const types::Scalar*>(&type)) {
67✔
65
        val << primitive_type(scalar_type->primitive_type());
33✔
66
        val << " ";
33✔
67
        val << name;
33✔
68
    } else if (auto array_type = dynamic_cast<const types::Array*>(&type)) {
34✔
69
        auto& element_type = array_type->element_type();
10✔
70
        val << declaration(name + "[" + this->expression(array_type->num_elements()) + "]", element_type);
10✔
71
    } else if (auto pointer_type = dynamic_cast<const types::Pointer*>(&type)) {
24✔
72
        if (pointer_type->has_pointee_type()) {
20✔
73
            const types::IType& pointee = pointer_type->pointee_type();
18✔
74

75
            const bool pointee_is_function_or_array = dynamic_cast<const types::Function*>(&pointee) ||
18✔
76
                                                      dynamic_cast<const types::Array*>(&pointee);
18✔
77

78
            // Parenthesise *only* when it is needed to bind tighter than [] or ()
79
            std::string decorated = pointee_is_function_or_array ? "(*" + name + ")" : "*" + name;
18✔
80

81
            val << declaration(decorated, pointee);
18✔
82
        } else {
18✔
83
            val << "void*";
2✔
84
            val << " " << name;
2✔
85
        }
2✔
86
    } else if (auto ref_type = dynamic_cast<const Reference*>(&type)) {
20✔
87
        val << declaration("&" + name, ref_type->reference_type());
×
88
    } else if (auto structure_type = dynamic_cast<const types::Structure*>(&type)) {
4✔
89
        val << structure_type->name();
4✔
90
        val << " ";
4✔
91
        val << name;
4✔
92
    } else if (auto function_type = dynamic_cast<const types::Function*>(&type)) {
4✔
93
        std::stringstream params;
×
94
        for (size_t i = 0; i < function_type->num_params(); ++i) {
×
95
            params << declaration("", function_type->param_type(symbolic::integer(i)));
×
96
            if (i + 1 < function_type->num_params()) params << ", ";
×
97
        }
×
98
        if (function_type->is_var_arg()) {
×
99
            if (function_type->num_params() > 0) {
×
100
                params << ", ";
×
101
            }
×
102
            params << "...";
×
103
        }
×
104

105
        const std::string fun_name = name + "(" + params.str() + ")";
×
106
        val << declaration(fun_name, function_type->return_type());
×
107
    } else {
×
108
        throw std::runtime_error("Unknown declaration type");
×
109
    }
×
110

111
    if (use_alignment && type.alignment() > 0) {
67✔
112
        val << " __attribute__((aligned(" << type.alignment() << ")))";
×
113
    }
×
114
    if (use_initializer && !type.initializer().empty()) {
67✔
115
        val << " = " << type.initializer();
×
116
    }
×
117

118
    return val.str();
67✔
119
};
67✔
120

121
std::string CPPLanguageExtension::type_cast(const std::string& name, const types::IType& type) {
8✔
122
    std::stringstream val;
8✔
123

124
    val << "reinterpret_cast";
8✔
125
    val << "<";
8✔
126
    val << declaration("", type);
8✔
127
    val << ">";
8✔
128
    val << "(" << name << ")";
8✔
129

130
    return val.str();
8✔
131
};
8✔
132

133
std::string CPPLanguageExtension::subset(const types::IType& type, const data_flow::Subset& sub) {
16✔
134
    if (sub.empty()) {
16✔
135
        return "";
6✔
136
    }
6✔
137

138
    if (dynamic_cast<const types::Scalar*>(&type)) {
10✔
139
        return "";
×
140
    } else if (auto array_type = dynamic_cast<const types::Array*>(&type)) {
10✔
141
        std::string subset_str = "[" + this->expression(sub.at(0)) + "]";
5✔
142

143
        if (sub.size() > 1) {
5✔
144
            data_flow::Subset element_subset(sub.begin() + 1, sub.end());
×
145
            auto& element_type = array_type->element_type();
×
146
            return subset_str + subset(element_type, element_subset);
×
147
        } else {
5✔
148
            return subset_str;
5✔
149
        }
5✔
150
    } else if (auto pointer_type = dynamic_cast<const types::Pointer*>(&type)) {
5✔
151
        std::string subset_str = "[" + this->expression(sub.at(0)) + "]";
4✔
152

153
        data_flow::Subset element_subset(sub.begin() + 1, sub.end());
4✔
154
        auto& pointee_type = pointer_type->pointee_type();
4✔
155
        return subset_str + subset(pointee_type, element_subset);
4✔
156
    } else if (auto structure_type = dynamic_cast<const types::Structure*>(&type)) {
4✔
157
        auto& definition = this->function_.structure(structure_type->name());
1✔
158

159
        std::string subset_str = ".member_" + this->expression(sub.at(0));
1✔
160
        if (sub.size() > 1) {
1✔
161
            auto member = SymEngine::rcp_dynamic_cast<const SymEngine::Integer>(sub.at(0));
×
162
            auto& member_type = definition.member_type(member);
×
163
            data_flow::Subset element_subset(sub.begin() + 1, sub.end());
×
164
            return subset_str + subset(member_type, element_subset);
×
165
        } else {
1✔
166
            return subset_str;
1✔
167
        }
1✔
168
    }
1✔
169

170
    throw std::invalid_argument("Invalid subset type");
×
171
};
10✔
172

173
std::string CPPLanguageExtension::expression(const symbolic::Expression expr) {
37✔
174
    CPPSymbolicPrinter printer(this->function_, this->external_prefix_);
37✔
175
    return printer.apply(expr);
37✔
176
};
37✔
177

178
std::string CPPLanguageExtension::access_node(const data_flow::AccessNode& node) {
9✔
179
    if (dynamic_cast<const data_flow::ConstantNode*>(&node)) {
9✔
180
        std::string name = node.data();
×
181
        if (symbolic::is_nullptr(symbolic::symbol(name))) {
×
182
            return "nullptr";
×
183
        }
×
184
        return name;
×
185
    } else {
9✔
186
        std::string name = node.data();
9✔
187
        if (this->function_.is_external(name)) {
9✔
188
            return "(&" + this->external_prefix_ + name + ")";
×
189
        }
×
190
        return name;
9✔
191
    }
9✔
192
};
9✔
193

194
std::string CPPLanguageExtension::tasklet(const data_flow::Tasklet& tasklet) {
1✔
195
    switch (tasklet.code()) {
1✔
196
        case data_flow::TaskletCode::assign:
×
197
            return tasklet.inputs().at(0);
×
198
        case data_flow::TaskletCode::fp_neg:
×
199
            return "-" + tasklet.inputs().at(0);
×
200
        case data_flow::TaskletCode::fp_add:
×
201
            return tasklet.inputs().at(0) + " + " + tasklet.inputs().at(1);
×
202
        case data_flow::TaskletCode::fp_sub:
×
203
            return tasklet.inputs().at(0) + " - " + tasklet.inputs().at(1);
×
204
        case data_flow::TaskletCode::fp_mul:
×
205
            return tasklet.inputs().at(0) + " * " + tasklet.inputs().at(1);
×
206
        case data_flow::TaskletCode::fp_div:
×
207
            return tasklet.inputs().at(0) + " / " + tasklet.inputs().at(1);
×
208
        case data_flow::TaskletCode::fp_rem:
×
209
            return "fmod(" + tasklet.inputs().at(0) + ", " + tasklet.inputs().at(1) + ")";
×
210
        case data_flow::TaskletCode::fp_fma:
1✔
211
            return tasklet.inputs().at(0) + " * " + tasklet.inputs().at(1) + " + " + tasklet.inputs().at(2);
1✔
212
        case data_flow::TaskletCode::fp_oeq:
×
213
            return tasklet.inputs().at(0) + " == " + tasklet.inputs().at(1);
×
214
        case data_flow::TaskletCode::fp_one:
×
215
            return "!std::isnan(" + tasklet.inputs().at(0) + ") && !std::isnan(" + tasklet.inputs().at(1) + ") && " +
×
216
                   tasklet.inputs().at(0) + " != " + tasklet.inputs().at(1);
×
217
        case data_flow::TaskletCode::fp_ogt:
×
218
            return tasklet.inputs().at(0) + " > " + tasklet.inputs().at(1);
×
219
        case data_flow::TaskletCode::fp_oge:
×
220
            return tasklet.inputs().at(0) + " >= " + tasklet.inputs().at(1);
×
221
        case data_flow::TaskletCode::fp_olt:
×
222
            return tasklet.inputs().at(0) + " < " + tasklet.inputs().at(1);
×
223
        case data_flow::TaskletCode::fp_ole:
×
224
            return tasklet.inputs().at(0) + " <= " + tasklet.inputs().at(1);
×
225
        case data_flow::TaskletCode::fp_ord:
×
226
            return "std::isnan(" + tasklet.inputs().at(0) + ") && std::isnan(" + tasklet.inputs().at(1) + ")";
×
227
        case data_flow::TaskletCode::fp_ueq:
×
228
            return "std::isnan(" + tasklet.inputs().at(0) + ") || std::isnan(" + tasklet.inputs().at(1) + ")" + " || " +
×
229
                   tasklet.inputs().at(0) + " == " + tasklet.inputs().at(1);
×
230
        case data_flow::TaskletCode::fp_une:
×
231
            return "std::isnan(" + tasklet.inputs().at(0) + ") || std::isnan(" + tasklet.inputs().at(1) + ")" + " || " +
×
232
                   tasklet.inputs().at(0) + " != " + tasklet.inputs().at(1);
×
233
        case data_flow::TaskletCode::fp_ugt:
×
234
            return "std::isnan(" + tasklet.inputs().at(0) + ") || std::isnan(" + tasklet.inputs().at(1) + ")" + " || " +
×
235
                   tasklet.inputs().at(0) + " > " + tasklet.inputs().at(1);
×
236
        case data_flow::TaskletCode::fp_uge:
×
237
            return "std::isnan(" + tasklet.inputs().at(0) + ") || std::isnan(" + tasklet.inputs().at(1) + ")" + " || " +
×
238
                   tasklet.inputs().at(0) + " >= " + tasklet.inputs().at(1);
×
239
        case data_flow::TaskletCode::fp_ult:
×
240
            return "std::isnan(" + tasklet.inputs().at(0) + ") || std::isnan(" + tasklet.inputs().at(1) + ")" + " || " +
×
241
                   tasklet.inputs().at(0) + " < " + tasklet.inputs().at(1);
×
242
        case data_flow::TaskletCode::fp_ule:
×
243
            return "std::isnan(" + tasklet.inputs().at(0) + ") || std::isnan(" + tasklet.inputs().at(1) + ")" + " || " +
×
244
                   tasklet.inputs().at(0) + " <= " + tasklet.inputs().at(1);
×
245
        case data_flow::TaskletCode::fp_uno:
×
246
            return "std::isnan(" + tasklet.inputs().at(0) + ") || std::isnan(" + tasklet.inputs().at(1) + ")";
×
247
        case data_flow::TaskletCode::int_add:
×
248
            return tasklet.inputs().at(0) + " + " + tasklet.inputs().at(1);
×
249
        case data_flow::TaskletCode::int_sub:
×
250
            return tasklet.inputs().at(0) + " - " + tasklet.inputs().at(1);
×
251
        case data_flow::TaskletCode::int_mul:
×
252
            return tasklet.inputs().at(0) + " * " + tasklet.inputs().at(1);
×
253
        case data_flow::TaskletCode::int_sdiv:
×
254
            return tasklet.inputs().at(0) + " / " + tasklet.inputs().at(1);
×
255
        case data_flow::TaskletCode::int_srem:
×
256
            return tasklet.inputs().at(0) + " % " + tasklet.inputs().at(1);
×
257
        case data_flow::TaskletCode::int_udiv:
×
258
            return tasklet.inputs().at(0) + " / " + tasklet.inputs().at(1);
×
259
        case data_flow::TaskletCode::int_urem:
×
260
            return tasklet.inputs().at(0) + " % " + tasklet.inputs().at(1);
×
261
        case data_flow::TaskletCode::int_and:
×
262
            return tasklet.inputs().at(0) + " & " + tasklet.inputs().at(1);
×
263
        case data_flow::TaskletCode::int_or:
×
264
            return tasklet.inputs().at(0) + " | " + tasklet.inputs().at(1);
×
265
        case data_flow::TaskletCode::int_xor:
×
266
            return tasklet.inputs().at(0) + " ^ " + tasklet.inputs().at(1);
×
267
        case data_flow::TaskletCode::int_shl:
×
268
            return tasklet.inputs().at(0) + " << " + tasklet.inputs().at(1);
×
269
        case data_flow::TaskletCode::int_lshr:
×
270
            return tasklet.inputs().at(0) + " >> " + tasklet.inputs().at(1);
×
271
        case data_flow::TaskletCode::int_ashr:
×
272
            return tasklet.inputs().at(0) + " >> " + tasklet.inputs().at(1);
×
273
        case data_flow::TaskletCode::int_smin:
×
274
            return tasklet.inputs().at(0) + " < " + tasklet.inputs().at(1) + " ? " + tasklet.inputs().at(0) + " : " +
×
275
                   tasklet.inputs().at(1);
×
276
        case data_flow::TaskletCode::int_smax:
×
277
            return tasklet.inputs().at(0) + " > " + tasklet.inputs().at(1) + " ? " + tasklet.inputs().at(0) + " : " +
×
278
                   tasklet.inputs().at(1);
×
279
        case data_flow::TaskletCode::int_scmp:
×
280
            return tasklet.inputs().at(0) + " < " + tasklet.inputs().at(1) + " ? -1 : (" + tasklet.inputs().at(0) +
×
281
                   " > " + tasklet.inputs().at(1) + " ? 1 : 0)";
×
282
        case data_flow::TaskletCode::int_umin:
×
283
            return tasklet.inputs().at(0) + " < " + tasklet.inputs().at(1) + " ? " + tasklet.inputs().at(0) + " : " +
×
284
                   tasklet.inputs().at(1);
×
285
        case data_flow::TaskletCode::int_umax:
×
286
            return tasklet.inputs().at(0) + " > " + tasklet.inputs().at(1) + " ? " + tasklet.inputs().at(0) + " : " +
×
287
                   tasklet.inputs().at(1);
×
288
        case data_flow::TaskletCode::int_ucmp:
×
289
            return tasklet.inputs().at(0) + " < " + tasklet.inputs().at(1) + " ? -1 : (" + tasklet.inputs().at(0) +
×
290
                   " > " + tasklet.inputs().at(1) + " ? 1 : 0)";
×
291
        case data_flow::TaskletCode::int_abs:
×
292
            return "(" + tasklet.inputs().at(0) + " < 0 ? -" + tasklet.inputs().at(0) + " : " + tasklet.inputs().at(0) +
×
293
                   ")";
×
294
        case data_flow::TaskletCode::int_eq:
×
295
            return tasklet.inputs().at(0) + " == " + tasklet.inputs().at(1);
×
296
        case data_flow::TaskletCode::int_ne:
×
297
            return tasklet.inputs().at(0) + " != " + tasklet.inputs().at(1);
×
298
        case data_flow::TaskletCode::int_sgt:
×
299
            return tasklet.inputs().at(0) + " > " + tasklet.inputs().at(1);
×
300
        case data_flow::TaskletCode::int_sge:
×
301
            return tasklet.inputs().at(0) + " >= " + tasklet.inputs().at(1);
×
302
        case data_flow::TaskletCode::int_slt:
×
303
            return tasklet.inputs().at(0) + " < " + tasklet.inputs().at(1);
×
304
        case data_flow::TaskletCode::int_sle:
×
305
            return tasklet.inputs().at(0) + " <= " + tasklet.inputs().at(1);
×
306
        case data_flow::TaskletCode::int_ugt:
×
307
            return tasklet.inputs().at(0) + " > " + tasklet.inputs().at(1);
×
308
        case data_flow::TaskletCode::int_uge:
×
309
            return tasklet.inputs().at(0) + " >= " + tasklet.inputs().at(1);
×
310
        case data_flow::TaskletCode::int_ult:
×
311
            return tasklet.inputs().at(0) + " < " + tasklet.inputs().at(1);
×
312
        case data_flow::TaskletCode::int_ule:
×
313
            return tasklet.inputs().at(0) + " <= " + tasklet.inputs().at(1);
×
NEW
314
        case data_flow::TaskletCode::complex_neg:
×
NEW
315
        case data_flow::TaskletCode::complex_real:
×
NEW
316
        case data_flow::TaskletCode::complex_imag:
×
NEW
317
        case data_flow::TaskletCode::complex_add:
×
NEW
318
        case data_flow::TaskletCode::complex_sub:
×
NEW
319
        case data_flow::TaskletCode::complex_mul:
×
NEW
320
        case data_flow::TaskletCode::complex_div:
×
NEW
321
        case data_flow::TaskletCode::complex_eq:
×
NEW
322
        case data_flow::TaskletCode::complex_ne:
×
NEW
323
            return complex_computation(tasklet, this->function_);
×
324
    };
1✔
325
    throw std::invalid_argument("Invalid tasklet code");
×
326
};
1✔
327

328
std::string CPPLanguageExtension::zero(const types::PrimitiveType prim_type) {
3✔
329
    switch (prim_type) {
3✔
330
        case types::Void:
×
331
            throw InvalidSDFGException("No zero for void type possible");
×
332
        case types::Bool:
×
333
            return "false";
×
334
        case types::Int8:
×
335
            return "0";
×
336
        case types::Int16:
×
337
            return "0";
×
338
        case types::Int32:
×
339
            return "0";
×
340
        case types::Int64:
×
341
            return "0ll";
×
342
        case types::Int128:
×
343
            return "0";
×
344
        case types::UInt8:
×
345
            return "0u";
×
346
        case types::UInt16:
×
347
            return "0u";
×
348
        case types::UInt32:
×
349
            return "0u";
×
350
        case types::UInt64:
×
351
            return "0ull";
×
352
        case types::UInt128:
×
353
            return "0u";
×
354
        case types::Half:
×
355
            throw InvalidSDFGException("Currently unsupported");
×
356
        case types::BFloat:
×
357
            throw InvalidSDFGException("Currently unsupported");
×
358
        case types::Float:
×
359
            return "0.0f";
×
360
        case types::Double:
×
361
            return "0.0";
×
362
        case types::X86_FP80:
×
363
            return "0.0l";
×
364
        case types::FP128:
×
365
            throw InvalidSDFGException("Currently unsupported");
×
366
        case types::PPC_FP128:
×
367
            throw InvalidSDFGException("Currently unsupported");
×
NEW
368
        case types::CHalf:
×
NEW
369
        case types::CBFloat:
×
370
        case types::CFloat:
1✔
371
        case types::CDouble:
2✔
372
        case types::CFP128:
3✔
373
            return complex_type_name(prim_type) + "{0, 0}";
3✔
374
    }
3✔
375
}
3✔
376

377
void CPPSymbolicPrinter::bvisit(const SymEngine::Infty& x) {
×
378
    if (x.is_negative_infinity())
×
379
        str_ = "-INFINITY";
×
380
    else if (x.is_positive_infinity())
×
381
        str_ = "INFINITY";
×
382
};
×
383

384
void CPPSymbolicPrinter::bvisit(const SymEngine::BooleanAtom& x) { str_ = x.get_val() ? "true" : "false"; };
×
385

386
void CPPSymbolicPrinter::bvisit(const SymEngine::Symbol& x) {
27✔
387
    if (symbolic::is_nullptr(symbolic::symbol(x.get_name()))) {
27✔
388
        str_ = "(reinterpret_cast<uintptr_t>(nullptr))";
×
389
        return;
×
390
    }
×
391
    std::string name = x.get_name();
27✔
392

393
    if (this->function_.is_external(name)) {
27✔
394
        name = "(reinterpret_cast<uintptr_t>(&" + this->external_prefix_ + name + "))";
1✔
395
    } else if (this->function_.exists(name) && this->function_.type(name).type_id() == types::TypeID::Pointer) {
26✔
396
        name = "(reinterpret_cast<uintptr_t>(" + name + "))";
×
397
    }
×
398

399
    str_ = name;
27✔
400
};
27✔
401

402
void CPPSymbolicPrinter::bvisit(const SymEngine::And& x) {
×
403
    std::ostringstream s;
×
404
    auto container = x.get_container();
×
405
    s << apply(*container.begin());
×
406
    for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
407
        s << " && " << apply(*it);
×
408
    }
×
409
    str_ = parenthesize(s.str());
×
410
};
×
411

412
void CPPSymbolicPrinter::bvisit(const SymEngine::Or& x) {
×
413
    std::ostringstream s;
×
414
    auto container = x.get_container();
×
415
    s << apply(*container.begin());
×
416
    for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
417
        s << " || " << apply(*it);
×
418
    }
×
419
    str_ = parenthesize(s.str());
×
420
};
×
421

422
void CPPSymbolicPrinter::bvisit(const SymEngine::Not& x) {
×
423
    str_ = "!" + apply(x.get_arg());
×
424
    str_ = parenthesize(str_);
×
425
};
×
426

427
void CPPSymbolicPrinter::bvisit(const SymEngine::Equality& x) {
×
428
    str_ = apply(x.get_args()[0]) + " == " + apply(x.get_args()[1]);
×
429
    str_ = parenthesize(str_);
×
430
};
×
431

432
void CPPSymbolicPrinter::bvisit(const SymEngine::Unequality& x) {
×
433
    str_ = apply(x.get_args()[0]) + " != " + apply(x.get_args()[1]);
×
434
    str_ = parenthesize(str_);
×
435
};
×
436

437
void CPPSymbolicPrinter::bvisit(const SymEngine::Min& x) {
×
438
    std::ostringstream s;
×
439
    auto container = x.get_args();
×
440
    if (container.size() == 1) {
×
441
        s << apply(*container.begin());
×
442
    } else {
×
443
        s << "__daisy_min(";
×
444
        s << apply(*container.begin());
×
445

446
        // Recursively apply __daisy_min to the arguments
447
        SymEngine::vec_basic subargs;
×
448
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
449
            subargs.push_back(*it);
×
450
        }
×
451
        auto submin = SymEngine::min(subargs);
×
452
        s << ", " << apply(submin);
×
453

454
        s << ")";
×
455
    }
×
456

457
    str_ = s.str();
×
458
};
×
459

460
void CPPSymbolicPrinter::bvisit(const SymEngine::Max& x) {
×
461
    std::ostringstream s;
×
462
    auto container = x.get_args();
×
463
    if (container.size() == 1) {
×
464
        s << apply(*container.begin());
×
465
    } else {
×
466
        s << "__daisy_max(";
×
467
        s << apply(*container.begin());
×
468

469
        // Recursively apply __daisy_max to the arguments
470
        SymEngine::vec_basic subargs;
×
471
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
472
            subargs.push_back(*it);
×
473
        }
×
474
        auto submax = SymEngine::max(subargs);
×
475
        s << ", " << apply(submax);
×
476

477
        s << ")";
×
478
    }
×
479

480
    str_ = s.str();
×
481
};
×
482

483
void CPPSymbolicPrinter::bvisit(const SymEngine::FunctionSymbol& x) {
1✔
484
    if (x.get_name() == "idiv") {
1✔
485
        str_ = "((" + apply(x.get_args()[0]) + ") / (" + apply(x.get_args()[1]) + "))";
×
486
    } else if (x.get_name() == "iabs") {
1✔
487
        str_ = "((" + apply(x.get_args()[0]) + ") < 0 ? -(" + apply(x.get_args()[0]) + ") : (" +
×
488
               apply(x.get_args()[0]) + "))";
×
489
    } else if (x.get_name() == "zext_i64") {
1✔
490
        str_ = "((long long) ((unsigned long long) (" + apply(x.get_args()[0]) + ")))";
×
491
    } else if (x.get_name() == "trunc_i32") {
1✔
492
        str_ = "((int) ((unsigned int) ((unsigned long long) (" + apply(x.get_args()[0]) + "))))";
×
493
    } else if (x.get_name() == "imod") {
1✔
494
        str_ = "((" + apply(x.get_args()[0]) + ") % (" + apply(x.get_args()[1]) + "))";
×
495
    } else if (x.get_name() == "sizeof") {
1✔
496
        auto& so = dynamic_cast<const symbolic::SizeOfTypeFunction&>(x);
1✔
497
        auto& type = so.get_type();
1✔
498
        CPPLanguageExtension lang(this->function_, this->external_prefix_);
1✔
499
        str_ = "sizeof(" + lang.declaration("", type) + ")";
1✔
500
    } else if (x.get_name() == "malloc_usable_size") {
1✔
501
        str_ = "malloc_usable_size(" +
×
502
               SymEngine::rcp_static_cast<const SymEngine::Symbol>(x.get_args()[0])->get_name() + ")";
×
503
    } else {
×
504
        throw std::runtime_error("Unsupported function symbol: " + x.get_name());
×
505
    }
×
506
};
1✔
507

508
void CPPSymbolicPrinter::_print_pow(
509
    std::ostringstream& o,
510
    const SymEngine::RCP<const SymEngine::Basic>& a,
511
    const SymEngine::RCP<const SymEngine::Basic>& b
512
) {
2✔
513
    if (SymEngine::eq(*a, *SymEngine::E)) {
2✔
514
        o << "exp(" << apply(b) << ")";
×
515
    } else if (SymEngine::eq(*b, *SymEngine::rational(1, 2))) {
2✔
516
        o << "sqrt(" << apply(a) << ")";
×
517
    } else if (SymEngine::eq(*b, *SymEngine::rational(1, 3))) {
2✔
518
        o << "cbrt(" << apply(a) << ")";
×
519
    } else if (SymEngine::eq(*b, *SymEngine::integer(2))) {
2✔
520
        o << "((" + apply(a) + ") * (" + apply(a) + "))";
2✔
521
    } else {
2✔
522
        o << "__daisy_sym_pow(" << apply(a) << ", " << apply(b) << ")";
×
523
    }
×
524
};
2✔
525

526
} // namespace codegen
527
} // namespace sdfg
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc