1931fb0b1f931378b91257d13650c3dafcfdab3c
[blender.git] / intern / libmv / libmv / base / vector.h
1 // Copyright (c) 2007, 2008 libmv authors.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to
5 // deal in the Software without restriction, including without limitation the
6 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 // sell copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 // IN THE SOFTWARE.
20 //
21 // Get an aligned vector implementation. Must be included before <vector>. The
22 // Eigen guys went through some trouble to make a portable override for the
23 // fixed size vector types.
24
25 #ifndef LIBMV_BASE_VECTOR_H
26 #define LIBMV_BASE_VECTOR_H
27
28 #include <cstring>
29 #include <new>
30
31 #include <Eigen/Core>
32
33 namespace libmv {
34
35 // A simple container class, which guarantees 16 byte alignment needed for most
36 // vectorization. Don't use this container for classes that cannot be copied
37 // via memcpy.
38 // FIXME: this class has some issues:
39 // - doesn't support iterators.
40 // - impede compatibility with code using STL.
41 // - the STL already provide support for custom allocators
42 // it could be replaced with a simple
43 // template <T> class vector : std::vector<T, aligned_allocator> {} declaration
44 // provided it doesn't break code relying on libmv::vector specific behavior
45 template <typename T,
46           typename Allocator = Eigen::aligned_allocator<T> >
47 class vector {
48  public:
49   ~vector()                        { clear();                 }
50
51   vector()                         { init();                  }
52   vector(int size)                 { init(); resize(size);    }
53   vector(int size, const T & val)  {
54     init();
55     resize(size);
56     std::fill(data_, data_+size_, val); }
57
58   // Copy constructor and assignment.
59   vector(const vector<T, Allocator> &rhs) {
60     init();
61     copy(rhs);
62   }
63   vector<T, Allocator> &operator=(const vector<T, Allocator> &rhs) {
64     if (&rhs != this) {
65       copy(rhs);
66     }
67     return *this;
68   }
69
70   /// Swaps the contents of two vectors in constant time.
71   void swap(vector<T, Allocator> &other) {
72     std::swap(allocator_, other.allocator_);
73     std::swap(size_, other.size_);
74     std::swap(capacity_, other.capacity_);
75     std::swap(data_, other.data_);
76   }
77
78         T *data()            const { return data_;            }
79   int      size()            const { return size_;            }
80   int      capacity()        const { return capacity_;        }
81   const T& back()            const { return data_[size_ - 1]; }
82         T& back()                  { return data_[size_ - 1]; }
83   const T& front()           const { return data_[0];         }
84         T& front()                 { return data_[0];         }
85   const T& operator[](int n) const { return data_[n];         }
86         T& operator[](int n)       { return data_[n];         }
87   const T& at(int n)         const { return data_[n];         }
88         T& at(int n)               { return data_[n];         }
89   const T * begin()          const { return data_;            }
90   const T * end()            const { return data_+size_;      }
91         T * begin()                { return data_;            }
92         T * end()                  { return data_+size_;      }
93
94   void resize(size_t size) {
95     reserve(size);
96     if (size > size_) {
97       construct(size_, size);
98     } else if (size < size_) {
99       destruct(size, size_);
100     }
101     size_ = size;
102   }
103
104   void push_back(const T &value) {
105     if (size_ == capacity_) {
106       reserve(size_ ? 2 * size_ : 1);
107     }
108     new (&data_[size_++]) T(value);
109   }
110
111   void pop_back() {
112     resize(size_ - 1);
113   }
114
115   void clear() {
116     destruct(0, size_);
117     deallocate();
118     init();
119   }
120
121   void reserve(unsigned int size) {
122     if (size > size_) {
123       T *data = static_cast<T *>(allocate(size));
124       memcpy(data, data_, sizeof(*data)*size_);
125       allocator_.deallocate(data_, capacity_);
126       data_ = data;
127       capacity_ = size;
128     }
129   }
130
131   bool empty() {
132     return size_ == 0;
133   }
134
135  private:
136   void construct(int start, int end) {
137     for (int i = start; i < end; ++i) {
138       new (&data_[i]) T;
139     }
140   }
141   void destruct(int start, int end) {
142     for (int i = start; i < end; ++i) {
143       data_[i].~T();
144     }
145   }
146   void init() {
147     size_ = 0;
148     data_ = 0;
149     capacity_ = 0;
150   }
151
152   void *allocate(int size) {
153     return size ? allocator_.allocate(size) : 0;
154   }
155
156   void deallocate() {
157     allocator_.deallocate(data_, size_);
158     data_ = 0;
159   }
160
161   void copy(const vector<T, Allocator> &rhs) {
162     resize(rhs.size());
163     for (int i = 0; i < rhs.size(); ++i) {
164       (*this)[i] = rhs[i];
165     }
166   }
167
168   Allocator allocator_;
169   size_t size_;
170   size_t capacity_;
171   T *data_;
172 };
173
174 }  // namespace libmv
175
176 #endif  // LIBMV_BASE_VECTOR_H