xfixed.hpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991
  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_FIXED_HPP
  10. #define XTENSOR_FIXED_HPP
  11. #include <algorithm>
  12. #include <array>
  13. #include <cstddef>
  14. #include <utility>
  15. #include <vector>
  16. #include <xtl/xsequence.hpp>
  17. #include "xcontainer.hpp"
  18. #include "xsemantic.hpp"
  19. #include "xstorage.hpp"
  20. #include "xstrides.hpp"
  21. #include "xtensor_config.hpp"
  22. namespace xtl
  23. {
  24. namespace detail
  25. {
  26. template <class T, std::size_t N>
  27. struct sequence_builder<xt::const_array<T, N>>
  28. {
  29. using sequence_type = xt::const_array<T, N>;
  30. using value_type = typename sequence_type::value_type;
  31. using size_type = typename sequence_type::size_type;
  32. inline static sequence_type make(size_type /*size*/, value_type /*v*/)
  33. {
  34. return sequence_type();
  35. }
  36. };
  37. }
  38. }
  39. namespace xt
  40. {
  41. /**********************
  42. * xfixed declaration *
  43. **********************/
  44. template <class ET, class S, layout_type L, bool SH, class Tag>
  45. class xfixed_container;
  46. namespace detail
  47. {
  48. /**************************************************************************************
  49. The following is something we can currently only dream about -- for when we drop
  50. support for a lot of the old compilers (e.g. GCC 4.9, MSVC 2017 ;)
  51. template <class T>
  52. constexpr std::size_t calculate_stride(T& shape, std::size_t idx, layout_type L)
  53. {
  54. if (shape[idx] == 1)
  55. {
  56. return std::size_t(0);
  57. }
  58. std::size_t data_size = 1;
  59. std::size_t stride = 1;
  60. if (L == layout_type::row_major)
  61. {
  62. // because we have a integer sequence that counts
  63. // from 0 to sz - 1, we need to "invert" idx here
  64. idx = shape.size() - idx;
  65. for (std::size_t i = idx; i != 0; --i)
  66. {
  67. stride = data_size;
  68. data_size = stride * shape[i - 1];
  69. }
  70. }
  71. else
  72. {
  73. for (std::size_t i = 0; i < idx + 1; ++i)
  74. {
  75. stride = data_size;
  76. data_size = stride * shape[i];
  77. }
  78. }
  79. return stride;
  80. }
  81. *****************************************************************************************/
  82. template <layout_type L, std::size_t I, std::size_t... X>
  83. struct calculate_stride;
  84. template <std::size_t I, std::size_t Y, std::size_t... X>
  85. struct calculate_stride<layout_type::column_major, I, Y, X...>
  86. {
  87. static constexpr std::ptrdiff_t value = Y
  88. * calculate_stride<layout_type::column_major, I - 1, X...>::value;
  89. };
  90. template <std::size_t Y, std::size_t... X>
  91. struct calculate_stride<layout_type::column_major, 0, Y, X...>
  92. {
  93. static constexpr std::ptrdiff_t value = 1;
  94. };
  95. template <std::size_t I, std::size_t... X>
  96. struct calculate_stride_row_major
  97. {
  98. static constexpr std::ptrdiff_t value = at<sizeof...(X) - I, X...>::value
  99. * calculate_stride_row_major<I - 1, X...>::value;
  100. };
  101. template <std::size_t... X>
  102. struct calculate_stride_row_major<0, X...>
  103. {
  104. static constexpr std::ptrdiff_t value = 1;
  105. };
  106. template <std::size_t I, std::size_t... X>
  107. struct calculate_stride<layout_type::row_major, I, X...>
  108. {
  109. static constexpr std::ptrdiff_t value = calculate_stride_row_major<sizeof...(X) - I - 1, X...>::value;
  110. };
  111. namespace workaround
  112. {
  113. template <layout_type L, size_t I, class SEQ>
  114. struct computed_strides;
  115. template <layout_type L, size_t I, size_t... X>
  116. struct computed_strides<L, I, std::index_sequence<X...>>
  117. {
  118. static constexpr std::ptrdiff_t value = calculate_stride<L, I, X...>::value;
  119. };
  120. template <layout_type L, size_t I, class SEQ>
  121. constexpr std::ptrdiff_t get_computed_strides(bool cond)
  122. {
  123. return cond ? 0 : computed_strides<L, I, SEQ>::value;
  124. }
  125. }
  126. template <layout_type L, class R, std::size_t... X, std::size_t... I>
  127. constexpr R get_strides_impl(const xt::fixed_shape<X...>& shape, std::index_sequence<I...>)
  128. {
  129. static_assert(
  130. (L == layout_type::row_major) || (L == layout_type::column_major),
  131. "Layout not supported for fixed array"
  132. );
  133. #if (_MSC_VER >= 1910)
  134. using temp_type = std::index_sequence<X...>;
  135. return R({workaround::get_computed_strides<L, I, temp_type>(shape[I] == 1)...});
  136. #else
  137. return R({shape[I] == 1 ? 0 : calculate_stride<L, I, X...>::value...});
  138. #endif
  139. }
  140. template <class S, class T, std::size_t... I>
  141. constexpr T get_backstrides_impl(const S& shape, const T& strides, std::index_sequence<I...>)
  142. {
  143. return T({(strides[I] * std::ptrdiff_t(shape[I] - 1))...});
  144. }
  145. template <std::size_t... X>
  146. struct fixed_compute_size_impl;
  147. template <std::size_t Y, std::size_t... X>
  148. struct fixed_compute_size_impl<Y, X...>
  149. {
  150. static constexpr std::size_t value = Y * fixed_compute_size_impl<X...>::value;
  151. };
  152. template <std::size_t X>
  153. struct fixed_compute_size_impl<X>
  154. {
  155. static constexpr std::size_t value = X;
  156. };
  157. template <>
  158. struct fixed_compute_size_impl<>
  159. {
  160. // support for 0D xtensor fixed (empty shape = xshape<>)
  161. static constexpr std::size_t value = 1;
  162. };
  163. // TODO unify with constexpr compute_size when dropping MSVC 2015
  164. template <class T>
  165. struct fixed_compute_size;
  166. template <std::size_t... X>
  167. struct fixed_compute_size<xt::fixed_shape<X...>>
  168. {
  169. static constexpr std::size_t value = fixed_compute_size_impl<X...>::value;
  170. };
  171. template <class V, std::size_t... X>
  172. struct get_init_type_impl;
  173. template <class V, std::size_t Y>
  174. struct get_init_type_impl<V, Y>
  175. {
  176. using type = V[Y];
  177. };
  178. template <class V>
  179. struct get_init_type_impl<V>
  180. {
  181. using type = V[1];
  182. };
  183. template <class V, std::size_t Y, std::size_t... X>
  184. struct get_init_type_impl<V, Y, X...>
  185. {
  186. using tmp_type = typename get_init_type_impl<V, X...>::type;
  187. using type = tmp_type[Y];
  188. };
  189. }
  190. template <layout_type L, class R, std::size_t... X>
  191. constexpr R get_strides(const fixed_shape<X...>& shape) noexcept
  192. {
  193. return detail::get_strides_impl<L, R>(shape, std::make_index_sequence<sizeof...(X)>{});
  194. }
  195. template <class S, class T>
  196. constexpr T get_backstrides(const S& shape, const T& strides) noexcept
  197. {
  198. return detail::get_backstrides_impl(shape, strides, std::make_index_sequence<std::tuple_size<T>::value>{});
  199. }
  200. template <class V, class S>
  201. struct get_init_type;
  202. template <class V, std::size_t... X>
  203. struct get_init_type<V, fixed_shape<X...>>
  204. {
  205. using type = typename detail::get_init_type_impl<V, X...>::type;
  206. };
  207. template <class V, class S>
  208. using get_init_type_t = typename get_init_type<V, S>::type;
  209. template <class ET, class S, layout_type L, bool SH, class Tag>
  210. struct xcontainer_inner_types<xfixed_container<ET, S, L, SH, Tag>>
  211. {
  212. using shape_type = S;
  213. using inner_shape_type = typename S::cast_type;
  214. using strides_type = get_strides_t<inner_shape_type>;
  215. using inner_strides_type = strides_type;
  216. using backstrides_type = inner_strides_type;
  217. using inner_backstrides_type = backstrides_type;
  218. // NOTE: 0D (S::size() == 0) results in storage for 1 element (scalar)
  219. #if defined(_MSC_VER) && _MSC_VER < 1910 && !defined(_WIN64)
  220. // WORKAROUND FOR MSVC 2015 32 bit, fallback to unaligned container for 0D scalar case
  221. using storage_type = std::array<ET, detail::fixed_compute_size<S>::value>;
  222. #else
  223. using storage_type = aligned_array<ET, detail::fixed_compute_size<S>::value>;
  224. #endif
  225. using reference = typename storage_type::reference;
  226. using const_reference = typename storage_type::const_reference;
  227. using size_type = typename storage_type::size_type;
  228. using temporary_type = xfixed_container<ET, S, L, SH, Tag>;
  229. static constexpr layout_type layout = L;
  230. };
  231. template <class ET, class S, layout_type L, bool SH, class Tag>
  232. struct xiterable_inner_types<xfixed_container<ET, S, L, SH, Tag>>
  233. : xcontainer_iterable_types<xfixed_container<ET, S, L, SH, Tag>>
  234. {
  235. };
  236. /**
  237. * @class xfixed_container
  238. * @brief Dense multidimensional container with tensor semantic and fixed
  239. * dimension.
  240. *
  241. * The xfixed_container class implements a dense multidimensional container
  242. * with tensor semantic and fixed dimension
  243. *
  244. * @tparam ET The type of the elements.
  245. * @tparam S The xshape template paramter of the container.
  246. * @tparam L The layout_type of the tensor.
  247. * @tparam SH Wether the tensor can be used as a shared expression.
  248. * @tparam Tag The expression tag.
  249. * @sa xtensor_fixed
  250. */
  251. template <class ET, class S, layout_type L, bool SH, class Tag>
  252. class xfixed_container : public xcontainer<xfixed_container<ET, S, L, SH, Tag>>,
  253. public xcontainer_semantic<xfixed_container<ET, S, L, SH, Tag>>
  254. {
  255. public:
  256. using self_type = xfixed_container<ET, S, L, SH, Tag>;
  257. using base_type = xcontainer<self_type>;
  258. using semantic_base = xcontainer_semantic<self_type>;
  259. using storage_type = typename base_type::storage_type;
  260. using value_type = typename base_type::value_type;
  261. using reference = typename base_type::reference;
  262. using const_reference = typename base_type::const_reference;
  263. using pointer = typename base_type::pointer;
  264. using const_pointer = typename base_type::const_pointer;
  265. using shape_type = typename base_type::shape_type;
  266. using inner_shape_type = typename base_type::inner_shape_type;
  267. using strides_type = typename base_type::strides_type;
  268. using backstrides_type = typename base_type::backstrides_type;
  269. using inner_backstrides_type = typename base_type::inner_backstrides_type;
  270. using inner_strides_type = typename base_type::inner_strides_type;
  271. using temporary_type = typename semantic_base::temporary_type;
  272. using expression_tag = Tag;
  273. static constexpr std::size_t N = std::tuple_size<shape_type>::value;
  274. static constexpr std::size_t rank = N;
  275. xfixed_container() = default;
  276. xfixed_container(const value_type& v);
  277. explicit xfixed_container(const inner_shape_type& shape, layout_type l = L);
  278. explicit xfixed_container(const inner_shape_type& shape, value_type v, layout_type l = L);
  279. // remove this enable_if when removing the other value_type constructor
  280. template <class IX = std::integral_constant<std::size_t, N>, class EN = std::enable_if_t<IX::value != 0, int>>
  281. xfixed_container(nested_initializer_list_t<value_type, N> t);
  282. ~xfixed_container() = default;
  283. xfixed_container(const xfixed_container&) = default;
  284. xfixed_container& operator=(const xfixed_container&) = default;
  285. xfixed_container(xfixed_container&&) = default;
  286. xfixed_container& operator=(xfixed_container&&) = default;
  287. template <class E>
  288. xfixed_container(const xexpression<E>& e);
  289. template <class E>
  290. xfixed_container& operator=(const xexpression<E>& e);
  291. template <class ST = std::array<std::size_t, N>>
  292. static xfixed_container from_shape(ST&& /*s*/);
  293. template <class ST = std::array<std::size_t, N>>
  294. void resize(ST&& shape, bool force = false) const;
  295. template <class ST = shape_type>
  296. void resize(ST&& shape, layout_type l) const;
  297. template <class ST = shape_type>
  298. void resize(ST&& shape, const strides_type& strides) const;
  299. template <class ST = std::array<std::size_t, N>>
  300. const auto& reshape(ST&& shape, layout_type layout = L) const;
  301. template <class ST>
  302. bool broadcast_shape(ST& s, bool reuse_cache = false) const;
  303. constexpr layout_type layout() const noexcept;
  304. bool is_contiguous() const noexcept;
  305. private:
  306. storage_type m_storage;
  307. XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_shape_type m_shape = S();
  308. XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_strides_type m_strides = get_strides<L, inner_strides_type>(S());
  309. XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_backstrides_type
  310. m_backstrides = get_backstrides(m_shape, m_strides);
  311. storage_type& storage_impl() noexcept;
  312. const storage_type& storage_impl() const noexcept;
  313. XTENSOR_CONSTEXPR_RETURN const inner_shape_type& shape_impl() const noexcept;
  314. XTENSOR_CONSTEXPR_RETURN const inner_strides_type& strides_impl() const noexcept;
  315. XTENSOR_CONSTEXPR_RETURN const inner_backstrides_type& backstrides_impl() const noexcept;
  316. friend class xcontainer<xfixed_container<ET, S, L, SH, Tag>>;
  317. };
  318. #ifdef XTENSOR_HAS_CONSTEXPR_ENHANCED
  319. // Out of line definitions to prevent linker errors prior to C++17
  320. template <class ET, class S, layout_type L, bool SH, class Tag>
  321. constexpr
  322. typename xfixed_container<ET, S, L, SH, Tag>::inner_shape_type xfixed_container<ET, S, L, SH, Tag>::m_shape;
  323. template <class ET, class S, layout_type L, bool SH, class Tag>
  324. constexpr
  325. typename xfixed_container<ET, S, L, SH, Tag>::inner_strides_type xfixed_container<ET, S, L, SH, Tag>::m_strides;
  326. template <class ET, class S, layout_type L, bool SH, class Tag>
  327. constexpr typename xfixed_container<ET, S, L, SH, Tag>::inner_backstrides_type
  328. xfixed_container<ET, S, L, SH, Tag>::m_backstrides;
  329. #endif
  330. /****************************************
  331. * xfixed_container_adaptor declaration *
  332. ****************************************/
  333. template <class EC, class S, layout_type L, bool SH, class Tag>
  334. class xfixed_adaptor;
  335. template <class EC, class S, layout_type L, bool SH, class Tag>
  336. struct xcontainer_inner_types<xfixed_adaptor<EC, S, L, SH, Tag>>
  337. {
  338. using storage_type = std::remove_reference_t<EC>;
  339. using reference = typename storage_type::reference;
  340. using const_reference = typename storage_type::const_reference;
  341. using size_type = typename storage_type::size_type;
  342. using shape_type = S;
  343. using inner_shape_type = typename S::cast_type;
  344. using strides_type = get_strides_t<inner_shape_type>;
  345. using backstrides_type = strides_type;
  346. using inner_strides_type = strides_type;
  347. using inner_backstrides_type = backstrides_type;
  348. using temporary_type = xfixed_container<typename storage_type::value_type, S, L, SH, Tag>;
  349. static constexpr layout_type layout = L;
  350. };
  351. template <class EC, class S, layout_type L, bool SH, class Tag>
  352. struct xiterable_inner_types<xfixed_adaptor<EC, S, L, SH, Tag>>
  353. : xcontainer_iterable_types<xfixed_adaptor<EC, S, L, SH, Tag>>
  354. {
  355. };
  356. /**
  357. * @class xfixed_adaptor
  358. * @brief Dense multidimensional container adaptor with tensor semantic
  359. * and fixed dimension.
  360. *
  361. * The xfixed_adaptor class implements a dense multidimensional
  362. * container adaptor with tensor semantic and fixed dimension. It
  363. * is used to provide a multidimensional container semantic and a
  364. * tensor semantic to stl-like containers.
  365. *
  366. * @tparam EC The closure for the container type to adapt.
  367. * @tparam S The xshape template parameter for the fixed shape of the adaptor
  368. * @tparam L The layout_type of the adaptor.
  369. * @tparam SH Wether the adaptor can be used as a shared expression.
  370. * @tparam Tag The expression tag.
  371. */
  372. template <class EC, class S, layout_type L, bool SH, class Tag>
  373. class xfixed_adaptor : public xcontainer<xfixed_adaptor<EC, S, L, SH, Tag>>,
  374. public xcontainer_semantic<xfixed_adaptor<EC, S, L, SH, Tag>>
  375. {
  376. public:
  377. using container_closure_type = EC;
  378. using self_type = xfixed_adaptor<EC, S, L, SH, Tag>;
  379. using base_type = xcontainer<self_type>;
  380. using semantic_base = xcontainer_semantic<self_type>;
  381. using storage_type = typename base_type::storage_type;
  382. using shape_type = typename base_type::shape_type;
  383. using strides_type = typename base_type::strides_type;
  384. using backstrides_type = typename base_type::backstrides_type;
  385. using inner_shape_type = typename base_type::inner_shape_type;
  386. using inner_strides_type = typename base_type::inner_strides_type;
  387. using inner_backstrides_type = typename base_type::inner_backstrides_type;
  388. using temporary_type = typename semantic_base::temporary_type;
  389. using expression_tag = Tag;
  390. static constexpr std::size_t N = S::size();
  391. xfixed_adaptor(storage_type&& data);
  392. xfixed_adaptor(const storage_type& data);
  393. template <class D>
  394. xfixed_adaptor(D&& data);
  395. ~xfixed_adaptor() = default;
  396. xfixed_adaptor(const xfixed_adaptor&) = default;
  397. xfixed_adaptor& operator=(const xfixed_adaptor&);
  398. xfixed_adaptor(xfixed_adaptor&&) = default;
  399. xfixed_adaptor& operator=(xfixed_adaptor&&);
  400. xfixed_adaptor& operator=(temporary_type&&);
  401. template <class E>
  402. xfixed_adaptor& operator=(const xexpression<E>& e);
  403. template <class ST = std::array<std::size_t, N>>
  404. void resize(ST&& shape, bool force = false) const;
  405. template <class ST = shape_type>
  406. void resize(ST&& shape, layout_type l) const;
  407. template <class ST = shape_type>
  408. void resize(ST&& shape, const strides_type& strides) const;
  409. template <class ST = std::array<std::size_t, N>>
  410. const auto& reshape(ST&& shape, layout_type layout = L) const;
  411. template <class ST>
  412. bool broadcast_shape(ST& s, bool reuse_cache = false) const;
  413. constexpr layout_type layout() const noexcept;
  414. bool is_contiguous() const noexcept;
  415. private:
  416. container_closure_type m_storage;
  417. XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_shape_type m_shape = S();
  418. XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_strides_type m_strides = get_strides<L, inner_strides_type>(S());
  419. XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_backstrides_type
  420. m_backstrides = get_backstrides(m_shape, m_strides);
  421. storage_type& storage_impl() noexcept;
  422. const storage_type& storage_impl() const noexcept;
  423. XTENSOR_CONSTEXPR_RETURN const inner_shape_type& shape_impl() const noexcept;
  424. XTENSOR_CONSTEXPR_RETURN const inner_strides_type& strides_impl() const noexcept;
  425. XTENSOR_CONSTEXPR_RETURN const inner_backstrides_type& backstrides_impl() const noexcept;
  426. friend class xcontainer<xfixed_adaptor<EC, S, L, SH, Tag>>;
  427. };
  428. #ifdef XTENSOR_HAS_CONSTEXPR_ENHANCED
  429. // Out of line definitions to prevent linker errors prior to C++17
  430. template <class EC, class S, layout_type L, bool SH, class Tag>
  431. constexpr
  432. typename xfixed_adaptor<EC, S, L, SH, Tag>::inner_shape_type xfixed_adaptor<EC, S, L, SH, Tag>::m_shape;
  433. template <class EC, class S, layout_type L, bool SH, class Tag>
  434. constexpr
  435. typename xfixed_adaptor<EC, S, L, SH, Tag>::inner_strides_type xfixed_adaptor<EC, S, L, SH, Tag>::m_strides;
  436. template <class EC, class S, layout_type L, bool SH, class Tag>
  437. constexpr typename xfixed_adaptor<EC, S, L, SH, Tag>::inner_backstrides_type
  438. xfixed_adaptor<EC, S, L, SH, Tag>::m_backstrides;
  439. #endif
  440. /************************************
  441. * xfixed_container implementation *
  442. ************************************/
  443. /**
  444. * @name Constructors
  445. */
  446. //@{
  447. /**
  448. * Create an uninitialized xfixed_container.
  449. * Note this function is only provided for homogeneity, and the shape & layout argument is
  450. * disregarded (the template shape is always used).
  451. *
  452. * @param shape the shape of the xfixed_container (unused!)
  453. * @param l the layout_type of the xfixed_container (unused!)
  454. */
  455. template <class ET, class S, layout_type L, bool SH, class Tag>
  456. inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(const inner_shape_type& shape, layout_type l)
  457. {
  458. (void) (shape);
  459. (void) (l);
  460. XTENSOR_ASSERT(shape.size() == N && std::equal(shape.begin(), shape.end(), m_shape.begin()));
  461. XTENSOR_ASSERT(L == l);
  462. }
  463. template <class ET, class S, layout_type L, bool SH, class Tag>
  464. inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(const value_type& v)
  465. {
  466. if (this->size() != 1)
  467. {
  468. XTENSOR_THROW(std::runtime_error, "wrong shape for scalar assignment (has to be xshape<>).");
  469. }
  470. m_storage[0] = v;
  471. }
  472. /**
  473. * Create an xfixed_container, and initialize with the value of v.
  474. * Note, the shape argument to this function is only provided for homogeneity,
  475. * and the shape argument is disregarded (the template shape is always used).
  476. *
  477. * @param shape the shape of the xfixed_container (unused!)
  478. * @param v the fill value
  479. * @param l the layout_type of the xfixed_container (unused!)
  480. */
  481. template <class ET, class S, layout_type L, bool SH, class Tag>
  482. inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(
  483. const inner_shape_type& shape,
  484. value_type v,
  485. layout_type l
  486. )
  487. {
  488. (void) (shape);
  489. (void) (l);
  490. XTENSOR_ASSERT(shape.size() == N && std::equal(shape.begin(), shape.end(), m_shape.begin()));
  491. XTENSOR_ASSERT(L == l);
  492. std::fill(m_storage.begin(), m_storage.end(), v);
  493. }
  494. namespace detail
  495. {
  496. template <std::size_t X>
  497. struct check_initializer_list_shape
  498. {
  499. template <class T, class S>
  500. static bool run(const T& t, const S& shape)
  501. {
  502. std::size_t IX = shape.size() - X;
  503. bool result = (shape[IX] == t.size());
  504. for (std::size_t i = 0; i < shape[IX]; ++i)
  505. {
  506. result = result && check_initializer_list_shape<X - 1>::run(t.begin()[i], shape);
  507. }
  508. return result;
  509. }
  510. };
  511. template <>
  512. struct check_initializer_list_shape<0>
  513. {
  514. template <class T, class S>
  515. static bool run(const T& /*t*/, const S& /*shape*/)
  516. {
  517. return true;
  518. }
  519. };
  520. }
  521. template <class ET, class S, layout_type L, bool SH, class Tag>
  522. template <class ST>
  523. inline xfixed_container<ET, S, L, SH, Tag> xfixed_container<ET, S, L, SH, Tag>::from_shape(ST&& shape)
  524. {
  525. (void) shape;
  526. self_type tmp;
  527. XTENSOR_ASSERT(shape.size() == N && std::equal(shape.begin(), shape.end(), tmp.shape().begin()));
  528. return tmp;
  529. }
  530. /**
  531. * Allocates an xfixed_container with shape S with values from a C array.
  532. * The type returned by get_init_type_t is raw C array ``value_type[X][Y][Z]`` for
  533. * ``xt::xshape<X, Y, Z>``. C arrays can be initialized with the initializer list syntax,
  534. * but the size is checked at compile time to prevent errors.
  535. * Note: for clang < 3.8 this is an initializer_list and the size is not checked at compile-or runtime.
  536. */
  537. template <class ET, class S, layout_type L, bool SH, class Tag>
  538. template <class IX, class EN>
  539. inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(nested_initializer_list_t<value_type, N> t)
  540. {
  541. XTENSOR_ASSERT_MSG(
  542. detail::check_initializer_list_shape<N>::run(t, this->shape()) == true,
  543. "initializer list shape does not match fixed shape"
  544. );
  545. constexpr auto tmp = layout_type::row_major;
  546. L == tmp ? nested_copy(m_storage.begin(), t) : nested_copy(this->template begin<tmp>(), t);
  547. }
  548. //@}
  549. /**
  550. * @name Extended copy semantic
  551. */
  552. //@{
  553. /**
  554. * The extended copy constructor.
  555. */
  556. template <class ET, class S, layout_type L, bool SH, class Tag>
  557. template <class E>
  558. inline xfixed_container<ET, S, L, SH, Tag>::xfixed_container(const xexpression<E>& e)
  559. {
  560. semantic_base::assign(e);
  561. }
  562. /**
  563. * The extended assignment operator.
  564. */
  565. template <class ET, class S, layout_type L, bool SH, class Tag>
  566. template <class E>
  567. inline auto xfixed_container<ET, S, L, SH, Tag>::operator=(const xexpression<E>& e) -> self_type&
  568. {
  569. return semantic_base::operator=(e);
  570. }
  571. //@}
  572. /**
  573. * Note that the xfixed_container **cannot** be resized. Attempting to resize with a different
  574. * size throws an assert in debug mode.
  575. */
  576. template <class ET, class S, layout_type L, bool SH, class Tag>
  577. template <class ST>
  578. inline void xfixed_container<ET, S, L, SH, Tag>::resize(ST&& shape, bool) const
  579. {
  580. (void) (shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
  581. XTENSOR_ASSERT(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size());
  582. }
  583. /**
  584. * Note that the xfixed_container **cannot** be resized. Attempting to resize with a different
  585. * size throws an assert in debug mode.
  586. */
  587. template <class ET, class S, layout_type L, bool SH, class Tag>
  588. template <class ST>
  589. inline void xfixed_container<ET, S, L, SH, Tag>::resize(ST&& shape, layout_type l) const
  590. {
  591. (void) (shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
  592. (void) (l);
  593. XTENSOR_ASSERT(
  594. std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size() && L == l
  595. );
  596. }
  597. /**
  598. * Note that the xfixed_container **cannot** be resized. Attempting to resize with a different
  599. * size throws an assert in debug mode.
  600. */
  601. template <class ET, class S, layout_type L, bool SH, class Tag>
  602. template <class ST>
  603. inline void xfixed_container<ET, S, L, SH, Tag>::resize(ST&& shape, const strides_type& strides) const
  604. {
  605. (void) (shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
  606. (void) (strides);
  607. XTENSOR_ASSERT(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size());
  608. XTENSOR_ASSERT(
  609. std::equal(strides.begin(), strides.end(), m_strides.begin()) && strides.size() == m_strides.size()
  610. );
  611. }
  612. /**
  613. * Note that the xfixed_container **cannot** be reshaped to a shape different from ``S``.
  614. */
  615. template <class ET, class S, layout_type L, bool SH, class Tag>
  616. template <class ST>
  617. inline const auto& xfixed_container<ET, S, L, SH, Tag>::reshape(ST&& shape, layout_type layout) const
  618. {
  619. if (!(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size()
  620. && layout == L))
  621. {
  622. XTENSOR_THROW(std::runtime_error, "Trying to reshape xtensor_fixed with different shape or layout.");
  623. }
  624. return *this;
  625. }
  626. template <class ET, class S, layout_type L, bool SH, class Tag>
  627. template <class ST>
  628. inline bool xfixed_container<ET, S, L, SH, Tag>::broadcast_shape(ST& shape, bool) const
  629. {
  630. return xt::broadcast_shape(m_shape, shape);
  631. }
  632. template <class ET, class S, layout_type L, bool SH, class Tag>
  633. constexpr layout_type xfixed_container<ET, S, L, SH, Tag>::layout() const noexcept
  634. {
  635. return base_type::static_layout;
  636. }
  637. template <class ET, class S, layout_type L, bool SH, class Tag>
  638. inline bool xfixed_container<ET, S, L, SH, Tag>::is_contiguous() const noexcept
  639. {
  640. using str_type = typename inner_strides_type::value_type;
  641. return m_strides.empty() || (layout() == layout_type::row_major && m_strides.back() == str_type(1))
  642. || (layout() == layout_type::column_major && m_strides.front() == str_type(1));
  643. }
  644. template <class ET, class S, layout_type L, bool SH, class Tag>
  645. inline auto xfixed_container<ET, S, L, SH, Tag>::storage_impl() noexcept -> storage_type&
  646. {
  647. return m_storage;
  648. }
  649. template <class ET, class S, layout_type L, bool SH, class Tag>
  650. inline auto xfixed_container<ET, S, L, SH, Tag>::storage_impl() const noexcept -> const storage_type&
  651. {
  652. return m_storage;
  653. }
  654. template <class ET, class S, layout_type L, bool SH, class Tag>
  655. XTENSOR_CONSTEXPR_RETURN auto xfixed_container<ET, S, L, SH, Tag>::shape_impl() const noexcept
  656. -> const inner_shape_type&
  657. {
  658. return m_shape;
  659. }
  660. template <class ET, class S, layout_type L, bool SH, class Tag>
  661. XTENSOR_CONSTEXPR_RETURN auto xfixed_container<ET, S, L, SH, Tag>::strides_impl() const noexcept
  662. -> const inner_strides_type&
  663. {
  664. return m_strides;
  665. }
  666. template <class ET, class S, layout_type L, bool SH, class Tag>
  667. XTENSOR_CONSTEXPR_RETURN auto xfixed_container<ET, S, L, SH, Tag>::backstrides_impl() const noexcept
  668. -> const inner_backstrides_type&
  669. {
  670. return m_backstrides;
  671. }
  672. /*******************
  673. * xfixed_adaptor *
  674. *******************/
  675. /**
  676. * @name Constructors
  677. */
  678. //@{
  679. /**
  680. * Constructs an xfixed_adaptor of the given stl-like container.
  681. * @param data the container to adapt
  682. */
  683. template <class EC, class S, layout_type L, bool SH, class Tag>
  684. inline xfixed_adaptor<EC, S, L, SH, Tag>::xfixed_adaptor(storage_type&& data)
  685. : base_type()
  686. , m_storage(std::move(data))
  687. {
  688. }
  689. /**
  690. * Constructs an xfixed_adaptor of the given stl-like container.
  691. * @param data the container to adapt
  692. */
  693. template <class EC, class S, layout_type L, bool SH, class Tag>
  694. inline xfixed_adaptor<EC, S, L, SH, Tag>::xfixed_adaptor(const storage_type& data)
  695. : base_type()
  696. , m_storage(data)
  697. {
  698. }
  699. /**
  700. * Constructs an xfixed_adaptor of the given stl-like container,
  701. * with the specified shape and layout_type.
  702. * @param data the container to adapt
  703. */
  704. template <class EC, class S, layout_type L, bool SH, class Tag>
  705. template <class D>
  706. inline xfixed_adaptor<EC, S, L, SH, Tag>::xfixed_adaptor(D&& data)
  707. : base_type()
  708. , m_storage(std::forward<D>(data))
  709. {
  710. }
  711. //@}
  712. template <class EC, class S, layout_type L, bool SH, class Tag>
  713. inline auto xfixed_adaptor<EC, S, L, SH, Tag>::operator=(const xfixed_adaptor& rhs) -> self_type&
  714. {
  715. base_type::operator=(rhs);
  716. m_storage = rhs.m_storage;
  717. return *this;
  718. }
  719. template <class EC, class S, layout_type L, bool SH, class Tag>
  720. inline auto xfixed_adaptor<EC, S, L, SH, Tag>::operator=(xfixed_adaptor&& rhs) -> self_type&
  721. {
  722. base_type::operator=(std::move(rhs));
  723. m_storage = rhs.m_storage;
  724. return *this;
  725. }
  726. template <class EC, class S, layout_type L, bool SH, class Tag>
  727. inline auto xfixed_adaptor<EC, S, L, SH, Tag>::operator=(temporary_type&& rhs) -> self_type&
  728. {
  729. m_storage.resize(rhs.storage().size());
  730. std::copy(rhs.storage().cbegin(), rhs.storage().cend(), m_storage.begin());
  731. return *this;
  732. }
  733. /**
  734. * @name Extended copy semantic
  735. */
  736. //@{
  737. /**
  738. * The extended assignment operator.
  739. */
  740. template <class EC, class S, layout_type L, bool SH, class Tag>
  741. template <class E>
  742. inline auto xfixed_adaptor<EC, S, L, SH, Tag>::operator=(const xexpression<E>& e) -> self_type&
  743. {
  744. return semantic_base::operator=(e);
  745. }
  746. //@}
  747. /**
  748. * Note that the xfixed_adaptor **cannot** be resized. Attempting to resize with a different
  749. * size throws an assert in debug mode.
  750. */
  751. template <class ET, class S, layout_type L, bool SH, class Tag>
  752. template <class ST>
  753. inline void xfixed_adaptor<ET, S, L, SH, Tag>::resize(ST&& shape, bool) const
  754. {
  755. (void) (shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
  756. XTENSOR_ASSERT(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size());
  757. }
  758. /**
  759. * Note that the xfixed_adaptor **cannot** be resized. Attempting to resize with a different
  760. * size throws an assert in debug mode.
  761. */
  762. template <class ET, class S, layout_type L, bool SH, class Tag>
  763. template <class ST>
  764. inline void xfixed_adaptor<ET, S, L, SH, Tag>::resize(ST&& shape, layout_type l) const
  765. {
  766. (void) (shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
  767. (void) (l);
  768. XTENSOR_ASSERT(
  769. std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size() && L == l
  770. );
  771. }
  772. /**
  773. * Note that the xfixed_adaptor **cannot** be resized. Attempting to resize with a different
  774. * size throws an assert in debug mode.
  775. */
  776. template <class ET, class S, layout_type L, bool SH, class Tag>
  777. template <class ST>
  778. inline void xfixed_adaptor<ET, S, L, SH, Tag>::resize(ST&& shape, const strides_type& strides) const
  779. {
  780. (void) (shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
  781. (void) (strides);
  782. XTENSOR_ASSERT(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size());
  783. XTENSOR_ASSERT(
  784. std::equal(strides.begin(), strides.end(), m_strides.begin()) && strides.size() == m_strides.size()
  785. );
  786. }
  787. /**
  788. * Note that the xfixed_container **cannot** be reshaped to a shape different from ``S``.
  789. */
  790. template <class ET, class S, layout_type L, bool SH, class Tag>
  791. template <class ST>
  792. inline const auto& xfixed_adaptor<ET, S, L, SH, Tag>::reshape(ST&& shape, layout_type layout) const
  793. {
  794. if (!(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size()
  795. && layout == L))
  796. {
  797. XTENSOR_THROW(std::runtime_error, "Trying to reshape xtensor_fixed with different shape or layout.");
  798. }
  799. return *this;
  800. }
  801. template <class ET, class S, layout_type L, bool SH, class Tag>
  802. template <class ST>
  803. inline bool xfixed_adaptor<ET, S, L, SH, Tag>::broadcast_shape(ST& shape, bool) const
  804. {
  805. return xt::broadcast_shape(m_shape, shape);
  806. }
  807. template <class EC, class S, layout_type L, bool SH, class Tag>
  808. inline auto xfixed_adaptor<EC, S, L, SH, Tag>::storage_impl() noexcept -> storage_type&
  809. {
  810. return m_storage;
  811. }
  812. template <class EC, class S, layout_type L, bool SH, class Tag>
  813. inline auto xfixed_adaptor<EC, S, L, SH, Tag>::storage_impl() const noexcept -> const storage_type&
  814. {
  815. return m_storage;
  816. }
  817. template <class EC, class S, layout_type L, bool SH, class Tag>
  818. constexpr layout_type xfixed_adaptor<EC, S, L, SH, Tag>::layout() const noexcept
  819. {
  820. return base_type::static_layout;
  821. }
  822. template <class EC, class S, layout_type L, bool SH, class Tag>
  823. inline bool xfixed_adaptor<EC, S, L, SH, Tag>::is_contiguous() const noexcept
  824. {
  825. using str_type = typename inner_strides_type::value_type;
  826. return m_strides.empty() || (layout() == layout_type::row_major && m_strides.back() == str_type(1))
  827. || (layout() == layout_type::column_major && m_strides.front() == str_type(1));
  828. }
  829. template <class EC, class S, layout_type L, bool SH, class Tag>
  830. XTENSOR_CONSTEXPR_RETURN auto xfixed_adaptor<EC, S, L, SH, Tag>::shape_impl() const noexcept
  831. -> const inner_shape_type&
  832. {
  833. return m_shape;
  834. }
  835. template <class EC, class S, layout_type L, bool SH, class Tag>
  836. XTENSOR_CONSTEXPR_RETURN auto xfixed_adaptor<EC, S, L, SH, Tag>::strides_impl() const noexcept
  837. -> const inner_strides_type&
  838. {
  839. return m_strides;
  840. }
  841. template <class EC, class S, layout_type L, bool SH, class Tag>
  842. XTENSOR_CONSTEXPR_RETURN auto xfixed_adaptor<EC, S, L, SH, Tag>::backstrides_impl() const noexcept
  843. -> const inner_backstrides_type&
  844. {
  845. return m_backstrides;
  846. }
  847. }
  848. #endif