26 static_assert(support_type_for_array<T>(),
"type is not supported");
39 template<typename T2, std::enable_if_t<is_array_convertible<T2, T>(),
bool> =
true>
45 : _vec(std::move(v)) {
52 template<class T2, std::enable_if_t<is_array_convertible<T2, T>(),
bool> =
true>
54 _vec.assign(v.begin(), v.end());
58 : _vec(std::move(v._vec)) {
61 base_array(
const std::initializer_list<T>& list)
66 : _vec(v.data(), v.data() + v.size()) {
70 : _vec(v.data(), v.data() + v.size()) {
75 this->slice(0, indexing::end) = rhs;
82 template<typename T2, std::enable_if_t<is_array_convertible<T2, T>(),
bool> =
true>
84 _vec.assign(v.begin(), v.end());
87 template<typename T2, std::enable_if_t<is_array_convertible<T2, T>(),
bool> =
true>
89 _vec.assign(v.begin(), v.end());
114 template<
typename Index, std::enable_if_t<std::is_
integral_v<Index>,
bool> = true>
115 const T& operator[](Index i)
const noexcept {
116 const size_t n = _vec.size();
117 if constexpr (std::is_signed_v<Index>) {
118 const size_t idx = (i >= 0) ?
static_cast<size_t>(i) : (n + i);
119 DSPLIB_ASSUME(idx < n);
122 DSPLIB_ASSUME(i < n);
127 template<
typename Index, std::enable_if_t<std::is_
integral_v<Index>,
bool> = true>
128 T& operator[](Index i)
noexcept {
129 return const_cast<T&
>(
static_cast<const base_array<T>&
>(*this)[i]);
133 base_array<T> operator[](
const std::vector<bool>& idxs)
const {
134 DSPLIB_ASSERT(idxs.size() == _vec.size(),
"Array sizes must be equal");
136 res.reserve(_vec.size());
137 for (
size_t i = 0; i < idxs.size(); ++i) {
139 res.push_back(_vec[i]);
145 base_array<T> operator[](
const std::vector<int>& idxs)
const {
146 const size_t max_i = *std::max_element(idxs.begin(), idxs.end());
147 DSPLIB_ASSERT(max_i < _vec.size(),
"Index must not exceed the size of the vector");
148 std::vector<T> res(idxs.size());
149 for (
size_t i = 0; i < idxs.size(); ++i) {
150 res[i] = _vec[idxs[i]];
156 return (*
this)[idxs.to_vec()];
161 std::vector<bool> operator>(T val)
const noexcept {
162 std::vector<bool> res(_vec.size());
163 for (
size_t i = 0; i < _vec.size(); ++i) {
164 res[i] = (_vec[i] > val);
169 std::vector<bool> operator<(T val)
const noexcept {
170 std::vector<bool> res(_vec.size());
171 for (
size_t i = 0; i < _vec.size(); ++i) {
172 res[i] = (_vec[i] < val);
177 std::vector<bool> operator==(T val)
const noexcept {
178 std::vector<bool> res(_vec.size());
179 for (
size_t i = 0; i < _vec.size(); ++i) {
181 res[i] = (_vec[i] == val);
186 std::vector<bool> operator!=(T val)
const noexcept {
187 auto r = (*
this == val);
194 std::vector<bool> operator>(
const base_array<T>& rhs)
const noexcept {
195 std::vector<bool> res(_vec.size());
196 for (
size_t i = 0; i < _vec.size(); ++i) {
197 res[i] = (_vec[i] > rhs._vec[i]);
202 std::vector<bool> operator<(
const base_array<T>& rhs)
const noexcept {
203 std::vector<bool> res(_vec.size());
204 for (
size_t i = 0; i < _vec.size(); ++i) {
205 res[i] = (_vec[i] < rhs._vec[i]);
210 std::vector<bool> operator==(
const base_array<T>& rhs)
const noexcept {
211 std::vector<bool> res(_vec.size());
212 for (
size_t i = 0; i < _vec.size(); ++i) {
213 res[i] = (_vec[i] == rhs._vec[i]);
218 std::vector<bool> operator!=(
const base_array<T>& rhs)
const noexcept {
219 auto r = (*
this == rhs);
229 slice_t<T> slice(
int i1,
int i2,
int m)
const {
235 return this->slice(i1, size(), m);
239 return this->slice(i1, size(), m);
244 i1 = (i1 >= 0) ? i1 : (size() + i1);
245 i2 = (i2 >= 0) ? i2 : (size() + i2);
246 DSPLIB_ASSERT((i2 > i1) && (i1 >= 0) && (i2 <= size()),
"Invalid slice range");
251 return this->slice(i1, size());
255 i1 = (i1 >= 0) ? i1 : (size() + i1);
256 i2 = (i2 >= 0) ? i2 : (size() + i2);
257 DSPLIB_ASSERT((i2 > i1) && (i1 >= 0) && (i2 <= size()),
"Invalid slice range");
258 return span_t<T>(_vec.data() + i1, (i2 - i1));
262 return this->slice(i1, size());
266 using iterator =
typename std::vector<T>::iterator;
267 using const_iterator =
typename std::vector<T>::const_iterator;
269 iterator begin()
noexcept {
273 iterator end()
noexcept {
277 const_iterator begin()
const noexcept {
281 const_iterator end()
const noexcept {
289 const T* data()
const noexcept {
293 [[nodiscard]]
int size()
const noexcept {
294 return int(_vec.size());
297 [[nodiscard]]
bool empty()
const noexcept {
308 for (
size_t i = 0; i < r.size(); ++i) {
317 make_span(_vec) += rhs;
323 make_span(_vec) -= rhs;
329 make_span(_vec) *= rhs;
335 make_span(_vec) /= rhs;
342 auto operator+(
const T2& rhs)
const {
343 return make_span(_vec) + rhs;
347 auto operator-(
const T2& rhs)
const {
348 return make_span(_vec) - rhs;
352 auto operator*(
const T2& rhs)
const {
353 return make_span(_vec) * rhs;
357 auto operator/(
const T2& rhs)
const {
358 return make_span(_vec) / rhs;
362 template<
class T2,
class R = ResultType<T, T2>>
364 static_assert(std::is_same_v<T, R>,
"not supported array cast");
365 _vec.insert(_vec.end(), rhs.begin(), rhs.end());
369 template<
class T2,
class R = ResultType<T, T2>>
371 auto r = this->cast<R>();
377 [[nodiscard]] std::vector<R> to_vec()
const noexcept {
378 if constexpr (std::is_same_v<T, R>) {
381 static_assert(std::is_convertible_v<T, R>,
"type must be convertible");
382 return std::vector<R>(_vec.begin(), _vec.end());
386 [[nodiscard]]
const std::vector<T>& to_vec()
const noexcept {
391 [[nodiscard]]
auto cast()
const noexcept {
392 if constexpr (std::is_same_v<T, R>) {
395 static_assert(std::is_convertible_v<T, R>,
"type must be convertible");
402 auto apply(Fn func)
const {
403 using R =
decltype(func(T()));
404 if constexpr (std::is_same_v<T, R>) {
412 R* pout = out.data();
413 for (
const T& v : _vec) {
420 friend std::ostream& operator<<(std::ostream& os,
const base_array& x) {
425 std::ostream& _print(std::ostream& os)
const;