@@ -17,110 +17,76 @@ class mut_slice_t;
1717template <typename T>
1818class 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 */
7325template <typename T>
74- class slice_t : public base_slice_t
26+ class slice_t
7527{
7628public:
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+
11471protected:
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 */
12288template <typename T>
123- class mut_slice_t : public base_slice_t
89+ class mut_slice_t
12490{
12591public:
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+
223221protected:
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