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