/* Copyright 2019 The Mathworks, Inc. */ /* Copied from fullfile(matlabroot,'extern','include','coder','coder_array','coder_array_rtw.h') */ #ifndef _mw_coder_array_h #define _mw_coder_array_h // Usage: // // coder::array: T base type of data, N number of dimensions // // coder::array() // : default constructor // coder::array(const coder::array &) // : copy constructor (always make a deep copy of other array) // coder::array(const T *data, const SizeType *sz) // : Set data with sizes of this array. // : (Data is not copied, data is not deleted) // coder::array::operator = (coder coder::array &) // : Assign into this array; // : delete its previous contents (if owning the data.) // set(const T *data, SizeType sz1, SizeType sz2, ...) // : Set data with dimensions. // : (Data is not copied, data is not deleted) // set_size(SizeType sz1, SizeType sz2, ...) // : Set sizes of array. Reallocate memory of data if needed. // bool is_owner() : Return true if the data is owned by the class. // void set_owner(b) : Set if the data is owned by the class. // SizeType capacity() : How many entries are reserved by memory allocation. // reshape( SizeType sz1, SizeType sz2, ...) // : Reshape array to a different ND shape. Do not copy the data. // : The number of elements must not be changed (numel()==sz1*sz2*...) // : Return the array with possibly new number of dimensions. // clear() : Reset array to be empty. // SizeType numel() : Return the number of elements. // operator [] (SizeType index) : Extract element at linear index (0 based.) // size(SizeType dimension) : Size of array of the provided dimension. // SizeType * size() : Return the pointer to all the sizes of this array. // SizeType index(SizeType i1, SizeType i2, ...) // : Compute the linear index from ND index (i1,i2,...) // at(SizeType i1, SizeType i2, ...) : The element at index (i1,i2,...) #include #include #include #include #include #ifndef INT32_T #include "rtwtypes.h" #endif namespace coder { #ifndef CODER_ARRAY_NEW_DELETE #define CODER_ARRAY_NEW_DELETE #define CODER_NEW(T, N) new T[N] #define CODER_DELETE(P) delete[](P) #endif #ifndef CODER_ARRAY_SIZE_TYPE_DEFINED typedef int SizeType; #endif namespace std = ::std; namespace detail { #ifndef CODER_ARRAY_DATA_PTR_DEFINED template class data_ptr { public: typedef T value_type; typedef SZ size_type; data_ptr() : data_(NULL) , size_(0) , capacity_(0) , owner_(false) { } data_ptr(T* _data, SZ _sz) : data_(_data) , size_(_sz) , capacity_(_sz) , owner_(false) { } data_ptr(const data_ptr& _other) : data_(_other.owner_ ? NULL : _other.data_) , size_(_other.owner_ ? 0 : _other.size_) , capacity_(_other.owner_ ? 0 : _other.capacity_) , owner_(_other.owner_) { if (owner_) { resize(_other.size_); (void)std::copy(_other.data_, _other.data_ + size_, data_); } } ~data_ptr() { if (owner_) { CODER_DELETE(data_); } } SZ capacity() const { return capacity_; } void reserve(SZ _n) { if (_n > capacity_) { T* new_data = CODER_NEW(T, _n); (void)std::copy(data_, data_ + size_, new_data); if (owner_) { CODER_DELETE(data_); } data_ = new_data; capacity_ = _n; owner_ = true; } } void resize(SZ _n) { reserve(_n); size_ = _n; } private: // Prohibit use of assignment operator to prevent subtle bugs void operator=(const data_ptr& _other); public: void set(T* _data, const SZ _sz) { if (owner_) { CODER_DELETE(data_); } data_ = _data; size_ = _sz; owner_ = false; capacity_ = size_; } void copy(const T* _data, SZ _size) { if (data_ == _data) { size_ = _size; return; } if (owner_) { CODER_DELETE(data_); } data_ = CODER_NEW(T, _size); owner_ = true; size_ = _size; capacity_ = size_; (void)std::copy(_data, _data + _size, data_); } void copy(const data_ptr& _other) { copy(_other.data_, _other.size_); } operator T*() { return &data_[0]; } operator const T*() const { return &data_[0]; } T& operator[](SZ _index) { return data_[_index]; } const T& operator[](SZ _index) const { return data_[_index]; } T* operator->() { return data_; } const T* operator->() const { return data_; } bool is_null() const { return data_ == NULL; } void clear() { if (owner_) { CODER_DELETE(data_); } data_ = NULL; size_ = 0; capacity_ = 0; owner_ = false; } bool is_owner() const { return owner_; } void set_owner(bool _b) { owner_ = _b; } private: T* data_; SZ size_; SZ capacity_; bool owner_; }; #endif } // namespace detail // Implementing the random access iterator class so coder::array can be // used in STL iterators. template class array_iterator : public std::iterator { public: array_iterator() : arr_(NULL) , i_(0) { } array_iterator(const array_iterator& other) : arr_(other.arr_) , i_(other.i_) { } ~array_iterator() { } typename T::value_type& operator*() const { return (*arr_)[i_]; } typename T::value_type* operator->() const { return &(*arr_)[i_]; } typename T::value_type& operator[](typename T::size_type _di) const { return (*arr_)[i_ + _di]; } array_iterator& operator++() { ++i_; return *this; } array_iterator& operator--() { --i_; return *this; } array_iterator operator++(int) { array_iterator cp(*this); ++i_; return cp; } array_iterator operator--(int) { array_iterator cp(*this); --i_; return cp; } array_iterator& operator=(const array_iterator& _other) { this->i_ = _other.i_; return *this; } bool operator==(const array_iterator& _other) const { return i_ == _other.i_; } bool operator!=(const array_iterator& _other) const { return i_ != _other.i_; } bool operator<(const array_iterator& _other) const { return i_ < _other.i_; } bool operator>(const array_iterator& _other) const { return i_ > _other.i_; } bool operator<=(const array_iterator& _other) const { return i_ <= _other.i_; } bool operator>=(const array_iterator& _other) const { return i_ >= _other.i_; } array_iterator operator+(typename T::size_type _add) const { array_iterator cp(*this); cp.i_ += _add; return cp; } array_iterator& operator+=(typename T::size_type _add) { this->i_ += _add; return *this; } array_iterator operator-(typename T::size_type _subtract) const { array_iterator cp(*this); cp.i_ -= _subtract; return cp; } array_iterator& operator-=(typename T::size_type _subtract) { this->i_ -= _subtract; return *this; } typename T::size_type operator-(const array_iterator& _other) const { return static_cast(this->i_ - _other.i_); } array_iterator(T* _arr, typename T::size_type _i) : arr_(_arr) , i_(_i) { } private: T* arr_; typename T::size_type i_; }; // Const version of the array iterator. template class const_array_iterator : public std::iterator { public: const_array_iterator() : arr_(NULL) , i_(0) { } const_array_iterator(const const_array_iterator& other) : arr_(other.arr_) , i_(other.i_) { } ~const_array_iterator() { } const typename T::value_type& operator*() const { return (*arr_)[i_]; } const typename T::value_type* operator->() const { return &(*arr_)[i_]; } const typename T::value_type& operator[](typename T::size_type _di) const { return (*arr_)[i_ + _di]; } const_array_iterator& operator++() { ++i_; return *this; } const_array_iterator& operator--() { --i_; return *this; } const_array_iterator operator++(int) { const_array_iterator copy(*this); ++i_; return copy; } const_array_iterator operator--(int) { const_array_iterator copy(*this); --i_; return copy; } const_array_iterator& operator=(const const_array_iterator& _other) { this->i_ = _other.i_; return *this; } bool operator==(const const_array_iterator& _other) const { return i_ == _other.i_; } bool operator!=(const const_array_iterator& _other) const { return i_ != _other.i_; } bool operator<(const const_array_iterator& _other) const { return i_ < _other.i_; } bool operator>(const const_array_iterator& _other) const { return i_ > _other.i_; } bool operator<=(const const_array_iterator& _other) const { return i_ <= _other.i_; } bool operator>=(const const_array_iterator& _other) const { return i_ >= _other.i_; } const_array_iterator operator+(typename T::size_type _add) const { const_array_iterator cp(*this); cp.i_ += _add; return cp; } const_array_iterator& operator+=(typename T::size_type _add) { this->i_ += _add; return *this; } const_array_iterator operator-(typename T::size_type _subtract) const { const_array_iterator cp(*this); cp.i_ -= _subtract; return cp; } const_array_iterator& operator-=(typename T::size_type _subtract) { this->i_ -= _subtract; return *this; } typename T::size_type operator-(const const_array_iterator& _other) const { return static_cast(this->i_ - _other.i_); } const_array_iterator(const T* _arr, typename T::size_type _i) : arr_(_arr) , i_(_i) { } private: const T* arr_; typename T::size_type i_; typename T::size_type n_; }; namespace detail { // detail::numel: Compile-time product of the given size vector of length N. template class numel { public: template static SZ compute(SZ _size[]) { return _size[N - 1] * numel::compute(_size); } }; template <> class numel<0> { public: template static SZ compute(SZ[]) { return 1; } }; // Compute flat index from (column-major) ND size vector and a list of indices. template class index_nd { public: template static SZ compute(const SZ _size[], const SZ _indices[]) { const SZ weight = numel::compute(_size); return weight * _indices[I - 1] + index_nd::compute(_size, _indices); } }; template <> class index_nd<0> { public: template static SZ compute(SZ[], SZ[]) { return 0; } }; template struct match_dimensions {}; template <> struct match_dimensions { static void check() { } }; } // namespace detail // Base class for code::array. SZ is the type used for sizes (currently int32_t.) // Overloading up to 10 dimensions (not using variadic templates to // stay compatible with C++98.) template class array_base { public: typedef T value_type; typedef SZ size_type; array_base() { (void)::memset(size_, 0, sizeof(SZ) * N); } array_base(T* _data, const SZ* _sz) : data_(_data, coder::detail::numel::compute(_sz)) { (void)std::copy(_sz, _sz + N, size_); } array_base& operator=(const array_base& _other) { data_.copy(_other.data_); (void)std::copy(_other.size_, _other.size_ + N, size_); return *this; } void set(T* _data, SZ _n1) { coder::detail::match_dimensions::check(); data_.set(_data, _n1); size_[0] = _n1; } void set(T* _data, SZ _n1, SZ _n2) { coder::detail::match_dimensions::check(); data_.set(_data, _n1 * _n2); size_[0] = _n1; size_[1] = _n2; } void set(T* _data, SZ _n1, SZ _n2, SZ _n3) { coder::detail::match_dimensions::check(); data_.set(_data, _n1 * _n2 * _n3); size_[0] = _n1; size_[1] = _n2; size_[2] = _n3; } void set(T* _data, SZ _n1, SZ _n2, SZ _n3, SZ _n4) { coder::detail::match_dimensions::check(); data_.set(_data, _n1 * _n2 * _n3 * _n4); size_[0] = _n1; size_[1] = _n2; size_[2] = _n3; size_[3] = _n4; } void set(T* _data, SZ _n1, SZ _n2, SZ _n3, SZ _n4, SZ _n5) { coder::detail::match_dimensions::check(); data_.set(_data, _n1 * _n2 * _n3 * _n4 * _n5); size_[0] = _n1; size_[1] = _n2; size_[2] = _n3; size_[3] = _n4; size_[4] = _n5; } void set(T* _data, SZ _n1, SZ _n2, SZ _n3, SZ _n4, SZ _n5, SZ _n6) { coder::detail::match_dimensions::check(); data_.set(_data, _n1 * _n2 * _n3 * _n4 * _n5 * _n6); size_[0] = _n1; size_[1] = _n2; size_[2] = _n3; size_[3] = _n4; size_[4] = _n5; size_[5] = _n6; } void set(T* _data, SZ _n1, SZ _n2, SZ _n3, SZ _n4, SZ _n5, SZ _n6, SZ _n7) { coder::detail::match_dimensions::check(); data_.set(_data, _n1 * _n2 * _n3 * _n4 * _n5 * _n6 * _n7); size_[0] = _n1; size_[1] = _n2; size_[2] = _n3; size_[3] = _n4; size_[4] = _n5; size_[5] = _n6; size_[6] = _n7; } void set(T* _data, SZ _n1, SZ _n2, SZ _n3, SZ _n4, SZ _n5, SZ _n6, SZ _n7, SZ _n8) { coder::detail::match_dimensions::check(); data_.set(_data, _n1 * _n2 * _n3 * _n4 * _n5 * _n6 * _n7 * _n8); size_[0] = _n1; size_[1] = _n2; size_[2] = _n3; size_[3] = _n4; size_[4] = _n5; size_[5] = _n6; size_[6] = _n7; size_[7] = _n8; } void set(T* _data, SZ _n1, SZ _n2, SZ _n3, SZ _n4, SZ _n5, SZ _n6, SZ _n7, SZ _n8, SZ _n9) { coder::detail::match_dimensions::check(); data_.set(_data, _n1 * _n2 * _n3 * _n4 * _n5 * _n6 * _n7 * _n8 * _n9); size_[0] = _n1; size_[1] = _n2; size_[2] = _n3; size_[3] = _n4; size_[4] = _n5; size_[5] = _n6; size_[6] = _n7; size_[7] = _n8; size_[8] = _n9; } void set(T* _data, SZ _n1, SZ _n2, SZ _n3, SZ _n4, SZ _n5, SZ _n6, SZ _n7, SZ _n8, SZ _n9, SZ _n10) { coder::detail::match_dimensions::check(); data_.set(_data, _n1 * _n2 * _n3 * _n4 * _n5 * _n6 * _n7 * _n8 * _n9 * _n10); size_[0] = _n1; size_[1] = _n2; size_[2] = _n3; size_[3] = _n4; size_[4] = _n5; size_[5] = _n6; size_[6] = _n7; size_[7] = _n8; size_[8] = _n9; size_[9] = _n10; } bool is_owner() const { return data_.is_owner(); } void set_owner(bool b) { data_.set_owner(b); } SZ capacity() const { return data_.capacity(); } void set_size(SZ _n1) { coder::detail::match_dimensions::check(); size_[0] = _n1; ensureCapacity(numel()); } void set_size(SZ _n1, SZ _n2) { coder::detail::match_dimensions::check(); size_[0] = _n1; size_[1] = _n2; ensureCapacity(numel()); } void set_size(SZ _n1, SZ _n2, SZ _n3) { coder::detail::match_dimensions::check(); size_[0] = _n1; size_[1] = _n2; size_[2] = _n3; ensureCapacity(numel()); } void set_size(SZ _n1, SZ _n2, SZ _n3, SZ _n4) { coder::detail::match_dimensions::check(); size_[0] = _n1; size_[1] = _n2; size_[2] = _n3; size_[3] = _n4; ensureCapacity(numel()); } void set_size(SZ _n1, SZ _n2, SZ _n3, SZ _n4, SZ _n5) { coder::detail::match_dimensions::check(); size_[0] = _n1; size_[1] = _n2; size_[2] = _n3; size_[3] = _n4; size_[4] = _n5; ensureCapacity(numel()); } void set_size(SZ _n1, SZ _n2, SZ _n3, SZ _n4, SZ _n5, SZ _n6) { coder::detail::match_dimensions::check(); size_[0] = _n1; size_[1] = _n2; size_[2] = _n3; size_[3] = _n4; size_[4] = _n5; size_[5] = _n6; ensureCapacity(numel()); } void set_size(SZ _n1, SZ _n2, SZ _n3, SZ _n4, SZ _n5, SZ _n6, SZ _n7) { coder::detail::match_dimensions::check(); size_[0] = _n1; size_[1] = _n2; size_[2] = _n3; size_[3] = _n4; size_[4] = _n5; size_[5] = _n6; size_[6] = _n7; ensureCapacity(numel()); } void set_size(SZ _n1, SZ _n2, SZ _n3, SZ _n4, SZ _n5, SZ _n6, SZ _n7, SZ _n8) { coder::detail::match_dimensions::check(); size_[0] = _n1; size_[1] = _n2; size_[2] = _n3; size_[3] = _n4; size_[4] = _n5; size_[5] = _n6; size_[6] = _n7; size_[7] = _n8; ensureCapacity(numel()); } void set_size(SZ _n1, SZ _n2, SZ _n3, SZ _n4, SZ _n5, SZ _n6, SZ _n7, SZ _n8, SZ _n9) { coder::detail::match_dimensions::check(); size_[0] = _n1; size_[1] = _n2; size_[2] = _n3; size_[3] = _n4; size_[4] = _n5; size_[5] = _n6; size_[6] = _n7; size_[7] = _n8; size_[8] = _n9; ensureCapacity(numel()); } void set_size(SZ _n1, SZ _n2, SZ _n3, SZ _n4, SZ _n5, SZ _n6, SZ _n7, SZ _n8, SZ _n9, SZ _n10) { coder::detail::match_dimensions::check(); size_[0] = _n1; size_[1] = _n2; size_[2] = _n3; size_[3] = _n4; size_[4] = _n5; size_[5] = _n6; size_[6] = _n7; size_[7] = _n8; size_[8] = _n9; size_[9] = _n10; ensureCapacity(numel()); } template array_base reshape_n(const SZ (&_ns)[N1]) const { array_base reshaped(const_cast(&data_[0]), _ns); return reshaped; } array_base reshape(SZ _n1) const { const SZ ns[] = {_n1}; return reshape_n(ns); } array_base reshape(SZ _n1, SZ _n2) const { const SZ ns[] = {_n1, _n2}; return reshape_n(ns); } array_base reshape(SZ _n1, SZ _n2, SZ _n3) const { const SZ ns[] = {_n1, _n2, _n3}; return reshape_n(ns); } array_base reshape(SZ _n1, SZ _n2, SZ _n3, SZ _n4) const { const SZ ns[] = {_n1, _n2, _n3, _n4}; return reshape_n(ns); } array_base reshape(SZ _n1, SZ _n2, SZ _n3, SZ _n4, SZ _n5) const { const SZ ns[] = {_n1, _n2, _n3, _n4, _n5}; return reshape_n(ns); } array_base reshape(SZ _n1, SZ _n2, SZ _n3, SZ _n4, SZ _n5, SZ _n6) const { const SZ ns[] = {_n1, _n2, _n3, _n4, _n5, _n6}; return reshape_n(ns); } array_base reshape(SZ _n1, SZ _n2, SZ _n3, SZ _n4, SZ _n5, SZ _n6, SZ _n7) const { const SZ ns[] = {_n1, _n2, _n3, _n4, _n5, _n6, _n7}; return reshape_n(ns); } array_base reshape(SZ _n1, SZ _n2, SZ _n3, SZ _n4, SZ _n5, SZ _n6, SZ _n7, SZ _n8) const { const SZ ns[] = {_n1, _n2, _n3, _n4, _n5, _n6, _n7, _n8}; return reshape_n(ns); } array_base reshape(SZ _n1, SZ _n2, SZ _n3, SZ _n4, SZ _n5, SZ _n6, SZ _n7, SZ _n8, SZ _n9) const { const SZ ns[] = {_n1, _n2, _n3, _n4, _n5, _n6, _n7, _n8, _n9}; return reshape_n(ns); } array_base reshape(SZ _n1, SZ _n2, SZ _n3, SZ _n4, SZ _n5, SZ _n6, SZ _n7, SZ _n8, SZ _n9, SZ _n10) const { const SZ ns[] = {_n1, _n2, _n3, _n4, _n5, _n6, _n7, _n8, _n9, _n10}; return reshape_n(ns); } T& operator[](SZ _index) { return data_[_index]; } const T& operator[](SZ _index) const { return data_[_index]; } void clear() { data_.clear(); } T* data() { return data_; } const T* data() const { return data_; } const SZ* size() const { return &size_[0]; } SZ size(SZ _index) const { return size_[_index]; } SZ numel() const { return coder::detail::numel::compute(size_); } SZ index(SZ _n1) const { coder::detail::match_dimensions::check(); const SZ indices[] = {_n1}; return coder::detail::index_nd<1>::compute(size_, indices); } SZ index(SZ _n1, SZ _n2) const { coder::detail::match_dimensions::check(); const SZ indices[] = {_n1, _n2}; return coder::detail::index_nd<2>::compute(size_, indices); } SZ index(SZ _n1, SZ _n2, SZ _n3) const { coder::detail::match_dimensions::check(); const SZ indices[] = {_n1, _n2, _n3}; return coder::detail::index_nd<3>::compute(size_, indices); } SZ index(SZ _n1, SZ _n2, SZ _n3, SZ _n4) const { coder::detail::match_dimensions::check(); const SZ indices[] = {_n1, _n2, _n3, _n4}; return coder::detail::index_nd<4>::compute(size_, indices); } SZ index(SZ _n1, SZ _n2, SZ _n3, SZ _n4, SZ _n5) const { coder::detail::match_dimensions::check(); const SZ indices[] = {_n1, _n2, _n3, _n4, _n5}; return coder::detail::index_nd<5>::compute(size_, indices); } SZ index(SZ _n1, SZ _n2, SZ _n3, SZ _n4, SZ _n5, SZ _n6) const { coder::detail::match_dimensions::check(); const SZ indices[] = {_n1, _n2, _n3, _n4, _n5, _n6}; return coder::detail::index_nd<6>::compute(size_, indices); } SZ index(SZ _n1, SZ _n2, SZ _n3, SZ _n4, SZ _n5, SZ _n6, SZ _n7) const { coder::detail::match_dimensions::check(); const SZ indices[] = {_n1, _n2, _n3, _n4, _n5, _n6, _n7}; return coder::detail::index_nd<7>::compute(size_, indices); } SZ index(SZ _n1, SZ _n2, SZ _n3, SZ _n4, SZ _n5, SZ _n6, SZ _n7, SZ _n8) const { coder::detail::match_dimensions::check(); const SZ indices[] = {_n1, _n2, _n3, _n4, _n5, _n6, _n7, _n8}; return coder::detail::index_nd<8>::compute(size_, indices); } SZ index(SZ _n1, SZ _n2, SZ _n3, SZ _n4, SZ _n5, SZ _n6, SZ _n7, SZ _n8, SZ _n9) const { coder::detail::match_dimensions::check(); const SZ indices[] = {_n1, _n2, _n3, _n4, _n5, _n6, _n7, _n8, _n9}; return coder::detail::index_nd<9>::compute(size_, indices); } SZ index(SZ _n1, SZ _n2, SZ _n3, SZ _n4, SZ _n5, SZ _n6, SZ _n7, SZ _n8, SZ _n9, SZ _n10) const { coder::detail::match_dimensions::check(); const SZ indices[] = {_n1, _n2, _n3, _n4, _n5, _n6, _n7, _n8, _n9, _n10}; return coder::detail::index_nd<10>::compute(size_, indices); } T& at(SZ _i1) { coder::detail::match_dimensions::check(); return data_[_i1]; } T& at(SZ _i1, SZ _i2) { coder::detail::match_dimensions::check(); return data_[index(_i1, _i2)]; } T& at(SZ _i1, SZ _i2, SZ _i3) { coder::detail::match_dimensions::check(); return data_[index(_i1, _i2, _i3)]; } T& at(SZ _i1, SZ _i2, SZ _i3, SZ _i4) { coder::detail::match_dimensions::check(); return data_[index(_i1, _i2, _i3, _i4)]; } T& at(SZ _i1, SZ _i2, SZ _i3, SZ _i4, SZ _i5) { coder::detail::match_dimensions::check(); return data_[index(_i1, _i2, _i3, _i4, _i5)]; } T& at(SZ _i1, SZ _i2, SZ _i3, SZ _i4, SZ _i5, SZ _i6) { coder::detail::match_dimensions::check(); return data_[index(_i1, _i2, _i3, _i4, _i5, _i6)]; } T& at(SZ _i1, SZ _i2, SZ _i3, SZ _i4, SZ _i5, SZ _i6, SZ _i7) { coder::detail::match_dimensions::check(); return data_[index(_i1, _i2, _i3, _i4, _i5, _i6, _i7)]; } T& at(SZ _i1, SZ _i2, SZ _i3, SZ _i4, SZ _i5, SZ _i6, SZ _i7, SZ _i8) { coder::detail::match_dimensions::check(); return data_[index(_i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8)]; } T& at(SZ _i1, SZ _i2, SZ _i3, SZ _i4, SZ _i5, SZ _i6, SZ _i7, SZ _i8, SZ _i9) { coder::detail::match_dimensions::check(); return data_[index(_i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9)]; } T& at(SZ _i1, SZ _i2, SZ _i3, SZ _i4, SZ _i5, SZ _i6, SZ _i7, SZ _i8, SZ _i9, SZ _i10) { coder::detail::match_dimensions::check(); return data_[index(_i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, _i10)]; } const T& at(SZ _i1) const { coder::detail::match_dimensions::check(); return data_[_i1]; } const T& at(SZ _i1, SZ _i2) const { coder::detail::match_dimensions::check(); return data_[index(_i1, _i2)]; } const T& at(SZ _i1, SZ _i2, SZ _i3) const { coder::detail::match_dimensions::check(); return data_[index(_i1, _i2, _i3)]; } const T& at(SZ _i1, SZ _i2, SZ _i3, SZ _i4) const { coder::detail::match_dimensions::check(); return data_[index(_i1, _i2, _i3, _i4)]; } const T& at(SZ _i1, SZ _i2, SZ _i3, SZ _i4, SZ _i5) const { coder::detail::match_dimensions::check(); return data_[index(_i1, _i2, _i3, _i4, _i5)]; } const T& at(SZ _i1, SZ _i2, SZ _i3, SZ _i4, SZ _i5, SZ _i6) const { coder::detail::match_dimensions::check(); return data_[index(_i1, _i2, _i3, _i4, _i5, _i6)]; } const T& at(SZ _i1, SZ _i2, SZ _i3, SZ _i4, SZ _i5, SZ _i6, SZ _i7) const { coder::detail::match_dimensions::check(); return data_[index(_i1, _i2, _i3, _i4, _i5, _i6, _i7)]; } const T& at(SZ _i1, SZ _i2, SZ _i3, SZ _i4, SZ _i5, SZ _i6, SZ _i7, SZ _i8) const { coder::detail::match_dimensions::check(); return data_[index(_i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8)]; } const T& at(SZ _i1, SZ _i2, SZ _i3, SZ _i4, SZ _i5, SZ _i6, SZ _i7, SZ _i8, SZ _i9) const { coder::detail::match_dimensions::check(); return data_[index(_i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9)]; } const T& at(SZ _i1, SZ _i2, SZ _i3, SZ _i4, SZ _i5, SZ _i6, SZ _i7, SZ _i8, SZ _i9, SZ _i10) const { coder::detail::match_dimensions::check(); return data_[index(_i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, _i10)]; } array_iterator > begin() { return array_iterator >(this, 0); } array_iterator > end() { return array_iterator >(this, this->numel()); } const_array_iterator > begin() const { return const_array_iterator >(this, 0); } const_array_iterator > end() const { return const_array_iterator >(this, this->numel()); } protected: coder::detail::data_ptr data_; SZ size_[N]; private: void ensureCapacity(SZ _newNumel) { if (_newNumel > data_.capacity()) { SZ i = data_.capacity(); if (i < 16) { i = 16; } while (i < _newNumel) { if (i > 1073741823) { i = MAX_int32_T; } else { i <<= 1; } } data_.reserve(i); } data_.resize(_newNumel); } }; // The standard coder::array class with base type and number of dimensions. template class array : public array_base { private: typedef array_base Base; public: array() : Base() { } array(const array& _other) : Base(_other) { } array(const Base& _other) : Base(_other) { } array(T* _data, const SizeType* _sz) : Base(_data, _sz) { } }; // Specialize on char_T (row vector) for better support on strings. template <> class array : public array_base { private: typedef array_base Base; public: array() : array_base() { } array(const array& _other) : Base(_other) { } array(const Base& _other) : Base(_other) { } array(const std::string& _str) { operator=(_str); } array(const char_T* _str) { operator=(_str); } array(const std::vector& _vec) { SizeType n = static_cast(_vec.size()); set_size(1, n); data_.copy(&_vec[0], n); } array& operator=(const std::string& _str) { SizeType n = static_cast(_str.size()); set_size(1, n); data_.copy(_str.c_str(), n); return *this; } array& operator=(const char_T* _str) { SizeType n = static_cast(strlen(_str)); set_size(1, n); data_.copy(_str, n); return *this; } operator std::string() const { return std::string(static_cast(&(*this)[0]), static_cast(size(1))); } }; // Specialize on 2 dimensions for better support interactions with // std::vector and row vectors. template class array : public array_base { private: typedef array_base Base; public: array() : Base() { } array(const array& _other) : Base(_other) { } array(const Base& _other) : Base(_other) { } array(const std::vector& _vec) { operator=(_vec); } array& operator=(const std::vector& _vec) { SizeType n = static_cast(_vec.size()); Base::set_size(1, n); Base::data_.copy(&_vec[0], n); return *this; } operator std::vector() const { const T* p = &Base::data_[0]; return std::vector(p, p + Base::numel()); } }; // Specialize on 1 dimension for better support with std::vector and // column vectors. template class array : public array_base { private: typedef array_base Base; public: array() : Base() { } array(const array& _other) : Base(_other) { } array(const Base& _other) : Base(_other) { } array(const std::vector& _vec) { operator=(_vec); } array& operator=(const std::vector& _vec) { SizeType n = static_cast(_vec.size()); Base::set_size(n); Base::data_.copy(&_vec[0], n); return *this; } operator std::vector() const { const T* p = &Base::data_[0]; return std::vector(p, p + Base::numel()); } }; } // namespace coder #endif