Vc  1.0.0-dev
SIMD Vector Classes for C++
array
1 /* This file is part of the Vc library. {{{
2 Copyright © 2015 Matthias Kretz <kretz@kde.org>
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6  * Redistributions of source code must retain the above copyright
7  notice, this list of conditions and the following disclaimer.
8  * Redistributions in binary form must reproduce the above copyright
9  notice, this list of conditions and the following disclaimer in the
10  documentation and/or other materials provided with the distribution.
11  * Neither the names of contributing organizations nor the
12  names of its contributors may be used to endorse or promote products
13  derived from this software without specific prior written permission.
14 
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
19 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 }}}*/
27 //===---------------------------- array -----------------------------------===//
28 //
29 // The LLVM Compiler Infrastructure
30 //
31 // This file is dual licensed under the MIT and the University of Illinois Open
32 // Source Licenses. See LICENSE.TXT for details.
33 //
34 //===----------------------------------------------------------------------===//
35 
36 #ifndef VC_INCLUDE_VC_ARRAY_
37 #define VC_INCLUDE_VC_ARRAY_
38 
39 #include <type_traits>
40 #include <utility>
41 #include <iterator>
42 #include <algorithm>
43 #include <stdexcept>
44 
45 #include "common/subscript.h"
46 
47 namespace Vc_VERSIONED_NAMESPACE
48 {
49 template <class T, size_t Size> struct array {
50  // types:
51  typedef array self_;
52  typedef T value_type;
53  typedef value_type& reference;
54  typedef const value_type& const_reference;
55  typedef value_type* iterator;
56  typedef const value_type* const_iterator;
57  typedef value_type* pointer;
58  typedef const value_type* const_pointer;
59  typedef size_t size_type;
60  typedef ptrdiff_t difference_type;
61  typedef std::reverse_iterator<iterator> reverse_iterator;
62  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
63 
64  value_type elems_[Size > 0 ? Size : 1];
65 
66  // No explicit construct/copy/destroy for aggregate type
67  void fill(const value_type& u_) { std::fill_n(elems_, Size, u_); }
68  void swap(array& a_) noexcept(std::swap(std::declval<T &>(), std::declval<T &>()))
69  {
70  std::swap_ranges(elems_, elems_ + Size, a_.elems_);
71  }
72 
73  // iterators:
74  iterator begin() noexcept { return iterator(elems_); }
75  const_iterator begin() const noexcept { return const_iterator(elems_); }
76  iterator end() noexcept { return iterator(elems_ + Size); }
77  const_iterator end() const noexcept { return const_iterator(elems_ + Size); }
78  reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
79  const_reverse_iterator rbegin() const noexcept
80  {
81  return const_reverse_iterator(end());
82  }
83  reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
84  const_reverse_iterator rend() const noexcept
85  {
86  return const_reverse_iterator(begin());
87  }
88 
89  const_iterator cbegin() const noexcept { return begin(); }
90  const_iterator cend() const noexcept { return end(); }
91  const_reverse_iterator crbegin() const noexcept { return rbegin(); }
92  const_reverse_iterator crend() const noexcept { return rend(); }
93  // capacity:
94  constexpr size_type size() const noexcept { return Size; }
95  constexpr size_type max_size() const noexcept { return Size; }
96  constexpr bool empty() const noexcept { return Size == 0; }
97  // element access:
98  reference operator[](size_type n_) { return elems_[n_]; }
99  constexpr const_reference operator[](size_type n_) const { return elems_[n_]; }
100 
101  /**
102  * \name Data-Parallel Subscripting for Gather & Scatter
103  */
104  ///@{
105  template <typename I>
106  Vc_ALWAYS_INLINE auto operator[](I&& arg__)
107  -> decltype(subscript_operator(*this, std::forward<I>(arg__)))
108  {
109  return subscript_operator(*this, std::forward<I>(arg__));
110  }
111 
112  template <typename I>
113  Vc_ALWAYS_INLINE auto operator[](I&& arg__) const
114  -> decltype(subscript_operator(*this, std::forward<I>(arg__)))
115  {
116  return subscript_operator(*this, std::forward<I>(arg__));
117  }
118  ///@}
119 
120  reference at(size_type n_);
121  constexpr const_reference at(size_type n_) const;
122 
123  reference front() { return elems_[0]; }
124  constexpr const_reference front() const { return elems_[0]; }
125  reference back() { return elems_[Size > 0 ? Size - 1 : 0]; }
126  constexpr const_reference back() const { return elems_[Size > 0 ? Size - 1 : 0]; }
127  value_type* data() noexcept { return elems_; }
128  const value_type* data() const noexcept { return elems_; }
129 };
130 
131 template <class T, size_t Size>
132 typename array<T, Size>::reference array<T, Size>::at(size_type n_)
133 {
134  if (n_ >= Size) {
135  throw std::out_of_range("array::at");
136  }
137  return elems_[n_];
138 }
139 
140 template <class T, size_t Size>
141 constexpr typename array<T, Size>::const_reference array<T, Size>::at(size_type n_) const
142 {
143  return n_ >= Size ? (throw std::out_of_range("array::at"), elems_[0]) : elems_[n_];
144 }
145 
146 template <class T, size_t Size>
147 inline bool operator==(const array<T, Size>& x_, const array<T, Size>& y_)
148 {
149  return std::equal(x_.elems_, x_.elems_ + Size, y_.elems_);
150 }
151 
152 template <class T, size_t Size>
153 inline bool operator!=(const array<T, Size>& x_, const array<T, Size>& y_)
154 {
155  return !(x_ == y_);
156 }
157 
158 template <class T, size_t Size>
159 inline bool operator<(const array<T, Size>& x_, const array<T, Size>& y_)
160 {
161  return std::lexicographical_compare(x_.elems_, x_.elems_ + Size, y_.elems_,
162  y_.elems_ + Size);
163 }
164 
165 template <class T, size_t Size>
166 inline bool operator>(const array<T, Size>& x_, const array<T, Size>& y_)
167 {
168  return y_ < x_;
169 }
170 
171 template <class T, size_t Size>
172 inline bool operator<=(const array<T, Size>& x_, const array<T, Size>& y_)
173 {
174  return !(y_ < x_);
175 }
176 
177 template <class T, size_t Size>
178 inline bool operator>=(const array<T, Size>& x_, const array<T, Size>& y_)
179 {
180  return !(x_ < y_);
181 }
182 
183 /**\name non-member begin & end
184  * Implement the non-member begin & end functions in the %Vc namespace so that ADL works
185  * and `begin(some_vc_array)` always works.
186  */
187 ///@{
188 template <typename T, std::size_t N>
189 inline auto begin(array<T, N>& arr) -> decltype(arr.begin())
190 {
191  return arr.begin();
192 }
193 template <typename T, std::size_t N>
194 inline auto begin(const array<T, N>& arr) -> decltype(arr.begin())
195 {
196  return arr.begin();
197 }
198 template <typename T, std::size_t N>
199 inline auto end(array<T, N>& arr) -> decltype(arr.end())
200 {
201  return arr.end();
202 }
203 template <typename T, std::size_t N>
204 inline auto end(const array<T, N>& arr) -> decltype(arr.end())
205 {
206  return arr.end();
207 }
208 ///@}
209 
210 namespace Traits
211 {
212 template <typename T, std::size_t N>
213 struct has_no_allocated_data_impl<Vc::array<T, N>> : public std::true_type
214 {
215 };
216 template <typename T, std::size_t N>
217 struct has_contiguous_storage_impl<Vc::array<T, N>> : public std::true_type
218 {
219 };
220 
221 static_assert(has_no_allocated_data<const volatile Vc::array<int, 256> &>::value, "");
222 static_assert(has_no_allocated_data<const volatile Vc::array<int, 256>>::value, "");
223 static_assert(has_no_allocated_data<volatile Vc::array<int, 256> &>::value, "");
224 static_assert(has_no_allocated_data<volatile Vc::array<int, 256>>::value, "");
225 static_assert(has_no_allocated_data<const Vc::array<int, 256> &>::value, "");
226 static_assert(has_no_allocated_data<const Vc::array<int, 256>>::value, "");
227 static_assert(has_no_allocated_data<Vc::array<int, 256>>::value, "");
228 static_assert(has_no_allocated_data<Vc::array<int, 256> &>::value, "");
229 static_assert(has_no_allocated_data<Vc::array<int, 256> &&>::value, "");
230 
231 } // namespace Traits
232 } // namespace Vc
233 
234 namespace std
235 {
236 template <class T, size_t Size>
237 inline
238  typename enable_if<is_same<void, decltype(swap(declval<T&>(), declval<T&>()))>::value,
239  void>::type
240  swap(const Vc::array<T, Size>& x_,
241  const Vc::array<T, Size>& y_) noexcept(swap(declval<T&>(), declval<T&>()))
242 {
243  x_.swap(y_);
244 }
245 
246 template <class T, size_t Size>
247 class tuple_size<Vc::array<T, Size>> : public integral_constant<size_t, Size>
248 {
249 };
250 
251 template <size_t I, class T, size_t Size> class tuple_element<I, Vc::array<T, Size>>
252 {
253 public:
254  typedef T type;
255 };
256 
257 template <size_t I, class T, size_t Size>
258 inline constexpr typename std::enable_if<(I < Size), T&>::type get(
259  Vc::array<T, Size>& a_) noexcept
260 {
261  return a_.elems_[I];
262 }
263 
264 template <size_t I, class T, size_t Size>
265 inline constexpr typename std::enable_if<(I < Size), const T&>::type get(
266  const Vc::array<T, Size>& a_) noexcept
267 {
268  return a_.elems_[I];
269 }
270 
271 template <size_t I, class T, size_t Size>
272 inline constexpr typename std::enable_if<(I < Size), T&&>::type get(
273  Vc::array<T, Size>&& a_) noexcept
274 {
275  return std::move(a_.elems_[I]);
276 }
277 } // namespace std
278 
279 #endif // VC_INCLUDE_VC_ARRAY_
280 
281 // vim: ft=cpp foldmethod=marker