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

daisytuner / docc / 21863804378

10 Feb 2026 11:53AM UTC coverage: 66.276% (-0.2%) from 66.496%
21863804378

Pull #513

github

web-flow
Merge 1e171c5b3 into 4576e646b
Pull Request #513: adds tensor type

217 of 404 new or added lines in 18 files covered. (53.71%)

1 existing line in 1 file now uncovered.

23373 of 35266 relevant lines covered (66.28%)

372.08 hits per line

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

43.71
/sdfg/src/types/tensor.cpp
1
#include "sdfg/types/tensor.h"
2

3
#include "sdfg/types/scalar.h"
4

5
namespace sdfg {
6
namespace types {
7

8
symbolic::MultiExpression Tensor::strides_from_shape(const symbolic::MultiExpression& shape) {
9✔
9
    if (shape.empty()) {
9✔
NEW
10
        return {};
×
NEW
11
    }
×
12
    symbolic::MultiExpression strides(shape.size());
9✔
13
    strides.back() = SymEngine::integer(1);
9✔
14
    for (size_t i = shape.size() - 1; i > 0; --i) {
16✔
15
        strides[i - 1] = SymEngine::mul(strides[i], shape[i]);
7✔
16
    }
7✔
17
    return strides;
9✔
18
}
9✔
19

20
Tensor::Tensor(const Scalar& element_type, const symbolic::MultiExpression& shape)
21
    : element_type_(std::unique_ptr<Scalar>(static_cast<Scalar*>(element_type.clone().release()))), shape_(shape),
9✔
22
      strides_(strides_from_shape(shape)), offset_(symbolic::zero()) {};
9✔
23

24
Tensor::Tensor(
25
    const Scalar& element_type,
26
    const symbolic::MultiExpression& shape,
27
    const symbolic::MultiExpression& strides,
28
    const symbolic::Expression& offset
29
)
30
    : element_type_(std::unique_ptr<Scalar>(static_cast<Scalar*>(element_type.clone().release()))), shape_(shape),
2✔
31
      strides_(strides), offset_(offset) {};
2✔
32

33
Tensor::Tensor(
34
    StorageType storage_type,
35
    size_t alignment,
36
    const std::string& initializer,
37
    const Scalar& element_type,
38
    const symbolic::MultiExpression& shape,
39
    const symbolic::MultiExpression& strides,
40
    const symbolic::Expression& offset
41
)
42
    : IType(storage_type, alignment, initializer),
8✔
43
      element_type_(std::unique_ptr<Scalar>(static_cast<Scalar*>(element_type.clone().release()))), shape_(shape),
8✔
44
      strides_(strides), offset_(offset) {};
8✔
45

46
PrimitiveType Tensor::primitive_type() const { return this->element_type_->primitive_type(); };
1✔
47

48
bool Tensor::is_symbol() const { return false; };
1✔
49

50
const Scalar& Tensor::element_type() const { return *this->element_type_; };
11✔
51

52
const symbolic::MultiExpression& Tensor::shape() const { return this->shape_; };
19✔
53

54
const symbolic::MultiExpression& Tensor::strides() const { return this->strides_; };
11✔
55

56
const symbolic::Expression& Tensor::offset() const { return this->offset_; };
5✔
57

58
TypeID Tensor::type_id() const { return TypeID::Tensor; };
17✔
59

60
bool Tensor::operator==(const IType& other) const {
3✔
61
    if (!dynamic_cast<const Tensor*>(&other)) {
3✔
NEW
62
        return false;
×
NEW
63
    }
×
64
    const auto& tensor_type = static_cast<const Tensor&>(other);
3✔
65

66
    if (!(*this->element_type_ == *tensor_type.element_type_)) {
3✔
67
        return false;
1✔
68
    }
1✔
69
    if (!symbolic::eq(this->offset_, tensor_type.offset_)) {
2✔
NEW
70
        return false;
×
NEW
71
    }
×
72

73
    if (this->shape_.size() != tensor_type.shape_.size()) {
2✔
NEW
74
        return false;
×
NEW
75
    }
×
76
    for (size_t i = 0; i < this->shape_.size(); ++i) {
5✔
77
        if (!symbolic::eq(this->shape_.at(i), tensor_type.shape_.at(i))) {
4✔
78
            return false;
1✔
79
        }
1✔
80
    }
4✔
81

82
    if (this->strides_.size() != tensor_type.strides_.size()) {
1✔
NEW
83
        return false;
×
NEW
84
    }
×
85
    for (size_t i = 0; i < this->strides_.size(); ++i) {
3✔
86
        if (!symbolic::eq(this->strides_.at(i), tensor_type.strides_.at(i))) {
2✔
NEW
87
            return false;
×
NEW
88
        }
×
89
    }
2✔
90

91
    return true;
1✔
92
};
1✔
93

94
std::unique_ptr<IType> Tensor::clone() const {
6✔
95
    return std::make_unique<Tensor>(
6✔
96
        this->storage_type(),
6✔
97
        this->alignment(),
6✔
98
        this->initializer(),
6✔
99
        *this->element_type_,
6✔
100
        this->shape_,
6✔
101
        this->strides_,
6✔
102
        this->offset_
6✔
103
    );
6✔
104
};
6✔
105

NEW
106
std::string Tensor::print() const {
×
NEW
107
    std::string result = "Tensor(" + this->element_type_->print() + ", shape=[";
×
NEW
108
    for (size_t i = 0; i < this->shape_.size(); ++i) {
×
NEW
109
        result += this->shape_.at(i)->__str__();
×
NEW
110
        if (i < this->shape_.size() - 1) {
×
NEW
111
            result += ", ";
×
NEW
112
        }
×
NEW
113
    }
×
NEW
114
    result += "]";
×
NEW
115
    result += ")";
×
NEW
116
    return result;
×
NEW
117
};
×
118

NEW
119
std::unique_ptr<Tensor> Tensor::newaxis(size_t axis) const {
×
NEW
120
    if (axis > this->shape_.size()) {
×
NEW
121
        throw std::out_of_range("axis out of range for newaxis");
×
NEW
122
    }
×
123

NEW
124
    symbolic::MultiExpression new_shape = this->shape_;
×
NEW
125
    symbolic::MultiExpression new_strides = this->strides_;
×
126

NEW
127
    new_shape.insert(new_shape.begin() + axis, SymEngine::integer(1));
×
NEW
128
    new_strides.insert(new_strides.begin() + axis, SymEngine::integer(0));
×
129

NEW
130
    return std::make_unique<Tensor>(
×
NEW
131
        this->storage_type(),
×
NEW
132
        this->alignment(),
×
NEW
133
        this->initializer(),
×
NEW
134
        *this->element_type_,
×
NEW
135
        new_shape,
×
NEW
136
        new_strides,
×
NEW
137
        this->offset_
×
NEW
138
    );
×
NEW
139
}
×
140

141
std::unique_ptr<Tensor> Tensor::flip(size_t axis) const {
1✔
142
    if (axis >= this->shape_.size()) {
1✔
NEW
143
        throw std::out_of_range("axis out of range for flip");
×
NEW
144
    }
×
145

146
    symbolic::MultiExpression new_strides = this->strides_;
1✔
147

148
    // Negate the stride for the specified axis
149
    new_strides[axis] = SymEngine::neg(this->strides_[axis]);
1✔
150

151
    // Compute new offset: offset += stride * (shape - 1)
152
    auto shape_minus_one = SymEngine::sub(this->shape_[axis], SymEngine::integer(1));
1✔
153
    auto offset_adjustment = SymEngine::mul(this->strides_[axis], shape_minus_one);
1✔
154

155
    symbolic::Expression new_offset = this->offset_;
1✔
156
    if (SymEngine::is_a<SymEngine::Integer>(*offset_adjustment)) {
1✔
157
        new_offset = SymEngine::add(new_offset, offset_adjustment);
1✔
158
    }
1✔
159

160
    return std::make_unique<Tensor>(
1✔
161
        this->storage_type(),
1✔
162
        this->alignment(),
1✔
163
        this->initializer(),
1✔
164
        *this->element_type_,
1✔
165
        this->shape_,
1✔
166
        new_strides,
1✔
167
        new_offset
1✔
168
    );
1✔
169
}
1✔
170

NEW
171
std::unique_ptr<Tensor> Tensor::unsqueeze(size_t axis) const { return this->newaxis(axis); }
×
172

NEW
173
std::unique_ptr<Tensor> Tensor::squeeze(size_t axis) const {
×
NEW
174
    if (axis >= this->shape_.size()) {
×
NEW
175
        throw std::out_of_range("axis out of range for squeeze");
×
NEW
176
    }
×
177

NEW
178
    if (!SymEngine::is_a<SymEngine::Integer>(*this->shape_.at(axis))) {
×
NEW
179
        throw std::invalid_argument("cannot squeeze axis with symbolic size");
×
NEW
180
    }
×
NEW
181
    auto dim_size = SymEngine::rcp_dynamic_cast<const SymEngine::Integer>(this->shape_.at(axis))->as_int();
×
NEW
182
    if (dim_size != 1) {
×
NEW
183
        throw std::invalid_argument("cannot squeeze axis with size != 1");
×
NEW
184
    }
×
185

NEW
186
    symbolic::MultiExpression new_shape = this->shape_;
×
NEW
187
    symbolic::MultiExpression new_strides = this->strides_;
×
188

NEW
189
    new_shape.erase(new_shape.begin() + axis);
×
NEW
190
    new_strides.erase(new_strides.begin() + axis);
×
191

NEW
192
    return std::make_unique<Tensor>(
×
NEW
193
        this->storage_type(),
×
NEW
194
        this->alignment(),
×
NEW
195
        this->initializer(),
×
NEW
196
        *this->element_type_,
×
NEW
197
        new_shape,
×
NEW
198
        new_strides,
×
NEW
199
        this->offset_
×
NEW
200
    );
×
NEW
201
}
×
202

NEW
203
std::unique_ptr<Tensor> Tensor::squeeze() const {
×
NEW
204
    symbolic::MultiExpression new_shape;
×
NEW
205
    symbolic::MultiExpression new_strides;
×
206

NEW
207
    for (size_t i = 0; i < this->shape_.size(); ++i) {
×
NEW
208
        bool is_size_one = false;
×
NEW
209
        if (SymEngine::is_a<SymEngine::Integer>(*this->shape_.at(i))) {
×
NEW
210
            auto dim_size = SymEngine::rcp_dynamic_cast<const SymEngine::Integer>(this->shape_.at(i))->as_int();
×
NEW
211
            is_size_one = (dim_size == 1);
×
NEW
212
        }
×
213

NEW
214
        if (!is_size_one) {
×
NEW
215
            new_shape.push_back(this->shape_.at(i));
×
NEW
216
            new_strides.push_back(this->strides_.at(i));
×
NEW
217
        }
×
NEW
218
    }
×
219

NEW
220
    return std::make_unique<Tensor>(
×
NEW
221
        this->storage_type(),
×
NEW
222
        this->alignment(),
×
NEW
223
        this->initializer(),
×
NEW
224
        *this->element_type_,
×
NEW
225
        new_shape,
×
NEW
226
        new_strides,
×
NEW
227
        this->offset_
×
NEW
228
    );
×
NEW
229
}
×
230

231
} // namespace types
232
} // 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