• 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

41.53
/sdfg/src/codegen/language_extensions/c_language_extension.cpp
1
#include "sdfg/codegen/language_extensions/c_language_extension.h"
2

3
#include <cstddef>
4
#include <string>
5

6
#include "sdfg/codegen/utils.h"
7
#include "sdfg/data_flow/tasklet.h"
8
#include "sdfg/exceptions.h"
9
#include "sdfg/types/type.h"
10

11
namespace sdfg {
12
namespace codegen {
13

14
std::string CLanguageExtension::primitive_type(const types::PrimitiveType prim_type) {
64✔
15
    switch (prim_type) {
64✔
16
        case types::PrimitiveType::Void:
2✔
17
            return "void";
2✔
18
        case types::PrimitiveType::Bool:
1✔
19
            return "bool";
1✔
20
        case types::PrimitiveType::Int8:
1✔
21
            return "signed char";
1✔
22
        case types::PrimitiveType::Int16:
1✔
23
            return "short";
1✔
24
        case types::PrimitiveType::Int32:
17✔
25
            return "int";
17✔
26
        case types::PrimitiveType::Int64:
4✔
27
            return "long long";
4✔
28
        case types::PrimitiveType::Int128:
×
29
            return "__int128";
×
30
        case types::PrimitiveType::UInt8:
3✔
31
            return "char";
3✔
32
        case types::PrimitiveType::UInt16:
1✔
33
            return "unsigned short";
1✔
34
        case types::PrimitiveType::UInt32:
1✔
35
            return "unsigned int";
1✔
36
        case types::PrimitiveType::UInt64:
1✔
37
            return "unsigned long long";
1✔
38
        case types::PrimitiveType::UInt128:
×
39
            return "unsigned __int128";
×
40
        case types::PrimitiveType::Half:
×
41
            return "_Float16";
×
42
        case types::PrimitiveType::BFloat:
×
43
            return "__bf16";
×
44
        case types::PrimitiveType::Float:
18✔
45
            return "float";
18✔
46
        case types::PrimitiveType::Double:
6✔
47
            return "double";
6✔
48
        case types::PrimitiveType::X86_FP80:
×
49
            return "long double";
×
50
        case types::PrimitiveType::FP128:
×
51
            return "__float128";
×
52
        case types::PrimitiveType::PPC_FP128:
×
53
            return "__float128";
×
54
        case types::PrimitiveType::CHalf:
1✔
55
        case types::PrimitiveType::CBFloat:
2✔
56
        case types::PrimitiveType::CFloat:
6✔
57
        case types::PrimitiveType::CDouble:
7✔
58
        case types::PrimitiveType::CFP128:
8✔
59
            return complex_type_name(prim_type);
8✔
60
    }
64✔
61

62
    throw std::runtime_error("Unknown primitive type");
×
63
};
64✔
64

65
std::string CLanguageExtension::
66
    declaration(const std::string& name, const types::IType& type, bool use_initializer, bool use_alignment) {
83✔
67
    std::stringstream val;
83✔
68

69
    if (auto scalar_type = dynamic_cast<const types::Scalar*>(&type)) {
83✔
70
        val << primitive_type(scalar_type->primitive_type());
47✔
71
        val << " ";
47✔
72
        val << name;
47✔
73
    } else if (auto array_type = dynamic_cast<const types::Array*>(&type)) {
47✔
74
        auto& element_type = array_type->element_type();
3✔
75
        val << declaration(name + "[" + this->expression(array_type->num_elements()) + "]", element_type);
3✔
76
    } else if (auto pointer_type = dynamic_cast<const types::Pointer*>(&type)) {
33✔
77
        if (pointer_type->has_pointee_type()) {
29✔
78
            const types::IType& pointee = pointer_type->pointee_type();
28✔
79

80
            const bool pointee_is_function_or_array = dynamic_cast<const types::Function*>(&pointee) ||
28✔
81
                                                      dynamic_cast<const types::Array*>(&pointee);
28✔
82

83
            // Parenthesise *only* when it is needed to bind tighter than [] or ()
84
            std::string decorated = pointee_is_function_or_array ? "(*" + name + ")" : "*" + name;
28✔
85

86
            val << declaration(decorated, pointee);
28✔
87
        } else {
28✔
88
            val << "void*";
1✔
89
            val << " " << name;
1✔
90
        }
1✔
91
    } else if (auto ref_type = dynamic_cast<const Reference*>(&type)) {
29✔
92
        val << declaration("&" + name, ref_type->reference_type());
×
93
    } else if (auto structure_type = dynamic_cast<const types::Structure*>(&type)) {
4✔
94
        val << structure_type->name();
4✔
95
        val << " ";
4✔
96
        val << name;
4✔
97
    } else if (auto function_type = dynamic_cast<const types::Function*>(&type)) {
4✔
98
        std::stringstream params;
×
99
        for (size_t i = 0; i < function_type->num_params(); ++i) {
×
100
            params << declaration("", function_type->param_type(symbolic::integer(i)));
×
101
            if (i + 1 < function_type->num_params()) params << ", ";
×
102
        }
×
103
        if (function_type->is_var_arg()) {
×
104
            // ISO C forbids empty parameter lists before ...
105
            if (function_type->num_params() > 0) {
×
106
                params << ", ";
×
107
                params << "...";
×
108
            }
×
109
        }
×
110

111
        const std::string fun_name = name + "(" + params.str() + ")";
×
112
        val << declaration(fun_name, function_type->return_type());
×
113
    } else {
×
114
        throw std::runtime_error("Unknown declaration type");
×
115
    }
×
116

117
    if (use_alignment && type.alignment() > 0) {
83✔
118
        val << " __attribute__((aligned(" << type.alignment() << ")))";
×
119
    }
×
120

121
    if (use_initializer && !type.initializer().empty()) {
83✔
122
        val << " = " << type.initializer();
×
123
    }
×
124

125
    return val.str();
83✔
126
};
83✔
127

128
std::string CLanguageExtension::type_cast(const std::string& name, const types::IType& type) {
15✔
129
    std::stringstream val;
15✔
130

131
    val << "(";
15✔
132
    val << declaration("", type);
15✔
133
    val << ") ";
15✔
134
    val << name;
15✔
135

136
    return val.str();
15✔
137
};
15✔
138

139
std::string CLanguageExtension::subset(const types::IType& type, const data_flow::Subset& sub) {
45✔
140
    if (sub.empty()) {
45✔
141
        return "";
39✔
142
    }
39✔
143

144
    if (dynamic_cast<const types::Scalar*>(&type)) {
6✔
145
        return "";
×
146
    } else if (auto array_type = dynamic_cast<const types::Array*>(&type)) {
6✔
147
        std::string subset_str = "[" + this->expression(sub.at(0)) + "]";
4✔
148

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

159
        data_flow::Subset element_subset(sub.begin() + 1, sub.end());
1✔
160
        auto& pointee_type = pointer_type->pointee_type();
1✔
161
        return subset_str + subset(pointee_type, element_subset);
1✔
162
    } else if (auto structure_type = dynamic_cast<const types::Structure*>(&type)) {
1✔
163
        auto& definition = this->function_.structure(structure_type->name());
1✔
164

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

176
    throw std::invalid_argument("Invalid subset type");
×
177
};
6✔
178

179
std::string CLanguageExtension::expression(const symbolic::Expression expr) {
134✔
180
    CSymbolicPrinter printer(this->function_, this->external_prefix_);
134✔
181
    return printer.apply(expr);
134✔
182
};
134✔
183

184
std::string CLanguageExtension::access_node(const data_flow::AccessNode& node) {
51✔
185
    if (dynamic_cast<const data_flow::ConstantNode*>(&node)) {
51✔
186
        std::string name = node.data();
5✔
187
        if (symbolic::is_nullptr(symbolic::symbol(name))) {
5✔
188
            return "NULL";
2✔
189
        }
2✔
190
        return name;
3✔
191
    } else {
46✔
192
        std::string name = node.data();
46✔
193
        if (this->function_.is_external(name)) {
46✔
194
            return "(&" + this->external_prefix_ + name + ")";
×
195
        }
×
196
        return name;
46✔
197
    }
46✔
198
};
51✔
199

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

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

382
void CSymbolicPrinter::bvisit(const SymEngine::Infty& x) {
×
383
    if (x.is_negative_infinity())
×
384
        str_ = "-INFINITY";
×
385
    else if (x.is_positive_infinity())
×
386
        str_ = "INFINITY";
×
387
};
×
388

389
void CSymbolicPrinter::bvisit(const SymEngine::BooleanAtom& x) { str_ = x.get_val() ? "true" : "false"; };
2✔
390

391
void CSymbolicPrinter::bvisit(const SymEngine::Symbol& x) {
89✔
392
    if (symbolic::is_nullptr(symbolic::symbol(x.get_name()))) {
89✔
393
        str_ = "((uintptr_t) NULL)";
×
394
        return;
×
395
    }
×
396

397
    std::string name = x.get_name();
89✔
398

399
    if (this->function_.is_external(name)) {
89✔
400
        name = "((uintptr_t) (&" + this->external_prefix_ + name + "))";
1✔
401
    } else if (this->function_.exists(name) && this->function_.type(name).type_id() == types::TypeID::Pointer) {
88✔
402
        name = "((uintptr_t) " + name + ")";
×
403
    }
×
404

405
    str_ = name;
89✔
406
};
89✔
407

408
void CSymbolicPrinter::bvisit(const SymEngine::And& x) {
×
409
    std::ostringstream s;
×
410
    auto container = x.get_container();
×
411
    s << apply(*container.begin());
×
412
    for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
413
        s << " && " << apply(*it);
×
414
    }
×
415
    str_ = parenthesize(s.str());
×
416
};
×
417

418
void CSymbolicPrinter::bvisit(const SymEngine::Or& x) {
×
419
    std::ostringstream s;
×
420
    auto container = x.get_container();
×
421
    s << apply(*container.begin());
×
422
    for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
423
        s << " || " << apply(*it);
×
424
    }
×
425
    str_ = parenthesize(s.str());
×
426
};
×
427

428
void CSymbolicPrinter::bvisit(const SymEngine::Not& x) {
×
429
    str_ = "!" + apply(x.get_arg());
×
430
    str_ = parenthesize(str_);
×
431
};
×
432

433
void CSymbolicPrinter::bvisit(const SymEngine::Equality& x) {
1✔
434
    str_ = apply(x.get_args()[0]) + " == " + apply(x.get_args()[1]);
1✔
435
    str_ = parenthesize(str_);
1✔
436
};
1✔
437

438
void CSymbolicPrinter::bvisit(const SymEngine::Unequality& x) {
1✔
439
    str_ = apply(x.get_args()[0]) + " != " + apply(x.get_args()[1]);
1✔
440
    str_ = parenthesize(str_);
1✔
441
};
1✔
442

443
void CSymbolicPrinter::bvisit(const SymEngine::Min& x) {
1✔
444
    std::ostringstream s;
1✔
445
    auto container = x.get_args();
1✔
446
    if (container.size() == 1) {
1✔
447
        s << apply(*container.begin());
×
448
    } else {
1✔
449
        if (this->use_rtl_functions_) {
1✔
450
            s << "__daisy_min(";
1✔
451
        } else {
1✔
452
            s << "min(";
×
453
        }
×
454
        s << apply(*container.begin());
1✔
455

456
        // Recursively apply __daisy_min to the arguments
457
        SymEngine::vec_basic subargs;
1✔
458
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
2✔
459
            subargs.push_back(*it);
1✔
460
        }
1✔
461
        auto submin = SymEngine::min(subargs);
1✔
462
        s << ", " << apply(submin);
1✔
463

464
        s << ")";
1✔
465
    }
1✔
466

467
    str_ = s.str();
1✔
468
};
1✔
469

