// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "platform.h" #include "alloc.h" namespace embree { /*! static array with static size */ template<typename T, size_t N> class array_t { public: /********************** Iterators ****************************/ __forceinline T* begin() const { return items; }; __forceinline T* end () const { return items+N; }; /********************** Capacity ****************************/ __forceinline bool empty () const { return N == 0; } __forceinline size_t size () const { return N; } __forceinline size_t max_size () const { return N; } /******************** Element access **************************/ __forceinline T& operator[](size_t i) { assert(i < N); return items[i]; } __forceinline const T& operator[](size_t i) const { assert(i < N); return items[i]; } __forceinline T& at(size_t i) { assert(i < N); return items[i]; } __forceinline const T& at(size_t i) const { assert(i < N); return items[i]; } __forceinline T& front() const { assert(N > 0); return items[0]; }; __forceinline T& back () const { assert(N > 0); return items[N-1]; }; __forceinline T* data() { return items; }; __forceinline const T* data() const { return items; }; private: T items[N]; }; /*! static array with dynamic size */ template<typename T, size_t N> class darray_t { public: __forceinline darray_t () : M(0) {} __forceinline darray_t (const T& v) : M(0) { for (size_t i=0; i<N; i++) items[i] = v; } /********************** Iterators ****************************/ __forceinline T* begin() const { return items; }; __forceinline T* end () const { return items+M; }; /********************** Capacity ****************************/ __forceinline bool empty () const { return M == 0; } __forceinline size_t size () const { return M; } __forceinline size_t capacity () const { return N; } __forceinline size_t max_size () const { return N; } void resize(size_t new_size) { assert(new_size < max_size()); M = new_size; } /******************** Modifiers **************************/ __forceinline void push_back(const T& v) { assert(M+1 < max_size()); items[M++] = v; } __forceinline void pop_back() { assert(!empty()); M--; } __forceinline void clear() { M = 0; } /******************** Element access **************************/ __forceinline T& operator[](size_t i) { assert(i < M); return items[i]; } __forceinline const T& operator[](size_t i) const { assert(i < M); return items[i]; } __forceinline T& at(size_t i) { assert(i < M); return items[i]; } __forceinline const T& at(size_t i) const { assert(i < M); return items[i]; } __forceinline T& front() const { assert(M > 0); return items[0]; }; __forceinline T& back () const { assert(M > 0); return items[M-1]; }; __forceinline T* data() { return items; }; __forceinline const T* data() const { return items; }; private: size_t M; T items[N]; }; /*! dynamic sized array that is allocated on the stack */ #define dynamic_large_stack_array(Ty,Name,N,max_stack_bytes) StackArray<Ty,max_stack_bytes> Name(N) template<typename Ty, size_t max_stack_bytes> struct __aligned(64) StackArray { __forceinline StackArray (const size_t N) : N(N) { if (N*sizeof(Ty) <= max_stack_bytes) data = &arr[0]; else data = (Ty*) alignedMalloc(N*sizeof(Ty),64); } __forceinline ~StackArray () { if (data != &arr[0]) alignedFree(data); } __forceinline operator Ty* () { return data; } __forceinline operator const Ty* () const { return data; } __forceinline Ty& operator[](const int i) { assert(i>=0 && i<N); return data[i]; } __forceinline const Ty& operator[](const int i) const { assert(i>=0 && i<N); return data[i]; } __forceinline Ty& operator[](const unsigned i) { assert(i<N); return data[i]; } __forceinline const Ty& operator[](const unsigned i) const { assert(i<N); return data[i]; } #if defined(__64BIT__) __forceinline Ty& operator[](const size_t i) { assert(i<N); return data[i]; } __forceinline const Ty& operator[](const size_t i) const { assert(i<N); return data[i]; } #endif private: Ty arr[max_stack_bytes/sizeof(Ty)]; Ty* data; size_t N; private: StackArray (const StackArray& other) DELETED; // do not implement StackArray& operator= (const StackArray& other) DELETED; // do not implement }; /*! dynamic sized array that is allocated on the stack */ template<typename Ty, size_t max_stack_elements, size_t max_total_elements> struct __aligned(64) DynamicStackArray { __forceinline DynamicStackArray () : data(&arr[0]) {} __forceinline ~DynamicStackArray () { if (!isStackAllocated()) delete[] data; } __forceinline bool isStackAllocated() const { return data == &arr[0]; } __forceinline size_t size() const { if (isStackAllocated()) return max_stack_elements; else return max_total_elements; } __forceinline void resize(size_t M) { assert(M <= max_total_elements); if (likely(M <= max_stack_elements)) return; if (likely(!isStackAllocated())) return; data = new Ty[max_total_elements]; for (size_t i=0; i<max_stack_elements; i++) data[i] = arr[i]; } __forceinline operator Ty* () { return data; } __forceinline operator const Ty* () const { return data; } __forceinline Ty& operator[](const int i) { assert(i>=0 && i<max_total_elements); resize(i+1); return data[i]; } __forceinline Ty& operator[](const unsigned i) { assert(i<max_total_elements); resize(i+1); return data[i]; } #if defined(__64BIT__) __forceinline Ty& operator[](const size_t i) { assert(i<max_total_elements); resize(i+1); return data[i]; } #endif __forceinline DynamicStackArray (const DynamicStackArray& other) : data(&arr[0]) { for (size_t i=0; i<other.size(); i++) this->operator[] (i) = other[i]; } DynamicStackArray& operator= (const DynamicStackArray& other) { for (size_t i=0; i<other.size(); i++) this->operator[] (i) = other[i]; return *this; } private: Ty arr[max_stack_elements]; Ty* data; }; }