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 | |
19 | __forceinline T* begin() const { return items; }; |
20 | __forceinline T* end () const { return items+N; }; |
21 | |
22 | |
23 | /********************** Capacity ****************************/ |
24 | |
25 | __forceinline bool empty () const { return N == 0; } |
26 | __forceinline size_t size () const { return N; } |
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 | |
35 | __forceinline T& at(size_t i) { assert(i < N); return items[i]; } |
36 | __forceinline const T& at(size_t i) const { assert(i < N); return items[i]; } |
37 | |
38 | __forceinline T& front() const { assert(N > 0); return items[0]; }; |
39 | __forceinline T& back () const { assert(N > 0); return items[N-1]; }; |
40 | |
41 | __forceinline T* data() { return items; }; |
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 | |
54 | __forceinline darray_t () : M(0) {} |
55 | |
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 | |
62 | __forceinline T* begin() const { return (T*)items; }; |
63 | __forceinline T* end () const { return (T*)items+M; }; |
64 | |
65 | |
66 | /********************** Capacity ****************************/ |
67 | |
68 | __forceinline bool empty () const { return M == 0; } |
69 | __forceinline size_t size () const { return M; } |
70 | __forceinline size_t capacity () const { return N; } |
71 | __forceinline size_t max_size () const { return N; } |
72 | |
73 | void resize(size_t new_size) { |
74 | assert(new_size < max_size()); |
75 | M = new_size; |
76 | } |
77 | |
78 | /******************** Modifiers **************************/ |
79 | |
80 | __forceinline void push_back(const T& v) |
81 | { |
82 | assert(M+1 < max_size()); |
83 | items[M++] = v; |
84 | } |
85 | |
86 | __forceinline void pop_back() |
87 | { |
88 | assert(!empty()); |
89 | M--; |
90 | } |
91 | |
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 | |
101 | __forceinline T& at(size_t i) { assert(i < M); return items[i]; } |
102 | __forceinline const T& at(size_t i) const { assert(i < M); return items[i]; } |
103 | |
104 | __forceinline T& front() { assert(M > 0); return items[0]; }; |
105 | __forceinline T& back () { assert(M > 0); return items[M-1]; }; |
106 | |
107 | __forceinline T* data() { return items; }; |
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 | { |
120 | __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(size: N*sizeof(Ty),align: 64); |
127 | } |
128 | |
129 | __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__) || defined(__EMSCRIPTEN__) |
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 | { |
162 | __forceinline DynamicStackArray () |
163 | : data(&arr[0]) {} |
164 | |
165 | __forceinline ~DynamicStackArray () |
166 | { |
167 | if (!isStackAllocated()) |
168 | delete[] data; |
169 | } |
170 | |
171 | __forceinline bool isStackAllocated() const { |
172 | return data == &arr[0]; |
173 | } |
174 | |
175 | __forceinline size_t size() const |
176 | { |
177 | if (isStackAllocated()) return max_stack_elements; |
178 | else return max_total_elements; |
179 | } |
180 | |
181 | __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(M: i+1); return data[i]; } |
197 | __forceinline Ty& operator[](const unsigned i) { assert(i<max_total_elements); resize(M: i+1); return data[i]; } |
198 | |
199 | #if defined(__64BIT__) || defined(__EMSCRIPTEN__) |
200 | __forceinline Ty& operator[](const size_t i) { assert(i<max_total_elements); resize(M: i+1); return data[i]; } |
201 | #endif |
202 | |
203 | __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 | |