xref: /aosp_15_r20/external/executorch/runtime/core/array_ref.h (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree.
7  */
8 
9 //===--- ArrayRef.h - Array Reference Wrapper -------------------*- C++ -*-===//
10 //
11 //                     The LLVM Compiler Infrastructure
12 //
13 // This file is distributed under the University of Illinois Open Source
14 // License. See LICENSE.TXT for details.
15 //
16 //===----------------------------------------------------------------------===//
17 
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 // remove constructors for std::array
23 // remove constructors and operators for std::vector
24 // removed some prevention of accidental assignments from temporary that
25 // required std::enable_if meta-programming
26 // removed reverse iterator
27 
28 #pragma once
29 
30 #include <cstdint>
31 
32 #include <executorch/runtime/platform/assert.h>
33 
34 namespace executorch {
35 namespace runtime {
36 
37 /**
38  * Represents a constant reference to an array (0 or more elements
39  * consecutively in memory), i.e. a start pointer and a length.  It allows
40  * various APIs to take consecutive elements easily and conveniently.
41  *
42  * This class does not own the underlying data, it is expected to be used in
43  * situations where the data resides in some other buffer, whose lifetime
44  * extends past that of the ArrayRef. For this reason, it is not in general
45  * safe to store an ArrayRef.
46  *
47  * Span and ArrayRef are extrememly similar with the difference being ArrayRef
48  * views a list of constant elements and Span views a list of mutable elements.
49  * Clients should decide between the two based on if the list elements for their
50  * use case should be mutable.
51  *
52  * This is intended to be trivially copyable, so it should be passed by
53  * value.
54  */
55 template <typename T>
56 class ArrayRef final {
57  public:
58   using iterator = const T*;
59   using const_iterator = const T*;
60   using size_type = size_t;
61   using value_type = T;
62 
63  private:
64   /// The start of the array, in an external buffer.
65   const T* Data;
66 
67   /// The number of elements.
68   size_type Length;
69 
70  public:
71   /// @name Constructors
72   /// @{
73 
74   /// Construct an empty ArrayRef.
ArrayRef()75   /* implicit */ constexpr ArrayRef() : Data(nullptr), Length(0) {}
76 
77   /// Construct a ArrayRef from a single element. Implicitly convert element
78   /// type. It is aligned with PyTorch's c10::ArrayRef.
ArrayRef(const T & OneElt)79   /* implicit */ constexpr ArrayRef(const T& OneElt)
80       : Data(&OneElt), Length(1) {}
81 
82   /// Construct a ArrayRef from a pointer and length.
ArrayRef(const T * data,size_t length)83   ArrayRef(const T* data, size_t length) : Data(data), Length(length) {
84     ET_DCHECK(Data != nullptr || Length == 0);
85   }
86 
87   /// Construct a ArrayRef from a range.
ArrayRef(const T * begin,const T * end)88   ArrayRef(const T* begin, const T* end) : Data(begin), Length(end - begin) {}
89 
90   /// Construct a ArrayRef from a C array.
91   template <size_t N>
ArrayRef(const T (& Arr)[N])92   /* implicit */ constexpr ArrayRef(const T (&Arr)[N]) : Data(Arr), Length(N) {}
93 
94   /// @}
95   /// @name Simple Operations
96   /// @{
97 
begin()98   constexpr iterator begin() const {
99     return Data;
100   }
end()101   constexpr iterator end() const {
102     return Data + Length;
103   }
104 
105   // These are actually the same as iterator, since ArrayRef only
106   // gives you const iterators.
cbegin()107   constexpr const_iterator cbegin() const {
108     return Data;
109   }
cend()110   constexpr const_iterator cend() const {
111     return Data + Length;
112   }
113 
114   /// empty - Check if the array is empty.
empty()115   constexpr bool empty() const {
116     return Length == 0;
117   }
118 
data()119   constexpr const T* data() const {
120     return Data;
121   }
122 
123   /// size - Get the array size.
size()124   constexpr size_t size() const {
125     return Length;
126   }
127 
128   /// front - Get the first element.
front()129   const T& front() const {
130     // ArrayRef: attempted to access front() of empty list
131     ET_CHECK(!empty());
132     return Data[0];
133   }
134 
135   /// back - Get the last element.
back()136   const T& back() const {
137     // ArrayRef: attempted to access back() of empty list
138     ET_CHECK(!empty());
139     return Data[Length - 1];
140   }
141 
142   /// equals - Check for element-wise equality.
equals(ArrayRef RHS)143   bool equals(ArrayRef RHS) const {
144     if (Length != RHS.Length) {
145       return false;
146     }
147     for (size_t i = 0; i < this->Length; i++) {
148       if (Data[i] != RHS.Data[i]) {
149         return false;
150       }
151     }
152     return true;
153   }
154 
155   /// slice(n, m) - Take M elements of the array starting at element N
slice(size_t N,size_t M)156   ArrayRef<T> slice(size_t N, size_t M) const {
157     // cant slice longer then the array
158     ET_CHECK(N + M <= size());
159     return ArrayRef<T>(data() + N, M);
160   }
161 
162   /// slice(n) - Chop off the first N elements of the array.
slice(size_t N)163   constexpr ArrayRef<T> slice(size_t N) const {
164     return slice(N, size() - N);
165   }
166 
167   /// @}
168   /// @name Operator Overloads
169   /// @{
170   constexpr const T& operator[](size_t Index) const {
171     return Data[Index];
172   }
173 
174   /// Vector compatibility
at(size_t Index)175   const T& at(size_t Index) const {
176     // invalid index
177     ET_CHECK(Index < Length);
178     return Data[Index];
179   }
180 
181   /// @}
182 };
183 
184 /// @name ArrayRef Convenience constructors
185 /// @{
186 
187 /// Construct an ArrayRef from a single element.
188 template <typename T>
makeArrayRef(const T & OneElt)189 ArrayRef<T> makeArrayRef(const T& OneElt) {
190   return OneElt;
191 }
192 
193 /// Construct an ArrayRef from a pointer and length.
194 template <typename T>
makeArrayRef(const T * data,size_t length)195 ArrayRef<T> makeArrayRef(const T* data, size_t length) {
196   return ArrayRef<T>(data, length);
197 }
198 
199 /// Construct an ArrayRef from a range.
200 template <typename T>
makeArrayRef(const T * begin,const T * end)201 ArrayRef<T> makeArrayRef(const T* begin, const T* end) {
202   return ArrayRef<T>(begin, end);
203 }
204 
205 /// Construct an ArrayRef from an ArrayRef (no-op) (const)
206 template <typename T>
makeArrayRef(const ArrayRef<T> & Vec)207 ArrayRef<T> makeArrayRef(const ArrayRef<T>& Vec) {
208   return Vec;
209 }
210 
211 /// Construct an ArrayRef from an ArrayRef (no-op)
212 template <typename T>
makeArrayRef(ArrayRef<T> & Vec)213 ArrayRef<T>& makeArrayRef(ArrayRef<T>& Vec) {
214   return Vec;
215 }
216 
217 /// Construct an ArrayRef from a C array.
218 template <typename T, size_t N>
makeArrayRef(const T (& Arr)[N])219 ArrayRef<T> makeArrayRef(const T (&Arr)[N]) {
220   return ArrayRef<T>(Arr);
221 }
222 
223 // WARNING: Template instantiation will NOT be willing to do an implicit
224 // conversions to get you to an ArrayRef, which is why we need so
225 // many overloads.
226 
227 template <typename T>
228 bool operator==(ArrayRef<T> a1, ArrayRef<T> a2) {
229   return a1.equals(a2);
230 }
231 
232 template <typename T>
233 bool operator!=(ArrayRef<T> a1, ArrayRef<T> a2) {
234   return !a1.equals(a2);
235 }
236 
237 using IntArrayRef = ArrayRef<int64_t>;
238 
239 } // namespace runtime
240 } // namespace executorch
241 
242 namespace torch {
243 namespace executor {
244 // TODO(T197294990): Remove these deprecated aliases once all users have moved
245 // to the new `::executorch` namespaces.
246 using ::executorch::runtime::ArrayRef;
247 using ::executorch::runtime::IntArrayRef;
248 using ::executorch::runtime::makeArrayRef;
249 } // namespace executor
250 } // namespace torch
251