470
void CSymbolicPrinter::bvisit(const SymEngine::Max& x) {
×
471
    std::ostringstream s;
×
472
    auto container = x.get_args();
×
473
    if (container.size() == 1) {
×
474
        s << apply(*container.begin());
×
475
    } else {
×
476
        if (this->use_rtl_functions_) {
×
477
            s << "__daisy_max(";
×
478
        } else {
×
479
            s << "max(";
×
480
        }
×
481
        s << apply(*container.begin());
×
482

483
        // Recursively apply __daisy_max to the arguments
484
        SymEngine::vec_basic subargs;
×
485
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
486
            subargs.push_back(*it);
×
487
        }
×
488
        auto submax = SymEngine::max(subargs);
×
489
        s << ", " << apply(submax);
×
490

491
        s << ")";
×
492
    }
×
493

494
    str_ = s.str();
×
495
};
×
496

497
void CSymbolicPrinter::bvisit(const SymEngine::FunctionSymbol& x) {
1✔
498
    if (x.get_name() == "idiv") {
1✔
499
        str_ = "((" + apply(x.get_args()[0]) + ") / (" + apply(x.get_args()[1]) + "))";
×
500
    } else if (x.get_name() == "iabs") {
1✔
501
        str_ = "((" + apply(x.get_args()[0]) + ") < 0 ? -(" + apply(x.get_args()[0]) + ") : (" +
×
502
               apply(x.get_args()[0]) + "))";
×
503
    } else if (x.get_name() == "zext_i64") {
1✔
504
        str_ = "((long long) ((unsigned long long) (" + apply(x.get_args()[0]) + ")))";
×
505
    } else if (x.get_name() == "trunc_i32") {
1✔
506
        str_ = "((int) ((unsigned int) ((unsigned long long) (" + apply(x.get_args()[0]) + "))))";
×
507
    } else if (x.get_name() == "imod") {
1✔
508
        str_ = "((" + apply(x.get_args()[0]) + ") % (" + apply(x.get_args()[1]) + "))";
×
509
    } else if (x.get_name() == "sizeof") {
1✔
510
        auto& so = dynamic_cast<const symbolic::SizeOfTypeFunction&>(x);
1✔
511
        auto& type = so.get_type();
1✔
512
        CLanguageExtension lang(this->function_, this->external_prefix_);
1✔
513
        str_ = "sizeof(" + lang.declaration("", type) + ")";
1✔
514
    } else if (x.get_name() == "malloc_usable_size") {
1✔
515
        str_ = "malloc_usable_size(" +
×
516
               SymEngine::rcp_static_cast<const SymEngine::Symbol>(x.get_args()[0])->get_name() + ")";
×
517
    } else {
×
518
        throw std::runtime_error("Unsupported function symbol: " + x.get_name());
×
519
    }
×
520
};
1✔
521

522
void CSymbolicPrinter::_print_pow(
523
    std::ostringstream& o,
524
    const SymEngine::RCP<const SymEngine::Basic>& a,
525
    const SymEngine::RCP<const SymEngine::Basic>& b
526
) {
2✔
527
    if (SymEngine::eq(*a, *SymEngine::E)) {
2✔
528
        o << "exp(" << apply(b) << ")";
×
529
    } else if (SymEngine::eq(*b, *SymEngine::rational(1, 2))) {
2✔
530
        o << "sqrt(" << apply(a) << ")";
×
531
    } else if (SymEngine::eq(*b, *SymEngine::rational(1, 3))) {
2✔
532
        o << "cbrt(" << apply(a) << ")";
×
533
    } else if (SymEngine::eq(*b, *SymEngine::integer(2))) {
2✔
534
        o << "((" + apply(a) + ") * (" + apply(a) + "))";
2✔
535
    } else {
2✔
536
        o << "__daisy_sym_pow(" << apply(a) << ", " << apply(b) << ")";
×
537
    }
×
538
};
2✔
539

540
} // namespace codegen
541
} // 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