Caffe2 - C++ API
A deep learning, cross platform ML framework
Array.h
1 
17 // Copyright (C) 2007-2017 Free Software Foundation, Inc.
18 //
19 // This file is part of the GNU ISO C++ Library. This library is free
20 // software; you can redistribute it and/or modify it under the
21 // terms of the GNU General Public License as published by the
22 // Free Software Foundation; either version 3, or (at your option)
23 // any later version.
24 
25 // This library is distributed in the hope that it will be useful,
26 // but WITHOUT ANY WARRANTY; without even the implied warranty of
27 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 // GNU General Public License for more details.
29 
30 // Under Section 7 of GPL version 3, you are granted additional
31 // permissions described in the GCC Runtime Library Exception, version
32 // 3.1, as published by the Free Software Foundation.
33 
34 // You should have received a copy of the GNU General Public License and
35 // a copy of the GCC Runtime Library Exception along with this program;
36 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
37 // <http://www.gnu.org/licenses/>.
38 
39 #pragma once
40 
41 #include <c10/util/C++17.h>
42 #include <stdexcept>
43 #include <string>
44 #include <utility>
45 
46 namespace c10 { namespace guts {
47 
48 namespace detail {
49 template<typename _Tp, std::size_t _Nm>
50 struct __array_traits final {
51  using _Type = _Tp[_Nm];
52 
53  static constexpr _Tp& _S_ref(const _Type& __t, std::size_t __n) noexcept {
54  return const_cast<_Tp&>(__t[__n]);
55  }
56 
57  static constexpr _Tp* _S_ptr(const _Type& __t) noexcept {
58  return const_cast<_Tp*>(__t);
59  }
60 };
61 
62 template<typename _Tp>
63 struct __array_traits<_Tp, 0> final {
64  struct _Type final {};
65 
66  static constexpr _Tp& _S_ref(const _Type& __t, std::size_t) noexcept {
67  return *_S_ptr(__t);
68  }
69 
70  static constexpr _Tp* _S_ptr(const _Type&) noexcept {
71  return nullptr;
72  }
73 };
74 
75 [[noreturn]] inline void __throw_out_of_range(std::string msg) {
76  throw std::out_of_range(std::move(msg));
77 }
78 }
79 
80 template<typename _Tp, std::size_t _Nm>
81 class array final {
82 public:
83  using value_type = _Tp;
84  using pointer = value_type*;
85  using const_pointer = const value_type*;
86  using reference = value_type&;
87  using const_reference = const value_type&;
88  using iterator = value_type*;
89  using const_iterator = const value_type*;
90  using size_type = std::size_t;
91  using difference_type = std::ptrdiff_t;
92  using reverse_iterator = std::reverse_iterator<iterator>;
93  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
94 
95 private:
97 public: // needs to be public member for aggregate initialization
98  typename _AT_Type::_Type _M_elems;
99 
100 public:
101  // No explicit construct/copy/destroy for aggregate type.
102 
103  // DR 776.
104  AT_CPP14_CONSTEXPR void fill(const value_type& __u)
105  { std::fill_n(begin(), size(), __u); }
106 
107  AT_CPP14_CONSTEXPR void swap(array& __other)
108  { std::swap_ranges(begin(), end(), __other.begin()); }
109 
110  // Iterators.
111  AT_CPP14_CONSTEXPR iterator begin() noexcept
112  { return iterator(data()); }
113 
114  constexpr const_iterator begin() const noexcept
115  { return const_iterator(data()); }
116 
117  AT_CPP14_CONSTEXPR iterator end() noexcept
118  { return iterator(data() + _Nm); }
119 
120  constexpr const_iterator end() const noexcept
121  { return const_iterator(data() + _Nm); }
122 
123  AT_CPP14_CONSTEXPR reverse_iterator rbegin() noexcept
124  { return reverse_iterator(end()); }
125 
126  constexpr const_reverse_iterator rbegin() const noexcept
127  { return const_reverse_iterator(end()); }
128 
129  AT_CPP14_CONSTEXPR reverse_iterator rend() noexcept
130  { return reverse_iterator(begin()); }
131 
132  constexpr const_reverse_iterator rend() const noexcept
133  { return const_reverse_iterator(begin()); }
134 
135  constexpr const_iterator cbegin() const noexcept
136  { return const_iterator(data()); }
137 
138  constexpr const_iterator cend() const noexcept
139  { return const_iterator(data() + _Nm); }
140 
141  constexpr const_reverse_iterator crbegin() const noexcept
142  { return const_reverse_iterator(end()); }
143 
144  constexpr const_reverse_iterator crend() const noexcept
145  { return const_reverse_iterator(begin()); }
146 
147  // Capacity.
148  constexpr size_type size() const noexcept { return _Nm; }
149 
150  constexpr size_type max_size() const noexcept { return _Nm; }
151 
152  constexpr bool empty() const noexcept { return size() == 0; }
153 
154  // Element access.
155  AT_CPP14_CONSTEXPR reference operator[](size_type __n) noexcept
156  { return _AT_Type::_S_ref(_M_elems, __n); }
157 
158  constexpr const_reference operator[](size_type __n) const noexcept
159  { return _AT_Type::_S_ref(_M_elems, __n); }
160 
161  AT_CPP14_CONSTEXPR reference at(size_type __n) {
162  if (__n >= _Nm) {
163  detail::__throw_out_of_range(std::string() +
164  "array::at: __n (which is " + to_string(__n) + ") " +
165  ">= _Nm (which is " + to_string(_Nm) + ")");
166  }
167  return _AT_Type::_S_ref(_M_elems, __n);
168  }
169 
170  constexpr const_reference at(size_type __n) const {
171  // Result of conditional expression must be an lvalue so use
172  // boolean ? lvalue : (throw-expr, lvalue)
173  return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n)
174  : (detail::__throw_out_of_range(std::string() +
175  "array::at: __n (which is " + to_string(__n) + ") " +
176  ">= _Nm (which is " + to_string(_Nm) + ")"),
177  _AT_Type::_S_ref(_M_elems, 0));
178  }
179 
180  AT_CPP14_CONSTEXPR reference front() noexcept
181  { return *begin(); }
182 
183  constexpr const_reference front() const noexcept
184  { return _AT_Type::_S_ref(_M_elems, 0); }
185 
186  AT_CPP14_CONSTEXPR reference back() noexcept
187  { return _Nm ? *(end() - 1) : *end(); }
188 
189  constexpr const_reference back() const noexcept
190  {
191  return _Nm ? _AT_Type::_S_ref(_M_elems, _Nm - 1)
192  : _AT_Type::_S_ref(_M_elems, 0);
193  }
194 
195  AT_CPP14_CONSTEXPR pointer data() noexcept
196  { return _AT_Type::_S_ptr(_M_elems); }
197 
198  constexpr const_pointer data() const noexcept
199  { return _AT_Type::_S_ptr(_M_elems); }
200 };
201 
202 #if defined(__cpp_deduction_guides) && __cpp_deduction_guides >= 201606
203  template<typename _Tp, typename... _Up>
204  array(_Tp, _Up...) ->
205  array<enable_if_t<(std::is_same<_Tp, _Up>::value && ...), _Tp>, 1 + sizeof...(_Up)>;
206 #endif
207 
208 // Array comparisons.
209 namespace detail {
210 template<class T, size_t N>
211 constexpr inline bool array_equals_(const array<T, N>& lhs, const array<T, N>& rhs, size_t current_index) {
212  return (current_index == N)
213  ? true
214  : (lhs.at(current_index) == rhs.at(current_index) && array_equals_(lhs, rhs, current_index + 1));
215 }
216 template<class T, size_t N>
217 constexpr inline bool array_less_(const array<T, N>& lhs, const array<T, N>& rhs, size_t current_index) {
218  return (current_index == N)
219  ? false
220  : (lhs.at(current_index) < rhs.at(current_index) || array_less_(lhs, rhs, current_index + 1));
221 }
222 }
223 template<typename _Tp, std::size_t _Nm>
224 constexpr inline bool operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
225 { return detail::array_equals_(__one, __two, 0); }
226 
227 template<typename _Tp, std::size_t _Nm>
228 constexpr inline bool operator!=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
229 { return !(__one == __two); }
230 
231 template<typename _Tp, std::size_t _Nm>
232 constexpr inline bool operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b)
233 { return detail::array_less_(__a, __b, 0); }
234 
235 template<typename _Tp, std::size_t _Nm>
236 constexpr inline bool operator>(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
237 { return __two < __one; }
238 
239 template<typename _Tp, std::size_t _Nm>
240 constexpr inline bool operator<=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
241 { return !(__one > __two); }
242 
243 template<typename _Tp, std::size_t _Nm>
244 constexpr inline bool operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
245 { return !(__one < __two); }
246 
247 // Specialized algorithms.
248 template<typename _Tp, std::size_t _Nm>
249 inline void swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two) noexcept(noexcept(__one.swap(__two)))
250 { __one.swap(__two); }
251 
252 template<std::size_t _Int, typename _Tp, std::size_t _Nm>
253 constexpr _Tp& get(array<_Tp, _Nm>& __arr) noexcept {
254  static_assert(_Int < _Nm, "array index is within bounds");
255  return detail::__array_traits<_Tp, _Nm>::_S_ref(__arr._M_elems, _Int);
256 }
257 
258 template<std::size_t _Int, typename _Tp, std::size_t _Nm>
259 constexpr _Tp&& get(array<_Tp, _Nm>&& __arr) noexcept
260 {
261  static_assert(_Int < _Nm, "array index is within bounds");
262  return guts::move(get<_Int>(__arr));
263 }
264 
265 template<std::size_t _Int, typename _Tp, std::size_t _Nm>
266 constexpr const _Tp& get(const array<_Tp, _Nm>& __arr) noexcept
267 {
268  static_assert(_Int < _Nm, "array index is within bounds");
269  return detail::__array_traits<_Tp, _Nm>::_S_ref(__arr._M_elems, _Int);
270 }
271 
279 namespace detail {
280 template<class T, size_t N, size_t... I>
281 constexpr inline array<T, N-1> tail_(const array<T, N>& arg, guts::index_sequence<I...>) {
282  static_assert(sizeof...(I) == N-1, "invariant");
283  return {{get<I+1>(arg)...}};
284 }
285 }
286 template<class T, size_t N>
287 constexpr inline array<T, N-1> tail(const array<T, N>& arg) {
288  static_assert(N > 0, "Can only call tail() on an array with at least one element");
289  return detail::tail_(arg, guts::make_index_sequence<N-1>());
290 }
291 
292 namespace detail {
293 template<class T, size_t N, size_t... I>
294 constexpr inline array<T, N+1> prepend_(T&& head, const array<T, N>& tail, guts::index_sequence<I...>) {
295  return {{guts::forward<T>(head), get<I>(tail)...}};
296 }
297 }
298 template<class T, size_t N>
299 constexpr inline array<T, N+1> prepend(T&& head, const array<T, N>& tail) {
300  return detail::prepend_(guts::forward<T>(head), tail, guts::make_index_sequence<N>());
301 }
302 
310 namespace detail {
311 template<class T, size_t N, size_t... I>
312 constexpr array<T, N> to_array_(const T (&arr)[N], guts::index_sequence<I...>) {
313  return {{arr[I]...}};
314 }
315 }
316 
317 template<class T, size_t N>
318 constexpr array<T, N> to_array(const T (&arr)[N]) {
319  return detail::to_array_(arr, guts::make_index_sequence<N>());
320 }
321 
322 }}
To register your own kernel for an operator, do in one (!) cpp file: C10_REGISTER_KERNEL(OperatorHand...
Definition: alias_info.h:7
Flush-To-Zero and Denormals-Are-Zero mode.