xsemantic.hpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  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_SEMANTIC_HPP
  10. #define XTENSOR_SEMANTIC_HPP
  11. #include <functional>
  12. #include <utility>
  13. #include "xassign.hpp"
  14. #include "xexpression_traits.hpp"
  15. namespace xt
  16. {
  17. namespace detail
  18. {
  19. template <class D>
  20. struct is_sharable
  21. {
  22. static constexpr bool value = true;
  23. };
  24. template <class ET, class S, layout_type L, bool SH, class Tag>
  25. struct is_sharable<xfixed_container<ET, S, L, SH, Tag>>
  26. {
  27. static constexpr bool value = SH;
  28. };
  29. template <class ET, class S, layout_type L, bool SH, class Tag>
  30. struct is_sharable<xfixed_adaptor<ET, S, L, SH, Tag>>
  31. {
  32. static constexpr bool value = SH;
  33. };
  34. }
  35. template <class D>
  36. using select_expression_base_t = std::
  37. conditional_t<detail::is_sharable<D>::value, xsharable_expression<D>, xexpression<D>>;
  38. /**
  39. * @class xsemantic_base
  40. * @brief Base interface for assignable xexpressions.
  41. *
  42. * The xsemantic_base class defines the interface for assignable
  43. * xexpressions.
  44. *
  45. * @tparam D The derived type, i.e. the inheriting class for which xsemantic_base
  46. * provides the interface.
  47. */
  48. template <class D>
  49. class xsemantic_base : public select_expression_base_t<D>
  50. {
  51. public:
  52. using base_type = select_expression_base_t<D>;
  53. using derived_type = typename base_type::derived_type;
  54. using temporary_type = typename xcontainer_inner_types<D>::temporary_type;
  55. template <class E>
  56. disable_xexpression<E, derived_type&> operator+=(const E&);
  57. template <class E>
  58. disable_xexpression<E, derived_type&> operator-=(const E&);
  59. template <class E>
  60. disable_xexpression<E, derived_type&> operator*=(const E&);
  61. template <class E>
  62. disable_xexpression<E, derived_type&> operator/=(const E&);
  63. template <class E>
  64. disable_xexpression<E, derived_type&> operator%=(const E&);
  65. template <class E>
  66. disable_xexpression<E, derived_type&> operator&=(const E&);
  67. template <class E>
  68. disable_xexpression<E, derived_type&> operator|=(const E&);
  69. template <class E>
  70. disable_xexpression<E, derived_type&> operator^=(const E&);
  71. template <class E>
  72. derived_type& operator+=(const xexpression<E>&);
  73. template <class E>
  74. derived_type& operator-=(const xexpression<E>&);
  75. template <class E>
  76. derived_type& operator*=(const xexpression<E>&);
  77. template <class E>
  78. derived_type& operator/=(const xexpression<E>&);
  79. template <class E>
  80. derived_type& operator%=(const xexpression<E>&);
  81. template <class E>
  82. derived_type& operator&=(const xexpression<E>&);
  83. template <class E>
  84. derived_type& operator|=(const xexpression<E>&);
  85. template <class E>
  86. derived_type& operator^=(const xexpression<E>&);
  87. template <class E>
  88. derived_type& assign(const xexpression<E>&);
  89. template <class E>
  90. derived_type& plus_assign(const xexpression<E>&);
  91. template <class E>
  92. derived_type& minus_assign(const xexpression<E>&);
  93. template <class E>
  94. derived_type& multiplies_assign(const xexpression<E>&);
  95. template <class E>
  96. derived_type& divides_assign(const xexpression<E>&);
  97. template <class E>
  98. derived_type& modulus_assign(const xexpression<E>&);
  99. template <class E>
  100. derived_type& bit_and_assign(const xexpression<E>&);
  101. template <class E>
  102. derived_type& bit_or_assign(const xexpression<E>&);
  103. template <class E>
  104. derived_type& bit_xor_assign(const xexpression<E>&);
  105. protected:
  106. xsemantic_base() = default;
  107. ~xsemantic_base() = default;
  108. xsemantic_base(const xsemantic_base&) = default;
  109. xsemantic_base& operator=(const xsemantic_base&) = default;
  110. xsemantic_base(xsemantic_base&&) = default;
  111. xsemantic_base& operator=(xsemantic_base&&) = default;
  112. template <class E>
  113. derived_type& operator=(const xexpression<E>&);
  114. };
  115. template <class E>
  116. using is_assignable = is_crtp_base_of<xsemantic_base, E>;
  117. template <class E, class R = void>
  118. using enable_assignable = typename std::enable_if<is_assignable<E>::value, R>::type;
  119. template <class E, class R = void>
  120. using disable_assignable = typename std::enable_if<!is_assignable<E>::value, R>::type;
  121. /**
  122. * @class xcontainer_semantic
  123. * @brief Implementation of the xsemantic_base interface
  124. * for dense multidimensional containers.
  125. *
  126. * The xcontainer_semantic class is an implementation of the
  127. * xsemantic_base interface for dense multidimensional
  128. * containers.
  129. *
  130. * @tparam D the derived type
  131. */
  132. template <class D>
  133. class xcontainer_semantic : public xsemantic_base<D>
  134. {
  135. public:
  136. using base_type = xsemantic_base<D>;
  137. using derived_type = D;
  138. using temporary_type = typename base_type::temporary_type;
  139. derived_type& assign_temporary(temporary_type&&);
  140. template <class E>
  141. derived_type& assign_xexpression(const xexpression<E>& e);
  142. template <class E>
  143. derived_type& computed_assign(const xexpression<E>& e);
  144. template <class E, class F>
  145. derived_type& scalar_computed_assign(const E& e, F&& f);
  146. protected:
  147. xcontainer_semantic() = default;
  148. ~xcontainer_semantic() = default;
  149. xcontainer_semantic(const xcontainer_semantic&) = default;
  150. xcontainer_semantic& operator=(const xcontainer_semantic&) = default;
  151. xcontainer_semantic(xcontainer_semantic&&) = default;
  152. xcontainer_semantic& operator=(xcontainer_semantic&&) = default;
  153. template <class E>
  154. derived_type& operator=(const xexpression<E>&);
  155. };
  156. template <class E>
  157. using has_container_semantics = is_crtp_base_of<xcontainer_semantic, E>;
  158. template <class E, class R = void>
  159. using enable_xcontainer_semantics = typename std::enable_if<has_container_semantics<E>::value, R>::type;
  160. template <class E, class R = void>
  161. using disable_xcontainer_semantics = typename std::enable_if<!has_container_semantics<E>::value, R>::type;
  162. template <class D>
  163. class xview_semantic;
  164. template <class E>
  165. struct overlapping_memory_checker_traits<
  166. E,
  167. std::enable_if_t<!has_memory_address<E>::value && is_crtp_base_of<xview_semantic, E>::value>>
  168. {
  169. static bool check_overlap(const E& expr, const memory_range& dst_range)
  170. {
  171. if (expr.size() == 0)
  172. {
  173. return false;
  174. }
  175. else
  176. {
  177. using ChildE = std::decay_t<decltype(expr.expression())>;
  178. return overlapping_memory_checker_traits<ChildE>::check_overlap(expr.expression(), dst_range);
  179. }
  180. }
  181. };
  182. /**
  183. * @class xview_semantic
  184. * @brief Implementation of the xsemantic_base interface for
  185. * multidimensional views
  186. *
  187. * The xview_semantic is an implementation of the xsemantic_base
  188. * interface for multidimensional views.
  189. *
  190. * @tparam D the derived type
  191. */
  192. template <class D>
  193. class xview_semantic : public xsemantic_base<D>
  194. {
  195. public:
  196. using base_type = xsemantic_base<D>;
  197. using derived_type = D;
  198. using temporary_type = typename base_type::temporary_type;
  199. derived_type& assign_temporary(temporary_type&&);
  200. template <class E>
  201. derived_type& assign_xexpression(const xexpression<E>& e);
  202. template <class E>
  203. derived_type& computed_assign(const xexpression<E>& e);
  204. template <class E, class F>
  205. derived_type& scalar_computed_assign(const E& e, F&& f);
  206. protected:
  207. xview_semantic() = default;
  208. ~xview_semantic() = default;
  209. xview_semantic(const xview_semantic&) = default;
  210. xview_semantic& operator=(const xview_semantic&) = default;
  211. xview_semantic(xview_semantic&&) = default;
  212. xview_semantic& operator=(xview_semantic&&) = default;
  213. template <class E>
  214. derived_type& operator=(const xexpression<E>&);
  215. };
  216. template <class E>
  217. using has_view_semantics = is_crtp_base_of<xview_semantic, E>;
  218. template <class E, class R = void>
  219. using enable_xview_semantics = typename std::enable_if<has_view_semantics<E>::value, R>::type;
  220. template <class E, class R = void>
  221. using disable_xview_semantics = typename std::enable_if<!has_view_semantics<E>::value, R>::type;
  222. /*********************************
  223. * xsemantic_base implementation *
  224. *********************************/
  225. /**
  226. * @name Computed assignement
  227. */
  228. //@{
  229. /**
  230. * Adds the scalar \c e to \c *this.
  231. * @param e the scalar to add.
  232. * @return a reference to \c *this.
  233. */
  234. template <class D>
  235. template <class E>
  236. inline auto xsemantic_base<D>::operator+=(const E& e) -> disable_xexpression<E, derived_type&>
  237. {
  238. return this->derived_cast().scalar_computed_assign(e, std::plus<>());
  239. }
  240. /**
  241. * Subtracts the scalar \c e from \c *this.
  242. * @param e the scalar to subtract.
  243. * @return a reference to \c *this.
  244. */
  245. template <class D>
  246. template <class E>
  247. inline auto xsemantic_base<D>::operator-=(const E& e) -> disable_xexpression<E, derived_type&>
  248. {
  249. return this->derived_cast().scalar_computed_assign(e, std::minus<>());
  250. }
  251. /**
  252. * Multiplies \c *this with the scalar \c e.
  253. * @param e the scalar involved in the operation.
  254. * @return a reference to \c *this.
  255. */
  256. template <class D>
  257. template <class E>
  258. inline auto xsemantic_base<D>::operator*=(const E& e) -> disable_xexpression<E, derived_type&>
  259. {
  260. return this->derived_cast().scalar_computed_assign(e, std::multiplies<>());
  261. }
  262. /**
  263. * Divides \c *this by the scalar \c e.
  264. * @param e the scalar involved in the operation.
  265. * @return a reference to \c *this.
  266. */
  267. template <class D>
  268. template <class E>
  269. inline auto xsemantic_base<D>::operator/=(const E& e) -> disable_xexpression<E, derived_type&>
  270. {
  271. return this->derived_cast().scalar_computed_assign(e, std::divides<>());
  272. }
  273. /**
  274. * Computes the remainder of \c *this after division by the scalar \c e.
  275. * @param e the scalar involved in the operation.
  276. * @return a reference to \c *this.
  277. */
  278. template <class D>
  279. template <class E>
  280. inline auto xsemantic_base<D>::operator%=(const E& e) -> disable_xexpression<E, derived_type&>
  281. {
  282. return this->derived_cast().scalar_computed_assign(e, std::modulus<>());
  283. }
  284. /**
  285. * Computes the bitwise and of \c *this and the scalar \c e and assigns it to \c *this.
  286. * @param e the scalar involved in the operation.
  287. * @return a reference to \c *this.
  288. */
  289. template <class D>
  290. template <class E>
  291. inline auto xsemantic_base<D>::operator&=(const E& e) -> disable_xexpression<E, derived_type&>
  292. {
  293. return this->derived_cast().scalar_computed_assign(e, std::bit_and<>());
  294. }
  295. /**
  296. * Computes the bitwise or of \c *this and the scalar \c e and assigns it to \c *this.
  297. * @param e the scalar involved in the operation.
  298. * @return a reference to \c *this.
  299. */
  300. template <class D>
  301. template <class E>
  302. inline auto xsemantic_base<D>::operator|=(const E& e) -> disable_xexpression<E, derived_type&>
  303. {
  304. return this->derived_cast().scalar_computed_assign(e, std::bit_or<>());
  305. }
  306. /**
  307. * Computes the bitwise xor of \c *this and the scalar \c e and assigns it to \c *this.
  308. * @param e the scalar involved in the operation.
  309. * @return a reference to \c *this.
  310. */
  311. template <class D>
  312. template <class E>
  313. inline auto xsemantic_base<D>::operator^=(const E& e) -> disable_xexpression<E, derived_type&>
  314. {
  315. return this->derived_cast().scalar_computed_assign(e, std::bit_xor<>());
  316. }
  317. /**
  318. * Adds the xexpression \c e to \c *this.
  319. * @param e the xexpression to add.
  320. * @return a reference to \c *this.
  321. */
  322. template <class D>
  323. template <class E>
  324. inline auto xsemantic_base<D>::operator+=(const xexpression<E>& e) -> derived_type&
  325. {
  326. return this->derived_cast() = this->derived_cast() + e.derived_cast();
  327. }
  328. /**
  329. * Subtracts the xexpression \c e from \c *this.
  330. * @param e the xexpression to subtract.
  331. * @return a reference to \c *this.
  332. */
  333. template <class D>
  334. template <class E>
  335. inline auto xsemantic_base<D>::operator-=(const xexpression<E>& e) -> derived_type&
  336. {
  337. return this->derived_cast() = this->derived_cast() - e.derived_cast();
  338. }
  339. /**
  340. * Multiplies \c *this with the xexpression \c e.
  341. * @param e the xexpression involved in the operation.
  342. * @return a reference to \c *this.
  343. */
  344. template <class D>
  345. template <class E>
  346. inline auto xsemantic_base<D>::operator*=(const xexpression<E>& e) -> derived_type&
  347. {
  348. return this->derived_cast() = this->derived_cast() * e.derived_cast();
  349. }
  350. /**
  351. * Divides \c *this by the xexpression \c e.
  352. * @param e the xexpression involved in the operation.
  353. * @return a reference to \c *this.
  354. */
  355. template <class D>
  356. template <class E>
  357. inline auto xsemantic_base<D>::operator/=(const xexpression<E>& e) -> derived_type&
  358. {
  359. return this->derived_cast() = this->derived_cast() / e.derived_cast();
  360. }
  361. /**
  362. * Computes the remainder of \c *this after division by the xexpression \c e.
  363. * @param e the xexpression involved in the operation.
  364. * @return a reference to \c *this.
  365. */
  366. template <class D>
  367. template <class E>
  368. inline auto xsemantic_base<D>::operator%=(const xexpression<E>& e) -> derived_type&
  369. {
  370. return this->derived_cast() = this->derived_cast() % e.derived_cast();
  371. }
  372. /**
  373. * Computes the bitwise and of \c *this and the xexpression \c e and assigns it to \c *this.
  374. * @param e the xexpression involved in the operation.
  375. * @return a reference to \c *this.
  376. */
  377. template <class D>
  378. template <class E>
  379. inline auto xsemantic_base<D>::operator&=(const xexpression<E>& e) -> derived_type&
  380. {
  381. return this->derived_cast() = this->derived_cast() & e.derived_cast();
  382. }
  383. /**
  384. * Computes the bitwise or of \c *this and the xexpression \c e and assigns it to \c *this.
  385. * @param e the xexpression involved in the operation.
  386. * @return a reference to \c *this.
  387. */
  388. template <class D>
  389. template <class E>
  390. inline auto xsemantic_base<D>::operator|=(const xexpression<E>& e) -> derived_type&
  391. {
  392. return this->derived_cast() = this->derived_cast() | e.derived_cast();
  393. }
  394. /**
  395. * Computes the bitwise xor of \c *this and the xexpression \c e and assigns it to \c *this.
  396. * @param e the xexpression involved in the operation.
  397. * @return a reference to \c *this.
  398. */
  399. template <class D>
  400. template <class E>
  401. inline auto xsemantic_base<D>::operator^=(const xexpression<E>& e) -> derived_type&
  402. {
  403. return this->derived_cast() = this->derived_cast() ^ e.derived_cast();
  404. }
  405. //@}
  406. /**
  407. * @name Assign functions
  408. */
  409. /**
  410. * Assigns the xexpression \c e to \c *this. Ensures no temporary
  411. * will be used to perform the assignment.
  412. * @param e the xexpression to assign.
  413. * @return a reference to \c *this.
  414. */
  415. template <class D>
  416. template <class E>
  417. inline auto xsemantic_base<D>::assign(const xexpression<E>& e) -> derived_type&
  418. {
  419. return this->derived_cast().assign_xexpression(e);
  420. }
  421. /**
  422. * Adds the xexpression \c e to \c *this. Ensures no temporary
  423. * will be used to perform the assignment.
  424. * @param e the xexpression to add.
  425. * @return a reference to \c *this.
  426. */
  427. template <class D>
  428. template <class E>
  429. inline auto xsemantic_base<D>::plus_assign(const xexpression<E>& e) -> derived_type&
  430. {
  431. return this->derived_cast().computed_assign(this->derived_cast() + e.derived_cast());
  432. }
  433. /**
  434. * Subtracts the xexpression \c e to \c *this. Ensures no temporary
  435. * will be used to perform the assignment.
  436. * @param e the xexpression to subtract.
  437. * @return a reference to \c *this.
  438. */
  439. template <class D>
  440. template <class E>
  441. inline auto xsemantic_base<D>::minus_assign(const xexpression<E>& e) -> derived_type&
  442. {
  443. return this->derived_cast().computed_assign(this->derived_cast() - e.derived_cast());
  444. }
  445. /**
  446. * Multiplies \c *this with the xexpression \c e. Ensures no temporary
  447. * will be used to perform the assignment.
  448. * @param e the xexpression involved in the operation.
  449. * @return a reference to \c *this.
  450. */
  451. template <class D>
  452. template <class E>
  453. inline auto xsemantic_base<D>::multiplies_assign(const xexpression<E>& e) -> derived_type&
  454. {
  455. return this->derived_cast().computed_assign(this->derived_cast() * e.derived_cast());
  456. }
  457. /**
  458. * Divides \c *this by the xexpression \c e. Ensures no temporary
  459. * will be used to perform the assignment.
  460. * @param e the xexpression involved in the operation.
  461. * @return a reference to \c *this.
  462. */
  463. template <class D>
  464. template <class E>
  465. inline auto xsemantic_base<D>::divides_assign(const xexpression<E>& e) -> derived_type&
  466. {
  467. return this->derived_cast().computed_assign(this->derived_cast() / e.derived_cast());
  468. }
  469. /**
  470. * Computes the remainder of \c *this after division by the xexpression \c e.
  471. * Ensures no temporary will be used to perform the assignment.
  472. * @param e the xexpression involved in the operation.
  473. * @return a reference to \c *this.
  474. */
  475. template <class D>
  476. template <class E>
  477. inline auto xsemantic_base<D>::modulus_assign(const xexpression<E>& e) -> derived_type&
  478. {
  479. return this->derived_cast().computed_assign(this->derived_cast() % e.derived_cast());
  480. }
  481. /**
  482. * Computes the bitwise and of \c e to \c *this. Ensures no temporary
  483. * will be used to perform the assignment.
  484. * @param e the xexpression to add.
  485. * @return a reference to \c *this.
  486. */
  487. template <class D>
  488. template <class E>
  489. inline auto xsemantic_base<D>::bit_and_assign(const xexpression<E>& e) -> derived_type&
  490. {
  491. return this->derived_cast().computed_assign(this->derived_cast() & e.derived_cast());
  492. }
  493. /**
  494. * Computes the bitwise or of \c e to \c *this. Ensures no temporary
  495. * will be used to perform the assignment.
  496. * @param e the xexpression to add.
  497. * @return a reference to \c *this.
  498. */
  499. template <class D>
  500. template <class E>
  501. inline auto xsemantic_base<D>::bit_or_assign(const xexpression<E>& e) -> derived_type&
  502. {
  503. return this->derived_cast().computed_assign(this->derived_cast() | e.derived_cast());
  504. }
  505. /**
  506. * Computes the bitwise xor of \c e to \c *this. Ensures no temporary
  507. * will be used to perform the assignment.
  508. * @param e the xexpression to add.
  509. * @return a reference to \c *this.
  510. */
  511. template <class D>
  512. template <class E>
  513. inline auto xsemantic_base<D>::bit_xor_assign(const xexpression<E>& e) -> derived_type&
  514. {
  515. return this->derived_cast().computed_assign(this->derived_cast() ^ e.derived_cast());
  516. }
  517. template <class D>
  518. template <class E>
  519. inline auto xsemantic_base<D>::operator=(const xexpression<E>& e) -> derived_type&
  520. {
  521. #ifdef XTENSOR_FORCE_TEMPORARY_MEMORY_IN_ASSIGNMENTS
  522. temporary_type tmp(e);
  523. return this->derived_cast().assign_temporary(std::move(tmp));
  524. #else
  525. auto&& this_derived = this->derived_cast();
  526. auto memory_checker = make_overlapping_memory_checker(this_derived);
  527. if (memory_checker.check_overlap(e.derived_cast()))
  528. {
  529. temporary_type tmp(e);
  530. return this_derived.assign_temporary(std::move(tmp));
  531. }
  532. else
  533. {
  534. return this->assign(e);
  535. }
  536. #endif
  537. }
  538. /**************************************
  539. * xcontainer_semantic implementation *
  540. **************************************/
  541. /**
  542. * Assigns the temporary \c tmp to \c *this.
  543. * @param tmp the temporary to assign.
  544. * @return a reference to \c *this.
  545. */
  546. template <class D>
  547. inline auto xcontainer_semantic<D>::assign_temporary(temporary_type&& tmp) -> derived_type&
  548. {
  549. return (this->derived_cast() = std::move(tmp));
  550. }
  551. template <class D>
  552. template <class E>
  553. inline auto xcontainer_semantic<D>::assign_xexpression(const xexpression<E>& e) -> derived_type&
  554. {
  555. xt::assign_xexpression(*this, e);
  556. return this->derived_cast();
  557. }
  558. template <class D>
  559. template <class E>
  560. inline auto xcontainer_semantic<D>::computed_assign(const xexpression<E>& e) -> derived_type&
  561. {
  562. xt::computed_assign(*this, e);
  563. return this->derived_cast();
  564. }
  565. template <class D>
  566. template <class E, class F>
  567. inline auto xcontainer_semantic<D>::scalar_computed_assign(const E& e, F&& f) -> derived_type&
  568. {
  569. xt::scalar_computed_assign(*this, e, std::forward<F>(f));
  570. return this->derived_cast();
  571. }
  572. template <class D>
  573. template <class E>
  574. inline auto xcontainer_semantic<D>::operator=(const xexpression<E>& e) -> derived_type&
  575. {
  576. return base_type::operator=(e);
  577. }
  578. /*********************************
  579. * xview_semantic implementation *
  580. *********************************/
  581. /**
  582. * Assigns the temporary \c tmp to \c *this.
  583. * @param tmp the temporary to assign.
  584. * @return a reference to \c *this.
  585. */
  586. template <class D>
  587. inline auto xview_semantic<D>::assign_temporary(temporary_type&& tmp) -> derived_type&
  588. {
  589. this->derived_cast().assign_temporary_impl(std::move(tmp));
  590. return this->derived_cast();
  591. }
  592. namespace detail
  593. {
  594. template <class F>
  595. bool get_rhs_triviality(const F&)
  596. {
  597. return true;
  598. }
  599. template <class F, class R, class... CT>
  600. bool get_rhs_triviality(const xfunction<F, R, CT...>& rhs)
  601. {
  602. using index_type = xindex_type_t<typename xfunction<F, R, CT...>::shape_type>;
  603. using size_type = typename index_type::size_type;
  604. size_type size = rhs.dimension();
  605. index_type shape = uninitialized_shape<index_type>(size);
  606. bool trivial_broadcast = rhs.broadcast_shape(shape, true);
  607. return trivial_broadcast;
  608. }
  609. }
  610. template <class D>
  611. template <class E>
  612. inline auto xview_semantic<D>::assign_xexpression(const xexpression<E>& e) -> derived_type&
  613. {
  614. xt::assert_compatible_shape(*this, e);
  615. xt::assign_data(*this, e, detail::get_rhs_triviality(e.derived_cast()));
  616. return this->derived_cast();
  617. }
  618. template <class D>
  619. template <class E>
  620. inline auto xview_semantic<D>::computed_assign(const xexpression<E>& e) -> derived_type&
  621. {
  622. xt::assert_compatible_shape(*this, e);
  623. xt::assign_data(*this, e, detail::get_rhs_triviality(e.derived_cast()));
  624. return this->derived_cast();
  625. }
  626. namespace xview_semantic_detail
  627. {
  628. template <class D>
  629. auto get_begin(D&& lhs, std::true_type)
  630. {
  631. return lhs.linear_begin();
  632. }
  633. template <class D>
  634. auto get_begin(D&& lhs, std::false_type)
  635. {
  636. return lhs.begin();
  637. }
  638. }
  639. template <class D>
  640. template <class E, class F>
  641. inline auto xview_semantic<D>::scalar_computed_assign(const E& e, F&& f) -> derived_type&
  642. {
  643. D& d = this->derived_cast();
  644. using size_type = typename D::size_type;
  645. auto dst = xview_semantic_detail::get_begin(d, std::integral_constant<bool, D::contiguous_layout>());
  646. for (size_type i = d.size(); i > 0; --i)
  647. {
  648. *dst = f(*dst, e);
  649. ++dst;
  650. }
  651. return this->derived_cast();
  652. }
  653. template <class D>
  654. template <class E>
  655. inline auto xview_semantic<D>::operator=(const xexpression<E>& rhs) -> derived_type&
  656. {
  657. bool cond = (rhs.derived_cast().shape().size() == this->derived_cast().dimension())
  658. && std::equal(
  659. this->derived_cast().shape().begin(),
  660. this->derived_cast().shape().end(),
  661. rhs.derived_cast().shape().begin()
  662. );
  663. if (!cond)
  664. {
  665. base_type::operator=(broadcast(rhs.derived_cast(), this->derived_cast().shape()));
  666. }
  667. else
  668. {
  669. base_type::operator=(rhs);
  670. }
  671. return this->derived_cast();
  672. }
  673. }
  674. #endif