xadapt.hpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921
  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_ADAPT_HPP
  10. #define XTENSOR_ADAPT_HPP
  11. #include <array>
  12. #include <cstddef>
  13. #include <memory>
  14. #include <type_traits>
  15. #include <xtl/xsequence.hpp>
  16. #include "xarray.hpp"
  17. #include "xbuffer_adaptor.hpp"
  18. #include "xfixed.hpp"
  19. #include "xtensor.hpp"
  20. namespace xt
  21. {
  22. /**
  23. * @defgroup xt_xadapt Adaptors of STL-like containers
  24. */
  25. namespace detail
  26. {
  27. template <class>
  28. struct array_size_impl;
  29. template <class T, std::size_t N>
  30. struct array_size_impl<std::array<T, N>>
  31. {
  32. static constexpr std::size_t value = N;
  33. };
  34. template <class C>
  35. using array_size = array_size_impl<std::decay_t<C>>;
  36. template <class P>
  37. struct default_allocator_for_ptr
  38. {
  39. using type = std::allocator<std::remove_const_t<std::remove_pointer_t<std::remove_reference_t<P>>>>;
  40. };
  41. template <class P>
  42. using default_allocator_for_ptr_t = typename default_allocator_for_ptr<P>::type;
  43. template <class T>
  44. using not_an_array = xtl::negation<is_array<T>>;
  45. template <class T>
  46. using not_a_pointer = xtl::negation<std::is_pointer<T>>;
  47. template <class T>
  48. using not_a_layout = xtl::negation<std::is_same<layout_type, T>>;
  49. }
  50. #ifndef IN_DOXYGEN
  51. /**************************
  52. * xarray_adaptor builder *
  53. **************************/
  54. /**
  55. * Constructs an xarray_adaptor of the given stl-like container,
  56. * with the specified shape and layout.
  57. *
  58. * @ingroup xt_xadapt
  59. * @param container the container to adapt
  60. * @param shape the shape of the xarray_adaptor
  61. * @param l the layout_type of the xarray_adaptor
  62. */
  63. template <
  64. layout_type L = XTENSOR_DEFAULT_LAYOUT,
  65. class C,
  66. class SC,
  67. XTL_REQUIRES(detail::not_an_array<std::decay_t<SC>>, detail::not_a_pointer<C>)>
  68. inline xarray_adaptor<xtl::closure_type_t<C>, L, std::decay_t<SC>>
  69. adapt(C&& container, const SC& shape, layout_type l = L)
  70. {
  71. static_assert(!xtl::is_integral<SC>::value, "shape cannot be a integer");
  72. using return_type = xarray_adaptor<xtl::closure_type_t<C>, L, std::decay_t<SC>>;
  73. return return_type(std::forward<C>(container), shape, l);
  74. }
  75. /**
  76. * Constructs an non-owning xarray_adaptor from a pointer with the specified shape and layout.
  77. *
  78. * @ingroup xt_xadapt
  79. * @param pointer the container to adapt
  80. * @param shape the shape of the xarray_adaptor
  81. * @param l the layout_type of the xarray_adaptor
  82. */
  83. template <
  84. layout_type L = XTENSOR_DEFAULT_LAYOUT,
  85. class C,
  86. class SC,
  87. XTL_REQUIRES(detail::not_an_array<std::decay_t<SC>>, std::is_pointer<std::remove_reference_t<C>>)>
  88. inline auto adapt(C&& pointer, const SC& shape, layout_type l = L)
  89. {
  90. static_assert(!xtl::is_integral<SC>::value, "shape cannot be a integer");
  91. using buffer_type = xbuffer_adaptor<C, xt::no_ownership, detail::default_allocator_for_ptr_t<C>>;
  92. using return_type = xarray_adaptor<buffer_type, L, std::decay_t<SC>>;
  93. std::size_t size = compute_size(shape);
  94. return return_type(buffer_type(pointer, size), shape, l);
  95. }
  96. /**
  97. * Constructs an xarray_adaptor of the given stl-like container,
  98. * with the specified shape and strides.
  99. *
  100. * @ingroup xt_xadapt
  101. * @param container the container to adapt
  102. * @param shape the shape of the xarray_adaptor
  103. * @param strides the strides of the xarray_adaptor
  104. */
  105. template <
  106. class C,
  107. class SC,
  108. class SS,
  109. XTL_REQUIRES(detail::not_an_array<std::decay_t<SC>>, detail::not_a_layout<std::decay_t<SS>>)>
  110. inline xarray_adaptor<xtl::closure_type_t<C>, layout_type::dynamic, std::decay_t<SC>>
  111. adapt(C&& container, SC&& shape, SS&& strides)
  112. {
  113. static_assert(!xtl::is_integral<std::decay_t<SC>>::value, "shape cannot be a integer");
  114. using return_type = xarray_adaptor<xtl::closure_type_t<C>, layout_type::dynamic, std::decay_t<SC>>;
  115. return return_type(
  116. std::forward<C>(container),
  117. xtl::forward_sequence<typename return_type::inner_shape_type, SC>(shape),
  118. xtl::forward_sequence<typename return_type::inner_strides_type, SS>(strides)
  119. );
  120. }
  121. /**
  122. * Constructs an xarray_adaptor of the given dynamically allocated C array,
  123. * with the specified shape and layout.
  124. *
  125. * @ingroup xt_xadapt
  126. * @param pointer the pointer to the beginning of the dynamic array
  127. * @param size the size of the dynamic array
  128. * @param ownership indicates whether the adaptor takes ownership of the array.
  129. * Possible values are ``no_ownership()`` or ``acquire_ownership()``
  130. * @param shape the shape of the xarray_adaptor
  131. * @param l the layout_type of the xarray_adaptor
  132. * @param alloc the allocator used for allocating / deallocating the dynamic array
  133. */
  134. template <
  135. layout_type L = XTENSOR_DEFAULT_LAYOUT,
  136. class P,
  137. class O,
  138. class SC,
  139. class A = detail::default_allocator_for_ptr_t<P>,
  140. XTL_REQUIRES(detail::not_an_array<std::decay_t<SC>>)>
  141. inline xarray_adaptor<xbuffer_adaptor<xtl::closure_type_t<P>, O, A>, L, SC> adapt(
  142. P&& pointer,
  143. typename A::size_type size,
  144. O ownership,
  145. const SC& shape,
  146. layout_type l = L,
  147. const A& alloc = A()
  148. )
  149. {
  150. static_assert(!xtl::is_integral<SC>::value, "shape cannot be a integer");
  151. (void) ownership;
  152. using buffer_type = xbuffer_adaptor<xtl::closure_type_t<P>, O, A>;
  153. using return_type = xarray_adaptor<buffer_type, L, SC>;
  154. buffer_type buf(std::forward<P>(pointer), size, alloc);
  155. return return_type(std::move(buf), shape, l);
  156. }
  157. /**
  158. * Constructs an xarray_adaptor of the given dynamically allocated C array,
  159. * with the specified shape and strides.
  160. *
  161. * @ingroup xt_xadapt
  162. * @param pointer the pointer to the beginning of the dynamic array
  163. * @param size the size of the dynamic array
  164. * @param ownership indicates whether the adaptor takes ownership of the array.
  165. * Possible values are ``no_ownership()`` or ``acquire_ownership()``
  166. * @param shape the shape of the xarray_adaptor
  167. * @param strides the strides of the xarray_adaptor
  168. * @param alloc the allocator used for allocating / deallocating the dynamic array
  169. */
  170. template <
  171. class P,
  172. class O,
  173. class SC,
  174. class SS,
  175. class A = detail::default_allocator_for_ptr_t<P>,
  176. XTL_REQUIRES(detail::not_an_array<std::decay_t<SC>>, detail::not_a_layout<std::decay_t<SS>>)>
  177. inline xarray_adaptor<xbuffer_adaptor<xtl::closure_type_t<P>, O, A>, layout_type::dynamic, std::decay_t<SC>>
  178. adapt(P&& pointer, typename A::size_type size, O ownership, SC&& shape, SS&& strides, const A& alloc = A())
  179. {
  180. static_assert(!xtl::is_integral<std::decay_t<SC>>::value, "shape cannot be a integer");
  181. (void) ownership;
  182. using buffer_type = xbuffer_adaptor<xtl::closure_type_t<P>, O, A>;
  183. using return_type = xarray_adaptor<buffer_type, layout_type::dynamic, std::decay_t<SC>>;
  184. buffer_type buf(std::forward<P>(pointer), size, alloc);
  185. return return_type(
  186. std::move(buf),
  187. xtl::forward_sequence<typename return_type::inner_shape_type, SC>(shape),
  188. xtl::forward_sequence<typename return_type::inner_strides_type, SS>(strides)
  189. );
  190. }
  191. /**
  192. * Constructs an xarray_adaptor of the given C array allocated on the stack, with the
  193. * specified shape and layout.
  194. *
  195. * @ingroup xt_xadapt
  196. * @param c_array the C array allocated on the stack
  197. * @param shape the shape of the xarray_adaptor
  198. * @param l the layout_type of the xarray_adaptor
  199. */
  200. template <
  201. layout_type L = XTENSOR_DEFAULT_LAYOUT,
  202. class T,
  203. std::size_t N,
  204. class SC,
  205. XTL_REQUIRES(detail::not_an_array<std::decay_t<SC>>)>
  206. inline auto adapt(T (&c_array)[N], const SC& shape, layout_type l = L)
  207. {
  208. return adapt(&c_array[0], N, xt::no_ownership(), shape, l);
  209. }
  210. /**
  211. * Constructs an xarray_adaptor of the given C array allocated on the stack, with the
  212. * specified shape and stirdes.
  213. *
  214. * @ingroup xt_xadapt
  215. * @param c_array the C array allocated on the stack
  216. * @param shape the shape of the xarray_adaptor
  217. * @param strides the strides of the xarray_adaptor
  218. */
  219. template <
  220. class T,
  221. std::size_t N,
  222. class SC,
  223. class SS,
  224. XTL_REQUIRES(detail::not_an_array<std::decay_t<SC>>, detail::not_a_layout<std::decay_t<SS>>)>
  225. inline auto adapt(T (&c_array)[N], SC&& shape, SS&& strides)
  226. {
  227. return adapt(&c_array[0], N, xt::no_ownership(), std::forward<SC>(shape), std::forward<SS>(strides));
  228. }
  229. /***************************
  230. * xtensor_adaptor builder *
  231. ***************************/
  232. /**
  233. * Constructs a 1-D xtensor_adaptor of the given stl-like container,
  234. * with the specified layout_type.
  235. *
  236. * @ingroup xt_xadapt
  237. * @param container the container to adapt
  238. * @param l the layout_type of the xtensor_adaptor
  239. */
  240. template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class C>
  241. inline xtensor_adaptor<C, 1, L> adapt(C&& container, layout_type l = L)
  242. {
  243. const std::array<typename std::decay_t<C>::size_type, 1> shape{container.size()};
  244. using return_type = xtensor_adaptor<xtl::closure_type_t<C>, 1, L>;
  245. return return_type(std::forward<C>(container), shape, l);
  246. }
  247. /**
  248. * Constructs an xtensor_adaptor of the given stl-like container,
  249. * with the specified shape and layout_type.
  250. *
  251. * @ingroup xt_xadapt
  252. * @param container the container to adapt
  253. * @param shape the shape of the xtensor_adaptor
  254. * @param l the layout_type of the xtensor_adaptor
  255. */
  256. template <
  257. layout_type L = XTENSOR_DEFAULT_LAYOUT,
  258. class C,
  259. class SC,
  260. XTL_REQUIRES(detail::is_array<std::decay_t<SC>>, detail::not_a_pointer<C>)>
  261. inline xtensor_adaptor<C, detail::array_size<SC>::value, L>
  262. adapt(C&& container, const SC& shape, layout_type l = L)
  263. {
  264. static_assert(!xtl::is_integral<SC>::value, "shape cannot be a integer");
  265. constexpr std::size_t N = detail::array_size<SC>::value;
  266. using return_type = xtensor_adaptor<xtl::closure_type_t<C>, N, L>;
  267. return return_type(std::forward<C>(container), shape, l);
  268. }
  269. /**
  270. * Constructs an non-owning xtensor_adaptor from a pointer with the specified shape and layout.
  271. *
  272. * @ingroup xt_xadapt
  273. * @param pointer the pointer to adapt
  274. * @param shape the shape of the xtensor_adaptor
  275. * @param l the layout_type of the xtensor_adaptor
  276. */
  277. template <
  278. layout_type L = XTENSOR_DEFAULT_LAYOUT,
  279. class C,
  280. class SC,
  281. XTL_REQUIRES(detail::is_array<std::decay_t<SC>>, std::is_pointer<std::remove_reference_t<C>>)>
  282. inline auto adapt(C&& pointer, const SC& shape, layout_type l = L)
  283. {
  284. static_assert(!xtl::is_integral<SC>::value, "shape cannot be a integer");
  285. using buffer_type = xbuffer_adaptor<C, xt::no_ownership, detail::default_allocator_for_ptr_t<C>>;
  286. constexpr std::size_t N = detail::array_size<SC>::value;
  287. using return_type = xtensor_adaptor<buffer_type, N, L>;
  288. return return_type(buffer_type(pointer, compute_size(shape)), shape, l);
  289. }
  290. /**
  291. * Constructs an xtensor_adaptor of the given stl-like container,
  292. * with the specified shape and strides.
  293. *
  294. * @ingroup xt_xadapt
  295. * @param container the container to adapt
  296. * @param shape the shape of the xtensor_adaptor
  297. * @param strides the strides of the xtensor_adaptor
  298. */
  299. template <
  300. class C,
  301. class SC,
  302. class SS,
  303. XTL_REQUIRES(detail::is_array<std::decay_t<SC>>, detail::not_a_layout<std::decay_t<SS>>)>
  304. inline xtensor_adaptor<C, detail::array_size<SC>::value, layout_type::dynamic>
  305. adapt(C&& container, SC&& shape, SS&& strides)
  306. {
  307. static_assert(!xtl::is_integral<std::decay_t<SC>>::value, "shape cannot be a integer");
  308. constexpr std::size_t N = detail::array_size<SC>::value;
  309. using return_type = xtensor_adaptor<xtl::closure_type_t<C>, N, layout_type::dynamic>;
  310. return return_type(
  311. std::forward<C>(container),
  312. xtl::forward_sequence<typename return_type::inner_shape_type, SC>(shape),
  313. xtl::forward_sequence<typename return_type::inner_strides_type, SS>(strides)
  314. );
  315. }
  316. /**
  317. * Constructs a 1-D xtensor_adaptor of the given dynamically allocated C array,
  318. * with the specified layout.
  319. *
  320. * @ingroup xt_xadapt
  321. * @param pointer the pointer to the beginning of the dynamic array
  322. * @param size the size of the dynamic array
  323. * @param ownership indicates whether the adaptor takes ownership of the array.
  324. * Possible values are ``no_ownership()`` or ``acquire_ownership()``
  325. * @param l the layout_type of the xtensor_adaptor
  326. * @param alloc the allocator used for allocating / deallocating the dynamic array
  327. */
  328. template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class P, class O, class A = detail::default_allocator_for_ptr_t<P>>
  329. inline xtensor_adaptor<xbuffer_adaptor<xtl::closure_type_t<P>, O, A>, 1, L>
  330. adapt(P&& pointer, typename A::size_type size, O ownership, layout_type l = L, const A& alloc = A())
  331. {
  332. (void) ownership;
  333. using buffer_type = xbuffer_adaptor<xtl::closure_type_t<P>, O, A>;
  334. using return_type = xtensor_adaptor<buffer_type, 1, L>;
  335. buffer_type buf(std::forward<P>(pointer), size, alloc);
  336. const std::array<typename A::size_type, 1> shape{size};
  337. return return_type(std::move(buf), shape, l);
  338. }
  339. /**
  340. * Constructs an xtensor_adaptor of the given dynamically allocated C array,
  341. * with the specified shape and layout.
  342. *
  343. * @ingroup xt_xadapt
  344. * @param pointer the pointer to the beginning of the dynamic array
  345. * @param size the size of the dynamic array
  346. * @param ownership indicates whether the adaptor takes ownership of the array.
  347. * Possible values are ``no_ownership()`` or ``acquire_ownership()``
  348. * @param shape the shape of the xtensor_adaptor
  349. * @param l the layout_type of the xtensor_adaptor
  350. * @param alloc the allocator used for allocating / deallocating the dynamic array
  351. */
  352. template <
  353. layout_type L = XTENSOR_DEFAULT_LAYOUT,
  354. class P,
  355. class O,
  356. class SC,
  357. class A = detail::default_allocator_for_ptr_t<P>,
  358. XTL_REQUIRES(detail::is_array<std::decay_t<SC>>)>
  359. inline xtensor_adaptor<xbuffer_adaptor<xtl::closure_type_t<P>, O, A>, detail::array_size<SC>::value, L>
  360. adapt(
  361. P&& pointer,
  362. typename A::size_type size,
  363. O ownership,
  364. const SC& shape,
  365. layout_type l = L,
  366. const A& alloc = A()
  367. )
  368. {
  369. static_assert(!xtl::is_integral<SC>::value, "shape cannot be a integer");
  370. (void) ownership;
  371. using buffer_type = xbuffer_adaptor<xtl::closure_type_t<P>, O, A>;
  372. constexpr std::size_t N = detail::array_size<SC>::value;
  373. using return_type = xtensor_adaptor<buffer_type, N, L>;
  374. buffer_type buf(std::forward<P>(pointer), size, alloc);
  375. return return_type(std::move(buf), shape, l);
  376. }
  377. /**
  378. * Constructs an xtensor_adaptor of the given dynamically allocated C array,
  379. * with the specified shape and strides.
  380. *
  381. * @ingroup xt_xadapt
  382. * @param pointer the pointer to the beginning of the dynamic array
  383. * @param size the size of the dynamic array
  384. * @param ownership indicates whether the adaptor takes ownership of the array.
  385. * Possible values are ``no_ownership()`` or ``acquire_ownership()``
  386. * @param shape the shape of the xtensor_adaptor
  387. * @param strides the strides of the xtensor_adaptor
  388. * @param alloc the allocator used for allocating / deallocating the dynamic array
  389. */
  390. template <
  391. class P,
  392. class O,
  393. class SC,
  394. class SS,
  395. class A = detail::default_allocator_for_ptr_t<P>,
  396. XTL_REQUIRES(detail::is_array<std::decay_t<SC>>, detail::not_a_layout<std::decay_t<SS>>)>
  397. inline xtensor_adaptor<xbuffer_adaptor<xtl::closure_type_t<P>, O, A>, detail::array_size<SC>::value, layout_type::dynamic>
  398. adapt(P&& pointer, typename A::size_type size, O ownership, SC&& shape, SS&& strides, const A& alloc = A())
  399. {
  400. static_assert(!xtl::is_integral<std::decay_t<SC>>::value, "shape cannot be a integer");
  401. (void) ownership;
  402. using buffer_type = xbuffer_adaptor<xtl::closure_type_t<P>, O, A>;
  403. constexpr std::size_t N = detail::array_size<SC>::value;
  404. using return_type = xtensor_adaptor<buffer_type, N, layout_type::dynamic>;
  405. buffer_type buf(std::forward<P>(pointer), size, alloc);
  406. return return_type(
  407. std::move(buf),
  408. xtl::forward_sequence<typename return_type::inner_shape_type, SC>(shape),
  409. xtl::forward_sequence<typename return_type::inner_strides_type, SS>(strides)
  410. );
  411. }
  412. /**
  413. * Constructs an xtensor_adaptor of the given C array allocated on the stack, with the
  414. * specified shape and layout.
  415. *
  416. * @ingroup xt_xadapt
  417. * @param c_array the C array allocated on the stack
  418. * @param shape the shape of the xarray_adaptor
  419. * @param l the layout_type of the xarray_adaptor
  420. */
  421. template <
  422. layout_type L = XTENSOR_DEFAULT_LAYOUT,
  423. class T,
  424. std::size_t N,
  425. class SC,
  426. XTL_REQUIRES(detail::is_array<std::decay_t<SC>>)>
  427. inline auto adapt(T (&c_array)[N], const SC& shape, layout_type l = L)
  428. {
  429. return adapt(&c_array[0], N, xt::no_ownership(), shape, l);
  430. }
  431. /**
  432. * Constructs an xtensor_adaptor of the given C array allocated on the stack, with the
  433. * specified shape and strides.
  434. *
  435. * @ingroup xt_xadapt
  436. * @param c_array the C array allocated on the stack
  437. * @param shape the shape of the xarray_adaptor
  438. * @param strides the strides of the xarray_adaptor
  439. */
  440. template <
  441. class T,
  442. std::size_t N,
  443. class SC,
  444. class SS,
  445. XTL_REQUIRES(detail::is_array<std::decay_t<SC>>, detail::not_a_layout<std::decay_t<SS>>)>
  446. inline auto adapt(T (&c_array)[N], SC&& shape, SS&& strides)
  447. {
  448. return adapt(&c_array[0], N, xt::no_ownership(), std::forward<SC>(shape), std::forward<SS>(strides));
  449. }
  450. /**
  451. * Constructs an non-owning xtensor_fixed_adaptor from a pointer with the
  452. * specified shape and layout.
  453. *
  454. * @ingroup xt_xadapt
  455. * @param pointer the pointer to adapt
  456. * @param shape the shape of the xtensor_fixed_adaptor
  457. */
  458. template <
  459. layout_type L = XTENSOR_DEFAULT_LAYOUT,
  460. class C,
  461. std::size_t... X,
  462. XTL_REQUIRES(std::is_pointer<std::remove_reference_t<C>>)>
  463. inline auto adapt(C&& pointer, const fixed_shape<X...>& /*shape*/)
  464. {
  465. using buffer_type = xbuffer_adaptor<C, xt::no_ownership, detail::default_allocator_for_ptr_t<C>>;
  466. using return_type = xfixed_adaptor<buffer_type, fixed_shape<X...>, L>;
  467. return return_type(buffer_type(pointer, detail::fixed_compute_size<fixed_shape<X...>>::value));
  468. }
  469. template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class C, class T, std::size_t N>
  470. inline auto adapt(C&& ptr, const T (&shape)[N])
  471. {
  472. using shape_type = std::array<std::size_t, N>;
  473. return adapt(std::forward<C>(ptr), xtl::forward_sequence<shape_type, decltype(shape)>(shape));
  474. }
  475. #else // IN_DOXYGEN
  476. /**
  477. * Constructs:
  478. * - an xarray_adaptor if SC is not an array type
  479. * - an xtensor_adaptor if SC is an array type
  480. *
  481. * from the given stl-like container or pointer, with the specified shape and layout.
  482. * If the adaptor is built from a pointer, it does not take its ownership.
  483. *
  484. * @ingroup xt_xadapt
  485. * @param container the container or pointer to adapt
  486. * @param shape the shape of the adaptor
  487. * @param l the layout_type of the adaptor
  488. */
  489. template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class C, class SC>
  490. inline auto adapt(C&& container, const SC& shape, layout_type l = L);
  491. /**
  492. * Constructs:
  493. * - an xarray_adaptor if SC is not an array type
  494. * - an xtensor_adaptor if SC is an array type
  495. *
  496. * from the given stl-like container with the specified shape and strides.
  497. *
  498. * @ingroup xt_xadapt
  499. * @param container the container to adapt
  500. * @param shape the shape of the adaptor
  501. * @param strides the strides of the adaptor
  502. */
  503. template <class C, class SC, class SS>
  504. inline auto adapt(C&& container, SC&& shape, SS&& strides);
  505. /**
  506. * Constructs:
  507. * - an xarray_adaptor if SC is not an array type
  508. * - an xtensor_adaptor if SC is an array type
  509. *
  510. * of the given dynamically allocated C array, with the specified shape and layout.
  511. *
  512. * @ingroup xt_xadapt
  513. * @param pointer the pointer to the beginning of the dynamic array
  514. * @param size the size of the dynamic array
  515. * @param ownership indicates whether the adaptor takes ownership of the array.
  516. * Possible values are ``no_ownership()`` or ``acquire_ownership()``
  517. * @param shape the shape of the adaptor
  518. * @param l the layout_type of the adaptor
  519. * @param alloc the allocator used for allocating / deallocating the dynamic array
  520. */
  521. template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class P, class O, class SC, class A = detail::default_allocator_for_ptr_t<P>>
  522. inline auto adapt(
  523. P&& pointer,
  524. typename A::size_type size,
  525. O ownership,
  526. const SC& shape,
  527. layout_type l = L,
  528. const A& alloc = A()
  529. );
  530. /**
  531. * Constructs:
  532. * - an xarray_adaptor if SC is not an array type
  533. * - an xtensor_adaptor if SC is an array type
  534. *
  535. * of the given dynamically allocated C array, with the specified shape and strides.
  536. *
  537. * @ingroup xt_xadapt
  538. * @param pointer the pointer to the beginning of the dynamic array
  539. * @param size the size of the dynamic array
  540. * @param ownership indicates whether the adaptor takes ownership of the array.
  541. * Possible values are ``no_ownership()`` or ``acquire_ownership()``
  542. * @param shape the shape of the adaptor
  543. * @param strides the strides of the adaptor
  544. * @param alloc the allocator used for allocating / deallocating the dynamic array
  545. */
  546. template <class P, class O, class SC, class SS, class A = detail::default_allocator_for_ptr_t<P>>
  547. inline auto
  548. adapt(P&& pointer, typename A::size_type size, O ownership, SC&& shape, SS&& strides, const A& alloc = A());
  549. /**
  550. * Constructs:
  551. * - an xarray_adaptor if SC is not an array type
  552. * - an xtensor_adaptor if SC is an array type
  553. *
  554. * of the given C array allocated on the stack, with the specified shape and layout.
  555. *
  556. * @ingroup xt_xadapt
  557. * @param c_array the C array allocated on the stack
  558. * @param shape the shape of the adaptor
  559. * @param l the layout_type of the adaptor
  560. */
  561. template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class T, std::size_t N, class SC>
  562. inline auto adapt(T (&c_array)[N], const SC& shape, layout_type l = L);
  563. /**
  564. * Constructs:
  565. * - an xarray_adaptor if SC is not an array type
  566. * - an xtensor_adaptor if SC is an array type
  567. *
  568. * of the given C array allocated on the stack, with the
  569. * specified shape and strides.
  570. *
  571. * @ingroup xt_xadapt
  572. * @param c_array the C array allocated on the stack
  573. * @param shape the shape of the adaptor
  574. * @param strides the strides of the adaptor
  575. */
  576. template <class T, std::size_t N, class SC, class SS>
  577. inline auto adapt(T (&c_array)[N], SC&& shape, SS&& strides);
  578. /**
  579. * Constructs an non-owning xtensor_fixed_adaptor from a pointer with the
  580. * specified shape and layout.
  581. *
  582. * @ingroup xt_xadapt
  583. * @param pointer the pointer to adapt
  584. * @param shape the shape of the xtensor_fixed_adaptor
  585. */
  586. template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class C, std::size_t... X>
  587. inline auto adapt(C&& pointer, const fixed_shape<X...>& /*shape*/);
  588. /**
  589. * Constructs a 1-D xtensor_adaptor of the given stl-like container,
  590. * with the specified layout_type.
  591. *
  592. * @ingroup xt_xadapt
  593. * @param container the container to adapt
  594. * @param l the layout_type of the xtensor_adaptor
  595. */
  596. template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class C>
  597. inline xtensor_adaptor<C, 1, L> adapt(C&& container, layout_type l = L);
  598. /**
  599. * Constructs a 1-D xtensor_adaptor of the given dynamically allocated C array,
  600. * with the specified layout.
  601. *
  602. * @ingroup xt_xadapt
  603. * @param pointer the pointer to the beginning of the dynamic array
  604. * @param size the size of the dynamic array
  605. * @param ownership indicates whether the adaptor takes ownership of the array.
  606. * Possible values are ``no_ownership()`` or ``acquire_ownership()``
  607. * @param l the layout_type of the xtensor_adaptor
  608. * @param alloc the allocator used for allocating / deallocating the dynamic array
  609. */
  610. template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class P, class O, class A = detail::default_allocator_for_ptr_t<P>>
  611. inline xtensor_adaptor<xbuffer_adaptor<xtl::closure_type_t<P>, O, A>, 1, L>
  612. adapt(P&& pointer, typename A::size_type size, O ownership, layout_type l = L, const A& alloc = A());
  613. #endif // IN_DOXYGEN
  614. /*****************************
  615. * smart_ptr adapter builder *
  616. *****************************/
  617. /**
  618. * Adapt a smart pointer to a typed memory block (unique_ptr or shared_ptr)
  619. *
  620. * @code{.cpp}
  621. * #include <xtensor/xadapt.hpp>
  622. * #include <xtensor/xio.hpp>
  623. *
  624. * std::shared_ptr<double> sptr(new double[8], std::default_delete<double[]>());
  625. * sptr.get()[2] = 321.;
  626. * std::vector<size_t> shape = {4, 2};
  627. * auto xptr = adapt_smart_ptr(sptr, shape);
  628. * xptr(1, 3) = 123.;
  629. * std::cout << xptr;
  630. * @endcode
  631. *
  632. * @ingroup xt_xadapt
  633. * @param smart_ptr a smart pointer to a memory block of T[]
  634. * @param shape The desired shape
  635. * @param l The desired memory layout
  636. *
  637. * @return xarray_adaptor for memory
  638. */
  639. template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class P, class SC, XTL_REQUIRES(detail::not_an_array<std::decay_t<SC>>)>
  640. auto adapt_smart_ptr(P&& smart_ptr, const SC& shape, layout_type l = L)
  641. {
  642. using buffer_adaptor = xbuffer_adaptor<decltype(smart_ptr.get()), smart_ownership, std::decay_t<P>>;
  643. return xarray_adaptor<buffer_adaptor, L, std::decay_t<SC>>(
  644. buffer_adaptor(smart_ptr.get(), compute_size(shape), std::forward<P>(smart_ptr)),
  645. shape,
  646. l
  647. );
  648. }
  649. /**
  650. * Adapt a smart pointer (shared_ptr or unique_ptr)
  651. *
  652. * This function allows to automatically adapt a shared or unique pointer to
  653. * a given shape and operate naturally on it. Memory will be automatically
  654. * handled by the smart pointer implementation.
  655. *
  656. * @code{.cpp}
  657. * #include <xtensor/xadapt.hpp>
  658. * #include <xtensor/xio.hpp>
  659. *
  660. * struct Buffer {
  661. * Buffer(std::vector<double>& buf) : m_buf(buf) {}
  662. * ~Buffer() { std::cout << "deleted" << std::endl; }
  663. * std::vector<double> m_buf;
  664. * };
  665. *
  666. * auto data = std::vector<double>{1,2,3,4,5,6,7,8};
  667. * auto shared_buf = std::make_shared<Buffer>(data);
  668. * auto unique_buf = std::make_unique<Buffer>(data);
  669. *
  670. * std::cout << shared_buf.use_count() << std::endl;
  671. * {
  672. * std::vector<size_t> shape = {2, 4};
  673. * auto obj = adapt_smart_ptr(shared_buf.get()->m_buf.data(),
  674. * shape, shared_buf);
  675. * // Use count increased to 2
  676. * std::cout << shared_buf.use_count() << std::endl;
  677. * std::cout << obj << std::endl;
  678. * }
  679. * // Use count reset to 1
  680. * std::cout << shared_buf.use_count() << std::endl;
  681. *
  682. * {
  683. * std::vector<size_t> shape = {2, 4};
  684. * auto obj = adapt_smart_ptr(unique_buf.get()->m_buf.data(),
  685. * shape, std::move(unique_buf));
  686. * std::cout << obj << std::endl;
  687. * }
  688. * @endcode
  689. *
  690. * @ingroup xt_xadapt
  691. * @param data_ptr A pointer to a typed data block (e.g. double*)
  692. * @param shape The desired shape
  693. * @param smart_ptr A smart pointer to move or copy, in order to manage memory
  694. * @param l The desired memory layout
  695. *
  696. * @return xarray_adaptor on the memory
  697. */
  698. template <
  699. layout_type L = XTENSOR_DEFAULT_LAYOUT,
  700. class P,
  701. class SC,
  702. class D,
  703. XTL_REQUIRES(detail::not_an_array<std::decay_t<SC>>, detail::not_a_layout<std::decay_t<D>>)>
  704. auto adapt_smart_ptr(P&& data_ptr, const SC& shape, D&& smart_ptr, layout_type l = L)
  705. {
  706. using buffer_adaptor = xbuffer_adaptor<P, smart_ownership, std::decay_t<D>>;
  707. return xarray_adaptor<buffer_adaptor, L, std::decay_t<SC>>(
  708. buffer_adaptor(data_ptr, compute_size(shape), std::forward<D>(smart_ptr)),
  709. shape,
  710. l
  711. );
  712. }
  713. /**
  714. * Adapt a smart pointer to a typed memory block (unique_ptr or shared_ptr)
  715. *
  716. * @code{.cpp}
  717. * #include <xtensor/xadapt.hpp>
  718. * #include <xtensor/xio.hpp>
  719. *
  720. * std::shared_ptr<double> sptr(new double[8], std::default_delete<double[]>());
  721. * sptr.get()[2] = 321.;
  722. * auto xptr = adapt_smart_ptr(sptr, {4, 2});
  723. * xptr(1, 3) = 123.;
  724. * std::cout << xptr;
  725. * @endcode
  726. *
  727. * @ingroup xt_xadapt
  728. * @param smart_ptr a smart pointer to a memory block of T[]
  729. * @param shape The desired shape
  730. * @param l The desired memory layout
  731. *
  732. * @return xtensor_adaptor for memory
  733. */
  734. template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class P, class I, std::size_t N>
  735. auto adapt_smart_ptr(P&& smart_ptr, const I (&shape)[N], layout_type l = L)
  736. {
  737. using buffer_adaptor = xbuffer_adaptor<decltype(smart_ptr.get()), smart_ownership, std::decay_t<P>>;
  738. std::array<std::size_t, N> fshape = xtl::forward_sequence<std::array<std::size_t, N>, decltype(shape)>(
  739. shape
  740. );
  741. return xtensor_adaptor<buffer_adaptor, N, L>(
  742. buffer_adaptor(smart_ptr.get(), compute_size(fshape), std::forward<P>(smart_ptr)),
  743. std::move(fshape),
  744. l
  745. );
  746. }
  747. /**
  748. * Adapt a smart pointer (shared_ptr or unique_ptr)
  749. *
  750. * This function allows to automatically adapt a shared or unique pointer to
  751. * a given shape and operate naturally on it. Memory will be automatically
  752. * handled by the smart pointer implementation.
  753. *
  754. * @code{.cpp}
  755. * #include <xtensor/xadapt.hpp>
  756. * #include <xtensor/xio.hpp>
  757. *
  758. * struct Buffer {
  759. * Buffer(std::vector<double>& buf) : m_buf(buf) {}
  760. * ~Buffer() { std::cout << "deleted" << std::endl; }
  761. * std::vector<double> m_buf;
  762. * };
  763. *
  764. * auto data = std::vector<double>{1,2,3,4,5,6,7,8};
  765. * auto shared_buf = std::make_shared<Buffer>(data);
  766. * auto unique_buf = std::make_unique<Buffer>(data);
  767. *
  768. * std::cout << shared_buf.use_count() << std::endl;
  769. * {
  770. * auto obj = adapt_smart_ptr(shared_buf.get()->m_buf.data(),
  771. * {2, 4}, shared_buf);
  772. * // Use count increased to 2
  773. * std::cout << shared_buf.use_count() << std::endl;
  774. * std::cout << obj << std::endl;
  775. * }
  776. * // Use count reset to 1
  777. * std::cout << shared_buf.use_count() << std::endl;
  778. *
  779. * {
  780. * auto obj = adapt_smart_ptr(unique_buf.get()->m_buf.data(),
  781. * {2, 4}, std::move(unique_buf));
  782. * std::cout << obj << std::endl;
  783. * }
  784. * @endcode
  785. *
  786. * @ingroup xt_xadapt
  787. * @param data_ptr A pointer to a typed data block (e.g. double*)
  788. * @param shape The desired shape
  789. * @param smart_ptr A smart pointer to move or copy, in order to manage memory
  790. * @param l The desired memory layout
  791. *
  792. * @return xtensor_adaptor on the memory
  793. */
  794. template <
  795. layout_type L = XTENSOR_DEFAULT_LAYOUT,
  796. class P,
  797. class I,
  798. std::size_t N,
  799. class D,
  800. XTL_REQUIRES(detail::not_a_layout<std::decay_t<D>>)>
  801. auto adapt_smart_ptr(P&& data_ptr, const I (&shape)[N], D&& smart_ptr, layout_type l = L)
  802. {
  803. using buffer_adaptor = xbuffer_adaptor<P, smart_ownership, std::decay_t<D>>;
  804. std::array<std::size_t, N> fshape = xtl::forward_sequence<std::array<std::size_t, N>, decltype(shape)>(
  805. shape
  806. );
  807. return xtensor_adaptor<buffer_adaptor, N, L>(
  808. buffer_adaptor(data_ptr, compute_size(fshape), std::forward<D>(smart_ptr)),
  809. std::move(fshape),
  810. l
  811. );
  812. }
  813. /**
  814. * @brief xtensor adaptor for a pointer.
  815. *
  816. * Construct for example with:
  817. *
  818. * @code{.cpp}
  819. * #include <xtensor/xadapt.hpp>
  820. *
  821. * std::array<size_t, 2> shape = {2, 2};
  822. * std::vector<double> data = {1, 2, 3, 4};
  823. *
  824. * xt::xtensor_pointer<double, 2> a = xt::adapt(data.data(), 4, xt::no_ownership(), shape);
  825. * @endcode
  826. *
  827. * @ingroup xt_xadapt
  828. * @tparam T The data type (e.g. ``double``).
  829. * @tparam N The number of dimensions.
  830. * @tparam L The xt::layout_type() of the xtensor.
  831. */
  832. template <class T, std::size_t N, layout_type L = XTENSOR_DEFAULT_LAYOUT>
  833. using xtensor_pointer = xtensor_adaptor<
  834. xbuffer_adaptor<xtl::closure_type_t<T*>, xt::no_ownership, detail::default_allocator_for_ptr_t<T>>,
  835. N,
  836. L>;
  837. /**
  838. * @brief xarray adaptor for a pointer.
  839. *
  840. * Construct for example with:
  841. *
  842. * @code{.cpp}
  843. * #include <xtensor/xadapt.hpp>
  844. *
  845. * std::vector<int> data(4, 0);
  846. * xt::svector<size_t> shape({2, 2});
  847. *
  848. * xt::xarray_pointer<int> a = xt::adapt(data.data(), data.size(), xt::no_ownership(), shape);
  849. * @endcode
  850. *
  851. * @ingroup xt_xadapt
  852. * @tparam T The data type (e.g. ``double``).
  853. * @tparam L The xt::layout_type() of the xarray.
  854. * @tparam SC The shape container type (e.g. ``xt::svector<size_t>``). Default matches
  855. * xt::adapt(P&&, typename A::size_type, O, const SC&, layout_type, const A& alloc)
  856. */
  857. template <
  858. class T,
  859. layout_type L = XTENSOR_DEFAULT_LAYOUT,
  860. class SC = XTENSOR_DEFAULT_SHAPE_CONTAINER(T, std::allocator<std::size_t>, std::allocator<std::size_t>)>
  861. using xarray_pointer = xarray_adaptor<
  862. xbuffer_adaptor<xtl::closure_type_t<T*>, xt::no_ownership, detail::default_allocator_for_ptr_t<T>>,
  863. L,
  864. SC>;
  865. }
  866. #endif