Warning, /include/Vc/array is written in an unsupported language. File is not indexed.
0001 /* This file is part of the Vc library. {{{
0002 Copyright © 2015 Matthias Kretz <kretz@kde.org>
0003
0004 Redistribution and use in source and binary forms, with or without
0005 modification, are permitted provided that the following conditions are met:
0006 * Redistributions of source code must retain the above copyright
0007 notice, this list of conditions and the following disclaimer.
0008 * Redistributions in binary form must reproduce the above copyright
0009 notice, this list of conditions and the following disclaimer in the
0010 documentation and/or other materials provided with the distribution.
0011 * Neither the names of contributing organizations nor the
0012 names of its contributors may be used to endorse or promote products
0013 derived from this software without specific prior written permission.
0014
0015 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
0016 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
0017 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0018 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
0019 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
0020 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
0021 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0022 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0023 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0024 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0025
0026 }}}*/
0027 //===---------------------------- array -----------------------------------===//
0028 //
0029 // The LLVM Compiler Infrastructure
0030 //
0031 // This file is dual licensed under the MIT and the University of Illinois Open
0032 // Source Licenses. See LICENSE.TXT for details.
0033 //
0034 //===----------------------------------------------------------------------===//
0035
0036 #ifndef VC_INCLUDE_VC_ARRAY_
0037 #define VC_INCLUDE_VC_ARRAY_
0038
0039 #include <type_traits>
0040 #include <utility>
0041 #include <iterator>
0042 #include <algorithm>
0043 #include <stdexcept>
0044
0045 #include "common/subscript.h"
0046
0047 namespace Vc_VERSIONED_NAMESPACE
0048 {
0049 /**
0050 * \ingroup Containers
0051 * This is `std::array` with additional subscript operators supporting gather and scatter operations.
0052 *
0053 * The [std::array](https://en.cppreference.com/w/cpp/container/array) documentation applies.
0054 *
0055 * Gathers from structured data (AoS: arrays of struct) are possible via a special
0056 * subscript operator.
0057 * Example:
0058 * \code
0059 * Vc::array<float, 100> data;
0060 * std::iota(data.begin(), data.end(), 0.f); // fill with values 0, 1, 2, ...
0061 * auto indexes = float_v::IndexType::IndexesFromZero();
0062 * float_v gathered = data[indexes]; // gathered == [0, 1, 2, ...]
0063 * \endcode
0064 *
0065 * This also works for gathers into arrays of structures:
0066 * \code
0067 * struct Point { float x, y, z; };
0068 * Vc::array<Point, 100> points;
0069 * // fill points ...
0070 * auto indexes = float_v::IndexType::IndexesFromZero();
0071 * float_v xs = data[indexes][&Point::x]; // [points[0].x, points[1].x, points[2].x, ...]
0072 * float_v ys = data[indexes][&Point::y]; // [points[0].y, points[1].y, points[2].y, ...]
0073 * float_v zs = data[indexes][&Point::z]; // [points[0].z, points[1].z, points[2].z, ...]
0074 * \endcode
0075 *
0076 * Arrays may also be nested:
0077 * \code:
0078 * Vc::array<Vc::array<float, 3>, 100> points;
0079 * // fill points ...
0080 * auto indexes = float_v::IndexType::IndexesFromZero();
0081 * float_v xs = data[indexes][0]; // [points[0][0], points[1][0], points[2][0], ...]
0082 * float_v ys = data[indexes][1]; // [points[0][1], points[1][1], points[2][1], ...]
0083 * float_v zs = data[indexes][2]; // [points[0][2], points[1][2], points[2][2], ...]
0084 * \endcode
0085 */
0086 template <class T, size_t Size> struct array {
0087 // types:
0088 typedef array self_;
0089 typedef T value_type;
0090 typedef value_type& reference;
0091 typedef const value_type& const_reference;
0092 typedef value_type* iterator;
0093 typedef const value_type* const_iterator;
0094 typedef value_type* pointer;
0095 typedef const value_type* const_pointer;
0096 typedef size_t size_type;
0097 typedef ptrdiff_t difference_type;
0098 typedef std::reverse_iterator<iterator> reverse_iterator;
0099 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
0100
0101 value_type elems_[Size > 0 ? Size : 1];
0102
0103 // No explicit construct/copy/destroy for aggregate type
0104 void fill(const value_type& u_) { std::fill_n(elems_, Size, u_); }
0105 void swap(array& a_) noexcept(std::swap(std::declval<T &>(), std::declval<T &>()))
0106 {
0107 std::swap_ranges(elems_, elems_ + Size, a_.elems_);
0108 }
0109
0110 // iterators:
0111 iterator begin() noexcept { return iterator(elems_); }
0112 const_iterator begin() const noexcept { return const_iterator(elems_); }
0113 iterator end() noexcept { return iterator(elems_ + Size); }
0114 const_iterator end() const noexcept { return const_iterator(elems_ + Size); }
0115 reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
0116 const_reverse_iterator rbegin() const noexcept
0117 {
0118 return const_reverse_iterator(end());
0119 }
0120 reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
0121 const_reverse_iterator rend() const noexcept
0122 {
0123 return const_reverse_iterator(begin());
0124 }
0125
0126 const_iterator cbegin() const noexcept { return begin(); }
0127 const_iterator cend() const noexcept { return end(); }
0128 const_reverse_iterator crbegin() const noexcept { return rbegin(); }
0129 const_reverse_iterator crend() const noexcept { return rend(); }
0130 // capacity:
0131 constexpr size_type size() const noexcept { return Size; }
0132 constexpr size_type max_size() const noexcept { return Size; }
0133 constexpr bool empty() const noexcept { return Size == 0; }
0134 // element access:
0135 reference operator[](size_type n_) { return elems_[n_]; }
0136 constexpr const_reference operator[](size_type n_) const { return elems_[n_]; }
0137
0138 /**
0139 * \name Data-Parallel Subscripting for Gather & Scatter
0140 */
0141 ///@{
0142 template <typename I>
0143 Vc_ALWAYS_INLINE auto operator[](I&& arg_)
0144 -> decltype(subscript_operator(*this, std::forward<I>(arg_)))
0145 {
0146 return subscript_operator(*this, std::forward<I>(arg_));
0147 }
0148
0149 template <typename I>
0150 Vc_ALWAYS_INLINE auto operator[](I&& arg_) const
0151 -> decltype(subscript_operator(*this, std::forward<I>(arg_)))
0152 {
0153 return subscript_operator(*this, std::forward<I>(arg_));
0154 }
0155 ///@}
0156
0157 reference at(size_type n_);
0158 constexpr const_reference at(size_type n_) const;
0159
0160 reference front() { return elems_[0]; }
0161 constexpr const_reference front() const { return elems_[0]; }
0162 reference back() { return elems_[Size > 0 ? Size - 1 : 0]; }
0163 constexpr const_reference back() const { return elems_[Size > 0 ? Size - 1 : 0]; }
0164 value_type* data() noexcept { return elems_; }
0165 const value_type* data() const noexcept { return elems_; }
0166 };
0167
0168 template <class T, size_t Size>
0169 typename array<T, Size>::reference array<T, Size>::at(size_type n_)
0170 {
0171 if (n_ >= Size) {
0172 throw std::out_of_range("array::at");
0173 }
0174 return elems_[n_];
0175 }
0176
0177 template <class T, size_t Size>
0178 constexpr typename array<T, Size>::const_reference array<T, Size>::at(size_type n_) const
0179 {
0180 return n_ >= Size ? (throw std::out_of_range("array::at"), elems_[0]) : elems_[n_];
0181 }
0182
0183 template <class T, size_t Size>
0184 inline bool operator==(const array<T, Size>& x_, const array<T, Size>& y_)
0185 {
0186 return std::equal(x_.elems_, x_.elems_ + Size, y_.elems_);
0187 }
0188
0189 template <class T, size_t Size>
0190 inline bool operator!=(const array<T, Size>& x_, const array<T, Size>& y_)
0191 {
0192 return !(x_ == y_);
0193 }
0194
0195 template <class T, size_t Size>
0196 inline bool operator<(const array<T, Size>& x_, const array<T, Size>& y_)
0197 {
0198 return std::lexicographical_compare(x_.elems_, x_.elems_ + Size, y_.elems_,
0199 y_.elems_ + Size);
0200 }
0201
0202 template <class T, size_t Size>
0203 inline bool operator>(const array<T, Size>& x_, const array<T, Size>& y_)
0204 {
0205 return y_ < x_;
0206 }
0207
0208 template <class T, size_t Size>
0209 inline bool operator<=(const array<T, Size>& x_, const array<T, Size>& y_)
0210 {
0211 return !(y_ < x_);
0212 }
0213
0214 template <class T, size_t Size>
0215 inline bool operator>=(const array<T, Size>& x_, const array<T, Size>& y_)
0216 {
0217 return !(x_ < y_);
0218 }
0219
0220 /**\name non-member begin & end
0221 * Implement the non-member begin & end functions in the %Vc namespace so that ADL works
0222 * and `begin(some_vc_array)` always works.
0223 */
0224 ///@{
0225 template <typename T, std::size_t N>
0226 inline auto begin(array<T, N>& arr) -> decltype(arr.begin())
0227 {
0228 return arr.begin();
0229 }
0230 template <typename T, std::size_t N>
0231 inline auto begin(const array<T, N>& arr) -> decltype(arr.begin())
0232 {
0233 return arr.begin();
0234 }
0235 template <typename T, std::size_t N>
0236 inline auto end(array<T, N>& arr) -> decltype(arr.end())
0237 {
0238 return arr.end();
0239 }
0240 template <typename T, std::size_t N>
0241 inline auto end(const array<T, N>& arr) -> decltype(arr.end())
0242 {
0243 return arr.end();
0244 }
0245 ///@}
0246
0247 namespace Traits
0248 {
0249 template <typename T, std::size_t N>
0250 struct has_no_allocated_data_impl<Vc::array<T, N>> : public std::true_type
0251 {
0252 };
0253 template <typename T, std::size_t N>
0254 struct has_contiguous_storage_impl<Vc::array<T, N>> : public std::true_type
0255 {
0256 };
0257 } // namespace Traits
0258 } // namespace Vc
0259
0260 namespace std
0261 {
0262 template <class T, size_t Size>
0263 inline
0264 #ifdef Vc_MSVC
0265 // MSVC fails to do SFINAE correctly and gets totally confused:
0266 // error C2433: 'type': 'inline' not permitted on data declarations
0267 // error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
0268 // error C2061: syntax error: identifier 'swap'
0269 void
0270 #else
0271 typename enable_if<is_same<void, decltype(swap(declval<T&>(), declval<T&>()))>::value,
0272 void>::type
0273 #endif
0274 swap(const Vc::array<T, Size>& x_,
0275 const Vc::array<T, Size>& y_) noexcept(swap(declval<T&>(), declval<T&>()))
0276 {
0277 x_.swap(y_);
0278 }
0279
0280 template <class T, size_t Size>
0281 class tuple_size<Vc::array<T, Size>> : public integral_constant<size_t, Size>
0282 {
0283 };
0284
0285 template <size_t I, class T, size_t Size> class tuple_element<I, Vc::array<T, Size>>
0286 {
0287 public:
0288 typedef T type;
0289 };
0290
0291 template <size_t I, class T, size_t Size>
0292 inline constexpr typename std::enable_if<(I < Size), T&>::type get(
0293 Vc::array<T, Size>& a_) noexcept
0294 {
0295 return a_.elems_[I];
0296 }
0297
0298 template <size_t I, class T, size_t Size>
0299 inline constexpr typename std::enable_if<(I < Size), const T&>::type get(
0300 const Vc::array<T, Size>& a_) noexcept
0301 {
0302 return a_.elems_[I];
0303 }
0304
0305 template <size_t I, class T, size_t Size>
0306 inline constexpr typename std::enable_if<(I < Size), T&&>::type get(
0307 Vc::array<T, Size>&& a_) noexcept
0308 {
0309 return std::move(a_.elems_[I]);
0310 }
0311 } // namespace std
0312
0313 #endif // VC_INCLUDE_VC_ARRAY_
0314
0315 // vim: ft=cpp foldmethod=marker