// // rarray - Runtime arrays: template classes for pointer-based, // runtime, reference counted, multi-dimensional // arrays. Documentation in rarraydoc.pdf // // Copyright (c) 2013-2022 Ramses van Zon // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // #ifndef RARRAY_H #define RARRAY_H #if __cplusplus >= 201103L //begin #include "versionheader.h" #define RA_VERSION "v2.5.0" #define RA_VERSION_NUMBER 2005000 //end #include "versionheader.h" //begin #include "rarraymacros.h" #ifndef _RARRAYMACROSH_ #define _RARRAYMACROSH_ #ifdef RA_BOUNDSCHECK #include #define RA_CHECKORSAY(a, b) if (not(a)) throw std::out_of_range(std::string(b) + " in function " + std::string(__PRETTY_FUNCTION__) + " (rarray:" + std::to_string(__LINE__) + ")") #define RA_NOEXCEPT(x) #define noboundscheck false #else #define RA_CHECKORSAY(a, b) #define RA_NOEXCEPT(x) noexcept(x) #define noboundscheck true #endif #if not defined(RA_INLINE) # if defined(__INTEL_COMPILER) # define RA_INLINE __forceinline # elif defined(__GNUC__) # define RA_INLINE __attribute__((always_inline)) inline # else # define RA_INLINE inline # endif #endif #define RA_INLINEF RA_INLINE #define RA_INLINE_ inline #endif //end #include "rarraymacros.h" //begin #include "shared_buffer.h" #ifndef SHAREDBUFFERH #define SHAREDBUFFERH //#include "rarraymacros.h" was already done above #include #include #include #include #include #include namespace ra { template class shared_buffer; } template int internal_check(const ra::shared_buffer& a, bool datavalue_shouldbe, V* datavalue, bool origvalue_shouldbe, V* origvalue, bool refsvalue_shouldbe, std::atomic* refsvalue, bool refscount_shouldbe, int refscount, bool sizevalue_shouldbe, typename ra::shared_buffer::size_type sizevalue); /***************************************************************************/ namespace ra { /***************************************************************************/ template class shared_buffer { public: typedef ssize_t size_type; shared_buffer() noexcept; explicit shared_buffer(size_type asize); shared_buffer(size_type asize, T* adata) RA_NOEXCEPT(true); shared_buffer(const shared_buffer& other) noexcept; shared_buffer(shared_buffer&& from) noexcept; shared_buffer& operator=(const shared_buffer& other) noexcept; void operator=(shared_buffer&& from) noexcept; ~shared_buffer() noexcept; const T& operator[](size_type index) const RA_NOEXCEPT(true); T& operator[](size_type index) RA_NOEXCEPT(true); const T& at(size_type index) const; T& at(size_type index); shared_buffer slice(size_type from, size_type to); const shared_buffer slice(size_type from, size_type to) const; size_type size() const noexcept; shared_buffer copy() const; typedef T* iterator; typedef const T* const_iterator; iterator begin() noexcept; iterator end() noexcept; const_iterator begin() const noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; reverse_iterator rbegin(); reverse_iterator rend(); const_reverse_iterator rbegin() const; const_reverse_iterator rend() const; const_reverse_iterator crbegin() const; const_reverse_iterator crend() const; void resize(size_type newsize, bool keep_content = false); void assign(const T& value); void assign(std::initializer_list ilist); template void assign_iter(InputIt first, InputIt last); private: T* data_; T* orig_; size_type size_; std::atomic* refs_; template friend int ::internal_check(const ra::shared_buffer& a, bool datavalue_shouldbe, V* datavalue, bool origvalue_shouldbe, V* origvalue, bool refsvalue_shouldbe, std::atomic* refsvalue, bool refscount_shouldbe, int refscount, bool sizevalue_shouldbe, typename ra::shared_buffer::size_type sizevalue); void uninit() noexcept; void incref() noexcept; void decref() noexcept; }; /***************************************************************************/ /* FUTURE FEATURE : #define RA_ALIGNMENT_IN_BYTES 64 template void malign(void*& orig, void*& place, size_t size, size_t bytealignment) { size_t paddedsizeinbytes = size*sizeof(T) + bytealignment - 1; void* some_orig = malloc(paddedsizeinbytes); if (some_orig) { void* some_place = some_orig; if (std::align(bytealignment, size*sizeof(T), some_place, paddedsizeinbytes)) { orig = some_orig; place = some_place; } else { free(some_orig); throw std::bad_alloc(); } } else { throw std::bad_alloc(); } } */ template shared_buffer::shared_buffer() noexcept { uninit(); } template shared_buffer::shared_buffer(size_type asize) : data_(nullptr), orig_(nullptr), size_(0), refs_(nullptr) { T* data; refs_ = new std::atomic(1); try { data = new T[asize]; } catch (...) { delete refs_; throw; } data_ = data; orig_ = data_; size_ = asize; } template shared_buffer::shared_buffer(size_type asize, T* adata) RA_NOEXCEPT(true) : data_(adata), orig_(nullptr), size_(asize), refs_(nullptr) { RA_CHECKORSAY(adata, "nullptr given as data"); } template shared_buffer::shared_buffer(const shared_buffer& other) noexcept : data_(other.data_), orig_(other.orig_), size_(other.size_), refs_(other.refs_) { incref(); } template shared_buffer::shared_buffer(shared_buffer&& from) noexcept : data_(from.data_), orig_(from.orig_), size_(from.size_), refs_(from.refs_) { from.uninit(); } template shared_buffer& shared_buffer::operator=(const shared_buffer& other) noexcept { if (this != &other) { decref(); data_ = other.data_; orig_ = other.orig_; size_ = other.size_; refs_ = other.refs_; incref(); } return *this; } template void shared_buffer::operator=(shared_buffer&& from) noexcept { decref(); data_ = from.data_; orig_ = from.orig_; size_ = from.size_; refs_ = from.refs_; from.uninit(); } template const T& shared_buffer::operator[](size_type index) const RA_NOEXCEPT(true) { RA_CHECKORSAY(index >= 0 and index < size(), "element not in buffer"); return data_[index]; } template T& shared_buffer::operator[](size_type index) RA_NOEXCEPT(true) { RA_CHECKORSAY(index >= 0 and index < size(), "element not in buffer"); return data_[index]; } template const T& shared_buffer::at(size_type index) const { if (index < 0 or index >= size_) throw std::out_of_range("shared_buffer::at"); return data_[index]; } template T& shared_buffer::at(size_type index) { if (index < 0 or index >= size_) throw std::out_of_range("shared_buffer::at"); return data_[index]; } template shared_buffer shared_buffer::slice(size_type from, size_type to) { if (from < 0 or to < 0 or from > size_ or to > size_) throw std::out_of_range("shared_buffer::slice"); shared_buffer result(*this); result.data_ += from; if (from <= to) result.size_ = to - from; else result.size_ = 0; return result; } template const shared_buffer shared_buffer::slice(size_type from, size_type to) const { if (from < 0 or to < 0 or from > size_ or to > size_) throw std::out_of_range("shared_buffer::slice"); shared_buffer result(*this); result.data_ += from; if (from <= to) result.size_ = to - from; else result.size_ = 0; return result; } template shared_buffer::~shared_buffer() noexcept { decref(); } template typename shared_buffer::size_type shared_buffer::size() const noexcept { return size_; } template shared_buffer shared_buffer::copy() const { shared_buffer result(size_); std::copy(cbegin(), cend(), result.begin()); return result; } template typename shared_buffer::iterator shared_buffer::begin() noexcept { return data_; } template typename shared_buffer::iterator shared_buffer::end() noexcept { return data_+size_; } template typename shared_buffer::const_iterator shared_buffer::cbegin() const noexcept { return data_; } template typename shared_buffer::const_iterator shared_buffer::cend() const noexcept { return data_+size_; } template typename shared_buffer::const_iterator shared_buffer::begin() const noexcept { return data_; } template typename shared_buffer::const_iterator shared_buffer::end() const noexcept { return data_+size_; } template typename shared_buffer::reverse_iterator shared_buffer::rbegin() { return std::reverse_iterator(data_+size_); } template typename shared_buffer::reverse_iterator shared_buffer::rend() { return std::reverse_iterator(data_); } template typename shared_buffer::const_reverse_iterator shared_buffer::crbegin() const { return std::reverse_iterator(data_+size_); } template typename shared_buffer::const_reverse_iterator shared_buffer::crend() const { return std::reverse_iterator(data_); } template typename shared_buffer::const_reverse_iterator shared_buffer::rbegin() const { return std::reverse_iterator(data_+size_); } template typename shared_buffer::const_reverse_iterator shared_buffer::rend() const { return std::reverse_iterator(data_); } template void shared_buffer::resize(size_type newsize, bool keep_content) { if ( (newsize* newrefs = new std::atomic(1); T* newdata; try { newdata = new T[newsize]; } catch (...) { delete newrefs; throw; } if (keep_content) { try { size_t n = ((size_ void shared_buffer::assign(const T& value) { for (int i=0;i template void shared_buffer::assign_iter(InputIt first, InputIt last) { resize(last-first); T* data = data_; for (InputIt it = first; it != last; it++) *(data++) = *it; } template void shared_buffer::assign(std::initializer_list ilist) { assign_iter(ilist.begin(), ilist.end()); } /***************************************************************************/ template void shared_buffer::uninit() noexcept { data_ = nullptr; orig_ = nullptr; size_ = 0; refs_ = nullptr; } template void shared_buffer::incref() noexcept { if (refs_) (*refs_)++; } template void shared_buffer::decref() noexcept { if (refs_) { if (--(*refs_) == 0) { delete[] orig_; delete refs_; uninit(); } } } /***************************************************************************/ } #endif //end #include "shared_buffer.h" //begin #include "shared_shape.h" #ifndef SHARED_SHAPEH #define SHARED_SHAPEH //#include "rarraymacros.h" was already done above //begin #include "offsets.h" #ifndef OFFSETSH #define OFFSETSH //#include "rarraymacros.h" was already done above #include #include #include /***************************************************************************/ class Offsets { public: Offsets(const std::vector& dims); template void*** apply_offsets(T* data) const; ssize_t get_num_data_offsets() const noexcept; ssize_t get_num_offsets() const noexcept; ssize_t get_rank() const noexcept; private: ssize_t rank_; std::vector offsets_; ssize_t ndataoffsets_; }; /***************************************************************************/ inline Offsets::Offsets(const std::vector& extent) { rank_ = extent.size(); ssize_t noffsets = 0; ndataoffsets_ = 0; if (rank_ > 0) { ndataoffsets_ = 1; for (ssize_t i = rank_ - 1; i--; ) noffsets = extent[i]*(1 + noffsets); for (ssize_t i = 0 ; i < rank_-1; i++ ) ndataoffsets_ *= extent[i]; offsets_.reserve(noffsets); offsets_.resize(noffsets); if (noffsets > 1) { ssize_t offsetnum = 0; ssize_t extenttot = extent[0]; for (ssize_t i = 1; i < rank_ - 1; i++) { for (ssize_t j = 0; j < extenttot; j++) offsets_[offsetnum+j] = offsetnum + extenttot + j*extent[i]; offsetnum += extenttot; extenttot *= extent[i]; } ndataoffsets_ = extenttot; for (ssize_t j = 0; j < ndataoffsets_; j++) offsets_[offsetnum + j] = j*extent[rank_ - 1]; } } } template inline void*** Offsets::apply_offsets(T* data) const { static_assert(sizeof(T*) == sizeof(void*) && sizeof(T*) == sizeof(void**), "rarray's Offsets requires all pointers to have the same size"); ssize_t noffsets = offsets_.size(); if (ndataoffsets_ == 0 && noffsets == 0) return nullptr; else if (ndataoffsets_ == 1 && noffsets == 0) return reinterpret_cast(data); else { void*** offsets = new void**[noffsets]; ssize_t i = 0; for (;i < noffsets - ndataoffsets_; i++) offsets[i] = reinterpret_cast(offsets) + offsets_[i]; for (;i < noffsets; i++) offsets[i] = reinterpret_cast( const_cast::type*>(data) + offsets_[i]); return offsets; } } inline ssize_t Offsets::get_num_data_offsets() const noexcept { return ndataoffsets_; } inline ssize_t Offsets::get_num_offsets() const noexcept { return offsets_.size(); } inline ssize_t Offsets::get_rank() const noexcept { return rank_; } /***************************************************************************/ #endif //end #include "offsets.h" #include #include #include int test_shared_shape_main(); /***************************************************************************/ namespace ra { /***************************************************************************/ template struct PointerArray { typedef typename PointerArray::type const* type; typedef typename PointerArray::noconst_type* noconst_type; }; template struct PointerArray { typedef T* type; typedef T* noconst_type; }; template struct PointerArray { typedef T& type; typedef T& noconst_type; }; /***************************************************************************/ template class shared_shape { public: typedef typename PointerArray::type ptrs_type; typedef ssize_t size_type; shared_shape() noexcept; shared_shape(const std::array&anextent, T*adata); shared_shape(const shared_shape& other) noexcept; shared_shape(shared_shape&& other) noexcept; shared_shape& operator=(const shared_shape& other) noexcept; void operator=(shared_shape&& other) noexcept; ~shared_shape(); shared_shape copy() const; void relocate(T* newdata); void reshape(const std::array&newextent); ptrs_type ptrs() const noexcept; T* data() const noexcept; size_type size() const noexcept; size_type extent(int i) const; const std::array& extent() const noexcept; shared_shape at(size_type r) const; private: std::array extent_; ptrs_type ptrs_; std::atomic* refs_; void*** orig_; size_type noffsets_; size_type ndataoffsets_; void uninit() noexcept; void incref() const noexcept; void decref() noexcept; void copy_before_write(); template friend class shared_shape; friend int ::test_shared_shape_main(); }; template class shared_shape { public: typedef T ptrs_type; typedef ssize_t size_type; private: std::array extent_; ptrs_type ptrs_; std::atomic* refs_; void*** orig_; size_type noffsets_; size_type ndataoffsets_; void incref() const noexcept {} template friend class shared_shape; }; /***************************************************************************/ template shared_shape::shared_shape() noexcept { uninit(); } template shared_shape::shared_shape(const std::array&anextent, T*adata) : extent_(anextent), ptrs_(nullptr), refs_(nullptr), orig_(nullptr) { Offsets P({extent_.begin(),extent_.end()}); orig_ = P.apply_offsets(adata); ptrs_ = reinterpret_cast(orig_); noffsets_ = P.get_num_offsets(); ndataoffsets_ = P.get_num_data_offsets(); if (R>1) { try { refs_ = new std::atomic(1); } catch(...) { delete[] orig_; throw; } } else { orig_ = nullptr; } } template shared_shape::shared_shape(const shared_shape& other) noexcept : extent_(other.extent_), ptrs_(other.ptrs_), refs_(other.refs_), orig_(other.orig_), noffsets_(other.noffsets_), ndataoffsets_(other.ndataoffsets_) { incref(); } template shared_shape::shared_shape(shared_shape&& other) noexcept : extent_(other.extent_), ptrs_(other.ptrs_), refs_(other.refs_), orig_(other.orig_), noffsets_(other.noffsets_), ndataoffsets_(other.ndataoffsets_) { other.uninit(); } template shared_shape& shared_shape::operator=(const shared_shape& other) noexcept { if (this != &other) { decref(); extent_ = other.extent_; ptrs_ = other.ptrs_; refs_ = other.refs_; orig_ = other.orig_; noffsets_ = other.noffsets_; ndataoffsets_ = other.ndataoffsets_; incref(); } return *this; } template void shared_shape::operator=(shared_shape&& other) noexcept { decref(); extent_ = other.extent_; ptrs_ = other.ptrs_; refs_ = other.refs_; orig_ = other.orig_; noffsets_ = other.noffsets_; ndataoffsets_ = other.ndataoffsets_; other.uninit(); } template shared_shape::~shared_shape() { decref(); } template void shared_shape::copy_before_write() { if (R > 1 and refs_ and *refs_ > 1) *this = this->copy(); } template struct _data_from_ptrs_noffsets_ndataoffsets { static T* call(typename PointerArray::type ptrs, typename shared_shape::size_type noffsets, typename shared_shape::size_type ndataoffsets) noexcept { return reinterpret_cast( const_cast::noconst_type>( ptrs[noffsets - ndataoffsets] ) ); } }; template struct _data_from_ptrs_noffsets_ndataoffsets { static T* call (typename PointerArray::type ptrs, typename shared_shape::size_type noffsets, typename shared_shape::size_type ndataoffsets) noexcept { return reinterpret_cast(ptrs); } }; template T* shared_shape::data() const noexcept { return _data_from_ptrs_noffsets_ndataoffsets::call(ptrs_,noffsets_,ndataoffsets_); } template typename shared_shape::size_type shared_shape::size() const noexcept { return ndataoffsets_ * extent_[R-1]; } template typename shared_shape::size_type shared_shape::extent(int i) const { if (i < 0 or i >= R) throw std::out_of_range("shared_shape::extent(int)"); return extent_[i]; } template const std::array::size_type,R>& shared_shape::extent() const noexcept { return extent_; } template void shared_shape::relocate(T* newdata) { if (R==1) { ptrs_ = reinterpret_cast(newdata); } else if (R>1) { std::ptrdiff_t shift = reinterpret_cast(newdata) - reinterpret_cast(data()); if (shift != 0) { copy_before_write(); for (size_type i = noffsets_ - ndataoffsets_; i < noffsets_; i++) orig_[i] = reinterpret_cast(reinterpret_cast(orig_[i]) + shift); } } } template shared_shape shared_shape::copy() const { shared_shape copy_of_this; copy_of_this.extent_ = extent_; copy_of_this.noffsets_ = noffsets_; copy_of_this.ndataoffsets_ = ndataoffsets_; if (R>1) { copy_of_this.refs_ = new std::atomic(1); copy_of_this.orig_ = new void**[noffsets_]; void*** old_eff_orig = reinterpret_cast( const_cast::noconst_type>( ptrs_ )); std::copy(old_eff_orig, old_eff_orig + noffsets_, copy_of_this.orig_); std::ptrdiff_t shift = reinterpret_cast(copy_of_this.orig_) - reinterpret_cast(old_eff_orig); for (size_type i = 0; i < noffsets_ - ndataoffsets_; i++) copy_of_this.orig_[i] = reinterpret_cast(reinterpret_cast(copy_of_this.orig_[i]) + shift); copy_of_this.ptrs_ = reinterpret_cast(copy_of_this.orig_); } else { copy_of_this.ptrs_ = ptrs_; } return copy_of_this; } template shared_shape shared_shape::at(size_type index) const { if (R < 1 or index < 0 or index >= extent_[0]) throw std::out_of_range("shared_shape::at"); shared_shape result; if (R>1) { for (size_type i = 0; i < R-1; ++i) result.extent_[i] = extent_[i+1]; result.ptrs_ = ptrs_[index]; result.refs_ = refs_; result.orig_ = orig_; result.noffsets_ = noffsets_/extent_[0] - 1; result.ndataoffsets_ = ndataoffsets_/extent_[0]; incref(); } return result; } template void shared_shape::reshape(const std::array&newextent) { if (newextent != extent_) { *this = shared_shape(newextent, data()); } } template typename shared_shape::ptrs_type shared_shape::ptrs() const noexcept { return ptrs_; } template void shared_shape::uninit() noexcept { ptrs_ = nullptr; orig_ = nullptr; refs_ = nullptr; noffsets_ = 0; ndataoffsets_ = 0; extent_.fill(0); } template void shared_shape::incref() const noexcept { if (refs_) (*refs_)++; } template void shared_shape::decref() noexcept { if (refs_) { if (--(*refs_) == 0) { if (R>1) delete[] orig_; delete refs_; uninit(); } } } /***************************************************************************/ } #endif //end #include "shared_shape.h" #include #include #include #include #include #include #include #include #include namespace ra { typedef ssize_t size_type; enum class RESIZE { NO, ALLOWED }; template class rarray; template class CommaOp; template RA_INLINE_ std::istream& operator>>(std::istream &i, rarray& r); template RA_INLINE_ std::ostream& operator<<(std::ostream &o, const rarray& r); template class _Bracket; template class _ConstBracket; #define ExOp class template class Expr; } namespace ra { template class rarray { public: typedef T value_type; typedef ssize_t difference_type; typedef ssize_t size_type; typedef T* iterator; typedef const T* const_iterator; typedef typename PointerArray::type parray_t; typedef typename PointerArray::noconst_type noconst_parray_t; RA_INLINE_ rarray(); template::type> RA_INLINE_ explicit rarray(size_type n0); template::type> RA_INLINE_ rarray(size_type n0, size_type n1); template::type> RA_INLINE_ rarray(size_type n0, size_type n1, size_type n2); template::type> RA_INLINE_ rarray(size_type n0, size_type n1, size_type n2, size_type n3); template::type> RA_INLINE_ rarray(size_type n0, size_type n1, size_type n2, size_type n3, size_type n4); template::type> RA_INLINE_ rarray(size_type n0, size_type n1, size_type n2, size_type n3, size_type n4, size_type n5); template::type> RA_INLINE_ rarray(size_type n0, size_type n1, size_type n2, size_type n3, size_type n4, size_type n5, size_type n6); template::type> RA_INLINE_ rarray(size_type n0, size_type n1, size_type n2, size_type n3, size_type n4, size_type n5, size_type n6, size_type n7); template::type> RA_INLINE_ rarray(size_type n0, size_type n1, size_type n2, size_type n3, size_type n4, size_type n5, size_type n6, size_type n7, size_type n8); template::type> RA_INLINE_ rarray(size_type n0, size_type n1, size_type n2, size_type n3, size_type n4, size_type n5, size_type n6, size_type n7, size_type n8, size_type n9); template::type> RA_INLINE_ rarray(size_type n0, size_type n1, size_type n2, size_type n3, size_type n4, size_type n5, size_type n6, size_type n7, size_type n8, size_type n9, size_type n10); RA_INLINE_ rarray(const size_type* anextent); template::type> RA_INLINE_ rarray(T* buffer, size_type n0); template::type> RA_INLINE_ rarray(T* buffer, size_type n0, size_type n1); template::type> RA_INLINE_ rarray(T* buffer, size_type n0, size_type n1, size_type n2); template::type> RA_INLINE_ rarray(T* buffer, size_type n0, size_type n1, size_type n2, size_type n3); template::type> RA_INLINE_ rarray(T* buffer, size_type n0, size_type n1, size_type n2, size_type n3, size_type n4); template::type> RA_INLINE_ rarray(T* buffer, size_type n0, size_type n1, size_type n2, size_type n3, size_type n4, size_type n5); template::type> RA_INLINE_ rarray(T* buffer, size_type n0, size_type n1, size_type n2, size_type n3, size_type n4, size_type n5, size_type n6); template::type> RA_INLINE_ rarray(T* buffer, size_type n0, size_type n1, size_type n2, size_type n3, size_type n4, size_type n5, size_type n6, size_type n7); template::type> RA_INLINE_ rarray(T* buffer, size_type n0, size_type n1, size_type n2, size_type n3, size_type n4, size_type n5, size_type n6, size_type n7, size_type n8); template::type> RA_INLINE_ rarray(T* buffer, size_type n0, size_type n1, size_type n2, size_type n3, size_type n4, size_type n5, size_type n6, size_type n7, size_type n8, size_type n9); template::type> RA_INLINE_ rarray(T* buffer, size_type n0, size_type n1, size_type n2, size_type n3, size_type n4, size_type n5, size_type n6, size_type n7, size_type n8, size_type n9, size_type n10); RA_INLINE_ rarray(T* buffer, const size_type* anextent); template::type> RA_INLINE_ explicit rarray(T (&a)[Z]); template::type> RA_INLINE_ explicit rarray(T (&a)[Y][Z]); template::type> RA_INLINE_ explicit rarray(T (&a)[X][Y][Z]); template::type> RA_INLINE_ explicit rarray(T (&a)[W][X][Y][Z]); template::type> RA_INLINE_ explicit rarray(T (&a)[V][W][X][Y][Z]); template::type> RA_INLINE_ explicit rarray(T (&a)[U][V][W][X][Y][Z]); template::type> RA_INLINE_ explicit rarray(T (&a)[T_][U][V][W][X][Y][Z]); template::type> RA_INLINE_ explicit rarray(T (&a)[S][T_][U][V][W][X][Y][Z]); template::type> RA_INLINE_ explicit rarray(T (&a)[R_][S][T_][U][V][W][X][Y][Z]); template::type> RA_INLINE_ explicit rarray(T (&a)[Q][R_][S][T_][U][V][W][X][Y][Z]); template::type> RA_INLINE_ explicit rarray(T (&a)[P][Q][R_][S][T_][U][V][W][X][Y][Z]); RA_INLINEF rarray(const rarray &a) noexcept; RA_INLINE_ rarray& operator=(const rarray &a) noexcept; rarray(rarray&& x) noexcept; rarray& operator=(rarray&& x) noexcept; RA_INLINE_ CommaOp operator=(const T& e) RA_NOEXCEPT(std::is_nothrow_copy_constructible()); RA_INLINEF ~rarray(); constexpr int rank() const noexcept { return R; } template RA_INLINEF explicit rarray (const Expr& e); template RA_INLINEF rarray& operator= (const Expr& e); template RA_INLINEF rarray& operator+=(const Expr& e); template RA_INLINEF rarray& operator-=(const Expr& e); template RA_INLINEF rarray& operator*=(const Expr& e); template RA_INLINEF rarray& operator/=(const Expr& e); template RA_INLINEF rarray& operator%=(const Expr& e); RA_INLINEF void clear() noexcept; template::type> RA_INLINE_ void reshape(size_type n0, RESIZE resize_allowed=RESIZE::NO); template::type> RA_INLINE_ void reshape(size_type n0, size_type n1, RESIZE resize_allowed=RESIZE::NO); template::type> RA_INLINE_ void reshape(size_type n0, size_type n1, size_type n2, RESIZE resize_allowed=RESIZE::NO); template::type> RA_INLINE_ void reshape(size_type n0, size_type n1, size_type n2, size_type n3, RESIZE resize_allowed=RESIZE::NO); template::type> RA_INLINE_ void reshape(size_type n0, size_type n1, size_type n2, size_type n3, size_type n4, RESIZE resize_allowed=RESIZE::NO); template::type> RA_INLINE_ void reshape(size_type n0, size_type n1, size_type n2, size_type n3, size_type n4, size_type n5, RESIZE resize_allowed=RESIZE::NO); template::type> RA_INLINE_ void reshape(size_type n0, size_type n1, size_type n2, size_type n3, size_type n4, size_type n5, size_type n6, RESIZE resize_allowed=RESIZE::NO); template::type> RA_INLINE_ void reshape(size_type n0, size_type n1, size_type n2, size_type n3, size_type n4, size_type n5, size_type n6, size_type n7, RESIZE resize_allowed=RESIZE::NO); template::type> RA_INLINE_ void reshape(size_type n0, size_type n1, size_type n2, size_type n3, size_type n4, size_type n5, size_type n6, size_type n7, size_type n8, RESIZE resize_allowed=RESIZE::NO); template::type> RA_INLINE_ void reshape(size_type n0, size_type n1, size_type n2, size_type n3, size_type n4, size_type n5, size_type n6, size_type n7, size_type n8, size_type n9, RESIZE resize_allowed=RESIZE::NO); template::type> RA_INLINE_ void reshape(size_type n0, size_type n1, size_type n2, size_type n3, size_type n4, size_type n5, size_type n6, size_type n7, size_type n8, size_type n9, size_type n10, RESIZE resize_allowed=RESIZE::NO); RA_INLINE_ void reshape(const size_type* extent, RESIZE resize_allowed=RESIZE::NO); RA_INLINE_ bool empty() const noexcept; RA_INLINE_ rarray copy() const; RA_INLINE_ size_type extent(int i) const; RA_INLINEF const size_type* shape() const noexcept; RA_INLINE_ size_type size() const noexcept; RA_INLINE_ T* data() noexcept; RA_INLINE_ const T* data() const noexcept; RA_INLINE_ parray_t ptr_array() const noexcept; RA_INLINE_ noconst_parray_t noconst_ptr_array() const noexcept; RA_INLINE_ const rarray& const_ref() const noexcept; RA_INLINE_ void fill(const T& value); RA_INLINE_ iterator begin() noexcept; RA_INLINE_ const_iterator begin() const noexcept; RA_INLINE_ const_iterator cbegin() const noexcept; RA_INLINE_ iterator end() noexcept; RA_INLINE_ const_iterator end() const noexcept; RA_INLINE_ const_iterator cend() const noexcept; RA_INLINE_ size_type index(const T& a, int i) const; RA_INLINE_ size_type index(const iterator& iter, int i) const; RA_INLINE_ std::array index(const T& a) const; RA_INLINE_ std::array index(const iterator& i) const; RA_INLINE_ size_type* index(const T& a, size_type* ind) const; RA_INLINE_ size_type* index(const iterator& i, size_type* ind) const; template> RA_INLINEF typename std::enable_if::type at(size_type i); template RA_INLINEF typename std::enable_if::type at(size_type i); template> RA_INLINEF typename std::enable_if::type at(size_type i) const; template RA_INLINEF typename std::enable_if::type at(size_type i) const; /* * * RA_INLINEF operator typename PointerArray::type () noexcept; RA_INLINEF operator typename PointerArray::type () const noexcept ; * * */ template typename std::enable_if::type operator[](ssize_t index) { RA_CHECKORSAY(index >= 0 and index < extent(0), "index out of range of array"); return buffer_.begin()[index]; } template typename std::enable_if >::type operator[](ssize_t index) { return { *this, index, this->shape() }; } template typename std::enable_if::type operator[](ssize_t index) const { RA_CHECKORSAY(index >= 0 and index < extent(0), "index out of range of array"); return buffer_.cbegin()[index]; } template typename std::enable_if >::type operator[](ssize_t index) const { return { *this, index, this->shape() }; } RA_INLINEF const T& leval(size_type i) const; private: friend class _Bracket>; friend class _ConstBracket>; RA_INLINEF typename PointerArray::type _at(ssize_t index); RA_INLINEF typename PointerArray::type _at(ssize_t index) const; friend class rarray; rarray(shared_buffer&& abuffer, shared_shape&& ashape) : buffer_(std::forward>(abuffer)), shape_(std::forward>(ashape)) {} rarray(const shared_buffer&& abuffer, shared_shape&& ashape) : buffer_(std::forward>(const_cast&& >(abuffer))), shape_(std::forward>(ashape)) {} shared_buffer buffer_; shared_shape shape_; }; template class CommaOp { public: RA_INLINEF CommaOp& operator,(const T& e); private: RA_INLINEF CommaOp(T* ptr, T* last) RA_NOEXCEPT(true); T *ptr_; T * const last_; template friend class rarray; template friend class subrarray; }; template class _Bracket { private: P& parent_; // what array/array expre is being accessed ssize_t index_; const ssize_t* shape_; public: RA_INLINEF _Bracket operator[](ssize_t nextindex) noexcept(noboundscheck); RA_INLINEF operator decltype(parent_.at(index_)) (); _Bracket(const _Bracket&) = delete; _Bracket(const _Bracket&&) = delete; _Bracket& operator=(const _Bracket&) = delete; _Bracket& operator=(const _Bracket&&) = delete; private: RA_INLINEF _Bracket(P& parent, ssize_t index, const ssize_t* shape) noexcept(noboundscheck); RA_INLINEF auto _at(ssize_t nextindex) noexcept(noboundscheck) -> decltype(parent_._at(index_)[nextindex]); template friend class ra::rarray; template friend class ra::_Bracket; public: RA_INLINEF auto at(ssize_t nextindex) -> decltype(parent_.at(index_).at(nextindex)); }; template class _Bracket { private: P& parent_; // what array/array expre is being accessed ssize_t index_; const ssize_t* shape_; public: RA_INLINEF T& operator[](ssize_t nextindex) noexcept(noboundscheck); RA_INLINEF operator decltype(parent_.at(index_)) (); _Bracket(const _Bracket&) = delete; _Bracket(const _Bracket&&) = delete; _Bracket& operator=(const _Bracket&) = delete; _Bracket& operator=(const _Bracket&&) = delete; private: RA_INLINEF _Bracket(P& parent, ssize_t index, const ssize_t* shape) noexcept(noboundscheck); RA_INLINEF auto _at(ssize_t nextindex) noexcept(noboundscheck) -> decltype(parent_._at(index_)[nextindex]); template friend class ra::rarray; template friend class ra::_Bracket; public: RA_INLINEF auto at(ssize_t nextindex) -> decltype(parent_.at(index_).at(nextindex)); }; template class _ConstBracket { private: const P& parent_; ssize_t index_; public: RA_INLINEF _ConstBracket operator[](ssize_t nextindex) const noexcept(noboundscheck); RA_INLINEF operator decltype(parent_.at(index_)) (); _ConstBracket(const _ConstBracket&) = delete; _ConstBracket(const _ConstBracket&&) = delete; _ConstBracket& operator=(const _ConstBracket&) = delete; _ConstBracket& operator=(const _ConstBracket&&) = delete; private: const ssize_t* shape_; RA_INLINEF _ConstBracket(const P& parent, ssize_t index, const ssize_t* shape) noexcept(noboundscheck); RA_INLINEF auto _at(ssize_t nextindex) const noexcept(noboundscheck) -> decltype(parent_._at(index_)[nextindex]); template friend class ra::rarray; template friend class ra::_ConstBracket; public: RA_INLINEF auto at(ssize_t nextindex) const -> decltype(parent_.at(index_).at(nextindex)); }; template class _ConstBracket { private: const P& parent_; ssize_t index_; public: RA_INLINEF const T& operator[](ssize_t nextindex) const noexcept(noboundscheck); RA_INLINEF operator decltype(parent_.at(index_)) (); _ConstBracket(const _ConstBracket&) = delete; _ConstBracket(const _ConstBracket&&) = delete; _ConstBracket& operator=(const _ConstBracket&) = delete; _ConstBracket& operator=(const _ConstBracket&&) = delete; private: const ssize_t* shape_; RA_INLINEF _ConstBracket(const P& parent, ssize_t index, const ssize_t* shape) noexcept(noboundscheck); RA_INLINEF auto _at(ssize_t nextindex) const noexcept(noboundscheck) -> decltype(parent_._at(index_)[nextindex]); template friend class ra::rarray; template friend class ra::_ConstBracket; public: RA_INLINEF auto at(ssize_t nextindex) const -> decltype(parent_.at(index_).at(nextindex)); }; template rarray linspace(S x1, S x2, int n=0, bool end_incl=true) // { if (n==0) { if (x2>x1) n = static_cast(x2 - x1 + end_incl); else n = static_cast(x1 - x2 + end_incl); } rarray x(n); for (int i = 0; i < n; i++) x[i] = x1 + static_cast(((x2-x1)*static_cast(i))/(n-end_incl)); if (end_incl) x[n-1] = x2; return x; } template class Xrange { private: struct const_iterator { typedef std::ptrdiff_t difference_type; typedef T value_type; typedef T* pointer; typedef T& reference; typedef std::input_iterator_tag iterator_category; const_iterator(T i, T di, T b): i_(i), di_(di), b_(b) {} bool operator!=(const const_iterator& other) const { return i_ != other.i_; } const const_iterator& operator++() { i_+=di_; if (di_>0 && i_ >= b_) i_ = b_; if (di_<0 && i_ <= b_) i_ = b_; return *this; } const T& operator*() { return i_; } T i_, di_, b_; }; T a_, b_, d_; public: Xrange(T a, T b, T d) : a_(a), b_(a + static_cast(static_cast(std::ceil(static_cast(b-a)/static_cast(d)))*d)), d_(d) {} const_iterator begin() const { return const_iterator(a_, d_, b_); } const_iterator end() const { return const_iterator(b_, d_, b_); } }; template Xrange xrange(T end) { return Xrange(static_cast(0), end, static_cast(1)); } template Xrange xrange(S begin, T end) { return Xrange(static_cast(begin), end, static_cast(1)); } template Xrange xrange(S begin, T end, U step) { return Xrange(static_cast(begin), end, static_cast(step)); } } template RA_INLINE_ ra::rarray::rarray() : buffer_(), shape_() {} template template RA_INLINE_ ra::rarray::rarray(ra::size_type n0) : buffer_(n0), shape_({n0}, buffer_.begin()) {} template template RA_INLINE_ ra::rarray::rarray(size_type n0,size_type n1) : buffer_(n0*n1), shape_({n0,n1}, buffer_.begin()) {} template template RA_INLINE_ ra::rarray::rarray(size_type n0,size_type n1,size_type n2) : buffer_(n0*n1*n2), shape_({n0,n1,n2}, buffer_.begin()) {} template template RA_INLINE_ ra::rarray::rarray(size_type n0,size_type n1,size_type n2,size_type n3) : buffer_(n0*n1*n2*n3), shape_({n0,n1,n2,n3}, buffer_.begin()) {} template template RA_INLINE_ ra::rarray::rarray(size_type n0,size_type n1,size_type n2,size_type n3,size_type n4) : buffer_(n0*n1*n2*n3*n4), shape_({n0,n1,n2,n3,n4}, buffer_.begin()) {} template template RA_INLINE_ ra::rarray::rarray(size_type n0,size_type n1,size_type n2,size_type n3,size_type n4,size_type n5) : buffer_(n0*n1*n2*n3*n4*n5), shape_({n0,n1,n2,n3,n4,n5}, buffer_.begin()) {} template template RA_INLINE_ ra::rarray::rarray(size_type n0,size_type n1,size_type n2,size_type n3,size_type n4,size_type n5,size_type n6) : buffer_(n0*n1*n2*n3*n4*n5*n6), shape_({n0,n1,n2,n3,n4,n5,n6}, buffer_.begin()) {} template template RA_INLINE_ ra::rarray::rarray(size_type n0,size_type n1,size_type n2,size_type n3,size_type n4,size_type n5,size_type n6,size_type n7) : buffer_(n0*n1*n2*n3*n4*n5*n6*n7), shape_({n0,n1,n2,n3,n4,n5,n6,n7}, buffer_.begin()) {} template template RA_INLINE_ ra::rarray::rarray(size_type n0,size_type n1,size_type n2,size_type n3,size_type n4,size_type n5,size_type n6,size_type n7,size_type n8) : buffer_(n0*n1*n2*n3*n4*n5*n6*n7*n8), shape_({n0,n1,n2,n3,n4,n5,n6,n7,n8}, buffer_.begin()) {} template template RA_INLINE_ ra::rarray::rarray(size_type n0,size_type n1,size_type n2,size_type n3,size_type n4,size_type n5,size_type n6,size_type n7,size_type n8,size_type n9) : buffer_(n0*n1*n2*n3*n4*n5*n6*n7*n8*n9), shape_({n0,n1,n2,n3,n4,n5,n6,n7,n8,n9}, buffer_.begin()) {} template template RA_INLINE_ ra::rarray::rarray(size_type n0,size_type n1,size_type n2,size_type n3,size_type n4,size_type n5,size_type n6,size_type n7,size_type n8,size_type n9,size_type n10) : buffer_(n0*n1*n2*n3*n4*n5*n6*n7*n8*n9*n10), shape_({n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10}, buffer_.begin()) {} template template RA_INLINE_ ra::rarray::rarray(T (&a)[Z]) : buffer_(Z, a), shape_({Z}, buffer_.begin()) {} template template RA_INLINE_ ra::rarray::rarray(T (&a)[Y][Z]) : buffer_(Y*Z, *a), shape_({Y,Z}, buffer_.begin()) {} template template RA_INLINE_ ra::rarray::rarray(T (&a)[X][Y][Z]) : buffer_(X*Y*Z, **a), shape_({X,Y,Z}, buffer_.begin()) {} template template RA_INLINE_ ra::rarray::rarray(T (&a)[W][X][Y][Z]) : buffer_(W*X*Y*Z, ***a), shape_({W,X,Y,Z}, buffer_.begin()) {} template template RA_INLINE_ ra::rarray::rarray(T (&a)[V][W][X][Y][Z]) : buffer_(V*W*X*Y*Z, ****a), shape_({V,W,X,Y,Z}, buffer_.begin()) {} template template RA_INLINE_ ra::rarray::rarray(T (&a)[U][V][W][X][Y][Z]) : buffer_(U*V*W*X*Y*Z, *****a), shape_({U,V,W,X,Y,Z}, buffer_.begin()) {} template template RA_INLINE_ ra::rarray::rarray(T (&a)[T_][U][V][W][X][Y][Z]) : buffer_(T_*U*V*W*X*Y*Z, ******a), shape_({T_,U,V,W,X,Y,Z}, buffer_.begin()) {} template template RA_INLINE_ ra::rarray::rarray(T (&a)[S][T_][U][V][W][X][Y][Z]) : buffer_(S*T_*U*V*W*X*Y*Z, *******a), shape_({S,T_,U,V,W,X,Y,Z}, buffer_.begin()) {} template template RA_INLINE_ ra::rarray::rarray(T (&a)[R_][S][T_][U][V][W][X][Y][Z]) : buffer_(R_*S*T_*U*V*W*X*Y*Z, ********a), shape_({R_,S,T_,U,V,W,X,Y,Z}, buffer_.begin()) {} template template RA_INLINE_ ra::rarray::rarray(T (&a)[Q][R_][S][T_][U][V][W][X][Y][Z]) : buffer_(Q*R_*S*T_*U*V*W*X*Y*Z, *********a), shape_({Q,R_,S,T_,U,V,W,X,Y,Z}, buffer_.begin()) {} template template RA_INLINE_ ra::rarray::rarray(T (&a)[P][Q][R_][S][T_][U][V][W][X][Y][Z]) : buffer_(P*Q*R_*S*T_*U*V*W*X*Y*Z, **********a), shape_({P,Q,R_,S,T_,U,V,W,X,Y,Z}, buffer_.begin()) {} template template RA_INLINE_ ra::rarray::rarray(T* buffer, size_type n0) : buffer_(n0, buffer), shape_({n0}, buffer) {} template template RA_INLINE_ ra::rarray::rarray(T* buffer, size_type n0,size_type n1) : buffer_(n0*n1, buffer), shape_({n0,n1}, buffer) {} template template RA_INLINE_ ra::rarray::rarray(T* buffer, size_type n0,size_type n1,size_type n2) : buffer_(n0*n1*n2, buffer), shape_({n0,n1,n2}, buffer) {} template template RA_INLINE_ ra::rarray::rarray(T* buffer, size_type n0,size_type n1,size_type n2,size_type n3) : buffer_(n0*n1*n2*n3, buffer), shape_({n0,n1,n2,n3}, buffer) {} template template RA_INLINE_ ra::rarray::rarray(T* buffer, size_type n0,size_type n1,size_type n2,size_type n3,size_type n4) : buffer_(n0*n1*n2*n3*n4, buffer), shape_({n0,n1,n2,n3,n4}, buffer) {} template template RA_INLINE_ ra::rarray::rarray(T* buffer, size_type n0,size_type n1,size_type n2,size_type n3,size_type n4,size_type n5) : buffer_(n0*n1*n2*n3*n4*n5, buffer), shape_({n0,n1,n2,n3,n4,n5}, buffer) {} template template RA_INLINE_ ra::rarray::rarray(T* buffer, size_type n0,size_type n1,size_type n2,size_type n3,size_type n4,size_type n5,size_type n6) : buffer_(n0*n1*n2*n3*n4*n5*n6, buffer), shape_({n0,n1,n2,n3,n4,n5,n6}, buffer) {} template template RA_INLINE_ ra::rarray::rarray(T* buffer, size_type n0,size_type n1,size_type n2,size_type n3,size_type n4,size_type n5,size_type n6,size_type n7) : buffer_(n0*n1*n2*n3*n4*n5*n6*n7, buffer), shape_({n0,n1,n2,n3,n4,n5,n6,n7}, buffer) {} template template RA_INLINE_ ra::rarray::rarray(T* buffer, size_type n0,size_type n1,size_type n2,size_type n3,size_type n4,size_type n5,size_type n6,size_type n7,size_type n8) : buffer_(n0*n1*n2*n3*n4*n5*n6*n7*n8, buffer), shape_({n0,n1,n2,n3,n4,n5,n6,n7,n8}, buffer) {} template template RA_INLINE_ ra::rarray::rarray(T* buffer, size_type n0,size_type n1,size_type n2,size_type n3,size_type n4,size_type n5,size_type n6,size_type n7,size_type n8,size_type n9) : buffer_(n0*n1*n2*n3*n4*n5*n6*n7*n8*n9, buffer), shape_({n0,n1,n2,n3,n4,n5,n6,n7,n8,n9}, buffer) {} template template RA_INLINE_ ra::rarray::rarray(T* buffer, size_type n0,size_type n1,size_type n2,size_type n3,size_type n4,size_type n5,size_type n6,size_type n7,size_type n8,size_type n9,size_type n10) : buffer_(n0*n1*n2*n3*n4*n5*n6*n7*n8*n9*n10, buffer), shape_({n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10}, buffer) {} namespace ra { RA_INLINE_ size_type mul(const size_type * x, std::size_t n) noexcept { size_type result = 1; for (std::size_t i=0;i RA_INLINE_ ra::rarray::rarray(const size_type* anextent) : buffer_(mul(anextent,R)), shape_(reinterpret_cast&>(*anextent), buffer_.begin()) {} template RA_INLINE_ ra::rarray::rarray(T* buffer, const size_type* anextent) : buffer_(mul(anextent,R), buffer), shape_(reinterpret_cast&>(*anextent), buffer) {} template RA_INLINEF ra::rarray::rarray(const rarray &a) noexcept : buffer_(a.buffer_), shape_(a.shape_) { } template RA_INLINEF ra::rarray::rarray(rarray&& x) noexcept : buffer_(std::move(x.buffer_)), shape_(std::move(x.shape_)) { } template RA_INLINE_ void ra::rarray::clear() noexcept { shape_ = shared_shape(); buffer_ = shared_buffer(); } template template RA_INLINE_ void ra::rarray::reshape(size_type n0, RESIZE resize_allowed) { if (size() == n0 or (resize_allowed == RESIZE::ALLOWED and size() >= n0)) { shape_ = shared_shape({n0}, buffer_.begin()); } else { throw std::out_of_range(std::string("Incompatible dimensions in function ") + std::string(__PRETTY_FUNCTION__)); } } template template RA_INLINE_ void ra::rarray::reshape(size_type n0, size_type n1, RESIZE resize_allowed) { if (size() == n0*n1 or (resize_allowed == RESIZE::ALLOWED and size() >= n0*n1)) { shape_ = shared_shape({n0,n1}, buffer_.begin()); } else { throw std::out_of_range(std::string("Incompatible dimensions in function ") + std::string(__PRETTY_FUNCTION__)); } } template template RA_INLINE_ void ra::rarray::reshape(size_type n0, size_type n1, size_type n2, RESIZE resize_allowed) { if (size() == n0*n1*n2 or (resize_allowed == RESIZE::ALLOWED and size() >= n0*n1*n2)) { shape_ = shared_shape({n0,n1,n2}, buffer_.begin()); } else { throw std::out_of_range(std::string("Incompatible dimensions in function ") + std::string(__PRETTY_FUNCTION__)); } } template template RA_INLINE_ void ra::rarray::reshape(size_type n0,size_type n1,size_type n2,size_type n3, RESIZE resize_allowed) { if (size() == n0*n1*n2*n3 or (resize_allowed == RESIZE::ALLOWED and size() >= n0*n1*n2*n3)) { shape_ = shared_shape({n0,n1,n2,n3}, buffer_.begin()); } else { throw std::out_of_range(std::string("Incompatible dimensions in function ") + std::string(__PRETTY_FUNCTION__)); } } template template RA_INLINE_ void ra::rarray::reshape(size_type n0,size_type n1,size_type n2,size_type n3,size_type n4, RESIZE resize_allowed) { if (size() == n0*n1*n2*n3*n4 or (resize_allowed == RESIZE::ALLOWED and size() >= n0*n1*n2*n3*n4)) { shape_ = shared_shape({n0,n1,n2,n3,n4}, buffer_.begin()); } else { throw std::out_of_range(std::string("Incompatible dimensions in function ") + std::string(__PRETTY_FUNCTION__)); } } template template RA_INLINE_ void ra::rarray::reshape(size_type n0,size_type n1,size_type n2,size_type n3,size_type n4,size_type n5, RESIZE resize_allowed) { if (size() == n0*n1*n2*n3*n4*n5 or (resize_allowed == RESIZE::ALLOWED and size() >= n0*n1*n2*n3*n4*n5)) { shape_ = shared_shape({n0,n1,n2,n3,n4,n5}, buffer_.begin()); } else { throw std::out_of_range(std::string("Incompatible dimensions in function ") + std::string(__PRETTY_FUNCTION__)); } } template template RA_INLINE_ void ra::rarray::reshape(size_type n0,size_type n1,size_type n2,size_type n3,size_type n4,size_type n5,size_type n6, RESIZE resize_allowed) { if (size() == n0*n1*n2*n3*n4*n5*n6 or (resize_allowed == RESIZE::ALLOWED and size() >= n0*n1*n2*n3*n4*n5*n6)) { shape_ = shared_shape({n0,n1,n2,n3,n4,n5,n6}, buffer_.begin()); } else { throw std::out_of_range(std::string("Incompatible dimensions in function ") + std::string(__PRETTY_FUNCTION__)); } } template template RA_INLINE_ void ra::rarray::reshape(size_type n0,size_type n1,size_type n2,size_type n3,size_type n4,size_type n5,size_type n6,size_type n7, RESIZE resize_allowed) { if (size() == n0*n1*n2*n3*n4*n5*n6*n7 or (resize_allowed == RESIZE::ALLOWED and size() >= n0*n1*n2*n3*n4*n5*n6*n7)) { shape_ = shared_shape({n0,n1,n2,n3,n4,n5,n6,n7}, buffer_.begin()); } else { throw std::out_of_range(std::string("Incompatible dimensions in function ") + std::string(__PRETTY_FUNCTION__)); } } template template RA_INLINE_ void ra::rarray::reshape(size_type n0,size_type n1,size_type n2,size_type n3,size_type n4,size_type n5,size_type n6,size_type n7,size_type n8, RESIZE resize_allowed) { if (size() == n0*n1*n2*n3*n4*n5*n6*n7*n8 or (resize_allowed == RESIZE::ALLOWED and size() >= n0*n1*n2*n3*n4*n5*n6*n7*n8)) { shape_ = shared_shape({n0,n1,n2,n3,n4,n5,n6,n7,n8}, buffer_.begin()); } else { throw std::out_of_range(std::string("Incompatible dimensions in function ") + std::string(__PRETTY_FUNCTION__)); } } template template RA_INLINE_ void ra::rarray::reshape(size_type n0,size_type n1,size_type n2,size_type n3,size_type n4,size_type n5,size_type n6,size_type n7,size_type n8,size_type n9, RESIZE resize_allowed) { if (size() == n0*n1*n2*n3*n4*n5*n6*n7*n8*n9 or (resize_allowed == RESIZE::ALLOWED and size() >= n0*n1*n2*n3*n4*n5*n6*n7*n8*n9)) { shape_ = shared_shape({n0,n1,n2,n3,n4,n5,n6,n7,n8,n9}, buffer_.begin()); } else { throw std::out_of_range(std::string("Incompatible dimensions in function ") + std::string(__PRETTY_FUNCTION__)); } } template template RA_INLINE_ void ra::rarray::reshape(size_type n0,size_type n1,size_type n2,size_type n3,size_type n4,size_type n5,size_type n6,size_type n7,size_type n8,size_type n9,size_type n10, RESIZE resize_allowed) { if (size() == n0*n1*n2*n3*n4*n5*n6*n7*n8*n9*n10 or (resize_allowed == RESIZE::ALLOWED and size() >= n0*n1*n2*n3*n4*n5*n6*n7*n8*n9*n10)) { shape_ = shared_shape({n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10}, buffer_.begin()); } else { throw std::out_of_range(std::string("Incompatible dimensions in function ") + std::string(__PRETTY_FUNCTION__)); } } template RA_INLINE_ void ra::rarray::reshape(const size_type* newshape, RESIZE resize_allowed) { if (size() == mul(newshape,R) or (resize_allowed == RESIZE::ALLOWED and size() >= mul(newshape,R))) { shape_ = shared_shape((const std::array&)(*newshape), buffer_.begin()); } else { throw std::out_of_range(std::string("Incompatible dimensions in function ") + std::string(__PRETTY_FUNCTION__)); } } template RA_INLINE_ ra::rarray::~rarray() {} template RA_INLINE_ ra::CommaOp ra::rarray::operator=(const T& e) RA_NOEXCEPT(std::is_nothrow_copy_constructible()) { RA_CHECKORSAY(not empty(), "assignment to unsized array"); RA_CHECKORSAY(size()>0,"assignment with more elements than in array"); T* first = &(buffer_[0]); if (size() > 0) *first = e; else return ra::CommaOp(nullptr, nullptr); ra::CommaOp co(first+1, first+size()-1); return co; } template RA_INLINE_ ra::CommaOp::CommaOp(T* ptr, T* last) RA_NOEXCEPT(true) : ptr_(ptr), last_(last) { RA_CHECKORSAY(ptr_!=nullptr and last_!=nullptr, "invalid comma operator"); } template RA_INLINE_ ra::CommaOp& ra::CommaOp::operator,(const T& e) { RA_CHECKORSAY(ptr_!=nullptr and last_!=nullptr, "invalid comma operator"); RA_CHECKORSAY(ptr_<=last_, "assignment with more elements than in array"); if (ptr_ and ptr_ <= last_) *ptr_++ = e; return *this; } template RA_INLINE_ bool ra::rarray::empty() const noexcept { return buffer_.cbegin() == nullptr; } template RA_INLINE_ ra::rarray ra::rarray::copy() const { rarray clone; clone.buffer_ = buffer_.copy(); clone.shape_ = shape_.copy(); clone.shape_.relocate(clone.buffer_.begin()); return clone; } template template RA_INLINEF typename std::enable_if::type ra::rarray::at(size_type i) { if (i < 0 or i >= extent(0)) throw std::out_of_range("rarray::at"); size_type stride = size()/extent(0); return ra::rarray(buffer_.slice(i*stride, (i+1)*stride), shape_.at(i)); } template template RA_INLINEF typename std::enable_if::type ra::rarray::at(size_type i) const { if (i < 0 or i >= extent(0)) throw std::out_of_range("rarray::at"); size_type stride = size()/extent(0); return ra::rarray(buffer_.slice(i*stride, (i+1)*stride), shape_.at(i)); } template template RA_INLINEF typename std::enable_if::type ra::rarray::at(size_type i) { if (i < 0 or i >= extent(0)) throw std::out_of_range("rarray::at"); return shape_.ptrs()[i]; } template template RA_INLINEF typename std::enable_if::type ra::rarray::at(size_type i) const { if (i < 0 or i >= extent(0)) throw std::out_of_range("rarray::at"); return shape_.ptrs()[i]; } template RA_INLINEF typename ra::PointerArray::type ra::rarray::_at(ssize_t index) { return shape_.ptrs()[index]; } template RA_INLINEF typename ra::PointerArray::type ra::rarray::_at(ssize_t index) const { return shape_.ptrs()[index]; } template RA_INLINEF const ra::size_type* ra::rarray::shape() const noexcept { return &(shape_.extent()[0]); } template RA_INLINE_ typename ra::rarray::parray_t ra::rarray::ptr_array() const noexcept { return shape_.ptrs(); } template RA_INLINE_ typename ra::rarray::noconst_parray_t ra::rarray::noconst_ptr_array() const noexcept { return const_cast(shape_.ptrs()); } template RA_INLINE_ const typename ra::rarray& ra::rarray::const_ref() const noexcept { return reinterpret_cast&>(*this); } template RA_INLINEF ra::rarray& ra::rarray::operator=(const rarray &a) noexcept { buffer_ = a.buffer_; shape_ = a.shape_; return *this; } template RA_INLINEF ra::rarray& ra::rarray::operator=(rarray &&a) noexcept { buffer_ = std::move(a.buffer_); shape_ = std::move(a.shape_); return *this; } template RA_INLINEF void ra::rarray::fill(const T& value) { buffer_.assign(value); } template RA_INLINEF ra::size_type ra::rarray::size() const noexcept { return shape_.size(); } template RA_INLINEF T* ra::rarray::data() noexcept { return buffer_.begin(); } template RA_INLINEF const T* ra::rarray::data() const noexcept { return buffer_.begin(); } template RA_INLINEF ra::size_type ra::rarray::extent(int i) const { return shape_.extent(i); } template RA_INLINEF typename ra::rarray::iterator ra::rarray::begin() noexcept { return buffer_.begin(); } template RA_INLINEF typename ra::rarray::const_iterator ra::rarray::begin() const noexcept { return buffer_.begin(); } template RA_INLINEF typename ra::rarray::const_iterator ra::rarray::cbegin() const noexcept { return buffer_.cbegin(); } template RA_INLINEF typename ra::rarray::iterator ra::rarray::end() noexcept { return buffer_.end(); } template RA_INLINEF typename ra::rarray::const_iterator ra::rarray::end() const noexcept { return buffer_.end(); } template RA_INLINEF typename ra::rarray::const_iterator ra::rarray::cend() const noexcept { return buffer_.cend(); } template RA_INLINE_ ra::size_type* ra::rarray::index(const iterator&i, size_type* ind) const { return index(*i, ind); } template RA_INLINE_ ra::size_type* ra::rarray::index(const T& a, size_type* ind) const { ptrdiff_t linearindex = &a - &(buffer_[0]); RA_CHECKORSAY(linearindex >= 0 and linearindex < size(), "element not in array"); int j = R; const size_type* extent_ = shape(); while (j-->0) { ind[j] = linearindex % extent_[j]; linearindex /= extent_[j]; } return ind; } template RA_INLINE_ std::array ra::rarray::index(const iterator&i) const { return index(*i); } template RA_INLINE_ std::array ra::rarray::index(const T& a) const { std::array ind; ptrdiff_t linearindex = &a - &(buffer_[0]); RA_CHECKORSAY(linearindex >=0 and linearindex < size(), "element not in array"); int j = R; const size_type* extent_ = shape(); while (j-->0) { ind[j] = linearindex % extent_[j]; linearindex /= extent_[j]; } return ind; } template RA_INLINE_ ra::size_type ra::rarray::index(const iterator&iter, int i) const { return index(*iter, i); } template RA_INLINE_ ra::size_type ra::rarray::index(const T& a, int i) const { ptrdiff_t linearindex = &a - &(buffer_[0]); if (linearindex < 0 or linearindex >= size()) throw ("element not in array"); const size_type* extent_ = shape(); for (int j = R-1; j > i; j--) linearindex /= extent_[j]; return linearindex % extent_[i]; } template RA_INLINEF ra::_Bracket> ra::_Bracket::operator[](ssize_t nextindex) noexcept(noboundscheck) { return { *this, nextindex, shape_ + 1 }; } template RA_INLINEF ra::_Bracket::operator decltype(parent_.at(index_)) () { return parent_.at(index_); } template RA_INLINEF ra::_Bracket::_Bracket(P& parent, ssize_t index, const ssize_t* shape) noexcept(noboundscheck) : parent_(parent), index_(index), shape_(shape) { RA_CHECKORSAY(index >=0 and index_ < shape_[0], "index out of range of array"); } template RA_INLINEF auto ra::_Bracket::_at(ssize_t nextindex) noexcept(noboundscheck) -> decltype(parent_._at(index_)[nextindex]) { return parent_._at(index_)[nextindex]; } template RA_INLINEF auto ra::_Bracket::at(ssize_t nextindex) -> decltype(parent_.at(index_).at(nextindex)) { return parent_.at(index_).at(nextindex); } template RA_INLINEF T& ra::_Bracket::operator[](ssize_t nextindex) noexcept(noboundscheck) { RA_CHECKORSAY(nextindex >=0 and nextindex < shape_[1], "index out of range of array"); return parent_._at(index_)[nextindex]; } template RA_INLINEF ra::_Bracket::operator decltype(parent_.at(index_)) () { return parent_.at(index_); } template RA_INLINEF ra::_Bracket::_Bracket(P& parent, ssize_t index, const ssize_t* shape) noexcept(noboundscheck) : parent_(parent), index_(index), shape_(shape) { RA_CHECKORSAY(index >=0 and index_ < shape_[0], "index out of range of array"); } template RA_INLINEF auto ra::_Bracket::at(ssize_t nextindex) -> decltype(parent_.at(index_).at(nextindex)) { return parent_.at(index_).at(nextindex); } template RA_INLINEF ra::_ConstBracket> ra::_ConstBracket::operator[](ssize_t nextindex) const noexcept(noboundscheck) { return { *this, nextindex, shape_ + 1 }; } template RA_INLINEF ra::_ConstBracket::operator decltype(parent_.at(index_)) () { return parent_.at(index_); } template RA_INLINEF ra::_ConstBracket::_ConstBracket(const P& parent, ssize_t index, const ssize_t* shape) noexcept(noboundscheck) : parent_(parent), index_(index), shape_(shape) { RA_CHECKORSAY(index >=0 and index_ < shape_[0], "index out of range of array"); } template RA_INLINEF auto ra::_ConstBracket::_at(ssize_t nextindex) const noexcept(noboundscheck) -> decltype(parent_._at(index_)[nextindex]) { return parent_._at(index_)[nextindex]; } template RA_INLINEF auto ra::_ConstBracket::at(ssize_t nextindex) const -> decltype(parent_.at(index_).at(nextindex)) { return parent_.at(index_).at(nextindex); } template RA_INLINEF const T& ra::_ConstBracket::operator[](ssize_t nextindex) const noexcept(noboundscheck) { RA_CHECKORSAY(nextindex >=0 and nextindex < shape_[1], "index out of range of array"); return parent_._at(index_)[nextindex]; } template RA_INLINEF ra::_ConstBracket::operator decltype(parent_.at(index_)) () { return parent_.at(index_); } template RA_INLINEF ra::_ConstBracket::_ConstBracket(const P& parent, ssize_t index, const ssize_t* shape) noexcept(noboundscheck) : parent_(parent), index_(index), shape_(shape) { RA_CHECKORSAY(index >=0 and index_ < shape_[0], "index out of range of array"); } template RA_INLINEF auto ra::_ConstBracket::at(ssize_t nextindex) const -> decltype(parent_.at(index_).at(nextindex)) { return parent_.at(index_).at(nextindex); } namespace ra { template size_type extent(const A &a, int i) { switch (i) { case 0: return std::extent(); case 1: return std::extent(); case 2: return std::extent(); case 3: return std::extent(); case 4: return std::extent(); case 5: return std::extent(); case 6: return std::extent(); case 7: return std::extent(); case 8: return std::extent(); case 9: return std::extent(); case 10: return std::extent(); default: return 0; } } template size_type extent(const rarray &a, int i) { return a.extent(i); } } //begin #include "rarrayio.h" namespace ra { template RA_INLINE_ std::ostream& text_output(std::ostream &o, const rarray& r); template RA_INLINE_ std::ostream& text_output(std::ostream &o, const rarray& r); template struct Deref { static RA_INLINEF T& access(typename PointerArray::type p, const size_type* indices); }; template struct Deref { static RA_INLINEF T& access(typename PointerArray::type p, const size_type* indices); }; template struct StringToValue { static RA_INLINE_ void get(const std::string& input, T& output); }; template<> struct StringToValue { static RA_INLINE_ void get(const std::string& input, std::string& output); }; enum class token { UNKNOWN=0, BRACEOPEN, BRACECLOSE, COMMA, DATASTRING, END }; inline char toch(const token& Token) { switch (Token) { case ra::token::BRACEOPEN: return '{'; case ra::token::BRACECLOSE: return '}'; case ra::token::COMMA: return ','; case ra::token::DATASTRING: return '$'; case ra::token::END: return '.'; default: return '?'; } } RA_INLINE_ std::list> parse_shape(std::istream & in, int R, size_type* shape); template RA_INLINE_ void parse_strings(const std::list> & tokens, const size_type* shape, typename PointerArray::type p); } template RA_INLINE_ std::ostream& ra::operator<<(std::ostream &o, const ra::rarray& r) { if (R>1) { return ra::text_output(o,r); } else if (R==1) { if (not r.empty()) { o << "{"; for (ra::size_type i=0; i0) o << ","; o << r.data()[i]; } o << "}"; } } return o; } template RA_INLINE_ std::ostream& ra::text_output(std::ostream &o, const ra::rarray& r) { if (not r.empty()) { o << "{\n"; for (size_type i=0; i0) o << ",\n"; o << r.at(i); } o << "\n}"; } else { for (int i=0; i RA_INLINE_ std::ostream& ra::text_output(std::ostream &o, const ra::rarray& r) { if (not r.empty()) { o << '{'; for (size_type i=0; i RA_INLINE_ void ra::StringToValue::get(const std::string& input, T& output) { std::stringstream str(input); str >> output; } RA_INLINE_ void ra::StringToValue::get(const std::string& input, std::string& output) { output = input; } template RA_INLINEF T& ra::Deref::access(typename PointerArray::type p, const size_type* indices) { return Deref::access(p[indices[0]-1], indices+1); } template RA_INLINEF T& ra::Deref::access(typename PointerArray::type p, const size_type* indices) { return p[indices[0]-1]; } static char get_but_eat_newline(std::istream & in) { char ch1='\n'; while (ch1=='\n' && ! in.eof()) in >> ch1; return ch1; } static char get_but_eat_whitespace(std::istream & in) { char ch1; in >> ch1; return ch1; } RA_INLINE_ std::list> ra::parse_shape(std::istream & in, int R, ra::size_type* shape) { if (shape == nullptr) { throw std::istream::failure("Parse call error"); } std::list> result; size_t init_file_ptr = in.tellg(); try { size_type current_shape[R]; for (int i=0; i=0) { if (current_depth==R-1) { char lastchar; std::string word = ""; do { if (word=="") { lastchar = get_but_eat_newline(in); } else { in.get(lastchar); } if (lastchar != ',' and lastchar != '}') { word += lastchar; } if (word == "#") { word=""; std::string skipstr; do { in.get(lastchar); skipstr += lastchar; } while (lastchar!=':'); int skip = atoi(skipstr.c_str());// for (int i=0; i RA_INLINE_ void ra::parse_strings(const std::list> & tokens, const ra::size_type* shape, typename ra::PointerArray::type p) { size_type index[R]; int current_depth = -1; for (auto& tokenpair: tokens) { switch (tokenpair.first) { case ra::token::BRACEOPEN: current_depth++; index[current_depth]=1; break; case ra::token::BRACECLOSE: current_depth--; break; case ra::token::COMMA: index[current_depth]++; break; case ra::token::DATASTRING: StringToValue::get(tokenpair.second, Deref::access(p, index)); break; case ra::token::END: break; default: throw std::istream::failure("Parsing error"); break; } if (tokenpair.first == ra::token::END) break; } } template RA_INLINE_ std::istream& ra::operator>>(std::istream &in, ra::rarray& r) { ra::size_type extent[R] = {0}; auto X = ra::parse_shape(in, R, extent); if (ra::mul(extent,R) <= r.size()) r.reshape(extent, ra::RESIZE::ALLOWED); else r = rarray(extent); ra::parse_strings(X, extent, r.ptr_array()); return in; } //end #include "rarrayio.h" //begin #include "rarraydelmacros.h" #undef RA_CHECKORSAY #undef RA_NOEXCEPT #undef RA_INLINE #undef RA_INLINEF #undef RA_INLINE_ #undef noboundscheck //end #include "rarraydelmacros.h" #define EXTENT(A,I) ra::extent(A,I) #define RARRAY(A) rarray::type,std::rank::value>(A) #define INDEX(A,X,I) RARRAY(A).index(X,I) namespace std { template struct remove_all_extents> { typedef T type; }; template struct rank> { static const size_t value = R; }; } using ra::rarray; using ra::linspace; using ra::xrange; template using rvector = rarray; template using rmatrix = rarray; template using rtensor = rarray; #else #error "This file requires C++11 or newer support." #endif #endif