dsplib 1.1.0
C++ DSP library for MATLAB-like coding
Loading...
Searching...
No Matches
slice.h
1#pragma once
2
3#include <algorithm>
4#include <cstring>
5
6#include <dsplib/assert.h>
7#include <dsplib/iterator.h>
8
9namespace dsplib {
10
11template<typename T>
12class base_array;
13
14template<typename T>
15class mut_slice_t;
16
17template<typename T>
18class slice_t;
19
25template<typename T>
27{
28public:
29 friend class mut_slice_t<T>;
31
32 slice_t() = default;
33
34 slice_t(const slice_t& rhs)
35 : data_{rhs.data_}
36 , stride_{rhs.stride_}
37 , count_{rhs.count_} {
38 }
39
40 slice_t(const mut_slice_t<T>& rhs)
41 : data_{rhs.data_}
42 , stride_{rhs.stride_}
43 , count_{rhs.count_} {
44 }
45
46 [[nodiscard]] int size() const noexcept {
47 return count_;
48 }
49
50 bool empty() const noexcept {
51 return count_ == 0;
52 }
53
54 [[nodiscard]] int stride() const noexcept {
55 return stride_;
56 }
57
58 const_iterator begin() const noexcept {
59 return const_iterator(data_, stride_);
60 }
61
62 const_iterator end() const noexcept {
63 auto current = begin();
64 std::advance(current, count_);
65 return current;
66 }
67
68 [[deprecated("use `copy` instead")]] base_array<T> operator*() const noexcept {
69 return base_array<T>(*this);
70 }
71
72 static slice_t make_slice(const T* data, int size, int i1, int i2, int step) {
73 auto mdata = const_cast<T*>(data);
74 return slice_t(mut_slice_t<T>::make_slice(mdata, size, i1, i2, step));
75 }
76
77 base_array<T> copy() const noexcept {
78 return base_array<T>(*this);
79 }
80
81protected:
82 explicit slice_t(const T* data, int stride, int count)
83 : data_{data}
84 , stride_{stride}
85 , count_{count} {
86 DSPLIB_ASSERT(count >= 0, "Count of elements must be positive");
87 }
88
89 const T* data_{nullptr};
90 int stride_{0};
91 int count_{0};
92};
93
98template<typename T>
100{
101public:
102 friend class slice_t<T>;
105
106 mut_slice_t() = default;
107
108 mut_slice_t(const mut_slice_t& rhs)
109 : data_{rhs.data_}
110 , stride_{rhs.stride_}
111 , count_{rhs.count_} {
112 }
113
114 [[nodiscard]] int size() const noexcept {
115 return count_;
116 }
117
118 bool empty() const noexcept {
119 return count_ == 0;
120 }
121
122 [[nodiscard]] int stride() const noexcept {
123 return stride_;
124 }
125
126 mut_slice_t& operator=(const slice_t<T>& rhs) {
127 this->assign(rhs);
128 return *this;
129 }
130
131 mut_slice_t& operator=(const mut_slice_t<T>& rhs) {
132 this->assign(slice_t<T>(rhs));
133 return *this;
134 }
135
136 mut_slice_t& operator=(const base_array<T>& rhs) {
137 DSPLIB_ASSERT(!is_same_memory(rhs.slice(0, rhs.size())), "Assigned array to same slice");
138 *this = rhs.slice(0, rhs.size());
139 return *this;
140 }
141
142 mut_slice_t& operator=(const T& value) {
143 std::fill(begin(), end(), value);
144 return *this;
145 }
146
147 mut_slice_t& operator=(const std::initializer_list<T>& rhs) {
148 std::copy(rhs.begin(), rhs.end(), this->begin());
149 return *this;
150 }
151
152 iterator begin() noexcept {
153 return iterator(data_, stride_);
154 }
155
156 iterator end() noexcept {
157 auto current = begin();
158 std::advance(current, count_);
159 return current;
160 }
161
162 const_iterator begin() const noexcept {
163 return const_iterator(data_, stride_);
164 }
165
166 const_iterator end() const noexcept {
167 auto current = begin();
168 std::advance(current, count_);
169 return current;
170 }
171
172 [[deprecated("use `copy` instead")]] base_array<T> operator*() const noexcept {
173 return base_array<T>(*this);
174 }
175
176 base_array<T> copy() const noexcept {
177 return base_array<T>(*this);
178 }
179
180 void assign(slice_t<T> rhs) {
181 DSPLIB_ASSERT(size() == rhs.size(), "Slices size must be equal");
182 const int count = size();
183
184 //empty slice assign
185 if (count == 0) {
186 return;
187 }
188
189 //simple block copy/move (optimization)
190 const bool is_same = is_same_memory(rhs);
191
192 //check all slices is span
193 if ((stride() == 1) && (rhs.stride() == 1)) {
194 const auto* src = rhs.data_;
195 auto* dst = data_;
196 if (!is_same) {
197 std::memcpy(dst, src, count * sizeof(*src));
198 } else {
199 std::memmove(dst, src, count * sizeof(*src));
200 }
201 return;
202 }
203
204 //same array, specific indexing
205 if (is_same) {
206 *this = base_array<T>(rhs);
207 return;
208 }
209
210 std::copy(rhs.begin(), rhs.end(), begin());
211 }
212
213 static mut_slice_t make_slice(T* data, int size, int i1, int i2, int step) {
214 if (size == 0) {
215 return mut_slice_t();
216 }
217
218 i1 = (i1 < 0) ? (size + i1) : i1;
219 i2 = (i2 < 0) ? (size + i2) : i2;
220
221 const int d = std::abs(i2 - i1);
222 const int tm = std::abs(step);
223 int count = (d % tm != 0) ? (d / tm + 1) : (d / tm);
224
225 DSPLIB_ASSERT(step != 0, "Slice stride cannot be zero");
226 DSPLIB_ASSERT((i1 >= 0) && (i1 < size), "Left slice index out of range");
227 DSPLIB_ASSERT((i2 >= 0) && (i2 <= size), "Right slice index out of range");
228 DSPLIB_ASSERT(!((step < 0) && (i1 < i2)), "First index is smaller for negative step");
229 DSPLIB_ASSERT(!((step > 0) && (i1 > i2)), "First index is greater for positive step");
230 DSPLIB_ASSERT(count <= size, "Slice range is greater array size");
231
232 return mut_slice_t(data + i1, step, count);
233 }
234
235protected:
236 explicit mut_slice_t(T* data, int stride, int count)
237 : data_{data}
238 , stride_{stride}
239 , count_{count} {
240 DSPLIB_ASSERT(count >= 0, "Count of elements must be positive");
241 }
242
243 bool is_same_memory(slice_t<T> rhs) noexcept {
244 if (empty() || rhs.empty()) {
245 return false;
246 }
247 auto start1 = rhs.data_;
248 auto end1 = start1 + (rhs.count_ * rhs.stride_);
249 if (start1 > end1) {
250 std::swap(start1, end1);
251 }
252
253 auto start2 = data_;
254 auto end2 = start2 + (count_ * stride_);
255 if (start2 > end2) {
256 std::swap(start2, end2);
257 }
258
259 return (start1 < end2) && (start2 < end1);
260 }
261
262 T* data_{nullptr};
263 int stride_{0};
264 int count_{0};
265};
266
267} // namespace dsplib
base dsplib array type
Definition array.h:25
Mutable slice object.
Definition slice.h:100
Non-mutable slice object.
Definition slice.h:27
Definition iterator.h:8