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

daisytuner / sdfglib / 15852980623

24 Jun 2025 02:16PM UTC coverage: 64.412% (+0.3%) from 64.145%
15852980623

push

github

web-flow
Merge pull request #72 from daisytuner/capture-instrumentation

Capture instrumentation

363 of 446 new or added lines in 19 files covered. (81.39%)

100 existing lines in 5 files now uncovered.

8389 of 13024 relevant lines covered (64.41%)

116.79 hits per line

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

52.42
/src/symbolic/maps.cpp
1
#include "sdfg/symbolic/maps.h"
2

3
#include <isl/ctx.h>
4
#include <isl/set.h>
5
#include <isl/space.h>
6

7
#include "sdfg/symbolic/extreme_values.h"
8
#include "sdfg/symbolic/polynomials.h"
9
#include "sdfg/symbolic/utils.h"
10

11
namespace sdfg {
12
namespace symbolic {
13
namespace maps {
14

15
bool is_monotonic_affine(const Expression& expr, const Symbol& sym, const Assumptions& assums) {
10✔
16
    SymbolVec symbols = {sym};
10✔
17
    auto poly = polynomial(expr, symbols);
10✔
18
    if (poly == SymEngine::null) {
10✔
19
        return false;
×
20
    }
21
    auto coeffs = affine_coefficients(poly, symbols);
10✔
22
    if (coeffs.empty()) {
10✔
UNCOV
23
        return false;
×
24
    }
25
    auto mul = minimum(coeffs[sym], {}, assums);
10✔
26
    if (mul == SymEngine::null) {
10✔
27
        return false;
×
28
    }
29
    if (!SymEngine::is_a<SymEngine::Integer>(*mul)) {
10✔
30
        return false;
×
31
    }
32
    auto mul_int = SymEngine::rcp_dynamic_cast<const SymEngine::Integer>(mul);
10✔
33
    if (mul_int->as_int() <= 0) {
10✔
UNCOV
34
        return false;
×
35
    }
36

37
    return true;
10✔
38
}
10✔
39

UNCOV
40
bool is_monotonic_pow(const Expression& expr, const Symbol& sym, const Assumptions& assums) {
×
UNCOV
41
    if (SymEngine::is_a<SymEngine::Pow>(*expr)) {
×
UNCOV
42
        auto pow = SymEngine::rcp_dynamic_cast<const SymEngine::Pow>(expr);
×
UNCOV
43
        auto base = pow->get_base();
×
UNCOV
44
        auto exp = pow->get_exp();
×
UNCOV
45
        if (SymEngine::is_a<SymEngine::Integer>(*exp) &&
×
UNCOV
46
            SymEngine::is_a<SymEngine::Symbol>(*base)) {
×
UNCOV
47
            auto exp_int = SymEngine::rcp_dynamic_cast<const SymEngine::Integer>(exp);
×
UNCOV
48
            if (exp_int->as_int() <= 0) {
×
49
                return false;
×
50
            }
UNCOV
51
            auto base_sym = SymEngine::rcp_static_cast<const SymEngine::Symbol>(base);
×
UNCOV
52
            auto ub_sym = minimum(base_sym, {}, assums);
×
UNCOV
53
            if (ub_sym == SymEngine::null) {
×
54
                return false;
×
55
            }
UNCOV
56
            auto positive = symbolic::Ge(ub_sym, symbolic::integer(0));
×
UNCOV
57
            return symbolic::is_true(positive);
×
UNCOV
58
        }
×
UNCOV
59
    }
×
60

UNCOV
61
    return false;
×
UNCOV
62
}
×
63

64
bool is_monotonic(const Expression& expr, const Symbol& sym, const Assumptions& assums) {
10✔
65
    if (is_monotonic_affine(expr, sym, assums)) {
10✔
66
        return true;
10✔
67
    }
UNCOV
68
    return is_monotonic_pow(expr, sym, assums);
×
69
}
10✔
70

71
bool is_disjoint_isl(const MultiExpression& expr1, const MultiExpression& expr2,
4✔
72
                     const Symbol& indvar, const Assumptions& assums1, const Assumptions& assums2) {
73
    if (expr1.size() != expr2.size()) {
4✔
74
        return false;
×
75
    }
76
    if (expr1.empty()) {
4✔
77
        return false;
×
78
    }
79

80
    isl_ctx* ctx = isl_ctx_alloc();
4✔
81

82
    // Transform both expressions into two maps with separate dimensions
83
    auto expr1_delinearized = delinearize(expr1, assums1);
4✔
84
    auto expr2_delinearized = delinearize(expr2, assums2);
4✔
85
    auto maps = expressions_to_intersection_map_str(expr1_delinearized, expr2_delinearized, indvar,
8✔
86
                                                    assums1, assums2);
4✔
87
    isl_map* map_1 = isl_map_read_from_str(ctx, std::get<0>(maps).c_str());
4✔
88
    isl_map* map_2 = isl_map_read_from_str(ctx, std::get<1>(maps).c_str());
4✔
89
    isl_map* map_3 = isl_map_read_from_str(ctx, std::get<2>(maps).c_str());
4✔
90
    if (!map_1 || !map_2 || !map_3) {
4✔
91
        if (map_1) {
×
92
            isl_map_free(map_1);
×
93
        }
×
94
        if (map_2) {
×
95
            isl_map_free(map_2);
×
96
        }
×
97
        if (map_3) {
×
98
            isl_map_free(map_3);
×
99
        }
×
100
        isl_ctx_free(ctx);
×
101
        return false;
×
102
    }
103

104
    // Find aliasing pairs under the constraint that dimensions are different
105

106
    isl_map* composed = isl_map_apply_domain(map_2, map_3);
4✔
107
    if (!composed) {
4✔
108
        isl_map_free(map_1);
×
109
        if (map_2) {
×
110
            isl_map_free(map_2);
×
111
        }
×
112
        if (map_3) {
×
113
            isl_map_free(map_3);
×
114
        }
×
115
        isl_ctx_free(ctx);
×
116
        return false;
×
117
    }
118
    isl_map* alias_pairs = isl_map_intersect(composed, map_1);
4✔
119
    if (!alias_pairs) {
4✔
120
        if (composed) {
×
121
            isl_map_free(composed);
×
122
        }
×
123
        if (map_1) {
×
124
            isl_map_free(map_1);
×
125
        }
×
126
        isl_ctx_free(ctx);
×
127
        return false;
×
128
    }
129

130
    bool disjoint = isl_map_is_empty(alias_pairs);
4✔
131
    isl_map_free(alias_pairs);
4✔
132
    isl_ctx_free(ctx);
4✔
133

134
    return disjoint;
4✔
135
}
4✔
136

137
bool is_disjoint_monotonic(const MultiExpression& expr1, const MultiExpression& expr2,
14✔
138
                           const Symbol& indvar, const Assumptions& assums1,
139
                           const Assumptions& assums2) {
140
    for (size_t i = 0; i < expr1.size(); i++) {
18✔
141
        auto& dim1 = expr1[i];
14✔
142
        if (expr2.size() <= i) {
14✔
143
            continue;
×
144
        }
145
        auto& dim2 = expr2[i];
14✔
146
        if (!symbolic::eq(dim1, dim2)) {
14✔
UNCOV
147
            continue;
×
148
        }
149

150
        // Collect all symbols
151
        symbolic::SymbolSet syms;
14✔
152
        for (auto& sym : symbolic::atoms(dim1)) {
28✔
153
            syms.insert(sym);
14✔
154
        }
155

156
        // Collect all non-constant symbols
157
        bool can_analyze = true;
14✔
158
        for (auto& sym : syms) {
24✔
159
            if (!assums1.at(sym).constant()) {
14✔
160
                if (sym->get_name() != indvar->get_name()) {
4✔
161
                    can_analyze = false;
4✔
162
                    break;
4✔
163
                }
164
            }
×
165
        }
166
        if (!can_analyze) {
14✔
167
            continue;
4✔
168
        }
169

170
        // Check if both dimensions are monotonic in non-constant symbols
171
        if (is_monotonic(dim1, indvar, assums1)) {
10✔
172
            return true;
10✔
173
        }
174
    }
14✔
175

176
    return false;
4✔
177
}
14✔
178

179
bool intersects(const MultiExpression& expr1, const MultiExpression& expr2, const Symbol& indvar,
14✔
180
                const Assumptions& assums1, const Assumptions& assums2) {
181
    if (is_disjoint_monotonic(expr1, expr2, indvar, assums1, assums2)) {
14✔
182
        return false;
10✔
183
    }
184
    return !is_disjoint_isl(expr1, expr2, indvar, assums1, assums2);
4✔
185
}
14✔
186

187
}  // namespace maps
188
}  // namespace symbolic
189
}  // 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