Merge of itasc branch. Project files, scons and cmake should be working. Makefile...
[blender.git] / extern / Eigen2 / Eigen / NewStdVector
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2009 Gael Guennebaud <g.gael@free.fr>
5 // Copyright (C) 2009 Hauke Heibel <hauke.heibel@googlemail.com>
6 //
7 // Eigen is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Lesser General Public
9 // License as published by the Free Software Foundation; either
10 // version 3 of the License, or (at your option) any later version.
11 //
12 // Alternatively, you can redistribute it and/or
13 // modify it under the terms of the GNU General Public License as
14 // published by the Free Software Foundation; either version 2 of
15 // the License, or (at your option) any later version.
16 //
17 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
20 // GNU General Public License for more details.
21 //
22 // You should have received a copy of the GNU Lesser General Public
23 // License and a copy of the GNU General Public License along with
24 // Eigen. If not, see <http://www.gnu.org/licenses/>.
25
26 #ifndef EIGEN_STDVECTOR_MODULE_H
27 #define EIGEN_STDVECTOR_MODULE_H
28
29 #include "Core"
30 #include <vector>
31
32 namespace Eigen {
33
34 // This one is needed to prevent reimplementing the whole std::vector.
35 template <class T>
36 class aligned_allocator_indirection : public aligned_allocator<T>
37 {
38 public:
39   typedef size_t    size_type;
40   typedef ptrdiff_t difference_type;
41   typedef T*        pointer;
42   typedef const T*  const_pointer;
43   typedef T&        reference;
44   typedef const T&  const_reference;
45   typedef T         value_type;
46
47   template<class U>
48   struct rebind
49   {
50     typedef aligned_allocator_indirection<U> other;
51   };
52
53   aligned_allocator_indirection() throw() {}
54   aligned_allocator_indirection(const aligned_allocator_indirection& ) throw() : aligned_allocator<T>() {}
55   aligned_allocator_indirection(const aligned_allocator<T>& ) throw() {}
56   template<class U>
57   aligned_allocator_indirection(const aligned_allocator_indirection<U>& ) throw() {}
58   template<class U>
59   aligned_allocator_indirection(const aligned_allocator<U>& ) throw() {}
60   ~aligned_allocator_indirection() throw() {}
61 };
62
63 #ifdef _MSC_VER
64
65   // sometimes, MSVC detects, at compile time, that the argument x
66   // in std::vector::resize(size_t s,T x) won't be aligned and generate an error
67   // even if this function is never called. Whence this little wrapper.
68   #define EIGEN_WORKAROUND_MSVC_STD_VECTOR(T) Eigen::ei_workaround_msvc_std_vector<T>
69   template<typename T> struct ei_workaround_msvc_std_vector : public T
70   {
71     inline ei_workaround_msvc_std_vector() : T() {}
72     inline ei_workaround_msvc_std_vector(const T& other) : T(other) {}
73     inline operator T& () { return *static_cast<T*>(this); }
74     inline operator const T& () const { return *static_cast<const T*>(this); }
75     template<typename OtherT>
76     inline T& operator=(const OtherT& other)
77     { T::operator=(other); return *this; }
78     inline ei_workaround_msvc_std_vector& operator=(const ei_workaround_msvc_std_vector& other)
79     { T::operator=(other); return *this; }
80   };
81
82 #else
83
84   #define EIGEN_WORKAROUND_MSVC_STD_VECTOR(T) T
85
86 #endif
87
88 }
89
90 namespace std {
91
92 #define EIGEN_STD_VECTOR_SPECIALIZATION_BODY \
93   public:  \
94     typedef T value_type; \
95     typedef typename vector_base::allocator_type allocator_type; \
96     typedef typename vector_base::size_type size_type;  \
97     typedef typename vector_base::iterator iterator;  \
98     typedef typename vector_base::const_iterator const_iterator;  \
99     explicit vector(const allocator_type& a = allocator_type()) : vector_base(a) {}  \
100     template<typename InputIterator> \
101     vector(InputIterator first, InputIterator last, const allocator_type& a = allocator_type()) \
102     : vector_base(first, last, a) {} \
103     vector(const vector& c) : vector_base(c) {}  \
104     explicit vector(size_type num, const value_type& val = value_type()) : vector_base(num, val) {} \
105     vector(iterator start, iterator end) : vector_base(start, end) {}  \
106     vector& operator=(const vector& x) {  \
107       vector_base::operator=(x);  \
108       return *this;  \
109     }
110
111 template<typename T>
112 class vector<T,Eigen::aligned_allocator<T> >
113   : public vector<EIGEN_WORKAROUND_MSVC_STD_VECTOR(T),
114                   Eigen::aligned_allocator_indirection<EIGEN_WORKAROUND_MSVC_STD_VECTOR(T)> >
115 {
116   typedef vector<EIGEN_WORKAROUND_MSVC_STD_VECTOR(T),
117                  Eigen::aligned_allocator_indirection<EIGEN_WORKAROUND_MSVC_STD_VECTOR(T)> > vector_base;
118   EIGEN_STD_VECTOR_SPECIALIZATION_BODY
119
120   void resize(size_type new_size)
121   { resize(new_size, T()); }
122
123 #if defined(_VECTOR_)
124   // workaround MSVC std::vector implementation
125   void resize(size_type new_size, const value_type& x)
126   {
127     if (vector_base::size() < new_size)
128       vector_base::_Insert_n(vector_base::end(), new_size - vector_base::size(), x);
129     else if (new_size < vector_base::size())
130       vector_base::erase(vector_base::begin() + new_size, vector_base::end());
131   }
132   void push_back(const value_type& x)
133   { vector_base::push_back(x); } 
134   using vector_base::insert;  
135   iterator insert(const_iterator position, const value_type& x)
136   { return vector_base::insert(position,x); }
137   void insert(const_iterator position, size_type new_size, const value_type& x)
138   { vector_base::insert(position, new_size, x); }
139 #elif defined(_GLIBCXX_VECTOR) && EIGEN_GNUC_AT_LEAST(4,2)
140   // workaround GCC std::vector implementation
141   void resize(size_type new_size, const value_type& x)
142   {
143     if (new_size < vector_base::size())
144       vector_base::_M_erase_at_end(this->_M_impl._M_start + new_size);
145     else
146       vector_base::insert(vector_base::end(), new_size - vector_base::size(), x);
147   }
148 #elif defined(_GLIBCXX_VECTOR) && (!EIGEN_GNUC_AT_LEAST(4,1))
149   // Note that before gcc-4.1 we already have: std::vector::resize(size_type,const T&),
150   // no no need to workaround !
151   using vector_base::resize;
152 #else
153   // either GCC 4.1 or non-GCC
154   // default implementation which should always work.
155   void resize(size_type new_size, const value_type& x)
156   {
157     if (new_size < vector_base::size())
158       vector_base::erase(vector_base::begin() + new_size, vector_base::end());
159     else if (new_size > vector_base::size())
160       vector_base::insert(vector_base::end(), new_size - vector_base::size(), x);
161   }
162 #endif
163
164 };
165
166 }
167
168 #endif // EIGEN_STDVECTOR_MODULE_H