Fix incorrect FLT_MIN use
[blender.git] / intern / cycles / util / util_vector.h
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef __UTIL_VECTOR_H__
18 #define __UTIL_VECTOR_H__
19
20 /* Vector */
21
22 #include <cassert>
23 #include <cstring>
24 #include <vector>
25
26 #include "util_aligned_malloc.h"
27 #include "util_guarded_allocator.h"
28 #include "util_types.h"
29
30 CCL_NAMESPACE_BEGIN
31
32 /* Vector
33  *
34  * Own subclass-ed vestion of std::vector. Subclass is needed because:
35  *
36  * - Use own allocator which keeps track of used/peak memory.
37  *
38  * - Have method to ensure capacity is re-set to 0.
39  */
40 template<typename value_type,
41          typename allocator_type = GuardedAllocator<value_type> >
42 class vector : public std::vector<value_type, allocator_type>
43 {
44 public:
45         /* Default constructor. */
46         explicit vector() : std::vector<value_type, allocator_type>() {  }
47
48         /* Fill constructor. */
49         explicit vector(size_t n, const value_type& val = value_type())
50                 : std::vector<value_type, allocator_type>(n, val) {  }
51
52         /* Range constructor. */
53         template <class InputIterator>
54         vector(InputIterator first, InputIterator last)
55                 : std::vector<value_type, allocator_type>(first, last) {  }
56
57         /* Copy constructor. */
58         vector(const vector &x) : std::vector<value_type, allocator_type>(x) {  }
59
60         void shrink_to_fit(void)
61         {
62 #if __cplusplus < 201103L
63                 vector<value_type>().swap(*this);
64 #else
65                 std::vector<value_type, allocator_type>::shrink_to_fit();
66 #endif
67         }
68
69         void free_memory(void)
70         {
71                 std::vector<value_type, allocator_type>::resize(0);
72                 shrink_to_fit();
73         }
74
75         /* Some external API might demand working with std::vector. */
76         operator std::vector<value_type>()
77         {
78                 return std::vector<value_type>(this->begin(), this->end());
79         }
80 };
81
82 /* Array
83  *
84  * Simplified version of vector, serving multiple purposes:
85  * - somewhat faster in that it does not clear memory on resize/alloc,
86  *   this was actually showing up in profiles quite significantly. it
87  *   also does not run any constructors/destructors
88  * - if this is used, we are not tempted to use inefficient operations
89  * - aligned allocation for SSE data types */
90
91 template<typename T, size_t alignment = 16>
92 class array
93 {
94 public:
95         array()
96         : data_(NULL),
97           datasize_(0),
98           capacity_(0)
99         {}
100
101         array(size_t newsize)
102         {
103                 if(newsize == 0) {
104                         data_ = NULL;
105                         datasize_ = 0;
106                         capacity_ = 0;
107                 }
108                 else {
109                         data_ = mem_allocate(newsize);
110                         datasize_ = newsize;
111                         capacity_ = datasize_;
112                 }
113         }
114
115         array(const array& from)
116         {
117                 *this = from;
118         }
119
120         array& operator=(const array& from)
121         {
122                 if(from.datasize == 0) {
123                         data_ = NULL;
124                         datasize_ = 0;
125                         capacity_ = 0;
126                 }
127                 else {
128                         data_ = mem_allocate(from.datasize);
129                         memcpy(data_, from.data, from.datasize*sizeof(T));
130                         datasize_ = from.datasize_;
131                         capacity_ = datasize_;
132                 }
133
134                 return *this;
135         }
136
137         array& operator=(const vector<T>& from)
138         {
139                 datasize_ = from.size();
140                 capacity_ = datasize_;
141                 data_ = NULL;
142
143                 if(datasize_ > 0) {
144                         data_ = mem_allocate(datasize_);
145                         memcpy(data_, &from[0], datasize_*sizeof(T));
146                 }
147
148                 return *this;
149         }
150
151         ~array()
152         {
153                 mem_free(data_, capacity_);
154         }
155
156         T* resize(size_t newsize)
157         {
158                 if(newsize == 0) {
159                         clear();
160                 }
161                 else if(newsize != datasize_) {
162                         if(newsize > capacity_) {
163                                 T *newdata = mem_allocate(newsize);
164                                 if(newdata == NULL) {
165                                         /* Allocation failed, likely out of memory. */
166                                         clear();
167                                         return NULL;
168                                 }
169                                 else if(data_ != NULL) {
170                                         memcpy(newdata, data_, ((datasize_ < newsize)? datasize_: newsize)*sizeof(T));
171                                         mem_free(data_, capacity_);
172                                 }
173                                 data_ = newdata;
174                                 capacity_ = newsize;
175                         }
176                         datasize_ = newsize;
177                 }
178                 return data_;
179         }
180
181         void clear()
182         {
183                 if(data_ != NULL) {
184                         mem_free(data_, capacity_);
185                         data_ = NULL;
186                 }
187                 datasize_ = 0;
188                 capacity_ = 0;
189         }
190
191         size_t size() const
192         {
193                 return datasize_;
194         }
195
196         T& operator[](size_t i) const
197         {
198                 assert(i < datasize_);
199                 return data_[i];
200         }
201
202         void reserve(size_t newcapacity) {
203                 if(newcapacity > capacity_) {
204                         T *newdata = mem_allocate(newcapacity);
205                         if(data_ != NULL) {
206                                 memcpy(newdata, data_, ((datasize_ < newcapacity)? datasize_: newcapacity)*sizeof(T));
207                                 mem_free(data_, capacity_);
208                         }
209                         data_ = newdata;
210                         capacity_ = newcapacity;
211                 }
212         }
213
214         size_t capacity() const {
215                 return capacity_;
216         }
217
218 protected:
219         inline T* mem_allocate(size_t N)
220         {
221                 if(N == 0) {
222                         return NULL;
223                 }
224                 T *mem = (T*)util_aligned_malloc(sizeof(T)*N, alignment);
225                 if(mem != NULL) {
226                         util_guarded_mem_alloc(sizeof(T)*N);
227                 }
228                 else {
229                         throw std::bad_alloc();
230                 }
231                 return mem;
232         }
233
234         inline void mem_free(T *mem, size_t N)
235         {
236                 if(mem != NULL) {
237                         util_guarded_mem_free(sizeof(T)*N);
238                         util_aligned_free(mem);
239                 }
240         }
241
242         T *data_;
243         size_t datasize_;
244         size_t capacity_;
245 };
246
247 CCL_NAMESPACE_END
248
249 #endif /* __UTIL_VECTOR_H__ */
250