1 // Copyright 2009-2021 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 
4 #pragma once
5 
6 #include "platform.h"
7 #include "alloc.h"
8 
9 namespace embree
10 {
11   /*! static array with static size */
12   template<typename T, size_t N>
13     class array_t
14     {
15     public:
16 
17       /********************** Iterators  ****************************/
18 
begin()19       __forceinline T* begin() const { return items; };
end()20       __forceinline T* end  () const { return items+N; };
21 
22 
23       /********************** Capacity ****************************/
24 
empty()25       __forceinline bool   empty    () const { return N == 0; }
size()26       __forceinline size_t size     () const { return N; }
max_size()27       __forceinline size_t max_size () const { return N; }
28 
29 
30       /******************** Element access **************************/
31 
32       __forceinline       T& operator[](size_t i)       { assert(i < N); return items[i]; }
33       __forceinline const T& operator[](size_t i) const { assert(i < N); return items[i]; }
34 
at(size_t i)35       __forceinline       T& at(size_t i)       { assert(i < N); return items[i]; }
at(size_t i)36       __forceinline const T& at(size_t i) const { assert(i < N); return items[i]; }
37 
front()38       __forceinline T& front() const { assert(N > 0); return items[0]; };
back()39       __forceinline T& back () const { assert(N > 0); return items[N-1]; };
40 
data()41       __forceinline       T* data()       { return items; };
data()42       __forceinline const T* data() const { return items; };
43 
44     private:
45       T items[N];
46     };
47 
48   /*! static array with dynamic size */
49   template<typename T, size_t N>
50     class darray_t
51     {
52     public:
53 
darray_t()54       __forceinline darray_t () : M(0) {}
55 
darray_t(const T & v)56       __forceinline darray_t (const T& v) : M(0) {
57         for (size_t i=0; i<N; i++) items[i] = v;
58       }
59 
60       /********************** Iterators  ****************************/
61 
begin()62       __forceinline T* begin() const { return (T*)items; };
end()63       __forceinline T* end  () const { return (T*)items+M; };
64 
65 
66       /********************** Capacity ****************************/
67 
empty()68       __forceinline bool   empty    () const { return M == 0; }
size()69       __forceinline size_t size     () const { return M; }
capacity()70       __forceinline size_t capacity () const { return N; }
max_size()71       __forceinline size_t max_size () const { return N; }
72 
resize(size_t new_size)73       void resize(size_t new_size) {
74         assert(new_size < max_size());
75         M = new_size;
76       }
77 
78       /******************** Modifiers **************************/
79 
push_back(const T & v)80       __forceinline void push_back(const T& v)
81       {
82         assert(M+1 < max_size());
83         items[M++] = v;
84       }
85 
pop_back()86       __forceinline void pop_back()
87       {
88         assert(!empty());
89         M--;
90       }
91 
clear()92       __forceinline void clear() {
93         M = 0;
94       }
95 
96       /******************** Element access **************************/
97 
98       __forceinline       T& operator[](size_t i)       { assert(i < M); return items[i]; }
99       __forceinline const T& operator[](size_t i) const { assert(i < M); return items[i]; }
100 
at(size_t i)101       __forceinline       T& at(size_t i)       { assert(i < M); return items[i]; }
at(size_t i)102       __forceinline const T& at(size_t i) const { assert(i < M); return items[i]; }
103 
front()104       __forceinline T& front() { assert(M > 0); return items[0]; };
back()105       __forceinline T& back () { assert(M > 0); return items[M-1]; };
106 
data()107       __forceinline       T* data()       { return items; };
data()108       __forceinline const T* data() const { return items; };
109 
110     private:
111       size_t M;
112       T items[N];
113     };
114 
115   /*! dynamic sized array that is allocated on the stack */
116 #define dynamic_large_stack_array(Ty,Name,N,max_stack_bytes) StackArray<Ty,max_stack_bytes> Name(N)
117   template<typename Ty, size_t max_stack_bytes>
118     struct __aligned(64) StackArray
119   {
StackArrayStackArray120     __forceinline StackArray (const size_t N)
121       : N(N)
122     {
123       if (N*sizeof(Ty) <= max_stack_bytes)
124         data = &arr[0];
125       else
126         data = (Ty*) alignedMalloc(N*sizeof(Ty),64);
127     }
128 
~StackArrayStackArray129     __forceinline ~StackArray () {
130       if (data != &arr[0]) alignedFree(data);
131     }
132 
133     __forceinline operator       Ty* ()       { return data; }
134     __forceinline operator const Ty* () const { return data; }
135 
136     __forceinline       Ty& operator[](const int i)       { assert(i>=0 && i<N); return data[i]; }
137     __forceinline const Ty& operator[](const int i) const { assert(i>=0 && i<N); return data[i]; }
138 
139     __forceinline       Ty& operator[](const unsigned i)       { assert(i<N); return data[i]; }
140     __forceinline const Ty& operator[](const unsigned i) const { assert(i<N); return data[i]; }
141 
142 #if defined(__64BIT__)
143     __forceinline       Ty& operator[](const size_t i)       { assert(i<N); return data[i]; }
144     __forceinline const Ty& operator[](const size_t i) const { assert(i<N); return data[i]; }
145 #endif
146 
147   private:
148     Ty arr[max_stack_bytes/sizeof(Ty)];
149     Ty* data;
150     size_t N;
151 
152   private:
153     StackArray (const StackArray& other) DELETED; // do not implement
154     StackArray& operator= (const StackArray& other) DELETED; // do not implement
155 
156   };
157 
158   /*! dynamic sized array that is allocated on the stack */
159   template<typename Ty, size_t max_stack_elements, size_t max_total_elements>
160     struct __aligned(64) DynamicStackArray
161   {
DynamicStackArrayDynamicStackArray162     __forceinline DynamicStackArray ()
163       : data(&arr[0]) {}
164 
~DynamicStackArrayDynamicStackArray165     __forceinline ~DynamicStackArray ()
166     {
167       if (!isStackAllocated())
168         delete[] data;
169     }
170 
isStackAllocatedDynamicStackArray171     __forceinline bool isStackAllocated() const {
172       return data == &arr[0];
173     }
174 
sizeDynamicStackArray175     __forceinline size_t size() const
176     {
177       if (isStackAllocated()) return max_stack_elements;
178       else return max_total_elements;
179     }
180 
resizeDynamicStackArray181     __forceinline void resize(size_t M)
182     {
183       assert(M <= max_total_elements);
184       if (likely(M <= max_stack_elements)) return;
185       if (likely(!isStackAllocated())) return;
186 
187       data = new Ty[max_total_elements];
188 
189       for (size_t i=0; i<max_stack_elements; i++)
190         data[i] = arr[i];
191     }
192 
193     __forceinline operator       Ty* ()       { return data; }
194     __forceinline operator const Ty* () const { return data; }
195 
196     __forceinline       Ty& operator[](const int i)      { assert(i>=0 && i<max_total_elements); resize(i+1); return data[i]; }
197     __forceinline       Ty& operator[](const unsigned i) { assert(i<max_total_elements); resize(i+1); return data[i]; }
198 
199 #if defined(__64BIT__)
200     __forceinline       Ty& operator[](const size_t i) { assert(i<max_total_elements); resize(i+1); return data[i]; }
201 #endif
202 
DynamicStackArrayDynamicStackArray203     __forceinline DynamicStackArray (const DynamicStackArray& other)
204       : data(&arr[0])
205     {
206       for (size_t i=0; i<other.size(); i++)
207         this->operator[] (i) = other[i];
208     }
209 
210     DynamicStackArray& operator= (const DynamicStackArray& other)
211     {
212       for (size_t i=0; i<other.size(); i++)
213         this->operator[] (i) = other[i];
214 
215       return *this;
216     }
217 
218   private:
219     Ty arr[max_stack_elements];
220     Ty* data;
221   };
222 }
223