|
| 1 | +//===--- ArrayRef.h - Array Reference Wrapper -------------------*- C++ -*-===// |
| 2 | +// |
| 3 | +// The LLVM Compiler Infrastructure |
| 4 | +// |
| 5 | +// This file is distributed under the University of Illinois Open Source |
| 6 | +// License. See LICENSE.TXT for details. |
| 7 | +// |
| 8 | +//===----------------------------------------------------------------------===// |
| 9 | + |
| 10 | +// ATen: modified from llvm::ArrayRef. |
| 11 | +// removed llvm-specific functionality |
| 12 | +// removed some implicit const -> non-const conversions that rely on |
| 13 | +// complicated std::enable_if meta-programming |
| 14 | +// removed a bunch of slice variants for simplicity... |
| 15 | + |
| 16 | +#pragma once |
| 17 | +#include <assert.h> |
| 18 | +#include <array> |
| 19 | +#include <vector> |
| 20 | + |
| 21 | +namespace at { |
| 22 | + /// ArrayRef - Represent a constant reference to an array (0 or more elements |
| 23 | + /// consecutively in memory), i.e. a start pointer and a length. It allows |
| 24 | + /// various APIs to take consecutive elements easily and conveniently. |
| 25 | + /// |
| 26 | + /// This class does not own the underlying data, it is expected to be used in |
| 27 | + /// situations where the data resides in some other buffer, whose lifetime |
| 28 | + /// extends past that of the ArrayRef. For this reason, it is not in general |
| 29 | + /// safe to store an ArrayRef. |
| 30 | + /// |
| 31 | + /// This is intended to be trivially copyable, so it should be passed by |
| 32 | + /// value. |
| 33 | + template<typename T> |
| 34 | + class ArrayRef { |
| 35 | + public: |
| 36 | + typedef const T *iterator; |
| 37 | + typedef const T *const_iterator; |
| 38 | + typedef size_t size_type; |
| 39 | + |
| 40 | + typedef std::reverse_iterator<iterator> reverse_iterator; |
| 41 | + |
| 42 | + private: |
| 43 | + /// The start of the array, in an external buffer. |
| 44 | + const T *Data; |
| 45 | + |
| 46 | + /// The number of elements. |
| 47 | + size_type Length; |
| 48 | + |
| 49 | + public: |
| 50 | + /// @name Constructors |
| 51 | + /// @{ |
| 52 | + |
| 53 | + /// Construct an empty ArrayRef. |
| 54 | + /*implicit*/ ArrayRef() : Data(nullptr), Length(0) {} |
| 55 | + |
| 56 | + /// Construct an ArrayRef from a single element. |
| 57 | + /*implicit*/ ArrayRef(const T &OneElt) |
| 58 | + : Data(&OneElt), Length(1) {} |
| 59 | + |
| 60 | + /// Construct an ArrayRef from a pointer and length. |
| 61 | + /*implicit*/ ArrayRef(const T *data, size_t length) |
| 62 | + : Data(data), Length(length) {} |
| 63 | + |
| 64 | + /// Construct an ArrayRef from a range. |
| 65 | + ArrayRef(const T *begin, const T *end) |
| 66 | + : Data(begin), Length(end - begin) {} |
| 67 | + |
| 68 | + /// Construct an ArrayRef from a std::vector. |
| 69 | + template<typename A> |
| 70 | + /*implicit*/ ArrayRef(const std::vector<T, A> &Vec) |
| 71 | + : Data(Vec.data()), Length(Vec.size()) {} |
| 72 | + |
| 73 | + /// Construct an ArrayRef from a std::array |
| 74 | + template <size_t N> |
| 75 | + /*implicit*/ constexpr ArrayRef(const std::array<T, N> &Arr) |
| 76 | + : Data(Arr.data()), Length(N) {} |
| 77 | + |
| 78 | + /// Construct an ArrayRef from a C array. |
| 79 | + template <size_t N> |
| 80 | + /*implicit*/ constexpr ArrayRef(const T (&Arr)[N]) : Data(Arr), Length(N) {} |
| 81 | + |
| 82 | + /// Construct an ArrayRef from a std::initializer_list. |
| 83 | + /*implicit*/ ArrayRef(const std::initializer_list<T> &Vec) |
| 84 | + : Data(Vec.begin() == Vec.end() ? (T*)nullptr : Vec.begin()), |
| 85 | + Length(Vec.size()) {} |
| 86 | + |
| 87 | + /// @} |
| 88 | + /// @name Simple Operations |
| 89 | + /// @{ |
| 90 | + |
| 91 | + iterator begin() const { return Data; } |
| 92 | + iterator end() const { return Data + Length; } |
| 93 | + |
| 94 | + reverse_iterator rbegin() const { return reverse_iterator(end()); } |
| 95 | + reverse_iterator rend() const { return reverse_iterator(begin()); } |
| 96 | + |
| 97 | + /// empty - Check if the array is empty. |
| 98 | + bool empty() const { return Length == 0; } |
| 99 | + |
| 100 | + const T *data() const { return Data; } |
| 101 | + |
| 102 | + /// size - Get the array size. |
| 103 | + size_t size() const { return Length; } |
| 104 | + |
| 105 | + /// front - Get the first element. |
| 106 | + const T &front() const { |
| 107 | + assert(!empty()); |
| 108 | + return Data[0]; |
| 109 | + } |
| 110 | + |
| 111 | + /// back - Get the last element. |
| 112 | + const T &back() const { |
| 113 | + assert(!empty()); |
| 114 | + return Data[Length-1]; |
| 115 | + } |
| 116 | + |
| 117 | + /// equals - Check for element-wise equality. |
| 118 | + bool equals(ArrayRef RHS) const { |
| 119 | + if (Length != RHS.Length) |
| 120 | + return false; |
| 121 | + return std::equal(begin(), end(), RHS.begin()); |
| 122 | + } |
| 123 | + |
| 124 | + /// slice(n, m) - Chop off the first N elements of the array, and keep M |
| 125 | + /// elements in the array. |
| 126 | + ArrayRef<T> slice(size_t N, size_t M) const { |
| 127 | + assert(N+M <= size() && "Invalid specifier"); |
| 128 | + return ArrayRef<T>(data()+N, M); |
| 129 | + } |
| 130 | + |
| 131 | + /// slice(n) - Chop off the first N elements of the array. |
| 132 | + ArrayRef<T> slice(size_t N) const { return slice(N, size() - N); } |
| 133 | + |
| 134 | + /// @} |
| 135 | + /// @name Operator Overloads |
| 136 | + /// @{ |
| 137 | + const T &operator[](size_t Index) const { |
| 138 | + assert(Index < Length && "Invalid index!"); |
| 139 | + return Data[Index]; |
| 140 | + } |
| 141 | + |
| 142 | + /// Disallow accidental assignment from a temporary. |
| 143 | + /// |
| 144 | + /// The declaration here is extra complicated so that "arrayRef = {}" |
| 145 | + /// continues to select the move assignment operator. |
| 146 | + template <typename U> |
| 147 | + typename std::enable_if<std::is_same<U, T>::value, ArrayRef<T>>::type & |
| 148 | + operator=(U &&Temporary) = delete; |
| 149 | + |
| 150 | + /// Disallow accidental assignment from a temporary. |
| 151 | + /// |
| 152 | + /// The declaration here is extra complicated so that "arrayRef = {}" |
| 153 | + /// continues to select the move assignment operator. |
| 154 | + template <typename U> |
| 155 | + typename std::enable_if<std::is_same<U, T>::value, ArrayRef<T>>::type & |
| 156 | + operator=(std::initializer_list<U>) = delete; |
| 157 | + |
| 158 | + /// @} |
| 159 | + /// @name Expensive Operations |
| 160 | + /// @{ |
| 161 | + std::vector<T> vec() const { |
| 162 | + return std::vector<T>(Data, Data+Length); |
| 163 | + } |
| 164 | + |
| 165 | + /// @} |
| 166 | + /// @name Conversion operators |
| 167 | + /// @{ |
| 168 | + operator std::vector<T>() const { |
| 169 | + return std::vector<T>(Data, Data+Length); |
| 170 | + } |
| 171 | + |
| 172 | + /// @} |
| 173 | + }; |
| 174 | + |
| 175 | +} // end namespace at |
0 commit comments