// // rarray - Runtime arrays: template classes for pointer-based, // runtime dimensionalized, multi-dimensional // arrays. Documentation in rarraydoc.pdf // // Copyright (c) 2013-2020 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 #include #include #include #include #include #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__)) #else #define RA_CHECKORSAY(a, b) #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 #ifndef SHAREDBUFFERH #define SHAREDBUFFERH #include #include #include #include #include #include int test_shared_buffer_main(); // for testing /***************************************************************************/ namespace ra { static char _buffername = 'A'; /***************************************************************************/ template class shared_buffer { public: typedef ssize_t size_type; shared_buffer(); explicit shared_buffer(size_type size); shared_buffer(size_type size, T* data); shared_buffer(const shared_buffer& other); shared_buffer(shared_buffer&& from); shared_buffer& operator=(const shared_buffer& other); // copy void operator=(shared_buffer&& from); // move ~shared_buffer(); const T& operator[](size_type index) const; T& operator[](size_type index); const T& at(size_type index) const; T& at(size_type index); shared_buffer slice(size_type from, size_type to); size_type size() const; shared_buffer copy() const; typedef T* iterator; typedef const T* const_iterator; iterator begin(); iterator end(); const_iterator begin() const; const_iterator end() const; const_iterator cbegin() const; const_iterator cend() const; 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_; friend int ::test_shared_buffer_main(); // for testing void uninit(); void incref(); void decref(); }; /***************************************************************************/ #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 { orig = nullptr; place = nullptr; } } } template shared_buffer::shared_buffer() { uninit(); } template shared_buffer::shared_buffer(size_type size) : data_(new T[size]), orig_(data_), size_(size), refs_(new std::atomic(1)) { } template shared_buffer::shared_buffer(size_type size, T* data) : data_(data), orig_(nullptr), size_(size), refs_(nullptr) { } template shared_buffer::shared_buffer(const shared_buffer& other) : data_(other.data_), orig_(other.orig_), size_(other.size_), refs_(other.refs_) { incref(); } template shared_buffer::shared_buffer(shared_buffer&& from) : data_(from.data_), orig_(from.orig_), size_(from.size_), refs_(from.refs_) { from.uninit(); } template shared_buffer& shared_buffer::operator=(const shared_buffer& other) { 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) { 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 { return data_[index]; } template T& shared_buffer::operator[](size_type index) { 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 shared_buffer::~shared_buffer() { decref(); } template typename shared_buffer::size_type shared_buffer::size() const { 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() { return data_; } template typename shared_buffer::iterator shared_buffer::end() { return data_+size_; } template typename shared_buffer::const_iterator shared_buffer::cbegin() const { return data_; } template typename shared_buffer::const_iterator shared_buffer::cend() const { return data_+size_; } template typename shared_buffer::const_iterator shared_buffer::begin() const { return data_; } template typename shared_buffer::const_iterator shared_buffer::end() const { 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); if (keep_content) { 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() { data_ = nullptr; orig_ = nullptr; size_ = 0; refs_ = nullptr; } template void shared_buffer::incref() { if (refs_) (*refs_)++; } template void shared_buffer::decref() { if (refs_) { if (--(*refs_) == 0) { delete[] orig_; delete refs_; uninit(); } } } /***************************************************************************/ } #endif #ifndef SHARED_SHAPEH #define SHARED_SHAPEH // //#include "offsets.h" #ifndef OFFSETSH #define OFFSETSH #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; ssize_t get_num_offsets() const; ssize_t get_rank() const; private: ssize_t rank_; std::vector offsets_; ssize_t ndataoffsets_; friend int test_offsets_main(); }; /***************************************************************************/ inline Offsets::Offsets(const std::vector& dims) { std::vector extent(dims); 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) { // catches rank_ == 1 and zero-dimensioned arrays 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 { ssize_t noffsets = offsets_.size(); if (ndataoffsets_ == 0 && noffsets == 0) return nullptr; else if (ndataoffsets_ == 1 && noffsets == 0) // that happens only for rank==1 return (void***)(data); else { void*** offsets = new void**[noffsets]; ssize_t i = 0; for (;i < noffsets - ndataoffsets_; i++) offsets[i] = (void**)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 { return ndataoffsets_; } inline ssize_t Offsets::get_num_offsets() const { return offsets_.size(); } inline ssize_t Offsets::get_rank() const { return rank_; } /***************************************************************************/ #endif //end of #include "offsets.h" #include #include #include int test_shared_shape_main(); /***************************************************************************/ namespace ra { /***************************************************************************/ template struct PointerArray { typedef typename PointerArray::type const* type; // const shape, recursive typedef typename PointerArray::noconst_type* noconst_type; // non-const variant }; template struct PointerArray { // We end the recursion by specifically defining the R=1 case typedef T* type; // no const as this would express that the elements are constant typedef T* noconst_type; }; template struct PointerArray { // We end the recursion also by specifically defining the R=0 case typedef T& type; // no const as this would express that the elements are constant typedef T& noconst_type; }; /***************************************************************************/ template class shared_shape { public: typedef typename PointerArray::type ptrs_type; typedef ssize_t size_type; shared_shape(); // non-functional shape shared_shape(const std::array&extent, T*data);// construct shape shared_shape(const shared_shape& other); // copy constructor shared_shape(shared_shape&& other); // move constructor shared_shape& operator=(const shared_shape& other); // copy void operator=(shared_shape&& other); // move ~shared_shape(); shared_shape copy() const; void relocate(T* newdata); // let shape point to other data block void reshape(const std::array&extent); // change shape (not the data) ptrs_type ptrs() const; // get pointer-to-pointer structure T* data() const; // get pointer to the data size_type size() const; // get total number of elements size_type extent(int i) const; // get extent in dimension i const std::array& extent() const; // get total extent array 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(); void incref() const; void decref(); void copy_before_write(); template friend class shared_shape; // for "at" 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() {} template friend class shared_shape; // for "at" }; /***************************************************************************/ template shared_shape::shared_shape() { uninit(); } template shared_shape::shared_shape(const std::array&extent, T*data) : extent_(extent), ptrs_(nullptr), refs_(nullptr), orig_(nullptr) { Offsets P({extent_.begin(),extent_.end()}); orig_ = P.apply_offsets(data); ptrs_ = reinterpret_cast(orig_); noffsets_ = P.get_num_offsets(); ndataoffsets_ = P.get_num_data_offsets(); if (R>1) { refs_ = new std::atomic(1); } else { orig_ = nullptr; } } template shared_shape::shared_shape(const shared_shape& other) : 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) : 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) { 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) { 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) { return (T*)(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) { return (T*)(ptrs); } }; template T* shared_shape::data() const { return _data_from_ptrs_noffsets_ndataoffsets::call(ptrs_,noffsets_,ndataoffsets_); } template typename shared_shape::size_type shared_shape::size() const { return ndataoffsets_ * extent_[R-1]; } template typename shared_shape::size_type shared_shape::extent(int i) const { return extent_[i]; } template const std::array::size_type,R>& shared_shape::extent() const { return extent_; } template void shared_shape::relocate(T* newdata) { if (R==1) { ptrs_ = reinterpret_cast(newdata); } else if (R>1) { std::ptrdiff_t shift = newdata - data(); if (shift != 0) { copy_before_write(); for (size_type i = noffsets_ - ndataoffsets_; i < noffsets_; i++) orig_[i] = reinterpret_cast((T*)(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_]; std::copy((void***)ptrs_, (void***)(ptrs_) + noffsets_, copy_of_this.orig_); std::ptrdiff_t shift = copy_of_this.orig_ - (void***)(ptrs_); for (size_type i = 0; i < noffsets_ - ndataoffsets_; i++) 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&extent) { if (extent != extent_) { *this = shared_shape(extent, data()); } } template typename shared_shape::ptrs_type shared_shape::ptrs() const { return ptrs_; } template void shared_shape::uninit() { ptrs_ = nullptr; orig_ = nullptr; refs_ = nullptr; noffsets_ = 0; ndataoffsets_ = 0; extent_.fill(0); } template void shared_shape::incref() const { if (refs_) (*refs_)++; } template void shared_shape::decref() { if (refs_) { if (--(*refs_) == 0) { if (R>1) delete[] orig_; delete refs_; uninit(); } } } /***************************************************************************/ } #endif namespace ra { typedef ssize_t size_type; enum class RESIZE { NO, ALLOWED }; } namespace ra { template class rarray; } namespace ra { template class CommaOp; } #define ExOp class namespace ra { template class Expr; } namespace ra { template class rarray { public: typedef ssize_t difference_type; // difference type for indices typedef ssize_t size_type; // type of indices typedef T* iterator; // iterator type typedef const T* const_iterator; // iterator type for constant access typedef typename PointerArray::type parray_t; // shorthand for T*const*const*... typedef typename PointerArray::noconst_type noconst_parray_t; // shorthand for T***... RA_INLINE_ rarray(); // constructor leaving rarray undefined RA_INLINE_ explicit rarray(size_type n0); // constructor creating its own buffer for R=1 RA_INLINE_ rarray(size_type n0, size_type n1); // constructor creating its own buffer for R=2 RA_INLINE_ rarray(size_type n0, size_type n1, size_type n2); // R=3 RA_INLINE_ rarray(size_type n0, size_type n1, size_type n2, size_type n3); // R=4 RA_INLINE_ rarray(size_type n0, size_type n1, size_type n2, size_type n3, size_type n4); // R=5 RA_INLINE_ rarray(size_type n0, size_type n1, size_type n2, size_type n3, size_type n4, size_type n5); // R=6 RA_INLINE_ rarray(size_type n0, size_type n1, size_type n2, size_type n3, size_type n4, size_type n5, size_type n6); // R=7 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); // R=8 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); // R=9 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); // R=10 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); // R=11 RA_INLINE_ rarray(const size_type* extent); // R>11 RA_INLINE_ rarray(T* buffer, size_type n0); // constructor from an existing buffer for R=1 RA_INLINE_ rarray(T* buffer, size_type n0, size_type n1); // R=2 RA_INLINE_ rarray(T* buffer, size_type n0, size_type n1, size_type n2); // R=3 RA_INLINE_ rarray(T* buffer, size_type n0, size_type n1, size_type n2, size_type n3); // R=4 RA_INLINE_ rarray(T* buffer, size_type n0, size_type n1, size_type n2, size_type n3, size_type n4); // R=5 RA_INLINE_ rarray(T* buffer, size_type n0, size_type n1, size_type n2, size_type n3, size_type n4, size_type n5); // R=6 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); // R=7 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); // R=8 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); // R=9 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); // R=10 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);// R=11 RA_INLINE_ rarray(T* buffer, const size_type* extent); // R>11 RA_INLINEF rarray(const rarray &a); // copy constructor RA_INLINE_ rarray& operator=(const rarray &a); // array assignment operator rarray(rarray&& x); // move constructor rarray& operator=(rarray&& x); // move assignment operator RA_INLINE_ CommaOp operator=(const T& e); // Comma separated element assignment RA_INLINEF ~rarray(); // destructor 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(); // clean up routine, make undefined RA_INLINE_ void reshape(size_type n0, RESIZE resize_allowed=RESIZE::NO); // reshape shallow copy keeping the underlying data for R=1 RA_INLINE_ void reshape(size_type n0, size_type n1, RESIZE resize_allowed=RESIZE::NO); // R=2 RA_INLINE_ void reshape(size_type n0, size_type n1, size_type n2, RESIZE resize_allowed=RESIZE::NO); // R=3 RA_INLINE_ void reshape(size_type n0, size_type n1, size_type n2, size_type n3, RESIZE resize_allowed=RESIZE::NO); // R=4 RA_INLINE_ void reshape(size_type n0, size_type n1, size_type n2, size_type n3, size_type n4, RESIZE resize_allowed=RESIZE::NO); // R=5 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); // R=6 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); // R=7 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); // R=8 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); // R=9 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); // R=10 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); // R=11 RA_INLINE_ void reshape(const size_type* extent, RESIZE resize_allowed=RESIZE::NO); // R>11 RA_INLINE_ bool is_clear() const; // check if undefined RA_INLINE_ rarray copy() const; // return a copy RA_INLINE_ size_type extent(int i) const; // retrieve array size in dimension i RA_INLINE_ const size_type* shape() const; // retrieve array sizes in all dimensions RA_INLINE_ size_type size() const; // retrieve the total number of elements RA_INLINE_ T* data(); // return a T* to the internal data RA_INLINE_ const T* data() const; // return a T* to the internal data RA_INLINE_ parray_t ptr_array() const; // return a T*const*.. acting similarly to this rarray when using []: RA_INLINE_ noconst_parray_t noconst_ptr_array() const; // return a T**.. acting similarly to this rarray when using []: RA_INLINE_ rarray& const_ref() const; // create a reference to this that treats elements as constant: RA_INLINE_ void fill(const T& value); // fill with uniform value RA_INLINE_ iterator begin(); // start of the content RA_INLINE_ const_iterator begin() const; // start of the content, when *this is constant RA_INLINE_ const_iterator cbegin() const; // start of the content, when *this can be constant and you need to be explicit RA_INLINE_ iterator end(); // end of the content RA_INLINE_ const_iterator end() const; // end of the content, when *this is constant RA_INLINE_ const_iterator cend() const; // end of the content, when *this is constant and you need to be explicit about that RA_INLINE_ size_type index(const T& a, int i) const; // if a an element in the array, get index i of that element RA_INLINE_ size_type index(const iterator& iter, int i) const; // if i points at an element in the array, get index i of that element RA_INLINE_ std::array index(const T& a) const; // if a an element in the array, get the indices of that element RA_INLINE_ std::array index(const iterator& i) const;// if i points at an element in the array, get the indices of that element RA_INLINE_ size_type* index(const T& a, size_type* ind) const; // if a an element in the array, get the indices of that element RA_INLINE_ size_type* index(const iterator& i, size_type* ind) const; // if i points at an element in the array, get the indices of that element RA_INLINEF rarray at(size_type i); RA_INLINEF rarray at(size_type i) const; RA_INLINEF operator typename PointerArray::type (); // makes a[..][..] work, as well as automatic conversion RA_INLINEF operator typename PointerArray::type () const; RA_INLINEF const T& leval(size_type i) const; rarray(shared_buffer&& buffer, shared_shape&& shape) : buffer_(std::forward>(buffer)), shape_(std::forward>(shape)) {} private: shared_buffer buffer_; shared_shape shape_; }; // end definition rarray template class rarray { public: typedef ssize_t difference_type; // difference type for indices typedef ssize_t size_type; // type of indices typedef T* iterator; // iterator type typedef const T* const_iterator; // iterator type for constant access typedef typename PointerArray::type parray_t; // shorthand for T*const*const*... typedef typename PointerArray::noconst_type noconst_parray_t; // shorthand for T***... RA_INLINE_ rarray() {}; // constructor leaving rarray undefined RA_INLINE_ rarray(const size_type* extent); // R>11 RA_INLINE_ rarray(T* buffer, const size_type* extent); // R>11 RA_INLINEF rarray(const rarray &a); // copy constructor RA_INLINE_ rarray& operator=(const rarray &a); // array assignment operator rarray(rarray&& x); // move constructor rarray& operator=(rarray&& x); // move assignment operator 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(); // clean up routine, make undefined RA_INLINE_ bool is_clear() const { return buffer_.cbegin() == nullptr; } // check if undefined RA_INLINE_ rarray copy() const; // return a copy RA_INLINE_ size_type extent(int i) const { return is_clear()?0:1; } // retrieve array size in dimension i RA_INLINE_ const size_type* shape() const; // retrieve array sizes in all dimensions RA_INLINE_ size_type size() const; // retrieve the total number of elements RA_INLINE_ T* data(); // return a T* to the internal data RA_INLINE_ const T* data() const { return buffer_.begin(); } // return a T* to the internal data RA_INLINE_ parray_t ptr_array() const; // return a T*const*.. acting similarly to this rarray when using []: RA_INLINE_ noconst_parray_t noconst_ptr_array() const; // return a T**.. acting similarly to this rarray when using []: RA_INLINE_ rarray& const_ref() const; // create a reference to this that treats elements as constant: RA_INLINE_ void fill(const T& value); // fill with uniform value RA_INLINE_ iterator begin(); // start of the content RA_INLINE_ const_iterator begin() const; // start of the content, when *this is constant RA_INLINE_ const_iterator cbegin() const; // start of the content, when *this can be constant and you need to be explicit RA_INLINE_ iterator end(); // end of the content RA_INLINE_ const_iterator end() const; // end of the content, when *this is constant RA_INLINE_ const_iterator cend() const; // end of the content, when *this is constant and you need to be explicit about that RA_INLINE_ size_type index(const T& a, size_type i) const; // if a an element in the array, get index i of that element RA_INLINE_ size_type index(const iterator& iter, size_type i); // if i points at an element in the array, get index i of that element RA_INLINE_ size_type index(const const_iterator& iter, size_type i) const;// if i points at an element in the array, get index i of that element RA_INLINE_ size_type* index(const T& a, size_type* ind) const; // if a an element in the array, get the indices of that element RA_INLINE_ size_type* index(const iterator& i, size_type* ind) const; // if i points at an element in the array, get the indices of that element RA_INLINE_ size_type* index(const const_iterator& i, size_type* ind) const;// if i points at an element in the array, get the indices of that element RA_INLINEF const T& leval(size_type i) const; rarray(shared_buffer&& buffer, const shared_shape& shape) : buffer_(std::forward>(buffer)) {} ~rarray() {} RA_INLINEF operator T& () { return buffer_[0]; } RA_INLINEF operator const T& () const { return buffer_[0]; } RA_INLINEF T& at(size_type i) { return buffer_[0]; } RA_INLINEF const T& at(size_type i) const { return buffer_[0]; } RA_INLINE_ CommaOp operator=(const T& e) // Comma separated element assignment { T* first = &(buffer_[0]); *first = e; ra::CommaOp co(first+1, first); return co; } private: shared_buffer buffer_; }; // end definition rarray template class CommaOp { public: RA_INLINEF CommaOp& operator,(const T& e); // puts the next number into the array. private: RA_INLINEF CommaOp(T* ptr, T* last); T *ptr_; // points to next element to be filled T * const last_; // points to last element template friend class rarray; template friend class subrarray; }; template RA_INLINE_ int extent_given_byte_size(A a[], int i, int byte_size); //for 1d array template RA_INLINE_ int extent_given_byte_size(A a[][Z], int i, int byte_size); //for 2d array template RA_INLINE_ int extent_given_byte_size(A a[][Y][Z], int i, int byte_size); //for 3d array template RA_INLINE_ int extent_given_byte_size(A a[][X][Y][Z], int i, int byte_size); //for 4d array template RA_INLINE_ int extent_given_byte_size(A a[][W][X][Y][Z], int i, int byte_size); //for 5d array template RA_INLINE_ int extent_given_byte_size(A a[][V][W][X][Y][Z], int i, int byte_size); //for 6d array template RA_INLINE_ int extent_given_byte_size(A a[][U][V][W][X][Y][Z], int i, int byte_size); //for 7d array template RA_INLINE_ int extent_given_byte_size(A a[][T][U][V][W][X][Y][Z], int i, int byte_size); //for 8d array template RA_INLINE_ int extent_given_byte_size(A a[][S][T][U][V][W][X][Y][Z], int i, int byte_size); //for 9d array template RA_INLINE_ int extent_given_byte_size(A a[][R][S][T][U][V][W][X][Y][Z], int i, int byte_size); //for 10d array template RA_INLINE_ int extent_given_byte_size(A a[][Q][R][S][T][U][V][W][X][Y][Z], int i, int byte_size); //for 11d array template RA_INLINE_ int extent_given_byte_size(const rarray& a, int i, int byte_size); // use rarray's extent function template RA_INLINE_ rarray make_rarray_given_byte_size(A a[], int byte_size); //for 1d array template RA_INLINE_ rarray make_rarray_given_byte_size(A a[][Z], int byte_size); //for 2d array template RA_INLINE_ rarray make_rarray_given_byte_size(A a[][Y][Z], int byte_size); //for 3d array template RA_INLINE_ rarray make_rarray_given_byte_size(A a[][X][Y][Z], int byte_size); //for 4d array template RA_INLINE_ rarray make_rarray_given_byte_size(A a[][W][X][Y][Z], int byte_size); //for 5d array template RA_INLINE_ rarray make_rarray_given_byte_size(A a[][V][W][X][Y][Z], int byte_size); //for 6d array template RA_INLINE_ rarray make_rarray_given_byte_size(A a[][U][V][W][X][Y][Z], int byte_size); //for 7d array template RA_INLINE_ rarray make_rarray_given_byte_size(A a[][T][U][V][W][X][Y][Z], int byte_size); //for 8d array template RA_INLINE_ rarray make_rarray_given_byte_size(A a[][S][T][U][V][W][X][Y][Z], int byte_size); //for 9d array template RA_INLINE_ rarray make_rarray_given_byte_size(A a[][R][S][T][U][V][W][X][Y][Z], int byte_size); //for 10d array template RA_INLINE_ rarray make_rarray_given_byte_size(A a[][Q][R][S][T][U][V][W][X][Y][Z], int byte_size);//for 11d array template RA_INLINE_ rarray make_rarray_given_byte_size(rarray a, int byte_size); // trivial action for rarray template rarray linspace(S x1, S x2, int n=0, bool end_incl=true) { if (n==0) { if (x2>x1) n = x2 - x1 + end_incl; else n = x1 - x2 + end_incl; } rarray x(n); for (int i = 0; i < n; i++) x[i] = x1 + ((x2-x1)*(long long int)(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 + size_t(std::ceil((b-a)/double(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((T)0, end, (T)1); } template Xrange xrange(S begin, T end) { return Xrange((T)begin, end, (T)1); } template Xrange xrange(S begin, T end, U step) { return Xrange((T)begin, end, (T)step); } } // end namespace ra #include #include template RA_INLINE_ ra::rarray::rarray() : buffer_(), shape_() {} template RA_INLINE_ ra::rarray::rarray(ra::size_type n0) : buffer_(n0), shape_({n0}, buffer_.begin()) { static_assert( R==1, "Incorrect number of dimensions in rarray constructor."); } template RA_INLINE_ ra::rarray::rarray(size_type n0,size_type n1) : buffer_(n0*n1), shape_({n0,n1}, buffer_.begin()) { static_assert( R==2, "Incorrect number of dimensions in rarray constructor."); } 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()) { static_assert( R==3, "Incorrect number of dimensions in rarray constructor."); } 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()) { static_assert( R==4, "Incorrect number of dimensions in rarray constructor."); } 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()) { static_assert( R==5, "Incorrect number of dimensions in rarray constructor."); } 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()) { static_assert( R==6, "Incorrect number of dimensions in rarray constructor."); } 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()) { static_assert( R==7, "Incorrect number of dimensions in rarray constructor."); } 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()) { static_assert( R==8, "Incorrect number of dimensions in rarray constructor."); } 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()) { static_assert( R==9, "Incorrect number of dimensions in rarray constructor."); } 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()) { static_assert( R==10, "Incorrect number of dimensions in rarray constructor."); } 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()) { static_assert( R==11, "Incorrect number of dimensions in rarray constructor."); } template RA_INLINE_ ra::rarray::rarray(T* buffer, size_type n0) : buffer_(n0, buffer), shape_({n0}, buffer) { static_assert( R==1, "Incorrect number of dimensions in rarray constructor."); } template RA_INLINE_ ra::rarray::rarray(T* buffer, size_type n0,size_type n1) : buffer_(n0*n1, buffer), shape_({n0,n1}, buffer) { static_assert( R==2, "Incorrect number of dimensions in rarray constructor."); } 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) { static_assert( R==3, "Incorrect number of dimensions in rarray constructor."); } 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) { static_assert( R==4, "Incorrect number of dimensions in rarray constructor."); } 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) { static_assert( R==5, "Incorrect number of dimensions in rarray constructor."); } 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) { static_assert( R==6, "Incorrect number of dimensions in rarray constructor."); } 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) { static_assert( R==7, "Incorrect number of dimensions in rarray constructor."); } 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) { static_assert( R==8, "Incorrect number of dimensions in rarray constructor."); } 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) { static_assert( R==9, "Incorrect number of dimensions in rarray constructor."); } 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) { static_assert( R==10, "Incorrect number of dimensions in rarray constructor."); } 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) { static_assert( R==11, "Incorrect number of dimensions in rarray constructor."); } namespace ra { RA_INLINE_ size_type mul(const size_type * x, int n) { size_type result = 1; for (int i=0;i RA_INLINE_ ra::rarray::rarray(const size_type* extent) : buffer_(mul(extent,R)), shape_((const std::array&)(*extent), buffer_.begin()) {} template RA_INLINE_ ra::rarray::rarray(T* buffer, const size_type* extent) : buffer_(mul(extent,R), buffer), shape_((const std::array&)(*extent), buffer) {} template RA_INLINEF ra::rarray::rarray(const rarray &a) : buffer_(a.buffer_), shape_(a.shape_) { } template RA_INLINEF ra::rarray::rarray(rarray&& x) : buffer_(std::move(x.buffer_)), shape_(std::move(x.shape_)) { } template RA_INLINE_ void ra::rarray::clear() { shape_ = shared_shape(); buffer_ = shared_buffer(); } template RA_INLINE_ void ra::rarray::reshape(size_type n0, RESIZE resize_allowed) { static_assert( R==1, "Incorrect number of dimensions in rarray::reshape method."); 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 RA_INLINE_ void ra::rarray::reshape(size_type n0, size_type n1, RESIZE resize_allowed) { static_assert( R==2, "Incorrect number of dimensions in rarray::reshape method."); 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 RA_INLINE_ void ra::rarray::reshape(size_type n0, size_type n1, size_type n2, RESIZE resize_allowed) { static_assert( R==3, "Incorrect number of dimensions in rarray::reshape method."); 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 RA_INLINE_ void ra::rarray::reshape(size_type n0,size_type n1,size_type n2,size_type n3, RESIZE resize_allowed) { static_assert( R==4, "Incorrect number of dimensions in rarray::reshape method."); 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 RA_INLINE_ void ra::rarray::reshape(size_type n0,size_type n1,size_type n2,size_type n3,size_type n4, RESIZE resize_allowed) { static_assert( R==5, "Incorrect number of dimensions in rarray::reshape method."); 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 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) { static_assert( R==6, "Incorrect number of dimensions in rarray::reshape method."); 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 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) { static_assert( R==7, "Incorrect number of dimensions in rarray::reshape method."); 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 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) { static_assert( R==8, "Incorrect number of dimensions in rarray::reshape method."); 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 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) { static_assert( R==9, "Incorrect number of dimensions in rarray::reshape method."); 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 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) { static_assert( R==10, "Incorrect number of dimensions in rarray::reshape method."); 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 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) { static_assert( R==11, "Incorrect number of dimensions in rarray::reshape method."); 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_CHECKORSAY(parray_!=nullptr, "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) : 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::is_clear() const { 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()); // something is wrong with relocate for some types return clone; } template RA_INLINEF ra::rarray 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 RA_INLINEF ra::rarray ra::rarray::at(size_type i) const { return const_cast*>(this)->at(i); // provisionary } template RA_INLINEF ra::rarray::operator typename PointerArray::type () { return shape_.ptrs(); // makes a[..][..] = ... work. } template RA_INLINEF ra::rarray::operator typename PointerArray::type () const { return shape_.ptrs(); // makes a[..][..] work. } template RA_INLINE_ const ra::size_type* ra::rarray::shape() const { return &(shape_.extent()[0]); } template RA_INLINE_ typename ra::rarray::parray_t ra::rarray::ptr_array() const { return shape_.ptrs(); } template RA_INLINE_ typename ra::rarray::noconst_parray_t ra::rarray::noconst_ptr_array() const { return const_cast(shape_.ptrs()); } template RA_INLINE_ typename ra::rarray& ra::rarray::const_ref() const { return (rarray&)(*this); } template RA_INLINEF ra::rarray& ra::rarray::operator=(const rarray &a) { buffer_ = a.buffer_; shape_ = a.shape_; return *this; } template RA_INLINEF ra::rarray& ra::rarray::operator=(rarray &&a) { 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 { return shape_.size(); } template RA_INLINEF T* ra::rarray::data() { return buffer_.begin(); } template RA_INLINEF const T* ra::rarray::data() const { 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() { return buffer_.begin(); } template RA_INLINEF typename ra::rarray::const_iterator ra::rarray::begin() const { return buffer_.begin(); } template RA_INLINEF typename ra::rarray::const_iterator ra::rarray::cbegin() const { return buffer_.cbegin(); } template RA_INLINEF typename ra::rarray::iterator ra::rarray::end() { return buffer_.end(); } template RA_INLINEF typename ra::rarray::const_iterator ra::rarray::end() const { return buffer_.end(); } template RA_INLINEF typename ra::rarray::const_iterator ra::rarray::cend() const { 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_INLINE_ int ra::extent_given_byte_size(A a[], int i, int byte_size) { RA_CHECKORSAY(i>=0 and i<1, "wrong dimension"); switch (i) { case 0: return byte_size/sizeof(A); default: return 1; } } template RA_INLINE_ int ra::extent_given_byte_size(A a[][Z], int i, int byte_size) { RA_CHECKORSAY(i>=0 and i<2, "wrong dimension"); switch (i) { case 0: return byte_size/sizeof(A)/Z; case 1: return Z; default: return 1; } } template RA_INLINE_ int ra::extent_given_byte_size(A a[][Y][Z], int i, int byte_size) { RA_CHECKORSAY(i>=0 and i<3, "wrong dimension"); switch (i) { case 0: return byte_size/sizeof(A)/Z/Y; case 1: return Y; case 2: return Z; default: return 1; } } template RA_INLINE_ int ra::extent_given_byte_size(A a[][X][Y][Z], int i, int byte_size) { RA_CHECKORSAY(i>=0 and i<4, "wrong dimension"); switch (i) { case 0: return byte_size/sizeof(A)/X/Z/Y; case 1: return X; case 2: return Y; case 3: return Z; default: return 1; } } template RA_INLINE_ int ra::extent_given_byte_size(A a[][W][X][Y][Z], int i, int byte_size) { RA_CHECKORSAY(i>=0 and i<5, "wrong dimension"); switch (i) { case 0: return byte_size/sizeof(A)/W/X/Z/Y; case 1: return W; case 2: return X; case 3: return Y; case 4: return Z; default: return 1; } } template RA_INLINE_ int ra::extent_given_byte_size(A a[][V][W][X][Y][Z], int i, int byte_size) { RA_CHECKORSAY(i>=0 and i<6, "wrong dimension"); switch (i) { case 0: return byte_size/sizeof(A)/V/W/X/Z/Y; case 1: return V; case 2: return W; case 3: return X; case 4: return Y; case 5: return Z; default: return 1; } } template RA_INLINE_ int ra::extent_given_byte_size(A a[][U][V][W][X][Y][Z], int i, int byte_size) { RA_CHECKORSAY(i>=0 and i<7, "wrong dimension"); switch (i) { case 0: return byte_size/sizeof(A)/U/V/W/X/Z/Y; case 1: return U; case 2: return V; case 3: return W; case 4: return X; case 5: return Y; case 6: return Z; default: return 1; } } template RA_INLINE_ int ra::extent_given_byte_size(A a[][T][U][V][W][X][Y][Z], int i, int byte_size) { RA_CHECKORSAY(i>=0 and i<8, "wrong dimension"); switch (i) { case 0: return byte_size/sizeof(A)/T/U/V/W/X/Z/Y; case 1: return T; case 2: return U; case 3: return V; case 4: return W; case 5: return X; case 6: return Y; case 7: return Z; default: return 1; } } template RA_INLINE_ int ra::extent_given_byte_size(A a[][S][T][U][V][W][X][Y][Z], int i, int byte_size) { RA_CHECKORSAY(i>=0 and i<9, "wrong dimension"); switch (i) { case 0: return byte_size/sizeof(A)/S/T/U/V/W/X/Z/Y; case 1: return S; case 2: return T; case 3: return U; case 4: return V; case 5: return W; case 6: return X; case 7: return Y; case 8: return Z; default: return 1; } } template RA_INLINE_ int ra::extent_given_byte_size(A a[][R][S][T][U][V][W][X][Y][Z], int i, int byte_size) { RA_CHECKORSAY(i>=0 and i<10, "wrong dimension"); switch (i) { case 0: return byte_size/sizeof(A)/R/S/T/U/V/W/X/Z/Y; case 1: return R; case 2: return S; case 3: return T; case 4: return U; case 5: return V; case 6: return W; case 7: return X; case 8: return Y; case 9: return Z; default: return 1; } } template RA_INLINE_ int ra::extent_given_byte_size(A a[][Q][R][S][T][U][V][W][X][Y][Z], int i, int byte_size) { RA_CHECKORSAY(i>=0 and i<11, "wrong dimension"); switch (i) { case 0: return byte_size/sizeof(A)/Q/R/S/T/U/V/W/X/Z/Y; case 1: return Q; case 2: return R; case 3: return S; case 4: return T; case 5: return U; case 6: return V; case 7: return W; case 8: return X; case 9: return Y; case 10: return Z; default: return 1; } } template RA_INLINE_ int ra::extent_given_byte_size(const ra::rarray& a, int i, int byte_size) { return a.extent(i); } template RA_INLINE_ ra::rarray ra::make_rarray_given_byte_size(A a[], int byte_size) { const int z = byte_size/sizeof(A); return ra::rarray(a,z); } template RA_INLINE_ ra::rarray ra::make_rarray_given_byte_size(A a[][Z], int byte_size) { const int y = byte_size/sizeof(A)/Z; return ra::rarray(*a,y,Z); } template RA_INLINE_ ra::rarray ra::make_rarray_given_byte_size(A a[][Y][Z], int byte_size) { const int x = byte_size/sizeof(A)/Z/Y; return ra::rarray(**a,x,Y,Z); } template RA_INLINE_ ra::rarray ra::make_rarray_given_byte_size(A a[][X][Y][Z], int byte_size) { const int w = byte_size/sizeof(A)/X/Z/Y; return ra::rarray(***a,w,X,Y,Z); } template RA_INLINE_ ra::rarray ra::make_rarray_given_byte_size(A a[][W][X][Y][Z], int byte_size) { const int v = byte_size/sizeof(A)/W/X/Z/Y; return ra::rarray(****a,v,W,X,Y,Z); } template RA_INLINE_ ra::rarray ra::make_rarray_given_byte_size(A a[][V][W][X][Y][Z], int byte_size) { const int u = byte_size/sizeof(A)/V/W/X/Z/Y; return ra::rarray(*****a,u,V,W,X,Y,Z); } template RA_INLINE_ ra::rarray ra::make_rarray_given_byte_size(A a[][U][V][W][X][Y][Z], int byte_size) { const int t = byte_size/sizeof(A)/U/V/W/X/Z/Y; return ra::rarray(******a,t,U,V,W,X,Y,Z); } template RA_INLINE_ ra::rarray ra::make_rarray_given_byte_size(A a[][T][U][V][W][X][Y][Z], int byte_size) { const int s = byte_size/sizeof(A)/T/U/V/W/X/Z/Y; return ra::rarray(*******a,s,T,U,V,W,X,Y,Z); } template RA_INLINE_ ra::rarray ra::make_rarray_given_byte_size(A a[][S][T][U][V][W][X][Y][Z], int byte_size) { const int r = byte_size/sizeof(A)/S/T/U/V/W/X/Z/Y; return ra::rarray(********a,r,S,T,U,V,W,X,Y,Z); } template RA_INLINE_ ra::rarray ra::make_rarray_given_byte_size(A a[][R][S][T][U][V][W][X][Y][Z], int byte_size) { const int q = byte_size/sizeof(A)/R/S/T/U/V/W/X/Z/Y; return ra::rarray(*********a,q,R,S,T,U,V,W,X,Y,Z); } template RA_INLINE_ ra::rarray ra::make_rarray_given_byte_size(A a[][Q][R][S][T][U][V][W][X][Y][Z], int byte_size) { const int p = byte_size/sizeof(A)/Q/R/S/T/U/V/W/X/Z/Y; return ra::rarray(**********a,p,Q,R,S,T,U,V,W,X,Y,Z); } template RA_INLINE_ ra::rarray ra::make_rarray_given_byte_size(ra::rarray a, int byte_size) { return a; } #undef RA_CHECKORSAY #undef RA_INLINE #undef RA_INLINEF #undef RA_INLINE_ #define EXTENT(A,I) ra::extent_given_byte_size(A,I,sizeof(A)) #define RARRAY(A) ra::make_rarray_given_byte_size(A,sizeof(A)) #define INDEX(A,X,I) RARRAY(A).index(X,I) #define as_rarray(A) ra::make_rarray_given_byte_size(A,sizeof(A)) 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