xfunctor_view.hpp 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649
  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_FUNCTOR_VIEW_HPP
  10. #define XTENSOR_FUNCTOR_VIEW_HPP
  11. #include <algorithm>
  12. #include <array>
  13. #include <cstddef>
  14. #include <type_traits>
  15. #include <utility>
  16. #include <xtl/xproxy_wrapper.hpp>
  17. #include "xaccessible.hpp"
  18. #include "xarray.hpp"
  19. #include "xexpression.hpp"
  20. #include "xiterator.hpp"
  21. #include "xsemantic.hpp"
  22. #include "xtensor.hpp"
  23. #include "xutils.hpp"
  24. namespace xt
  25. {
  26. /**
  27. * @defgroup xt_xfunctor_view
  28. *
  29. * Chunked array container.
  30. * Defined in ``xtensor/xfunctor_view.hpp``
  31. */
  32. /************************************************
  33. * xfunctor_view and xfunctor_adaptor extension *
  34. ************************************************/
  35. namespace extension
  36. {
  37. template <class Tag, class F, class CT>
  38. struct xfunctor_view_base_impl;
  39. template <class F, class CT>
  40. struct xfunctor_view_base_impl<xtensor_expression_tag, F, CT>
  41. {
  42. using type = xtensor_empty_base;
  43. };
  44. template <class F, class CT>
  45. struct xfunctor_view_base : xfunctor_view_base_impl<xexpression_tag_t<CT>, F, CT>
  46. {
  47. };
  48. template <class F, class CT>
  49. using xfunctor_view_base_t = typename xfunctor_view_base<F, CT>::type;
  50. }
  51. /*************************************
  52. * xfunctor_applier_base declaration *
  53. *************************************/
  54. template <class F, class IT>
  55. class xfunctor_iterator;
  56. template <class F, class ST>
  57. class xfunctor_stepper;
  58. template <class D>
  59. class xfunctor_applier_base : private xaccessible<D>
  60. {
  61. public:
  62. using self_type = xfunctor_applier_base<D>;
  63. using inner_types = xcontainer_inner_types<D>;
  64. using xexpression_type = typename inner_types::xexpression_type;
  65. using undecay_expression = typename inner_types::undecay_expression;
  66. using functor_type = typename inner_types::functor_type;
  67. using accessible_base = xaccessible<D>;
  68. using extension_base = extension::xfunctor_view_base_t<functor_type, undecay_expression>;
  69. using expression_tag = typename extension_base::expression_tag;
  70. using value_type = typename functor_type::value_type;
  71. using reference = typename inner_types::reference;
  72. using const_reference = typename inner_types::const_reference;
  73. using pointer = typename functor_type::pointer;
  74. using const_pointer = typename functor_type::const_pointer;
  75. using size_type = typename inner_types::size_type;
  76. using difference_type = typename xexpression_type::difference_type;
  77. using shape_type = typename xexpression_type::shape_type;
  78. using strides_type = xtl::mpl::eval_if_t<
  79. has_strides<xexpression_type>,
  80. detail::expr_strides_type<xexpression_type>,
  81. get_strides_type<shape_type>>;
  82. using backstrides_type = xtl::mpl::eval_if_t<
  83. has_strides<xexpression_type>,
  84. detail::expr_backstrides_type<xexpression_type>,
  85. get_strides_type<shape_type>>;
  86. using inner_shape_type = typename xexpression_type::inner_shape_type;
  87. using inner_strides_type = xtl::mpl::eval_if_t<
  88. has_strides<xexpression_type>,
  89. detail::expr_inner_strides_type<xexpression_type>,
  90. get_strides_type<shape_type>>;
  91. using inner_backstrides_type = xtl::mpl::eval_if_t<
  92. has_strides<xexpression_type>,
  93. detail::expr_inner_backstrides_type<xexpression_type>,
  94. get_strides_type<shape_type>>;
  95. using bool_load_type = xt::bool_load_type<value_type>;
  96. static constexpr layout_type static_layout = xexpression_type::static_layout;
  97. static constexpr bool contiguous_layout = xexpression_type::contiguous_layout;
  98. using stepper = xfunctor_stepper<functor_type, typename xexpression_type::stepper>;
  99. using const_stepper = xfunctor_stepper<const functor_type, typename xexpression_type::const_stepper>;
  100. template <layout_type L>
  101. using layout_iterator = xfunctor_iterator<functor_type, typename xexpression_type::template layout_iterator<L>>;
  102. template <layout_type L>
  103. using const_layout_iterator = xfunctor_iterator<
  104. const functor_type,
  105. typename xexpression_type::template const_layout_iterator<L>>;
  106. template <layout_type L>
  107. using reverse_layout_iterator = xfunctor_iterator<
  108. functor_type,
  109. typename xexpression_type::template reverse_layout_iterator<L>>;
  110. template <layout_type L>
  111. using const_reverse_layout_iterator = xfunctor_iterator<
  112. const functor_type,
  113. typename xexpression_type::template const_reverse_layout_iterator<L>>;
  114. template <class S, layout_type L>
  115. using broadcast_iterator = xfunctor_iterator<functor_type, xiterator<typename xexpression_type::stepper, S, L>>;
  116. template <class S, layout_type L>
  117. using const_broadcast_iterator = xfunctor_iterator<
  118. functor_type,
  119. xiterator<typename xexpression_type::const_stepper, S, L>>;
  120. template <class S, layout_type L>
  121. using reverse_broadcast_iterator = xfunctor_iterator<
  122. functor_type,
  123. typename xexpression_type::template reverse_broadcast_iterator<S, L>>;
  124. template <class S, layout_type L>
  125. using const_reverse_broadcast_iterator = xfunctor_iterator<
  126. functor_type,
  127. typename xexpression_type::template const_reverse_broadcast_iterator<S, L>>;
  128. using linear_iterator = xfunctor_iterator<functor_type, typename xexpression_type::linear_iterator>;
  129. using const_linear_iterator = xfunctor_iterator<const functor_type, typename xexpression_type::const_linear_iterator>;
  130. using reverse_linear_iterator = xfunctor_iterator<functor_type, typename xexpression_type::reverse_linear_iterator>;
  131. using const_reverse_linear_iterator = xfunctor_iterator<
  132. const functor_type,
  133. typename xexpression_type::const_reverse_linear_iterator>;
  134. using iterator = xfunctor_iterator<functor_type, typename xexpression_type::iterator>;
  135. using const_iterator = xfunctor_iterator<const functor_type, typename xexpression_type::const_iterator>;
  136. using reverse_iterator = xfunctor_iterator<functor_type, typename xexpression_type::reverse_iterator>;
  137. using const_reverse_iterator = xfunctor_iterator<const functor_type, typename xexpression_type::const_reverse_iterator>;
  138. explicit xfunctor_applier_base(undecay_expression) noexcept;
  139. template <class Func, class E>
  140. xfunctor_applier_base(Func&&, E&&) noexcept;
  141. size_type size() const noexcept;
  142. const inner_shape_type& shape() const noexcept;
  143. const inner_strides_type& strides() const noexcept;
  144. const inner_backstrides_type& backstrides() const noexcept;
  145. using accessible_base::dimension;
  146. using accessible_base::shape;
  147. layout_type layout() const noexcept;
  148. bool is_contiguous() const noexcept;
  149. template <class... Args>
  150. reference operator()(Args... args);
  151. template <class... Args>
  152. reference unchecked(Args... args);
  153. template <class IT>
  154. reference element(IT first, IT last);
  155. template <class... Args>
  156. const_reference operator()(Args... args) const;
  157. template <class... Args>
  158. const_reference unchecked(Args... args) const;
  159. template <class IT>
  160. const_reference element(IT first, IT last) const;
  161. using accessible_base::at;
  162. using accessible_base::operator[];
  163. using accessible_base::back;
  164. using accessible_base::front;
  165. using accessible_base::periodic;
  166. using accessible_base::in_bounds;
  167. xexpression_type& expression() noexcept;
  168. const xexpression_type& expression() const noexcept;
  169. template <class S>
  170. bool broadcast_shape(S& shape, bool reuse_cache = false) const;
  171. template <class S>
  172. bool has_linear_assign(const S& strides) const;
  173. template <class FCT = functor_type>
  174. auto data_element(size_type i)
  175. -> decltype(std::declval<FCT>()(std::declval<undecay_expression>().data_element(i)))
  176. {
  177. return m_functor(m_e.data_element(i));
  178. }
  179. template <class FCT = functor_type>
  180. auto data_element(size_type i) const
  181. -> decltype(std::declval<FCT>()(std::declval<const undecay_expression>().data_element(i)))
  182. {
  183. return m_functor(m_e.data_element(i));
  184. }
  185. template <class FCT = functor_type>
  186. auto flat(size_type i) -> decltype(std::declval<FCT>()(std::declval<undecay_expression>().flat(i)))
  187. {
  188. return m_functor(m_e.flat(i));
  189. }
  190. template <class FCT = functor_type>
  191. auto flat(size_type i) const
  192. -> decltype(std::declval<FCT>()(std::declval<const undecay_expression>().flat(i)))
  193. {
  194. return m_functor(m_e.flat(i));
  195. }
  196. // The following functions are defined inline because otherwise signatures
  197. // don't match on GCC.
  198. template <
  199. class align,
  200. class requested_type = typename xexpression_type::value_type,
  201. std::size_t N = xt_simd::simd_traits<requested_type>::size,
  202. class FCT = functor_type>
  203. auto load_simd(size_type i) const
  204. -> decltype(std::declval<FCT>().template proxy_simd_load<align, requested_type, N>(
  205. std::declval<undecay_expression>(),
  206. i
  207. ))
  208. {
  209. return m_functor.template proxy_simd_load<align, requested_type, N>(m_e, i);
  210. }
  211. template <class align, class simd, class FCT = functor_type>
  212. auto store_simd(size_type i, const simd& e)
  213. -> decltype(std::declval<FCT>()
  214. .template proxy_simd_store<align>(std::declval<undecay_expression>(), i, e))
  215. {
  216. return m_functor.template proxy_simd_store<align>(m_e, i, e);
  217. }
  218. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  219. auto begin() noexcept;
  220. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  221. auto end() noexcept;
  222. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  223. auto begin() const noexcept;
  224. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  225. auto end() const noexcept;
  226. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  227. auto cbegin() const noexcept;
  228. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  229. auto cend() const noexcept;
  230. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  231. auto rbegin() noexcept;
  232. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  233. auto rend() noexcept;
  234. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  235. auto rbegin() const noexcept;
  236. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  237. auto rend() const noexcept;
  238. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  239. auto crbegin() const noexcept;
  240. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  241. auto crend() const noexcept;
  242. template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  243. broadcast_iterator<S, L> begin(const S& shape) noexcept;
  244. template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  245. broadcast_iterator<S, L> end(const S& shape) noexcept;
  246. template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  247. const_broadcast_iterator<S, L> begin(const S& shape) const noexcept;
  248. template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  249. const_broadcast_iterator<S, L> end(const S& shape) const noexcept;
  250. template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  251. const_broadcast_iterator<S, L> cbegin(const S& shape) const noexcept;
  252. template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  253. const_broadcast_iterator<S, L> cend(const S& shape) const noexcept;
  254. template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  255. reverse_broadcast_iterator<S, L> rbegin(const S& shape) noexcept;
  256. template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  257. reverse_broadcast_iterator<S, L> rend(const S& shape) noexcept;
  258. template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  259. const_reverse_broadcast_iterator<S, L> rbegin(const S& shape) const noexcept;
  260. template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  261. const_reverse_broadcast_iterator<S, L> rend(const S& shape) const noexcept;
  262. template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  263. const_reverse_broadcast_iterator<S, L> crbegin(const S& shape) const noexcept;
  264. template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  265. const_reverse_broadcast_iterator<S, L> crend(const S& shape) const noexcept;
  266. linear_iterator linear_begin() noexcept;
  267. linear_iterator linear_end() noexcept;
  268. const_linear_iterator linear_begin() const noexcept;
  269. const_linear_iterator linear_end() const noexcept;
  270. const_linear_iterator linear_cbegin() const noexcept;
  271. const_linear_iterator linear_cend() const noexcept;
  272. reverse_linear_iterator linear_rbegin() noexcept;
  273. reverse_linear_iterator linear_rend() noexcept;
  274. const_reverse_linear_iterator linear_rbegin() const noexcept;
  275. const_reverse_linear_iterator linear_rend() const noexcept;
  276. const_reverse_linear_iterator linear_crbegin() const noexcept;
  277. const_reverse_linear_iterator linear_crend() const noexcept;
  278. template <class S>
  279. stepper stepper_begin(const S& shape) noexcept;
  280. template <class S>
  281. stepper stepper_end(const S& shape, layout_type l) noexcept;
  282. template <class S>
  283. const_stepper stepper_begin(const S& shape) const noexcept;
  284. template <class S>
  285. const_stepper stepper_end(const S& shape, layout_type l) const noexcept;
  286. protected:
  287. undecay_expression m_e;
  288. functor_type m_functor;
  289. private:
  290. friend class xaccessible<D>;
  291. friend class xconst_accessible<D>;
  292. };
  293. template <class D, class T>
  294. struct has_simd_interface<xfunctor_applier_base<D>, T>
  295. : xtl::conjunction<
  296. has_simd_type<T>,
  297. has_simd_interface<typename xfunctor_applier_base<D>::xexpression_type>,
  298. detail::has_simd_interface_impl<xfunctor_applier_base<D>, T>>
  299. {
  300. };
  301. /********************************
  302. * xfunctor_view_temporary_type *
  303. ********************************/
  304. namespace detail
  305. {
  306. // TODO replace with xexpression_for_shape ...
  307. template <class F, class S, layout_type L>
  308. struct functorview_temporary_type_impl
  309. {
  310. using type = xarray<typename F::value_type, L>;
  311. };
  312. template <class F, class T, std::size_t N, layout_type L>
  313. struct functorview_temporary_type_impl<F, std::array<T, N>, L>
  314. {
  315. using type = xtensor<typename F::value_type, N, L>;
  316. };
  317. }
  318. template <class F, class E>
  319. struct xfunctor_view_temporary_type
  320. {
  321. using type = typename detail::functorview_temporary_type_impl<F, typename E::shape_type, E::static_layout>::type;
  322. };
  323. /*****************************
  324. * xfunctor_view declaration *
  325. *****************************/
  326. template <class F, class CT>
  327. class xfunctor_view;
  328. template <class F, class CT>
  329. struct xcontainer_inner_types<xfunctor_view<F, CT>>
  330. {
  331. using xexpression_type = std::decay_t<CT>;
  332. using undecay_expression = CT;
  333. using functor_type = std::decay_t<F>;
  334. using reference = decltype(std::declval<F>()(std::declval<xexpression_type>()()));
  335. using const_reference = decltype(std::declval<F>()(std::declval<const xexpression_type>()()));
  336. using size_type = typename xexpression_type::size_type;
  337. using temporary_type = typename xfunctor_view_temporary_type<F, xexpression_type>::type;
  338. };
  339. template <class F, class CT, class T>
  340. struct has_simd_interface<xfunctor_view<F, CT>, T>
  341. : has_simd_interface<xfunctor_applier_base<xfunctor_view<F, CT>>, T>
  342. {
  343. };
  344. /**
  345. * View of an xexpression .
  346. *
  347. * The xt::xfunctor_view class is an expression addressing its elements by applying a functor to the
  348. * corresponding element of an underlying expression.
  349. * Unlike e.g. xgenerator, an xt::xfunctor_view is an lvalue.
  350. * It is used e.g. to access real and imaginary parts of complex expressions.
  351. *
  352. * xt::xfunctor_view has a view semantics and can be used on any expression.
  353. * For a similar feature with a container semantics, one can use xt::xfunctor_adaptor.
  354. *
  355. * xt::xfunctor_view is not meant to be used directly, but through helper functions such
  356. * as xt::real or xt::imag.
  357. *
  358. * @ingroup xt_xfunctor_view
  359. * @tparam F the functor type to be applied to the elements of specified expression.
  360. * @tparam CT the closure type of the xt::xexpression type underlying this view
  361. * @see xt::real, xt::imag
  362. */
  363. template <class F, class CT>
  364. class xfunctor_view : public xfunctor_applier_base<xfunctor_view<F, CT>>,
  365. public xview_semantic<xfunctor_view<F, CT>>,
  366. public extension::xfunctor_view_base_t<F, CT>
  367. {
  368. public:
  369. using self_type = xfunctor_view<F, CT>;
  370. using semantic_base = xview_semantic<self_type>;
  371. // constructors
  372. using xfunctor_applier_base<self_type>::xfunctor_applier_base;
  373. template <class E>
  374. self_type& operator=(const xexpression<E>& e);
  375. template <class E>
  376. disable_xexpression<E, self_type>& operator=(const E& e);
  377. template <class E>
  378. using rebind_t = xfunctor_view<F, E>;
  379. template <class E>
  380. rebind_t<E> build_functor_view(E&& e) const;
  381. private:
  382. using temporary_type = typename xcontainer_inner_types<self_type>::temporary_type;
  383. void assign_temporary_impl(temporary_type&& tmp);
  384. friend class xview_semantic<self_type>;
  385. friend class xaccessible<self_type>;
  386. };
  387. /********************************
  388. * xfunctor_adaptor declaration *
  389. ********************************/
  390. template <class F, class CT>
  391. class xfunctor_adaptor;
  392. template <class F, class CT>
  393. struct xcontainer_inner_types<xfunctor_adaptor<F, CT>>
  394. {
  395. using xexpression_type = std::decay_t<CT>;
  396. using undecay_expression = CT;
  397. using functor_type = std::decay_t<F>;
  398. using reference = typename functor_type::reference;
  399. using const_reference = typename functor_type::const_reference;
  400. using size_type = typename xexpression_type::size_type;
  401. using temporary_type = typename xfunctor_view_temporary_type<F, xexpression_type>::type;
  402. };
  403. template <class F, class CT, class T>
  404. struct has_simd_interface<xfunctor_adaptor<F, CT>, T>
  405. : has_simd_interface<xfunctor_applier_base<xfunctor_adaptor<F, CT>>, T>
  406. {
  407. };
  408. /**
  409. * Adapt a container with a functor, forwarding methods such as resize / reshape.
  410. *
  411. * xt::xfunctor_adaptor has a container semantics and can only be used with containers.
  412. * For a similar feature with a view semantics, one can use xt::xfunctor_view.
  413. *
  414. * @ingroup xt_xfunctor_view
  415. * @tparam F the functor type to be applied to the elements of specified expression.
  416. * @tparam CT the closure type of the xt::xexpression type underlying this view
  417. * @see xt::xfunctor_view
  418. */
  419. template <class F, class CT>
  420. class xfunctor_adaptor : public xfunctor_applier_base<xfunctor_adaptor<F, CT>>,
  421. public xcontainer_semantic<xfunctor_adaptor<F, CT>>,
  422. public extension::xfunctor_view_base_t<F, CT>
  423. {
  424. public:
  425. using self_type = xfunctor_adaptor<F, CT>;
  426. using semantic_base = xcontainer_semantic<self_type>;
  427. using xexpression_type = std::decay_t<CT>;
  428. using base_type = xfunctor_applier_base<self_type>;
  429. using shape_type = typename base_type::shape_type;
  430. using strides_type = typename xexpression_type::strides_type;
  431. // constructors
  432. using xfunctor_applier_base<self_type>::xfunctor_applier_base;
  433. template <class E>
  434. self_type& operator=(const xexpression<E>& e);
  435. template <class E>
  436. disable_xexpression<E, self_type>& operator=(const E& e);
  437. template <class S = shape_type>
  438. auto resize(S&& shape, bool force = false);
  439. template <class S = shape_type>
  440. auto resize(S&& shape, layout_type l);
  441. template <class S = shape_type>
  442. auto resize(S&& shape, const strides_type& strides);
  443. template <class S = shape_type>
  444. auto& reshape(S&& shape, layout_type layout = base_type::static_layout) &;
  445. private:
  446. using temporary_type = typename xcontainer_inner_types<self_type>::temporary_type;
  447. void assign_temporary_impl(temporary_type&& tmp);
  448. friend class xcontainer_semantic<self_type>;
  449. friend class xaccessible<self_type>;
  450. };
  451. /*********************************
  452. * xfunctor_iterator declaration *
  453. *********************************/
  454. template <class R>
  455. struct xproxy_inner_types
  456. {
  457. using reference = R;
  458. using pointer = std::add_pointer_t<std::remove_reference_t<R>>;
  459. };
  460. namespace detail
  461. {
  462. template <class F, class IT>
  463. struct xfunctor_invoker
  464. {
  465. using type = decltype(std::declval<F>()(*(std::declval<IT>())));
  466. };
  467. template <class F, class IT>
  468. using xfunctor_invoker_t = typename xfunctor_invoker<F, IT>::type;
  469. }
  470. template <class F, class IT>
  471. class xfunctor_iterator : public xtl::xrandom_access_iterator_base<
  472. xfunctor_iterator<F, IT>,
  473. typename std::decay_t<F>::value_type,
  474. typename std::iterator_traits<IT>::difference_type,
  475. typename xproxy_inner_types<detail::xfunctor_invoker_t<F, IT>>::pointer,
  476. typename xproxy_inner_types<detail::xfunctor_invoker_t<F, IT>>::reference>
  477. {
  478. public:
  479. using functor_type = F;
  480. using subiterator_traits = std::iterator_traits<IT>;
  481. using proxy_inner = xproxy_inner_types<detail::xfunctor_invoker_t<F, IT>>;
  482. using value_type = typename functor_type::value_type;
  483. using reference = typename proxy_inner::reference;
  484. using pointer = typename proxy_inner::pointer;
  485. using difference_type = typename subiterator_traits::difference_type;
  486. using iterator_category = typename subiterator_traits::iterator_category;
  487. using self_type = xfunctor_iterator<F, IT>;
  488. xfunctor_iterator(const IT&, functor_type*);
  489. self_type& operator++();
  490. self_type& operator--();
  491. self_type& operator+=(difference_type n);
  492. self_type& operator-=(difference_type n);
  493. difference_type operator-(xfunctor_iterator rhs) const;
  494. reference operator*() const;
  495. pointer operator->() const;
  496. bool equal(const xfunctor_iterator& rhs) const;
  497. bool less_than(const xfunctor_iterator& rhs) const;
  498. private:
  499. IT m_it;
  500. functor_type* p_functor;
  501. };
  502. template <class F, class IT>
  503. bool operator==(const xfunctor_iterator<F, IT>& lhs, const xfunctor_iterator<F, IT>& rhs);
  504. template <class F, class IT>
  505. bool operator<(const xfunctor_iterator<F, IT>& lhs, const xfunctor_iterator<F, IT>& rhs);
  506. /********************************
  507. * xfunctor_stepper declaration *
  508. ********************************/
  509. template <class F, class ST>
  510. class xfunctor_stepper
  511. {
  512. public:
  513. using functor_type = F;
  514. using proxy_inner = xproxy_inner_types<detail::xfunctor_invoker_t<F, ST>>;
  515. using value_type = typename functor_type::value_type;
  516. using reference = typename proxy_inner::reference;
  517. using pointer = std::remove_reference_t<reference>*;
  518. using size_type = typename ST::size_type;
  519. using difference_type = typename ST::difference_type;
  520. using shape_type = typename ST::shape_type;
  521. xfunctor_stepper() = default;
  522. xfunctor_stepper(const ST&, functor_type*);
  523. reference operator*() const;
  524. void step(size_type dim);
  525. void step_back(size_type dim);
  526. void step(size_type dim, size_type n);
  527. void step_back(size_type dim, size_type n);
  528. void reset(size_type dim);
  529. void reset_back(size_type dim);
  530. void to_begin();
  531. void to_end(layout_type);
  532. private:
  533. ST m_stepper;
  534. functor_type* p_functor;
  535. };
  536. /****************************************
  537. * xfunctor_applier_base implementation *
  538. ****************************************/
  539. /**
  540. * @name Constructors
  541. */
  542. //@{
  543. /**
  544. * Constructs an xfunctor_applier_base expression wrappering the specified xt::xexpression.
  545. *
  546. * @param e the underlying expression
  547. */
  548. template <class D>
  549. inline xfunctor_applier_base<D>::xfunctor_applier_base(undecay_expression e) noexcept
  550. : m_e(e)
  551. , m_functor(functor_type())
  552. {
  553. }
  554. /**
  555. * Constructs an xfunctor_applier_base expression wrappering the specified xt::xexpression.
  556. *
  557. * @param func the functor to be applied to the elements of the underlying expression.
  558. * @param e the underlying expression
  559. */
  560. template <class D>
  561. template <class Func, class E>
  562. inline xfunctor_applier_base<D>::xfunctor_applier_base(Func&& func, E&& e) noexcept
  563. : m_e(std::forward<E>(e))
  564. , m_functor(std::forward<Func>(func))
  565. {
  566. }
  567. //@}
  568. /**
  569. * @name Size and shape
  570. */
  571. /**
  572. * Returns the size of the expression.
  573. */
  574. template <class D>
  575. inline auto xfunctor_applier_base<D>::size() const noexcept -> size_type
  576. {
  577. return m_e.size();
  578. }
  579. /**
  580. * Returns the shape of the expression.
  581. */
  582. template <class D>
  583. inline auto xfunctor_applier_base<D>::shape() const noexcept -> const inner_shape_type&
  584. {
  585. return m_e.shape();
  586. }
  587. /**
  588. * Returns the strides of the expression.
  589. */
  590. template <class D>
  591. inline auto xfunctor_applier_base<D>::strides() const noexcept -> const inner_strides_type&
  592. {
  593. return m_e.strides();
  594. }
  595. /**
  596. * Returns the backstrides of the expression.
  597. */
  598. template <class D>
  599. inline auto xfunctor_applier_base<D>::backstrides() const noexcept -> const inner_backstrides_type&
  600. {
  601. return m_e.backstrides();
  602. }
  603. /**
  604. * Returns the layout_type of the expression.
  605. */
  606. template <class D>
  607. inline layout_type xfunctor_applier_base<D>::layout() const noexcept
  608. {
  609. return m_e.layout();
  610. }
  611. template <class D>
  612. inline bool xfunctor_applier_base<D>::is_contiguous() const noexcept
  613. {
  614. return m_e.is_contiguous();
  615. }
  616. //@}
  617. /**
  618. * @name Data
  619. */
  620. /**
  621. * Returns a reference to the element at the specified position in the expression.
  622. * @param args a list of indices specifying the position in the function. Indices
  623. * must be unsigned integers, the number of indices should be equal or greater than
  624. * the number of dimensions of the expression.
  625. */
  626. template <class D>
  627. template <class... Args>
  628. inline auto xfunctor_applier_base<D>::operator()(Args... args) -> reference
  629. {
  630. XTENSOR_TRY(check_index(shape(), args...));
  631. XTENSOR_CHECK_DIMENSION(shape(), args...);
  632. return m_functor(m_e(args...));
  633. }
  634. /**
  635. * Returns a reference to the element at the specified position in the expression.
  636. * @param args a list of indices specifying the position in the expression. Indices
  637. * must be unsigned integers, the number of indices must be equal to the number of
  638. * dimensions of the expression, else the behavior is undefined.
  639. *
  640. * @warning This method is meant for performance, for expressions with a dynamic
  641. * number of dimensions (i.e. not known at compile time). Since it may have
  642. * undefined behavior (see parameters), operator() should be preferred whenever
  643. * it is possible.
  644. * @warning This method is NOT compatible with broadcasting, meaning the following
  645. * code has undefined behavior:
  646. * @code{.cpp}
  647. * xt::xarray<double> a = {{0, 1}, {2, 3}};
  648. * xt::xarray<double> b = {0, 1};
  649. * auto fd = a + b;
  650. * double res = fd.unchecked(0, 1);
  651. * @endcode
  652. */
  653. template <class D>
  654. template <class... Args>
  655. inline auto xfunctor_applier_base<D>::unchecked(Args... args) -> reference
  656. {
  657. return m_functor(m_e.unchecked(args...));
  658. }
  659. /**
  660. * Returns a reference to the element at the specified position in the expression.
  661. * @param first iterator starting the sequence of indices
  662. * @param last iterator ending the sequence of indices
  663. * The number of indices in the sequence should be equal to or greater
  664. * than the number of dimensions of the function.
  665. */
  666. template <class D>
  667. template <class IT>
  668. inline auto xfunctor_applier_base<D>::element(IT first, IT last) -> reference
  669. {
  670. XTENSOR_TRY(check_element_index(shape(), first, last));
  671. return m_functor(m_e.element(first, last));
  672. }
  673. /**
  674. * Returns a constant reference to the element at the specified position in the expression.
  675. * @param args a list of indices specifying the position in the function. Indices
  676. * must be unsigned integers, the number of indices should be equal or greater than
  677. * the number of dimensions of the expression.
  678. */
  679. template <class D>
  680. template <class... Args>
  681. inline auto xfunctor_applier_base<D>::operator()(Args... args) const -> const_reference
  682. {
  683. XTENSOR_TRY(check_index(shape(), args...));
  684. XTENSOR_CHECK_DIMENSION(shape(), args...);
  685. return m_functor(m_e(args...));
  686. }
  687. /**
  688. * Returns a constant reference to the element at the specified position in the expression.
  689. * @param args a list of indices specifying the position in the expression. Indices
  690. * must be unsigned integers, the number of indices must be equal to the number of
  691. * dimensions of the expression, else the behavior is undefined.
  692. *
  693. * @warning This method is meant for performance, for expressions with a dynamic
  694. * number of dimensions (i.e. not known at compile time). Since it may have
  695. * undefined behavior (see parameters), operator() should be preferred whenever
  696. * it is possible.
  697. * @warning This method is NOT compatible with broadcasting, meaning the following
  698. * code has undefined behavior:
  699. * @code{.cpp}
  700. * xt::xarray<double> a = {{0, 1}, {2, 3}};
  701. * xt::xarray<double> b = {0, 1};
  702. * auto fd = a + b;
  703. * double res = fd.uncheked(0, 1);
  704. * @endcode
  705. */
  706. template <class D>
  707. template <class... Args>
  708. inline auto xfunctor_applier_base<D>::unchecked(Args... args) const -> const_reference
  709. {
  710. return m_functor(m_e.unchecked(args...));
  711. }
  712. /**
  713. * Returns a constant reference to the element at the specified position in the expression.
  714. * @param first iterator starting the sequence of indices
  715. * @param last iterator ending the sequence of indices
  716. * The number of indices in the sequence should be equal to or greater
  717. * than the number of dimensions of the function.
  718. */
  719. template <class D>
  720. template <class IT>
  721. inline auto xfunctor_applier_base<D>::element(IT first, IT last) const -> const_reference
  722. {
  723. XTENSOR_TRY(check_element_index(shape(), first, last));
  724. return m_functor(m_e.element(first, last));
  725. }
  726. /**
  727. * Returns a reference to the underlying expression of the view.
  728. */
  729. template <class D>
  730. inline auto xfunctor_applier_base<D>::expression() noexcept -> xexpression_type&
  731. {
  732. return m_e;
  733. }
  734. /**
  735. * Returns a consttant reference to the underlying expression of the view.
  736. */
  737. template <class D>
  738. inline auto xfunctor_applier_base<D>::expression() const noexcept -> const xexpression_type&
  739. {
  740. return m_e;
  741. }
  742. //@}
  743. /**
  744. * @name Broadcasting
  745. */
  746. //@{
  747. /**
  748. * Broadcast the shape of the function to the specified parameter.
  749. * @param shape the result shape
  750. * @param reuse_cache boolean for reusing a previously computed shape
  751. * @return a boolean indicating whether the broadcasting is trivial
  752. */
  753. template <class D>
  754. template <class S>
  755. inline bool xfunctor_applier_base<D>::broadcast_shape(S& shape, bool reuse_cache) const
  756. {
  757. return m_e.broadcast_shape(shape, reuse_cache);
  758. }
  759. /**
  760. * Checks whether the xfunctor_applier_base can be linearly assigned to an expression
  761. * with the specified strides.
  762. *
  763. * @return a boolean indicating whether a linear assign is possible
  764. */
  765. template <class D>
  766. template <class S>
  767. inline bool xfunctor_applier_base<D>::has_linear_assign(const S& strides) const
  768. {
  769. return m_e.has_linear_assign(strides);
  770. }
  771. //@}
  772. /**
  773. * @name Iterators
  774. */
  775. //@{
  776. /**
  777. * Returns an iterator to the first element of the expression.
  778. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  779. */
  780. template <class D>
  781. template <layout_type L>
  782. inline auto xfunctor_applier_base<D>::begin() noexcept
  783. {
  784. return xfunctor_iterator<functor_type, decltype(m_e.template begin<L>())>(
  785. m_e.template begin<L>(),
  786. &m_functor
  787. );
  788. }
  789. /**
  790. * Returns an iterator to the element following the last element
  791. * of the expression.
  792. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  793. */
  794. template <class D>
  795. template <layout_type L>
  796. inline auto xfunctor_applier_base<D>::end() noexcept
  797. {
  798. return xfunctor_iterator<functor_type, decltype(m_e.template end<L>())>(m_e.template end<L>(), &m_functor);
  799. }
  800. /**
  801. * Returns a constant iterator to the first element of the expression.
  802. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  803. */
  804. template <class D>
  805. template <layout_type L>
  806. inline auto xfunctor_applier_base<D>::begin() const noexcept
  807. {
  808. return this->template cbegin<L>();
  809. }
  810. /**
  811. * Returns a constant iterator to the element following the last element
  812. * of the expression.
  813. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  814. */
  815. template <class D>
  816. template <layout_type L>
  817. inline auto xfunctor_applier_base<D>::end() const noexcept
  818. {
  819. return this->template cend<L>();
  820. }
  821. /**
  822. * Returns a constant iterator to the first element of the expression.
  823. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  824. */
  825. template <class D>
  826. template <layout_type L>
  827. inline auto xfunctor_applier_base<D>::cbegin() const noexcept
  828. {
  829. return xfunctor_iterator<const functor_type, decltype(m_e.template cbegin<L>())>(
  830. m_e.template cbegin<L>(),
  831. &m_functor
  832. );
  833. }
  834. /**
  835. * Returns a constant iterator to the element following the last element
  836. * of the expression.
  837. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  838. */
  839. template <class D>
  840. template <layout_type L>
  841. inline auto xfunctor_applier_base<D>::cend() const noexcept
  842. {
  843. return xfunctor_iterator<const functor_type, decltype(m_e.template cend<L>())>(
  844. m_e.template cend<L>(),
  845. &m_functor
  846. );
  847. }
  848. //@}
  849. /**
  850. * @name Broadcast iterators
  851. */
  852. //@{
  853. /**
  854. * Returns a constant iterator to the first element of the expression. The
  855. * iteration is broadcasted to the specified shape.
  856. * @param shape the shape used for broadcasting
  857. * @tparam S type of the \c shape parameter.
  858. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  859. */
  860. template <class D>
  861. template <class S, layout_type L>
  862. inline auto xfunctor_applier_base<D>::begin(const S& shape) noexcept -> broadcast_iterator<S, L>
  863. {
  864. return broadcast_iterator<S, L>(m_e.template begin<S, L>(shape), &m_functor);
  865. }
  866. /**
  867. * Returns a constant iterator to the element following the last element of the
  868. * expression. The iteration is broadcasted to the specified shape.
  869. * @param shape the shape used for broadcasting
  870. * @tparam S type of the \c shape parameter.
  871. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  872. */
  873. template <class D>
  874. template <class S, layout_type L>
  875. inline auto xfunctor_applier_base<D>::end(const S& shape) noexcept -> broadcast_iterator<S, L>
  876. {
  877. return broadcast_iterator<S, L>(m_e.template end<S, L>(shape), &m_functor);
  878. }
  879. /**
  880. * Returns a constant iterator to the first element of the expression. The
  881. * iteration is broadcasted to the specified shape.
  882. * @param shape the shape used for broadcasting
  883. * @tparam S type of the \c shape parameter.
  884. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  885. */
  886. template <class D>
  887. template <class S, layout_type L>
  888. inline auto xfunctor_applier_base<D>::begin(const S& shape) const noexcept
  889. -> const_broadcast_iterator<S, L>
  890. {
  891. return cbegin<S, L>(shape);
  892. }
  893. /**
  894. * Returns a constant iterator to the element following the last element of the
  895. * expression. The iteration is broadcasted to the specified shape.
  896. * @param shape the shape used for broadcasting
  897. * @tparam S type of the \c shape parameter.
  898. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  899. */
  900. template <class D>
  901. template <class S, layout_type L>
  902. inline auto xfunctor_applier_base<D>::end(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
  903. {
  904. return cend<S, L>(shape);
  905. }
  906. /**
  907. * Returns a constant iterator to the first element of the expression. The
  908. * iteration is broadcasted to the specified shape.
  909. * @param shape the shape used for broadcasting
  910. * @tparam S type of the \c shape parameter.
  911. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  912. */
  913. template <class D>
  914. template <class S, layout_type L>
  915. inline auto xfunctor_applier_base<D>::cbegin(const S& shape) const noexcept
  916. -> const_broadcast_iterator<S, L>
  917. {
  918. return const_broadcast_iterator<S, L>(m_e.template cbegin<S, L>(shape), &m_functor);
  919. }
  920. /**
  921. * Returns a constant iterator to the element following the last element of the
  922. * expression. The iteration is broadcasted to the specified shape.
  923. * @param shape the shape used for broadcasting
  924. * @tparam S type of the \c shape parameter.
  925. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  926. */
  927. template <class D>
  928. template <class S, layout_type L>
  929. inline auto xfunctor_applier_base<D>::cend(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
  930. {
  931. return const_broadcast_iterator<S, L>(m_e.template cend<S, L>(shape), &m_functor);
  932. }
  933. //@}
  934. /**
  935. * @name Reverse iterators
  936. */
  937. //@{
  938. /**
  939. * Returns an iterator to the first element of the reversed expression.
  940. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  941. */
  942. template <class D>
  943. template <layout_type L>
  944. inline auto xfunctor_applier_base<D>::rbegin() noexcept
  945. {
  946. return xfunctor_iterator<functor_type, decltype(m_e.template rbegin<L>())>(
  947. m_e.template rbegin<L>(),
  948. &m_functor
  949. );
  950. }
  951. /**
  952. * Returns an iterator to the element following the last element
  953. * of the reversed expression.
  954. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  955. */
  956. template <class D>
  957. template <layout_type L>
  958. inline auto xfunctor_applier_base<D>::rend() noexcept
  959. {
  960. return xfunctor_iterator<functor_type, decltype(m_e.template rend<L>())>(
  961. m_e.template rend<L>(),
  962. &m_functor
  963. );
  964. }
  965. /**
  966. * Returns a constant iterator to the first element of the reversed expression.
  967. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  968. */
  969. template <class D>
  970. template <layout_type L>
  971. inline auto xfunctor_applier_base<D>::rbegin() const noexcept
  972. {
  973. return this->template crbegin<L>();
  974. }
  975. /**
  976. * Returns a constant iterator to the element following the last element
  977. * of the reversed expression.
  978. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  979. */
  980. template <class D>
  981. template <layout_type L>
  982. inline auto xfunctor_applier_base<D>::rend() const noexcept
  983. {
  984. return this->template crend<L>();
  985. }
  986. /**
  987. * Returns a constant iterator to the first element of the reversed expression.
  988. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  989. */
  990. template <class D>
  991. template <layout_type L>
  992. inline auto xfunctor_applier_base<D>::crbegin() const noexcept
  993. {
  994. return xfunctor_iterator<const functor_type, decltype(m_e.template crbegin<L>())>(
  995. m_e.template crbegin<L>(),
  996. &m_functor
  997. );
  998. }
  999. /**
  1000. * Returns a constant iterator to the element following the last element
  1001. * of the reversed expression.
  1002. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  1003. */
  1004. template <class D>
  1005. template <layout_type L>
  1006. inline auto xfunctor_applier_base<D>::crend() const noexcept
  1007. {
  1008. return xfunctor_iterator<const functor_type, decltype(m_e.template crend<L>())>(
  1009. m_e.template crend<L>(),
  1010. &m_functor
  1011. );
  1012. }
  1013. //@}
  1014. /**
  1015. * @name Reverse broadcast iterators
  1016. */
  1017. /**
  1018. * Returns an iterator to the first element of the expression. The
  1019. * iteration is broadcasted to the specified shape.
  1020. * @param shape the shape used for broadcasting
  1021. * @tparam S type of the \c shape parameter.
  1022. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  1023. */
  1024. template <class D>
  1025. template <class S, layout_type L>
  1026. inline auto xfunctor_applier_base<D>::rbegin(const S& shape) noexcept -> reverse_broadcast_iterator<S, L>
  1027. {
  1028. return reverse_broadcast_iterator<S, L>(m_e.template rbegin<S, L>(shape), &m_functor);
  1029. }
  1030. /**
  1031. * Returns an iterator to the element following the last element of the
  1032. * reversed expression. The iteration is broadcasted to the specified shape.
  1033. * @param shape the shape used for broadcasting
  1034. * @tparam S type of the \c shape parameter.
  1035. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  1036. */
  1037. template <class D>
  1038. template <class S, layout_type L>
  1039. inline auto xfunctor_applier_base<D>::rend(const S& shape) noexcept -> reverse_broadcast_iterator<S, L>
  1040. {
  1041. return reverse_broadcast_iterator<S, L>(m_e.template rend<S, L>(shape), &m_functor);
  1042. }
  1043. /**
  1044. * Returns a constant iterator to the first element of the reversed expression.
  1045. * The iteration is broadcasted to the specified shape.
  1046. * @param shape the shape used for broadcasting
  1047. * @tparam S type of the \c shape parameter.
  1048. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  1049. */
  1050. template <class D>
  1051. template <class S, layout_type L>
  1052. inline auto xfunctor_applier_base<D>::rbegin(const S& shape) const noexcept
  1053. -> const_reverse_broadcast_iterator<S, L>
  1054. {
  1055. return crbegin<S, L>(shape);
  1056. }
  1057. /**
  1058. * Returns a constant iterator to the element following the last element
  1059. * of the reversed expression.
  1060. * @param shape the shape used for broadcasting
  1061. * @tparam S type of the \c shape parameter.
  1062. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  1063. */
  1064. template <class D>
  1065. template <class S, layout_type L>
  1066. inline auto xfunctor_applier_base<D>::rend(const S& /*shape*/) const noexcept
  1067. -> const_reverse_broadcast_iterator<S, L>
  1068. {
  1069. return crend<S, L>();
  1070. }
  1071. /**
  1072. * Returns a constant iterator to the first element of the reversed expression.
  1073. * The iteration is broadcasted to the specified shape.
  1074. * @param shape the shape used for broadcasting
  1075. * @tparam S type of the \c shape parameter.
  1076. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  1077. */
  1078. template <class D>
  1079. template <class S, layout_type L>
  1080. inline auto xfunctor_applier_base<D>::crbegin(const S& /*shape*/) const noexcept
  1081. -> const_reverse_broadcast_iterator<S, L>
  1082. {
  1083. return const_reverse_broadcast_iterator<S, L>(m_e.template crbegin<S, L>(), &m_functor);
  1084. }
  1085. /**
  1086. * Returns a constant iterator to the element following the last element
  1087. * of the reversed expression.
  1088. * @param shape the shape used for broadcasting
  1089. * @tparam S type of the \c shape parameter.
  1090. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  1091. */
  1092. template <class D>
  1093. template <class S, layout_type L>
  1094. inline auto xfunctor_applier_base<D>::crend(const S& shape) const noexcept
  1095. -> const_reverse_broadcast_iterator<S, L>
  1096. {
  1097. return const_reverse_broadcast_iterator<S, L>(m_e.template crend<S, L>(shape), &m_functor);
  1098. }
  1099. //@}
  1100. template <class D>
  1101. inline auto xfunctor_applier_base<D>::linear_begin() noexcept -> linear_iterator
  1102. {
  1103. return linear_iterator(m_e.linear_begin(), &m_functor);
  1104. }
  1105. template <class D>
  1106. inline auto xfunctor_applier_base<D>::linear_end() noexcept -> linear_iterator
  1107. {
  1108. return linear_iterator(m_e.linear_end(), &m_functor);
  1109. }
  1110. template <class D>
  1111. inline auto xfunctor_applier_base<D>::linear_begin() const noexcept -> const_linear_iterator
  1112. {
  1113. return const_linear_iterator(m_e.linear_begin(), &m_functor);
  1114. }
  1115. template <class D>
  1116. inline auto xfunctor_applier_base<D>::linear_end() const noexcept -> const_linear_iterator
  1117. {
  1118. return const_linear_iterator(m_e.linear_end(), &m_functor);
  1119. }
  1120. template <class D>
  1121. inline auto xfunctor_applier_base<D>::linear_cbegin() const noexcept -> const_linear_iterator
  1122. {
  1123. return const_linear_iterator(m_e.linear_cbegin(), &m_functor);
  1124. }
  1125. template <class D>
  1126. inline auto xfunctor_applier_base<D>::linear_cend() const noexcept -> const_linear_iterator
  1127. {
  1128. return const_linear_iterator(m_e.linear_cend(), &m_functor);
  1129. }
  1130. template <class D>
  1131. inline auto xfunctor_applier_base<D>::linear_rbegin() noexcept -> reverse_linear_iterator
  1132. {
  1133. return reverse_linear_iterator(m_e.linear_rbegin(), &m_functor);
  1134. }
  1135. template <class D>
  1136. inline auto xfunctor_applier_base<D>::linear_rend() noexcept -> reverse_linear_iterator
  1137. {
  1138. return reverse_linear_iterator(m_e.linear_rend(), &m_functor);
  1139. }
  1140. template <class D>
  1141. inline auto xfunctor_applier_base<D>::linear_rbegin() const noexcept -> const_reverse_linear_iterator
  1142. {
  1143. return const_reverse_linear_iterator(m_e.linear_rbegin(), &m_functor);
  1144. }
  1145. template <class D>
  1146. inline auto xfunctor_applier_base<D>::linear_rend() const noexcept -> const_reverse_linear_iterator
  1147. {
  1148. return const_reverse_linear_iterator(m_e.linear_rend(), &m_functor);
  1149. }
  1150. template <class D>
  1151. inline auto xfunctor_applier_base<D>::linear_crbegin() const noexcept -> const_reverse_linear_iterator
  1152. {
  1153. return const_reverse_linear_iterator(m_e.linear_crbegin(), &m_functor);
  1154. }
  1155. template <class D>
  1156. inline auto xfunctor_applier_base<D>::linear_crend() const noexcept -> const_reverse_linear_iterator
  1157. {
  1158. return const_reverse_linear_iterator(m_e.linear_crend(), &m_functor);
  1159. }
  1160. /***************
  1161. * stepper api *
  1162. ***************/
  1163. template <class D>
  1164. template <class S>
  1165. inline auto xfunctor_applier_base<D>::stepper_begin(const S& shape) noexcept -> stepper
  1166. {
  1167. return stepper(m_e.stepper_begin(shape), &m_functor);
  1168. }
  1169. template <class D>
  1170. template <class S>
  1171. inline auto xfunctor_applier_base<D>::stepper_end(const S& shape, layout_type l) noexcept -> stepper
  1172. {
  1173. return stepper(m_e.stepper_end(shape, l), &m_functor);
  1174. }
  1175. template <class D>
  1176. template <class S>
  1177. inline auto xfunctor_applier_base<D>::stepper_begin(const S& shape) const noexcept -> const_stepper
  1178. {
  1179. const xexpression_type& const_m_e = m_e;
  1180. return const_stepper(const_m_e.stepper_begin(shape), &m_functor);
  1181. }
  1182. template <class D>
  1183. template <class S>
  1184. inline auto xfunctor_applier_base<D>::stepper_end(const S& shape, layout_type l) const noexcept
  1185. -> const_stepper
  1186. {
  1187. const xexpression_type& const_m_e = m_e;
  1188. return const_stepper(const_m_e.stepper_end(shape, l), &m_functor);
  1189. }
  1190. /********************************
  1191. * xfunctor_view implementation *
  1192. ********************************/
  1193. /**
  1194. * @name Extended copy semantic
  1195. */
  1196. //@{
  1197. /**
  1198. * The extended assignment operator.
  1199. */
  1200. template <class F, class CT>
  1201. template <class E>
  1202. inline auto xfunctor_view<F, CT>::operator=(const xexpression<E>& e) -> self_type&
  1203. {
  1204. bool cond = (e.derived_cast().shape().size() == this->dimension())
  1205. && std::equal(this->shape().begin(), this->shape().end(), e.derived_cast().shape().begin());
  1206. if (!cond)
  1207. {
  1208. semantic_base::operator=(broadcast(e.derived_cast(), this->shape()));
  1209. }
  1210. else
  1211. {
  1212. semantic_base::operator=(e);
  1213. }
  1214. return *this;
  1215. }
  1216. //@}
  1217. template <class F, class CT>
  1218. template <class E>
  1219. inline auto xfunctor_view<F, CT>::operator=(const E& e) -> disable_xexpression<E, self_type>&
  1220. {
  1221. std::fill(this->begin(), this->end(), e);
  1222. return *this;
  1223. }
  1224. template <class F, class CT>
  1225. inline void xfunctor_view<F, CT>::assign_temporary_impl(temporary_type&& tmp)
  1226. {
  1227. std::copy(tmp.cbegin(), tmp.cend(), this->begin());
  1228. }
  1229. template <class F, class CT>
  1230. template <class E>
  1231. inline auto xfunctor_view<F, CT>::build_functor_view(E&& e) const -> rebind_t<E>
  1232. {
  1233. return rebind_t<E>((this->m_functor), std::forward<E>(e));
  1234. }
  1235. /***********************************
  1236. * xfunctor_adaptor implementation *
  1237. ***********************************/
  1238. /**
  1239. * @name Extended copy semantic
  1240. */
  1241. //@{
  1242. /**
  1243. * The extended assignment operator.
  1244. */
  1245. template <class F, class CT>
  1246. template <class E>
  1247. inline auto xfunctor_adaptor<F, CT>::operator=(const xexpression<E>& e) -> self_type&
  1248. {
  1249. const auto& de = e.derived_cast();
  1250. this->m_e.resize(de.shape());
  1251. if (this->layout() == de.layout())
  1252. {
  1253. std::copy(de.linear_begin(), de.linear_end(), this->linear_begin());
  1254. }
  1255. else
  1256. {
  1257. // note: does this even select the current layout of *this* for iteration?
  1258. std::copy(de.begin(), de.end(), this->begin());
  1259. }
  1260. return *this;
  1261. }
  1262. //@}
  1263. template <class F, class CT>
  1264. template <class S>
  1265. auto xfunctor_adaptor<F, CT>::resize(S&& shape, bool force)
  1266. {
  1267. this->m_e.resize(std::forward<S>(shape), force);
  1268. }
  1269. template <class F, class CT>
  1270. template <class S>
  1271. auto xfunctor_adaptor<F, CT>::resize(S&& shape, layout_type l)
  1272. {
  1273. this->m_e.resize(std::forward<S>(shape), l);
  1274. }
  1275. template <class F, class CT>
  1276. template <class S>
  1277. auto xfunctor_adaptor<F, CT>::resize(S&& shape, const strides_type& strides)
  1278. {
  1279. this->m_e.resize(std::forward<S>(shape), strides);
  1280. }
  1281. template <class F, class CT>
  1282. template <class S>
  1283. auto& xfunctor_adaptor<F, CT>::reshape(S&& shape, layout_type layout) &
  1284. {
  1285. this->m_e.reshape(std::forward<S>(shape), layout);
  1286. return *this;
  1287. }
  1288. /************************************
  1289. * xfunctor_iterator implementation *
  1290. ************************************/
  1291. template <class F, class IT>
  1292. xfunctor_iterator<F, IT>::xfunctor_iterator(const IT& it, functor_type* pf)
  1293. : m_it(it)
  1294. , p_functor(pf)
  1295. {
  1296. }
  1297. template <class F, class IT>
  1298. inline auto xfunctor_iterator<F, IT>::operator++() -> self_type&
  1299. {
  1300. ++m_it;
  1301. return *this;
  1302. }
  1303. template <class F, class IT>
  1304. inline auto xfunctor_iterator<F, IT>::operator--() -> self_type&
  1305. {
  1306. --m_it;
  1307. return *this;
  1308. }
  1309. template <class F, class IT>
  1310. inline auto xfunctor_iterator<F, IT>::operator+=(difference_type n) -> self_type&
  1311. {
  1312. m_it += n;
  1313. return *this;
  1314. }
  1315. template <class F, class IT>
  1316. inline auto xfunctor_iterator<F, IT>::operator-=(difference_type n) -> self_type&
  1317. {
  1318. m_it -= n;
  1319. return *this;
  1320. }
  1321. template <class F, class IT>
  1322. inline auto xfunctor_iterator<F, IT>::operator-(xfunctor_iterator rhs) const -> difference_type
  1323. {
  1324. return m_it - rhs.m_it;
  1325. }
  1326. template <class F, class IT>
  1327. auto xfunctor_iterator<F, IT>::operator*() const -> reference
  1328. {
  1329. return (*p_functor)(*m_it);
  1330. }
  1331. template <class F, class IT>
  1332. auto xfunctor_iterator<F, IT>::operator->() const -> pointer
  1333. {
  1334. return &(operator*());
  1335. }
  1336. template <class F, class IT>
  1337. auto xfunctor_iterator<F, IT>::equal(const xfunctor_iterator& rhs) const -> bool
  1338. {
  1339. return m_it == rhs.m_it;
  1340. }
  1341. template <class F, class IT>
  1342. auto xfunctor_iterator<F, IT>::less_than(const xfunctor_iterator& rhs) const -> bool
  1343. {
  1344. return m_it < rhs.m_it;
  1345. }
  1346. template <class F, class IT>
  1347. bool operator==(const xfunctor_iterator<F, IT>& lhs, const xfunctor_iterator<F, IT>& rhs)
  1348. {
  1349. return lhs.equal(rhs);
  1350. }
  1351. template <class F, class IT>
  1352. bool operator<(const xfunctor_iterator<F, IT>& lhs, const xfunctor_iterator<F, IT>& rhs)
  1353. {
  1354. return !lhs.less_than(rhs);
  1355. }
  1356. /***********************************
  1357. * xfunctor_stepper implementation *
  1358. ***********************************/
  1359. template <class F, class ST>
  1360. xfunctor_stepper<F, ST>::xfunctor_stepper(const ST& stepper, functor_type* pf)
  1361. : m_stepper(stepper)
  1362. , p_functor(pf)
  1363. {
  1364. }
  1365. template <class F, class ST>
  1366. auto xfunctor_stepper<F, ST>::operator*() const -> reference
  1367. {
  1368. return (*p_functor)(*m_stepper);
  1369. }
  1370. template <class F, class ST>
  1371. void xfunctor_stepper<F, ST>::step(size_type dim)
  1372. {
  1373. m_stepper.step(dim);
  1374. }
  1375. template <class F, class ST>
  1376. void xfunctor_stepper<F, ST>::step_back(size_type dim)
  1377. {
  1378. m_stepper.step_back(dim);
  1379. }
  1380. template <class F, class ST>
  1381. void xfunctor_stepper<F, ST>::step(size_type dim, size_type n)
  1382. {
  1383. m_stepper.step(dim, n);
  1384. }
  1385. template <class F, class ST>
  1386. void xfunctor_stepper<F, ST>::step_back(size_type dim, size_type n)
  1387. {
  1388. m_stepper.step_back(dim, n);
  1389. }
  1390. template <class F, class ST>
  1391. void xfunctor_stepper<F, ST>::reset(size_type dim)
  1392. {
  1393. m_stepper.reset(dim);
  1394. }
  1395. template <class F, class ST>
  1396. void xfunctor_stepper<F, ST>::reset_back(size_type dim)
  1397. {
  1398. m_stepper.reset_back(dim);
  1399. }
  1400. template <class F, class ST>
  1401. void xfunctor_stepper<F, ST>::to_begin()
  1402. {
  1403. m_stepper.to_begin();
  1404. }
  1405. template <class F, class ST>
  1406. void xfunctor_stepper<F, ST>::to_end(layout_type l)
  1407. {
  1408. m_stepper.to_end(l);
  1409. }
  1410. }
  1411. #endif