1 /* This file is part of the Vc library. {{{
2 Copyright © 2015 Matthias Kretz <kretz@kde.org>
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.
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.
27 //===---------------------------- array -----------------------------------===//
29 // The LLVM Compiler Infrastructure
31 // This file is dual licensed under the MIT and the University of Illinois Open
32 // Source Licenses. See LICENSE.TXT for details.
34 //===----------------------------------------------------------------------===//
36 #ifndef VC_INCLUDE_VC_ARRAY_
37 #define VC_INCLUDE_VC_ARRAY_
39 #include <type_traits>
45 #include "common/subscript.h"
47 namespace Vc_VERSIONED_NAMESPACE
49 template <class T, size_t Size> struct array {
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;
64 value_type elems_[Size > 0 ? Size : 1];
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 &>()))
70 std::swap_ranges(elems_, elems_ + Size, a_.elems_);
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
81 return const_reverse_iterator(end());
83 reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
84 const_reverse_iterator rend() const noexcept
86 return const_reverse_iterator(begin());
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(); }
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; }
98 reference operator[](size_type n_) { return elems_[n_]; }
99 constexpr const_reference operator[](size_type n_) const { return elems_[n_]; }
102 * \name Data-Parallel Subscripting for Gather & Scatter
105 template <typename I>
106 Vc_ALWAYS_INLINE auto operator[](I&& arg_)
107 -> decltype(subscript_operator(*this, std::forward<I>(arg_)))
109 return subscript_operator(*this, std::forward<I>(arg_));
112 template <typename I>
113 Vc_ALWAYS_INLINE auto operator[](I&& arg_) const
114 -> decltype(subscript_operator(*this, std::forward<I>(arg_)))
116 return subscript_operator(*this, std::forward<I>(arg_));
120 reference at(size_type n_);
121 constexpr const_reference at(size_type n_) const;
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_; }
131 template <class T, size_t Size>
132 typename array<T, Size>::reference array<T, Size>::at(size_type n_)
135 throw std::out_of_range("array::at");
140 template <class T, size_t Size>
141 constexpr typename array<T, Size>::const_reference array<T, Size>::at(size_type n_) const
143 return n_ >= Size ? (throw std::out_of_range("array::at"), elems_[0]) : elems_[n_];
146 template <class T, size_t Size>
147 inline bool operator==(const array<T, Size>& x_, const array<T, Size>& y_)
149 return std::equal(x_.elems_, x_.elems_ + Size, y_.elems_);
152 template <class T, size_t Size>
153 inline bool operator!=(const array<T, Size>& x_, const array<T, Size>& y_)
158 template <class T, size_t Size>
159 inline bool operator<(const array<T, Size>& x_, const array<T, Size>& y_)
161 return std::lexicographical_compare(x_.elems_, x_.elems_ + Size, y_.elems_,
165 template <class T, size_t Size>
166 inline bool operator>(const array<T, Size>& x_, const array<T, Size>& y_)
171 template <class T, size_t Size>
172 inline bool operator<=(const array<T, Size>& x_, const array<T, Size>& y_)
177 template <class T, size_t Size>
178 inline bool operator>=(const array<T, Size>& x_, const array<T, Size>& y_)
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.
188 template <typename T, std::size_t N>
189 inline auto begin(array<T, N>& arr) -> decltype(arr.begin())
193 template <typename T, std::size_t N>
194 inline auto begin(const array<T, N>& arr) -> decltype(arr.begin())
198 template <typename T, std::size_t N>
199 inline auto end(array<T, N>& arr) -> decltype(arr.end())
203 template <typename T, std::size_t N>
204 inline auto end(const array<T, N>& arr) -> decltype(arr.end())
212 template <typename T, std::size_t N>
213 struct has_no_allocated_data_impl<Vc::array<T, N>> : public std::true_type
216 template <typename T, std::size_t N>
217 struct has_contiguous_storage_impl<Vc::array<T, N>> : public std::true_type
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, "");
231 } // namespace Traits
236 template <class T, size_t Size>
239 // MSVC fails to do SFINAE correctly and gets totally confused:
240 // error C2433: 'type': 'inline' not permitted on data declarations
241 // error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
242 // error C2061: syntax error: identifier 'swap'
245 typename enable_if<is_same<void, decltype(swap(declval<T&>(), declval<T&>()))>::value,
248 swap(const Vc::array<T, Size>& x_,
249 const Vc::array<T, Size>& y_) noexcept(swap(declval<T&>(), declval<T&>()))
254 template <class T, size_t Size>
255 class tuple_size<Vc::array<T, Size>> : public integral_constant<size_t, Size>
259 template <size_t I, class T, size_t Size> class tuple_element<I, Vc::array<T, Size>>
265 template <size_t I, class T, size_t Size>
266 inline constexpr typename std::enable_if<(I < Size), T&>::type get(
267 Vc::array<T, Size>& a_) noexcept
272 template <size_t I, class T, size_t Size>
273 inline constexpr typename std::enable_if<(I < Size), const T&>::type get(
274 const Vc::array<T, Size>& a_) noexcept
279 template <size_t I, class T, size_t Size>
280 inline constexpr typename std::enable_if<(I < Size), T&&>::type get(
281 Vc::array<T, Size>&& a_) noexcept
283 return std::move(a_.elems_[I]);
287 #endif // VC_INCLUDE_VC_ARRAY_
289 // vim: ft=cpp foldmethod=marker