Skip to content

Commit fb49d3f

Browse files
committed
slice type refactoring
1 parent 6cce4d2 commit fb49d3f

File tree

4 files changed

+116
-121
lines changed

4 files changed

+116
-121
lines changed

include/dsplib/array.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,11 +291,11 @@ class base_array
291291

292292
//--------------------------------------------------------------------
293293
mut_slice_t<T> slice(int i1, int i2, int m) {
294-
return mut_slice_t<T>(_vec.data(), _vec.size(), i1, i2, m);
294+
return mut_slice_t<T>::make_slice(_vec.data(), _vec.size(), i1, i2, m);
295295
}
296296

297297
slice_t<T> slice(int i1, int i2, int m) const {
298-
return slice_t<T>(_vec.data(), _vec.size(), i1, i2, m);
298+
return slice_t<T>::make_slice(_vec.data(), _vec.size(), i1, i2, m);
299299
}
300300

301301
//TODO: add slice(end, first, -1) like x[::-1] numpy

include/dsplib/iterator.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ struct SliceIterator
5555
return lhs.ptr_ != rhs.ptr_;
5656
};
5757

58+
friend bool operator>(const SliceIterator& lhs, const SliceIterator& rhs) noexcept {
59+
return lhs.ptr_ > rhs.ptr_;
60+
};
61+
62+
friend bool operator<(const SliceIterator& lhs, const SliceIterator& rhs) noexcept {
63+
return lhs.ptr_ < rhs.ptr_;
64+
};
65+
5866
private:
5967
pointer ptr_;
6068
int step_{1};

include/dsplib/slice.h

Lines changed: 81 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -17,110 +17,76 @@ class mut_slice_t;
1717
template<typename T>
1818
class slice_t;
1919

