xscalar.hpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098
  1. /***************************************************************************
  2. * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
  3. * Copyright (c) QuantStack *
  4. * *
  5. * Distributed under the terms of the BSD 3-Clause License. *
  6. * *
  7. * The full license is in the file LICENSE, distributed with this software. *
  8. ****************************************************************************/
  9. #ifndef XTENSOR_SCALAR_HPP
  10. #define XTENSOR_SCALAR_HPP
  11. #include <array>
  12. #include <cstddef>
  13. #include <utility>
  14. #include <xtl/xtype_traits.hpp>
  15. #include "xaccessible.hpp"
  16. #include "xexpression.hpp"
  17. #include "xiterable.hpp"
  18. #include "xlayout.hpp"
  19. #include "xtensor_simd.hpp"
  20. namespace xt
  21. {
  22. /*********************
  23. * xscalar extension *
  24. *********************/
  25. namespace extension
  26. {
  27. template <class Tag, class CT>
  28. struct xscalar_base_impl;
  29. template <class CT>
  30. struct xscalar_base_impl<xtensor_expression_tag, CT>
  31. {
  32. using type = xtensor_empty_base;
  33. };
  34. template <class CT>
  35. struct xscalar_base : xscalar_base_impl<get_expression_tag_t<std::decay_t<CT>>, CT>
  36. {
  37. };
  38. template <class CT>
  39. using xscalar_base_t = typename xscalar_base<CT>::type;
  40. }
  41. /***********
  42. * xscalar *
  43. ***********/
  44. // xscalar is a cheap wrapper for a scalar value as an xexpression.
  45. template <class CT>
  46. class xscalar;
  47. template <bool is_const, class CT>
  48. class xscalar_stepper;
  49. template <bool is_const, class CT>
  50. class xdummy_iterator;
  51. template <class CT>
  52. struct xiterable_inner_types<xscalar<CT>>
  53. {
  54. using value_type = std::decay_t<CT>;
  55. using inner_shape_type = std::array<std::size_t, 0>;
  56. using shape_type = inner_shape_type;
  57. using const_stepper = xscalar_stepper<true, CT>;
  58. using stepper = xscalar_stepper<false, CT>;
  59. };
  60. template <class CT>
  61. struct xcontainer_inner_types<xscalar<CT>>
  62. {
  63. using value_type = std::decay_t<CT>;
  64. using reference = value_type&;
  65. using const_reference = const value_type&;
  66. using size_type = std::size_t;
  67. };
  68. template <class CT>
  69. class xscalar : public xsharable_expression<xscalar<CT>>,
  70. private xiterable<xscalar<CT>>,
  71. private xaccessible<xscalar<CT>>,
  72. public extension::xscalar_base_t<CT>
  73. {
  74. public:
  75. using self_type = xscalar<CT>;
  76. using xexpression_type = std::decay_t<CT>;
  77. using extension_base = extension::xscalar_base_t<CT>;
  78. using accessible_base = xaccessible<self_type>;
  79. using expression_tag = typename extension_base::expression_tag;
  80. using inner_types = xcontainer_inner_types<self_type>;
  81. using value_type = typename inner_types::value_type;
  82. using reference = typename inner_types::reference;
  83. using const_reference = typename inner_types::const_reference;
  84. using pointer = value_type*;
  85. using const_pointer = const value_type*;
  86. using size_type = typename inner_types::size_type;
  87. using difference_type = std::ptrdiff_t;
  88. using simd_value_type = xt_simd::simd_type<value_type>;
  89. using bool_load_type = xt::bool_load_type<value_type>;
  90. using iterable_base = xiterable<self_type>;
  91. using inner_shape_type = typename iterable_base::inner_shape_type;
  92. using shape_type = inner_shape_type;
  93. using stepper = typename iterable_base::stepper;
  94. using const_stepper = typename iterable_base::const_stepper;
  95. template <layout_type L>
  96. using layout_iterator = typename iterable_base::template layout_iterator<L>;
  97. template <layout_type L>
  98. using const_layout_iterator = typename iterable_base::template const_layout_iterator<L>;
  99. template <layout_type L>
  100. using reverse_layout_iterator = typename iterable_base::template reverse_layout_iterator<L>;
  101. template <layout_type L>
  102. using const_reverse_layout_iterator = typename iterable_base::template const_reverse_layout_iterator<L>;
  103. template <class S, layout_type L>
  104. using broadcast_iterator = typename iterable_base::template broadcast_iterator<S, L>;
  105. template <class S, layout_type L>
  106. using const_broadcast_iterator = typename iterable_base::template const_broadcast_iterator<S, L>;
  107. template <class S, layout_type L>
  108. using reverse_broadcast_iterator = typename iterable_base::template reverse_broadcast_iterator<S, L>;
  109. template <class S, layout_type L>
  110. using const_reverse_broadcast_iterator = typename iterable_base::template const_reverse_broadcast_iterator<S, L>;
  111. using iterator = value_type*;
  112. using const_iterator = const value_type*;
  113. using reverse_iterator = std::reverse_iterator<iterator>;
  114. using const_reverse_iterator = std::reverse_iterator<const_iterator>;
  115. using dummy_iterator = xdummy_iterator<false, CT>;
  116. using const_dummy_iterator = xdummy_iterator<true, CT>;
  117. static constexpr layout_type static_layout = layout_type::any;
  118. static constexpr bool contiguous_layout = true;
  119. xscalar() noexcept;
  120. xscalar(CT value) noexcept;
  121. operator value_type&() noexcept;
  122. operator const value_type&() const noexcept;
  123. size_type size() const noexcept;
  124. const shape_type& shape() const noexcept;
  125. size_type shape(size_type i) const noexcept;
  126. layout_type layout() const noexcept;
  127. bool is_contiguous() const noexcept;
  128. using accessible_base::dimension;
  129. using accessible_base::shape;
  130. template <class... Args>
  131. reference operator()(Args...) noexcept;
  132. template <class... Args>
  133. reference unchecked(Args...) noexcept;
  134. template <class... Args>
  135. const_reference operator()(Args...) const noexcept;
  136. template <class... Args>
  137. const_reference unchecked(Args...) const noexcept;
  138. using accessible_base::at;
  139. using accessible_base::operator[];
  140. using accessible_base::back;
  141. using accessible_base::front;
  142. using accessible_base::in_bounds;
  143. using accessible_base::periodic;
  144. template <class It>
  145. reference element(It, It) noexcept;
  146. template <class It>
  147. const_reference element(It, It) const noexcept;
  148. xexpression_type& expression() noexcept;
  149. const xexpression_type& expression() const noexcept;
  150. template <class S>
  151. bool broadcast_shape(S& shape, bool reuse_cache = false) const noexcept;
  152. template <class S>
  153. bool has_linear_assign(const S& strides) const noexcept;
  154. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  155. iterator begin() noexcept;
  156. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  157. iterator end() noexcept;
  158. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  159. const_iterator begin() const noexcept;
  160. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  161. const_iterator end() const noexcept;
  162. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  163. const_iterator cbegin() const noexcept;
  164. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  165. const_iterator cend() const noexcept;
  166. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  167. reverse_iterator rbegin() noexcept;
  168. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  169. reverse_iterator rend() noexcept;
  170. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  171. const_reverse_iterator rbegin() const noexcept;
  172. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  173. const_reverse_iterator rend() const noexcept;
  174. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  175. const_reverse_iterator crbegin() const noexcept;
  176. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  177. const_reverse_iterator crend() const noexcept;
  178. template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  179. broadcast_iterator<S, L> begin(const S& shape) noexcept;
  180. template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  181. broadcast_iterator<S, L> end(const S& shape) noexcept;
  182. template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  183. const_broadcast_iterator<S, L> begin(const S& shape) const noexcept;
  184. template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  185. const_broadcast_iterator<S, L> end(const S& shape) const noexcept;
  186. template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  187. const_broadcast_iterator<S, L> cbegin(const S& shape) const noexcept;
  188. template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  189. const_broadcast_iterator<S, L> cend(const S& shape) const noexcept;
  190. template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  191. reverse_broadcast_iterator<S, L> rbegin(const S& shape) noexcept;
  192. template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  193. reverse_broadcast_iterator<S, L> rend(const S& shape) noexcept;
  194. template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  195. const_reverse_broadcast_iterator<S, L> rbegin(const S& shape) const noexcept;
  196. template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  197. const_reverse_broadcast_iterator<S, L> rend(const S& shape) const noexcept;
  198. template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  199. const_reverse_broadcast_iterator<S, L> crbegin(const S& shape) const noexcept;
  200. template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  201. const_reverse_broadcast_iterator<S, L> crend(const S& shape) const noexcept;
  202. iterator linear_begin() noexcept;
  203. iterator linear_end() noexcept;
  204. const_iterator linear_begin() const noexcept;
  205. const_iterator linear_end() const noexcept;
  206. const_iterator linear_cbegin() const noexcept;
  207. const_iterator linear_cend() const noexcept;
  208. reverse_iterator linear_rbegin() noexcept;
  209. reverse_iterator linear_rend() noexcept;
  210. const_reverse_iterator linear_rbegin() const noexcept;
  211. const_reverse_iterator linear_rend() const noexcept;
  212. const_reverse_iterator linear_crbegin() const noexcept;
  213. const_reverse_iterator linear_crend() const noexcept;
  214. template <class S>
  215. stepper stepper_begin(const S& shape) noexcept;
  216. template <class S>
  217. stepper stepper_end(const S& shape, layout_type l) noexcept;
  218. template <class S>
  219. const_stepper stepper_begin(const S& shape) const noexcept;
  220. template <class S>
  221. const_stepper stepper_end(const S& shape, layout_type l) const noexcept;
  222. dummy_iterator dummy_begin() noexcept;
  223. dummy_iterator dummy_end() noexcept;
  224. const_dummy_iterator dummy_begin() const noexcept;
  225. const_dummy_iterator dummy_end() const noexcept;
  226. reference data_element(size_type i) noexcept;
  227. const_reference data_element(size_type i) const noexcept;
  228. reference flat(size_type i) noexcept;
  229. const_reference flat(size_type i) const noexcept;
  230. template <class align, class simd = simd_value_type>
  231. void store_simd(size_type i, const simd& e);
  232. template <class align, class requested_type = value_type, std::size_t N = xt_simd::simd_traits<requested_type>::size>
  233. xt_simd::simd_return_type<value_type, requested_type> load_simd(size_type i) const;
  234. private:
  235. CT m_value;
  236. friend class xconst_iterable<self_type>;
  237. friend class xiterable<self_type>;
  238. friend class xaccessible<self_type>;
  239. friend class xconst_accessible<self_type>;
  240. };
  241. namespace detail
  242. {
  243. template <class E>
  244. struct is_xscalar_impl : std::false_type
  245. {
  246. };
  247. template <class E>
  248. struct is_xscalar_impl<xscalar<E>> : std::true_type
  249. {
  250. };
  251. }
  252. template <class E>
  253. using is_xscalar = detail::is_xscalar_impl<E>;
  254. namespace detail
  255. {
  256. template <class... E>
  257. struct all_xscalar
  258. {
  259. static constexpr bool value = xtl::conjunction<is_xscalar<std::decay_t<E>>...>::value;
  260. };
  261. }
  262. // Note: MSVC bug workaround. Cannot just define
  263. // template <class... E>
  264. // using all_xscalar = xtl::conjunction<is_xscalar<std::decay_t<E>>...>;
  265. template <class... E>
  266. using all_xscalar = detail::all_xscalar<E...>;
  267. /******************
  268. * xref and xcref *
  269. ******************/
  270. template <class T>
  271. xscalar<T&> xref(T& t);
  272. template <class T>
  273. xscalar<const T&> xcref(T& t);
  274. /*******************
  275. * xscalar_stepper *
  276. *******************/
  277. template <bool is_const, class CT>
  278. class xscalar_stepper
  279. {
  280. public:
  281. using self_type = xscalar_stepper<is_const, CT>;
  282. using storage_type = std::conditional_t<is_const, const xscalar<CT>, xscalar<CT>>;
  283. using value_type = typename storage_type::value_type;
  284. using reference = std::
  285. conditional_t<is_const, typename storage_type::const_reference, typename storage_type::reference>;
  286. using pointer = std::conditional_t<is_const, typename storage_type::const_pointer, typename storage_type::pointer>;
  287. using size_type = typename storage_type::size_type;
  288. using difference_type = typename storage_type::difference_type;
  289. using shape_type = typename storage_type::shape_type;
  290. template <class requested_type>
  291. using simd_return_type = xt_simd::simd_return_type<value_type, requested_type>;
  292. xscalar_stepper(storage_type* c) noexcept;
  293. reference operator*() const noexcept;
  294. void step(size_type dim, size_type n = 1) noexcept;
  295. void step_back(size_type dim, size_type n = 1) noexcept;
  296. void reset(size_type dim) noexcept;
  297. void reset_back(size_type dim) noexcept;
  298. void to_begin() noexcept;
  299. void to_end(layout_type l) noexcept;
  300. template <class T>
  301. simd_return_type<T> step_simd();
  302. void step_leading();
  303. private:
  304. storage_type* p_c;
  305. };
  306. /*******************
  307. * xdummy_iterator *
  308. *******************/
  309. namespace detail
  310. {
  311. template <bool is_const, class CT>
  312. using dummy_reference_t = std::
  313. conditional_t<is_const, typename xscalar<CT>::const_reference, typename xscalar<CT>::reference>;
  314. template <bool is_const, class CT>
  315. using dummy_pointer_t = std::
  316. conditional_t<is_const, typename xscalar<CT>::const_pointer, typename xscalar<CT>::pointer>;
  317. }
  318. template <bool is_const, class CT>
  319. class xdummy_iterator : public xtl::xrandom_access_iterator_base<
  320. xdummy_iterator<is_const, CT>,
  321. typename xscalar<CT>::value_type,
  322. typename xscalar<CT>::difference_type,
  323. detail::dummy_pointer_t<is_const, CT>,
  324. detail::dummy_reference_t<is_const, CT>>
  325. {
  326. public:
  327. using self_type = xdummy_iterator<is_const, CT>;
  328. using storage_type = std::conditional_t<is_const, const xscalar<CT>, xscalar<CT>>;
  329. using value_type = typename storage_type::value_type;
  330. using reference = detail::dummy_reference_t<is_const, CT>;
  331. using pointer = detail::dummy_pointer_t<is_const, CT>;
  332. using difference_type = typename storage_type::difference_type;
  333. using iterator_category = std::random_access_iterator_tag;
  334. explicit xdummy_iterator(storage_type* c) noexcept;
  335. self_type& operator++() noexcept;
  336. self_type& operator--() noexcept;
  337. self_type& operator+=(difference_type n) noexcept;
  338. self_type& operator-=(difference_type n) noexcept;
  339. difference_type operator-(const self_type& rhs) const noexcept;
  340. reference operator*() const noexcept;
  341. bool equal(const self_type& rhs) const noexcept;
  342. bool less_than(const self_type& rhs) const noexcept;
  343. private:
  344. storage_type* p_c;
  345. };
  346. template <bool is_const, class CT>
  347. bool
  348. operator==(const xdummy_iterator<is_const, CT>& lhs, const xdummy_iterator<is_const, CT>& rhs) noexcept;
  349. template <bool is_const, class CT>
  350. bool operator<(const xdummy_iterator<is_const, CT>& lhs, const xdummy_iterator<is_const, CT>& rhs) noexcept;
  351. template <class T>
  352. struct is_not_xdummy_iterator : std::true_type
  353. {
  354. };
  355. template <bool is_const, class CT>
  356. struct is_not_xdummy_iterator<xdummy_iterator<is_const, CT>> : std::false_type
  357. {
  358. };
  359. /*****************************
  360. * linear_begin / linear_end *
  361. *****************************/
  362. template <class CT>
  363. XTENSOR_CONSTEXPR_RETURN auto linear_begin(xscalar<CT>& c) noexcept -> decltype(c.dummy_begin())
  364. {
  365. return c.dummy_begin();
  366. }
  367. template <class CT>
  368. XTENSOR_CONSTEXPR_RETURN auto linear_end(xscalar<CT>& c) noexcept -> decltype(c.dummy_end())
  369. {
  370. return c.dummy_end();
  371. }
  372. template <class CT>
  373. XTENSOR_CONSTEXPR_RETURN auto linear_begin(const xscalar<CT>& c) noexcept -> decltype(c.dummy_begin())
  374. {
  375. return c.dummy_begin();
  376. }
  377. template <class CT>
  378. XTENSOR_CONSTEXPR_RETURN auto linear_end(const xscalar<CT>& c) noexcept -> decltype(c.dummy_end())
  379. {
  380. return c.dummy_end();
  381. }
  382. /**************************
  383. * xscalar implementation *
  384. **************************/
  385. // This constructor will not compile when CT is a reference type.
  386. template <class CT>
  387. inline xscalar<CT>::xscalar() noexcept
  388. : m_value()
  389. {
  390. }
  391. template <class CT>
  392. inline xscalar<CT>::xscalar(CT value) noexcept
  393. : m_value(value)
  394. {
  395. }
  396. template <class CT>
  397. inline xscalar<CT>::operator value_type&() noexcept
  398. {
  399. return m_value;
  400. }
  401. template <class CT>
  402. inline xscalar<CT>::operator const value_type&() const noexcept
  403. {
  404. return m_value;
  405. }
  406. template <class CT>
  407. inline auto xscalar<CT>::size() const noexcept -> size_type
  408. {
  409. return 1;
  410. }
  411. template <class CT>
  412. inline auto xscalar<CT>::shape() const noexcept -> const shape_type&
  413. {
  414. static std::array<size_type, 0> zero_shape;
  415. return zero_shape;
  416. }
  417. template <class CT>
  418. inline auto xscalar<CT>::shape(size_type) const noexcept -> size_type
  419. {
  420. return 0;
  421. }
  422. template <class CT>
  423. inline layout_type xscalar<CT>::layout() const noexcept
  424. {
  425. return static_layout;
  426. }
  427. template <class CT>
  428. inline bool xscalar<CT>::is_contiguous() const noexcept
  429. {
  430. return true;
  431. }
  432. template <class CT>
  433. template <class... Args>
  434. inline auto xscalar<CT>::operator()(Args...) noexcept -> reference
  435. {
  436. XTENSOR_CHECK_DIMENSION((std::array<int, 0>()), Args()...);
  437. return m_value;
  438. }
  439. template <class CT>
  440. template <class... Args>
  441. inline auto xscalar<CT>::unchecked(Args...) noexcept -> reference
  442. {
  443. return m_value;
  444. }
  445. template <class CT>
  446. template <class... Args>
  447. inline auto xscalar<CT>::operator()(Args...) const noexcept -> const_reference
  448. {
  449. XTENSOR_CHECK_DIMENSION((std::array<int, 0>()), Args()...);
  450. return m_value;
  451. }
  452. template <class CT>
  453. template <class... Args>
  454. inline auto xscalar<CT>::unchecked(Args...) const noexcept -> const_reference
  455. {
  456. return m_value;
  457. }
  458. template <class CT>
  459. template <class It>
  460. inline auto xscalar<CT>::element(It, It) noexcept -> reference
  461. {
  462. return m_value;
  463. }
  464. template <class CT>
  465. template <class It>
  466. inline auto xscalar<CT>::element(It, It) const noexcept -> const_reference
  467. {
  468. return m_value;
  469. }
  470. template <class CT>
  471. inline auto xscalar<CT>::expression() noexcept -> xexpression_type&
  472. {
  473. return m_value;
  474. }
  475. template <class CT>
  476. inline auto xscalar<CT>::expression() const noexcept -> const xexpression_type&
  477. {
  478. return m_value;
  479. }
  480. template <class CT>
  481. template <class S>
  482. inline bool xscalar<CT>::broadcast_shape(S&, bool) const noexcept
  483. {
  484. return true;
  485. }
  486. template <class CT>
  487. template <class S>
  488. inline bool xscalar<CT>::has_linear_assign(const S&) const noexcept
  489. {
  490. return true;
  491. }
  492. template <class CT>
  493. template <layout_type L>
  494. inline auto xscalar<CT>::begin() noexcept -> iterator
  495. {
  496. return &m_value;
  497. }
  498. template <class CT>
  499. template <layout_type L>
  500. inline auto xscalar<CT>::end() noexcept -> iterator
  501. {
  502. return &m_value + 1;
  503. }
  504. template <class CT>
  505. template <layout_type L>
  506. inline auto xscalar<CT>::begin() const noexcept -> const_iterator
  507. {
  508. return &m_value;
  509. }
  510. template <class CT>
  511. template <layout_type L>
  512. inline auto xscalar<CT>::end() const noexcept -> const_iterator
  513. {
  514. return &m_value + 1;
  515. }
  516. template <class CT>
  517. template <layout_type L>
  518. inline auto xscalar<CT>::cbegin() const noexcept -> const_iterator
  519. {
  520. return &m_value;
  521. }
  522. template <class CT>
  523. template <layout_type L>
  524. inline auto xscalar<CT>::cend() const noexcept -> const_iterator
  525. {
  526. return &m_value + 1;
  527. }
  528. template <class CT>
  529. template <layout_type L>
  530. inline auto xscalar<CT>::rbegin() noexcept -> reverse_iterator
  531. {
  532. return reverse_iterator(end());
  533. }
  534. template <class CT>
  535. template <layout_type L>
  536. inline auto xscalar<CT>::rend() noexcept -> reverse_iterator
  537. {
  538. return reverse_iterator(begin());
  539. }
  540. template <class CT>
  541. template <layout_type L>
  542. inline auto xscalar<CT>::rbegin() const noexcept -> const_reverse_iterator
  543. {
  544. return crbegin();
  545. }
  546. template <class CT>
  547. template <layout_type L>
  548. inline auto xscalar<CT>::rend() const noexcept -> const_reverse_iterator
  549. {
  550. return crend();
  551. }
  552. template <class CT>
  553. template <layout_type L>
  554. inline auto xscalar<CT>::crbegin() const noexcept -> const_reverse_iterator
  555. {
  556. return const_reverse_iterator(cend());
  557. }
  558. template <class CT>
  559. template <layout_type L>
  560. inline auto xscalar<CT>::crend() const noexcept -> const_reverse_iterator
  561. {
  562. return const_reverse_iterator(cbegin());
  563. }
  564. /*****************************
  565. * Broadcasting iterator api *
  566. *****************************/
  567. template <class CT>
  568. template <class S, layout_type L>
  569. inline auto xscalar<CT>::begin(const S& shape) noexcept -> broadcast_iterator<S, L>
  570. {
  571. return iterable_base::template begin<S, L>(shape);
  572. }
  573. template <class CT>
  574. template <class S, layout_type L>
  575. inline auto xscalar<CT>::end(const S& shape) noexcept -> broadcast_iterator<S, L>
  576. {
  577. return iterable_base::template end<S, L>(shape);
  578. }
  579. template <class CT>
  580. template <class S, layout_type L>
  581. inline auto xscalar<CT>::begin(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
  582. {
  583. return iterable_base::template begin<S, L>(shape);
  584. }
  585. template <class CT>
  586. template <class S, layout_type L>
  587. inline auto xscalar<CT>::end(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
  588. {
  589. return iterable_base::template end<S, L>(shape);
  590. }
  591. template <class CT>
  592. template <class S, layout_type L>
  593. inline auto xscalar<CT>::cbegin(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
  594. {
  595. return iterable_base::template cbegin<S, L>(shape);
  596. }
  597. template <class CT>
  598. template <class S, layout_type L>
  599. inline auto xscalar<CT>::cend(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
  600. {
  601. return iterable_base::template cend<S, L>(shape);
  602. }
  603. template <class CT>
  604. template <class S, layout_type L>
  605. inline auto xscalar<CT>::rbegin(const S& shape) noexcept -> reverse_broadcast_iterator<S, L>
  606. {
  607. return iterable_base::template rbegin<S, L>(shape);
  608. }
  609. template <class CT>
  610. template <class S, layout_type L>
  611. inline auto xscalar<CT>::rend(const S& shape) noexcept -> reverse_broadcast_iterator<S, L>
  612. {
  613. return iterable_base::template rend<S, L>(shape);
  614. }
  615. template <class CT>
  616. template <class S, layout_type L>
  617. inline auto xscalar<CT>::rbegin(const S& shape) const noexcept -> const_reverse_broadcast_iterator<S, L>
  618. {
  619. return iterable_base::template rbegin<S, L>(shape);
  620. }
  621. template <class CT>
  622. template <class S, layout_type L>
  623. inline auto xscalar<CT>::rend(const S& shape) const noexcept -> const_reverse_broadcast_iterator<S, L>
  624. {
  625. return iterable_base::template rend<S, L>(shape);
  626. }
  627. template <class CT>
  628. template <class S, layout_type L>
  629. inline auto xscalar<CT>::crbegin(const S& shape) const noexcept -> const_reverse_broadcast_iterator<S, L>
  630. {
  631. return iterable_base::template crbegin<S, L>(shape);
  632. }
  633. template <class CT>
  634. template <class S, layout_type L>
  635. inline auto xscalar<CT>::crend(const S& shape) const noexcept -> const_reverse_broadcast_iterator<S, L>
  636. {
  637. return iterable_base::template crend<S, L>(shape);
  638. }
  639. template <class CT>
  640. inline auto xscalar<CT>::linear_begin() noexcept -> iterator
  641. {
  642. return this->template begin<XTENSOR_DEFAULT_LAYOUT>();
  643. }
  644. template <class CT>
  645. inline auto xscalar<CT>::linear_end() noexcept -> iterator
  646. {
  647. return this->template end<XTENSOR_DEFAULT_LAYOUT>();
  648. }
  649. template <class CT>
  650. inline auto xscalar<CT>::linear_begin() const noexcept -> const_iterator
  651. {
  652. return this->template begin<XTENSOR_DEFAULT_LAYOUT>();
  653. }
  654. template <class CT>
  655. inline auto xscalar<CT>::linear_end() const noexcept -> const_iterator
  656. {
  657. return this->template end<XTENSOR_DEFAULT_LAYOUT>();
  658. }
  659. template <class CT>
  660. inline auto xscalar<CT>::linear_cbegin() const noexcept -> const_iterator
  661. {
  662. return this->template cbegin<XTENSOR_DEFAULT_LAYOUT>();
  663. }
  664. template <class CT>
  665. inline auto xscalar<CT>::linear_cend() const noexcept -> const_iterator
  666. {
  667. return this->template cend<XTENSOR_DEFAULT_LAYOUT>();
  668. }
  669. template <class CT>
  670. inline auto xscalar<CT>::linear_rbegin() noexcept -> reverse_iterator
  671. {
  672. return this->template rbegin<XTENSOR_DEFAULT_LAYOUT>();
  673. }
  674. template <class CT>
  675. inline auto xscalar<CT>::linear_rend() noexcept -> reverse_iterator
  676. {
  677. return this->template rend<XTENSOR_DEFAULT_LAYOUT>();
  678. }
  679. template <class CT>
  680. inline auto xscalar<CT>::linear_rbegin() const noexcept -> const_reverse_iterator
  681. {
  682. return this->template rbegin<XTENSOR_DEFAULT_LAYOUT>();
  683. }
  684. template <class CT>
  685. inline auto xscalar<CT>::linear_rend() const noexcept -> const_reverse_iterator
  686. {
  687. return this->template rend<XTENSOR_DEFAULT_LAYOUT>();
  688. }
  689. template <class CT>
  690. inline auto xscalar<CT>::linear_crbegin() const noexcept -> const_reverse_iterator
  691. {
  692. return this->template crbegin<XTENSOR_DEFAULT_LAYOUT>();
  693. }
  694. template <class CT>
  695. inline auto xscalar<CT>::linear_crend() const noexcept -> const_reverse_iterator
  696. {
  697. return this->template crend<XTENSOR_DEFAULT_LAYOUT>();
  698. }
  699. template <class CT>
  700. template <class S>
  701. inline auto xscalar<CT>::stepper_begin(const S&) noexcept -> stepper
  702. {
  703. return stepper(this, false);
  704. }
  705. template <class CT>
  706. template <class S>
  707. inline auto xscalar<CT>::stepper_end(const S&, layout_type) noexcept -> stepper
  708. {
  709. return stepper(this);
  710. }
  711. template <class CT>
  712. template <class S>
  713. inline auto xscalar<CT>::stepper_begin(const S&) const noexcept -> const_stepper
  714. {
  715. return const_stepper(this);
  716. }
  717. template <class CT>
  718. template <class S>
  719. inline auto xscalar<CT>::stepper_end(const S&, layout_type) const noexcept -> const_stepper
  720. {
  721. return const_stepper(this);
  722. }
  723. template <class CT>
  724. inline auto xscalar<CT>::dummy_begin() noexcept -> dummy_iterator
  725. {
  726. return dummy_iterator(this);
  727. }
  728. template <class CT>
  729. inline auto xscalar<CT>::dummy_end() noexcept -> dummy_iterator
  730. {
  731. return dummy_iterator(this);
  732. }
  733. template <class CT>
  734. inline auto xscalar<CT>::dummy_begin() const noexcept -> const_dummy_iterator
  735. {
  736. return const_dummy_iterator(this);
  737. }
  738. template <class CT>
  739. inline auto xscalar<CT>::dummy_end() const noexcept -> const_dummy_iterator
  740. {
  741. return const_dummy_iterator(this);
  742. }
  743. template <class CT>
  744. inline auto xscalar<CT>::data_element(size_type) noexcept -> reference
  745. {
  746. return m_value;
  747. }
  748. template <class CT>
  749. inline auto xscalar<CT>::data_element(size_type) const noexcept -> const_reference
  750. {
  751. return m_value;
  752. }
  753. template <class CT>
  754. inline auto xscalar<CT>::flat(size_type) noexcept -> reference
  755. {
  756. return m_value;
  757. }
  758. template <class CT>
  759. inline auto xscalar<CT>::flat(size_type) const noexcept -> const_reference
  760. {
  761. return m_value;
  762. }
  763. template <class CT>
  764. template <class align, class simd>
  765. inline void xscalar<CT>::store_simd(size_type, const simd& e)
  766. {
  767. m_value = static_cast<value_type>(e[0]);
  768. }
  769. template <class CT>
  770. template <class align, class requested_type, std::size_t N>
  771. inline auto xscalar<CT>::load_simd(size_type) const
  772. -> xt_simd::simd_return_type<value_type, requested_type>
  773. {
  774. return xt_simd::broadcast_as<requested_type>(m_value);
  775. }
  776. template <class T>
  777. inline xscalar<T&> xref(T& t)
  778. {
  779. return xscalar<T&>(t);
  780. }
  781. template <class T>
  782. inline xscalar<const T&> xcref(T& t)
  783. {
  784. return xscalar<const T&>(t);
  785. }
  786. /**********************************
  787. * xscalar_stepper implementation *
  788. **********************************/
  789. template <bool is_const, class CT>
  790. inline xscalar_stepper<is_const, CT>::xscalar_stepper(storage_type* c) noexcept
  791. : p_c(c)
  792. {
  793. }
  794. template <bool is_const, class CT>
  795. inline auto xscalar_stepper<is_const, CT>::operator*() const noexcept -> reference
  796. {
  797. return p_c->operator()();
  798. }
  799. template <bool is_const, class CT>
  800. inline void xscalar_stepper<is_const, CT>::step(size_type /*dim*/, size_type /*n*/) noexcept
  801. {
  802. }
  803. template <bool is_const, class CT>
  804. inline void xscalar_stepper<is_const, CT>::step_back(size_type /*dim*/, size_type /*n*/) noexcept
  805. {
  806. }
  807. template <bool is_const, class CT>
  808. inline void xscalar_stepper<is_const, CT>::reset(size_type /*dim*/) noexcept
  809. {
  810. }
  811. template <bool is_const, class CT>
  812. inline void xscalar_stepper<is_const, CT>::reset_back(size_type /*dim*/) noexcept
  813. {
  814. }
  815. template <bool is_const, class CT>
  816. inline void xscalar_stepper<is_const, CT>::to_begin() noexcept
  817. {
  818. }
  819. template <bool is_const, class CT>
  820. inline void xscalar_stepper<is_const, CT>::to_end(layout_type /*l*/) noexcept
  821. {
  822. }
  823. template <bool is_const, class CT>
  824. template <class T>
  825. inline auto xscalar_stepper<is_const, CT>::step_simd() -> simd_return_type<T>
  826. {
  827. return simd_return_type<T>(p_c->operator()());
  828. }
  829. template <bool is_const, class CT>
  830. inline void xscalar_stepper<is_const, CT>::step_leading()
  831. {
  832. }
  833. /**********************************
  834. * xdummy_iterator implementation *
  835. **********************************/
  836. template <bool is_const, class CT>
  837. inline xdummy_iterator<is_const, CT>::xdummy_iterator(storage_type* c) noexcept
  838. : p_c(c)
  839. {
  840. }
  841. template <bool is_const, class CT>
  842. inline auto xdummy_iterator<is_const, CT>::operator++() noexcept -> self_type&
  843. {
  844. return *this;
  845. }
  846. template <bool is_const, class CT>
  847. inline auto xdummy_iterator<is_const, CT>::operator--() noexcept -> self_type&
  848. {
  849. return *this;
  850. }
  851. template <bool is_const, class CT>
  852. inline auto xdummy_iterator<is_const, CT>::operator+=(difference_type) noexcept -> self_type&
  853. {
  854. return *this;
  855. }
  856. template <bool is_const, class CT>
  857. inline auto xdummy_iterator<is_const, CT>::operator-=(difference_type) noexcept -> self_type&
  858. {
  859. return *this;
  860. }
  861. template <bool is_const, class CT>
  862. inline auto xdummy_iterator<is_const, CT>::operator-(const self_type&) const noexcept -> difference_type
  863. {
  864. return 0;
  865. }
  866. template <bool is_const, class CT>
  867. inline auto xdummy_iterator<is_const, CT>::operator*() const noexcept -> reference
  868. {
  869. return p_c->operator()();
  870. }
  871. template <bool is_const, class CT>
  872. inline bool xdummy_iterator<is_const, CT>::equal(const self_type& rhs) const noexcept
  873. {
  874. return p_c == rhs.p_c;
  875. }
  876. template <bool is_const, class CT>
  877. inline bool xdummy_iterator<is_const, CT>::less_than(const self_type& rhs) const noexcept
  878. {
  879. return p_c < rhs.p_c;
  880. }
  881. template <bool is_const, class CT>
  882. inline bool
  883. operator==(const xdummy_iterator<is_const, CT>& lhs, const xdummy_iterator<is_const, CT>& rhs) noexcept
  884. {
  885. return lhs.equal(rhs);
  886. }
  887. template <bool is_const, class CT>
  888. inline bool
  889. operator<(const xdummy_iterator<is_const, CT>& lhs, const xdummy_iterator<is_const, CT>& rhs) noexcept
  890. {
  891. return lhs.less_than(rhs);
  892. }
  893. }
  894. #endif