20-
class base_slice_t
21-
{
22-
public:
23-
base_slice_t() = default;
24-
25-
explicit base_slice_t(int n, int i1, int i2, int m)
26-
: _m{m}
27-
, _n{n}
28-
, _i1{(i1 < 0) ? (_n + i1) : (i1)}
29-
, _i2{(i2 < 0) ? (_n + i2) : (i2)}
30-
, _nc{_count()} {
31-
if (_n == 0) {
32-
return;
33-
}
34-
35-
DSPLIB_ASSERT(m != 0, "Slice stride cannot be zero");
36-
DSPLIB_ASSERT((_i1 >= 0) && (_i1 < _n), "Left slice index out of range");
37-
DSPLIB_ASSERT((_i2 >= 0) && (_i2 <= _n), "Right slice index out of range");
38-
DSPLIB_ASSERT(!((_m < 0) && (_i1 < _i2)), "First index is smaller for negative step");
39-
DSPLIB_ASSERT(!((_m > 0) && (_i1 > _i2)), "First index is greater for positive step");
40-
DSPLIB_ASSERT(_nc <= _n, "Slice range is greater array size");
41-
}
42-
43-
bool empty() const noexcept {
44-
return (_nc == 0);
45-
}
46-
47-
protected:
48-
int _m{1};
49-
int _n{0};
50-
int _i1{0};
51-
int _i2{0};
52-
int _nc{0};
53-
54-
private:
55-
int _count() const noexcept {
56-
if (_n == 0) {
57-
return 0;
58-
}
59-
const int d = std::abs(_i2 - _i1);
60-
const int tm = std::abs(_m);
61-
const int size = (d % tm != 0) ? (d / tm + 1) : (d / tm);
62-
return size;
63-
}
64-
};
65-
66-
static_assert(std::is_trivially_copyable<base_slice_t>(), "type must be trivially copyable");
67-
6820
/**
6921
* @brief Non-mutable slice object
7022
* @todo add concatenate array = slice | array
7123
* @tparam T real_t/cmplx_t
7224
*/
7325
template<typename T>
74-
class slice_t : public base_slice_t
26+
class slice_t
7527
{
7628
public:
7729
friend class mut_slice_t<T>;
7830
using const_iterator = SliceIterator<const T>;
7931

8032
slice_t() = default;
8133

82-
slice_t(const T* data, int size, int i1, int i2, int m)
83-
: base_slice_t(size, i1, i2, m)
84-
, _data{data} {
85-
}
86-
8734
slice_t(const mut_slice_t<T>& rhs)
88-
: base_slice_t(rhs._n, rhs._i1, rhs._i2, rhs._m)
89-
, _data{rhs._data} {
35+
: data_{rhs.data_}
36+
, stride_{rhs.stride_}
37+
, count_{rhs.count_} {
9038
}
9139

9240
[[nodiscard]] int size() const noexcept {
93-
return _nc;
41+
return count_;
42+
}
43+
44+
bool empty() const noexcept {
45+
return count_ == 0;
9446
}
9547

9648
[[nodiscard]] int stride() const noexcept {
97-
return _m;
49+
return stride_;
9850
}
9951

10052
const_iterator begin() const noexcept {
101-
return const_iterator(_data + _i1, _m);
53+
return const_iterator(data_, stride_);
10254
}
10355

10456
const_iterator end() const noexcept {
10557
auto current = begin();
106-
std::advance(current, _nc);
58+
std::advance(current, count_);
10759
return current;
10860
}
10961

11062
base_array<T> operator*() const noexcept {
11163
return base_array<T>(*this);
11264
}
11365

66+
static slice_t make_slice(const T* data, int size, int i1, int i2, int step) {
67+
auto mdata = const_cast<T*>(data);
68+
return slice_t(mut_slice_t<T>::make_slice(mdata, size, i1, i2, step));
69+
}
70+
11471
protected:
115-
const T* _data{nullptr};
72+
explicit slice_t(const T* data, int stride, int count)
73+
: data_{data}
74+
, stride_{stride}
75+
, count_{count} {
76+
DSPLIB_ASSERT(count >= 0, "Count of elements must be positive");
77+
}
78+
79+
const T* data_{nullptr};
80+
int stride_{0};
81+
int count_{0};
11682
};
11783

11884
/**
11985
* @brief Mutable slice object
12086
* @tparam T real_t/cmplx_t
12187
*/
12288
template<typename T>
123-
class mut_slice_t : public base_slice_t
89+
class mut_slice_t
12490
{
12591
public:
12692
friend class slice_t<T>;
@@ -129,17 +95,16 @@ class mut_slice_t : public base_slice_t
12995

13096
mut_slice_t() = default;
13197

132-
mut_slice_t(T* data, int size, int i1, int i2, int m)
133-
: base_slice_t(size, i1, i2, m)
134-
, _data{data} {
98+
[[nodiscard]] int size() const noexcept {
99+
return count_;
135100
}
136101

137-
[[nodiscard]] int size() const noexcept {
138-
return _nc;
102+
bool empty() const noexcept {
103+
return count_ == 0;
139104
}
140105

141106
[[nodiscard]] int stride() const noexcept {
142-
return _m;
107+
return stride_;
143108
}
144109

145110
mut_slice_t& operator=(const slice_t<T>& rhs) {
@@ -152,14 +117,14 @@ class mut_slice_t : public base_slice_t
152117
}
153118

154119
//simple block copy/move (optimization)
155-
const bool is_same = _is_same_array(rhs);
120+
const bool is_same = is_same_memory(rhs, slice_t(*this));
156121
if ((this->stride() == 1) && (rhs.stride() == 1)) {
157122
const auto* src = &(*rhs.begin());
158123
auto* dst = &(*begin());
159124
if (!is_same) {
160125
std::memcpy(dst, src, count * sizeof(*src));
161126
} else {
162-
//TODO: check overlap and use memcpy
127+
//overlapped
163128
std::memmove(dst, src, count * sizeof(*src));
164129
}
165130
return *this;
@@ -181,7 +146,7 @@ class mut_slice_t : public base_slice_t
181146
}
182147

183148
mut_slice_t& operator=(const base_array<T>& rhs) {
184-
DSPLIB_ASSERT(!_is_same_array(rhs.slice(0, rhs.size())), "Assigned array to same slice");
149+
DSPLIB_ASSERT(!is_same_memory(rhs.slice(0, rhs.size()), *this), "Assigned array to same slice");
185150
*this = rhs.slice(0, rhs.size());
186151
return *this;
187152
}
@@ -197,39 +162,73 @@ class mut_slice_t : public base_slice_t
197162
}
198163

199164
iterator begin() noexcept {
200-
return iterator(_data + _i1, _m);
165+
return iterator(data_, stride_);
201166
}
202167

203168
iterator end() noexcept {
204169
auto current = begin();
205-
std::advance(current, _nc);
170+
std::advance(current, count_);
206171
return current;
207172
}
208173

209174
const_iterator begin() const noexcept {
210-
return const_iterator(_data + _i1, _m);
175+
return const_iterator(data_, stride_);
211176
}
212177

213178
const_iterator end() const noexcept {
214179
auto current = begin();
215-
std::advance(current, _nc);
180+
std::advance(current, count_);
216181
return current;
217182
}
218183

219184
base_array<T> operator*() const noexcept {
220185
return base_array<T>(*this);
221186
}
222187

188+
static bool is_same_memory(slice_t<T> r1, slice_t<T> r2) noexcept {
189+
if (r1.empty() || r2.empty()) {
190+
return false;
191+
}
192+
auto start1 = r1.begin();
193+
auto end1 = r1.end();
194+
auto start2 = r2.begin();
195+
auto end2 = r2.end();
196+
return (start1 < end2) && (start2 < end1);
197+
}
198+
199+
static mut_slice_t make_slice(T* data, int size, int i1, int i2, int step) {
200+
if (size == 0) {
201+
return mut_slice_t();
202+
}
203+
204+
i1 = (i1 < 0) ? (size + i1) : i1;
205+
i2 = (i2 < 0) ? (size + i2) : i2;
206+
207+
const int d = std::abs(i2 - i1);
208+
const int tm = std::abs(step);
209+
int count = (d % tm != 0) ? (d / tm + 1) : (d / tm);
210+
211+
DSPLIB_ASSERT(step != 0, "Slice stride cannot be zero");
212+
DSPLIB_ASSERT((i1 >= 0) && (i1 < size), "Left slice index out of range");
213+
DSPLIB_ASSERT((i2 >= 0) && (i2 <= size), "Right slice index out of range");
214+
DSPLIB_ASSERT(!((step < 0) && (i1 < i2)), "First index is smaller for negative step");
215+
DSPLIB_ASSERT(!((step > 0) && (i1 > i2)), "First index is greater for positive step");
216+
DSPLIB_ASSERT(count <= size, "Slice range is greater array size");
217+
218+
return mut_slice_t(data + i1, step, count);
219+
}
220+
223221
protected:
224-
bool _is_same_array(const slice_t<T>& rhs) const noexcept {
225-
auto l1 = _data;
226-
auto r1 = _data + _nc;
227-
auto l2 = rhs._data;
228-
auto r2 = rhs._data + rhs._nc;
229-
return ((l2 >= l1) && (l2 <= r1)) || ((r2 >= l1) && (r2 <= r1));
222+
explicit mut_slice_t(T* data, int stride, int count)
223+
: data_{data}
224+
, stride_{stride}
225+
, count_{count} {
226+
DSPLIB_ASSERT(count >= 0, "Count of elements must be positive");
230227
}
231228

232-
T* _data{nullptr};
229+
T* data_{nullptr};
230+
int stride_{0};
231+
int count_{0};
233232
};
234233

235234
} // namespace dsplib

0 commit comments

Comments
 (0)