mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
922 lines
35 KiB
C++
922 lines
35 KiB
C++
/***************************************************************************
|
|
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
|
* Copyright (c) QuantStack *
|
|
* *
|
|
* Distributed under the terms of the BSD 3-Clause License. *
|
|
* *
|
|
* The full license is in the file LICENSE, distributed with this software. *
|
|
****************************************************************************/
|
|
|
|
#ifndef XTENSOR_ADAPT_HPP
|
|
#define XTENSOR_ADAPT_HPP
|
|
|
|
#include <array>
|
|
#include <cstddef>
|
|
#include <memory>
|
|
#include <type_traits>
|
|
|
|
#include <xtl/xsequence.hpp>
|
|
|
|
#include "xarray.hpp"
|
|
#include "xbuffer_adaptor.hpp"
|
|
#include "xfixed.hpp"
|
|
#include "xtensor.hpp"
|
|
|
|
namespace xt
|
|
{
|
|
/**
|
|
* @defgroup xt_xadapt Adaptors of STL-like containers
|
|
*/
|
|
|
|
namespace detail
|
|
{
|
|
template <class>
|
|
struct array_size_impl;
|
|
|
|
template <class T, std::size_t N>
|
|
struct array_size_impl<std::array<T, N>>
|
|
{
|
|
static constexpr std::size_t value = N;
|
|
};
|
|
|
|
template <class C>
|
|
using array_size = array_size_impl<std::decay_t<C>>;
|
|
|
|
template <class P>
|
|
struct default_allocator_for_ptr
|
|
{
|
|
using type = std::allocator<std::remove_const_t<std::remove_pointer_t<std::remove_reference_t<P>>>>;
|
|
};
|
|
|
|
template <class P>
|
|
using default_allocator_for_ptr_t = typename default_allocator_for_ptr<P>::type;
|
|
|
|
template <class T>
|
|
using not_an_array = xtl::negation<is_array<T>>;
|
|
|
|
template <class T>
|
|
using not_a_pointer = xtl::negation<std::is_pointer<T>>;
|
|
|
|
template <class T>
|
|
using not_a_layout = xtl::negation<std::is_same<layout_type, T>>;
|
|
}
|
|
|
|
#ifndef IN_DOXYGEN
|
|
|
|
/**************************
|
|
* xarray_adaptor builder *
|
|
**************************/
|
|
|
|
/**
|
|
* Constructs an xarray_adaptor of the given stl-like container,
|
|
* with the specified shape and layout.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param container the container to adapt
|
|
* @param shape the shape of the xarray_adaptor
|
|
* @param l the layout_type of the xarray_adaptor
|
|
*/
|
|
template <
|
|
layout_type L = XTENSOR_DEFAULT_LAYOUT,
|
|
class C,
|
|
class SC,
|
|
XTL_REQUIRES(detail::not_an_array<std::decay_t<SC>>, detail::not_a_pointer<C>)>
|
|
inline xarray_adaptor<xtl::closure_type_t<C>, L, std::decay_t<SC>>
|
|
adapt(C&& container, const SC& shape, layout_type l = L)
|
|
{
|
|
static_assert(!xtl::is_integral<SC>::value, "shape cannot be a integer");
|
|
using return_type = xarray_adaptor<xtl::closure_type_t<C>, L, std::decay_t<SC>>;
|
|
return return_type(std::forward<C>(container), shape, l);
|
|
}
|
|
|
|
/**
|
|
* Constructs an non-owning xarray_adaptor from a pointer with the specified shape and layout.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param pointer the container to adapt
|
|
* @param shape the shape of the xarray_adaptor
|
|
* @param l the layout_type of the xarray_adaptor
|
|
*/
|
|
template <
|
|
layout_type L = XTENSOR_DEFAULT_LAYOUT,
|
|
class C,
|
|
class SC,
|
|
XTL_REQUIRES(detail::not_an_array<std::decay_t<SC>>, std::is_pointer<std::remove_reference_t<C>>)>
|
|
inline auto adapt(C&& pointer, const SC& shape, layout_type l = L)
|
|
{
|
|
static_assert(!xtl::is_integral<SC>::value, "shape cannot be a integer");
|
|
using buffer_type = xbuffer_adaptor<C, xt::no_ownership, detail::default_allocator_for_ptr_t<C>>;
|
|
using return_type = xarray_adaptor<buffer_type, L, std::decay_t<SC>>;
|
|
std::size_t size = compute_size(shape);
|
|
return return_type(buffer_type(pointer, size), shape, l);
|
|
}
|
|
|
|
/**
|
|
* Constructs an xarray_adaptor of the given stl-like container,
|
|
* with the specified shape and strides.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param container the container to adapt
|
|
* @param shape the shape of the xarray_adaptor
|
|
* @param strides the strides of the xarray_adaptor
|
|
*/
|
|
template <
|
|
class C,
|
|
class SC,
|
|
class SS,
|
|
XTL_REQUIRES(detail::not_an_array<std::decay_t<SC>>, detail::not_a_layout<std::decay_t<SS>>)>
|
|
inline xarray_adaptor<xtl::closure_type_t<C>, layout_type::dynamic, std::decay_t<SC>>
|
|
adapt(C&& container, SC&& shape, SS&& strides)
|
|
{
|
|
static_assert(!xtl::is_integral<std::decay_t<SC>>::value, "shape cannot be a integer");
|
|
using return_type = xarray_adaptor<xtl::closure_type_t<C>, layout_type::dynamic, std::decay_t<SC>>;
|
|
return return_type(
|
|
std::forward<C>(container),
|
|
xtl::forward_sequence<typename return_type::inner_shape_type, SC>(shape),
|
|
xtl::forward_sequence<typename return_type::inner_strides_type, SS>(strides)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Constructs an xarray_adaptor of the given dynamically allocated C array,
|
|
* with the specified shape and layout.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param pointer the pointer to the beginning of the dynamic array
|
|
* @param size the size of the dynamic array
|
|
* @param ownership indicates whether the adaptor takes ownership of the array.
|
|
* Possible values are ``no_ownership()`` or ``acquire_ownership()``
|
|
* @param shape the shape of the xarray_adaptor
|
|
* @param l the layout_type of the xarray_adaptor
|
|
* @param alloc the allocator used for allocating / deallocating the dynamic array
|
|
*/
|
|
template <
|
|
layout_type L = XTENSOR_DEFAULT_LAYOUT,
|
|
class P,
|
|
class O,
|
|
class SC,
|
|
class A = detail::default_allocator_for_ptr_t<P>,
|
|
XTL_REQUIRES(detail::not_an_array<std::decay_t<SC>>)>
|
|
inline xarray_adaptor<xbuffer_adaptor<xtl::closure_type_t<P>, O, A>, L, SC> adapt(
|
|
P&& pointer,
|
|
typename A::size_type size,
|
|
O ownership,
|
|
const SC& shape,
|
|
layout_type l = L,
|
|
const A& alloc = A()
|
|
)
|
|
{
|
|
static_assert(!xtl::is_integral<SC>::value, "shape cannot be a integer");
|
|
(void) ownership;
|
|
using buffer_type = xbuffer_adaptor<xtl::closure_type_t<P>, O, A>;
|
|
using return_type = xarray_adaptor<buffer_type, L, SC>;
|
|
buffer_type buf(std::forward<P>(pointer), size, alloc);
|
|
return return_type(std::move(buf), shape, l);
|
|
}
|
|
|
|
/**
|
|
* Constructs an xarray_adaptor of the given dynamically allocated C array,
|
|
* with the specified shape and strides.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param pointer the pointer to the beginning of the dynamic array
|
|
* @param size the size of the dynamic array
|
|
* @param ownership indicates whether the adaptor takes ownership of the array.
|
|
* Possible values are ``no_ownership()`` or ``acquire_ownership()``
|
|
* @param shape the shape of the xarray_adaptor
|
|
* @param strides the strides of the xarray_adaptor
|
|
* @param alloc the allocator used for allocating / deallocating the dynamic array
|
|
*/
|
|
template <
|
|
class P,
|
|
class O,
|
|
class SC,
|
|
class SS,
|
|
class A = detail::default_allocator_for_ptr_t<P>,
|
|
XTL_REQUIRES(detail::not_an_array<std::decay_t<SC>>, detail::not_a_layout<std::decay_t<SS>>)>
|
|
inline xarray_adaptor<xbuffer_adaptor<xtl::closure_type_t<P>, O, A>, layout_type::dynamic, std::decay_t<SC>>
|
|
adapt(P&& pointer, typename A::size_type size, O ownership, SC&& shape, SS&& strides, const A& alloc = A())
|
|
{
|
|
static_assert(!xtl::is_integral<std::decay_t<SC>>::value, "shape cannot be a integer");
|
|
(void) ownership;
|
|
using buffer_type = xbuffer_adaptor<xtl::closure_type_t<P>, O, A>;
|
|
using return_type = xarray_adaptor<buffer_type, layout_type::dynamic, std::decay_t<SC>>;
|
|
buffer_type buf(std::forward<P>(pointer), size, alloc);
|
|
return return_type(
|
|
std::move(buf),
|
|
xtl::forward_sequence<typename return_type::inner_shape_type, SC>(shape),
|
|
xtl::forward_sequence<typename return_type::inner_strides_type, SS>(strides)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Constructs an xarray_adaptor of the given C array allocated on the stack, with the
|
|
* specified shape and layout.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param c_array the C array allocated on the stack
|
|
* @param shape the shape of the xarray_adaptor
|
|
* @param l the layout_type of the xarray_adaptor
|
|
*/
|
|
template <
|
|
layout_type L = XTENSOR_DEFAULT_LAYOUT,
|
|
class T,
|
|
std::size_t N,
|
|
class SC,
|
|
XTL_REQUIRES(detail::not_an_array<std::decay_t<SC>>)>
|
|
inline auto adapt(T (&c_array)[N], const SC& shape, layout_type l = L)
|
|
{
|
|
return adapt(&c_array[0], N, xt::no_ownership(), shape, l);
|
|
}
|
|
|
|
/**
|
|
* Constructs an xarray_adaptor of the given C array allocated on the stack, with the
|
|
* specified shape and stirdes.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param c_array the C array allocated on the stack
|
|
* @param shape the shape of the xarray_adaptor
|
|
* @param strides the strides of the xarray_adaptor
|
|
*/
|
|
template <
|
|
class T,
|
|
std::size_t N,
|
|
class SC,
|
|
class SS,
|
|
XTL_REQUIRES(detail::not_an_array<std::decay_t<SC>>, detail::not_a_layout<std::decay_t<SS>>)>
|
|
inline auto adapt(T (&c_array)[N], SC&& shape, SS&& strides)
|
|
{
|
|
return adapt(&c_array[0], N, xt::no_ownership(), std::forward<SC>(shape), std::forward<SS>(strides));
|
|
}
|
|
|
|
/***************************
|
|
* xtensor_adaptor builder *
|
|
***************************/
|
|
|
|
/**
|
|
* Constructs a 1-D xtensor_adaptor of the given stl-like container,
|
|
* with the specified layout_type.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param container the container to adapt
|
|
* @param l the layout_type of the xtensor_adaptor
|
|
*/
|
|
template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class C>
|
|
inline xtensor_adaptor<C, 1, L> adapt(C&& container, layout_type l = L)
|
|
{
|
|
const std::array<typename std::decay_t<C>::size_type, 1> shape{container.size()};
|
|
using return_type = xtensor_adaptor<xtl::closure_type_t<C>, 1, L>;
|
|
return return_type(std::forward<C>(container), shape, l);
|
|
}
|
|
|
|
/**
|
|
* Constructs an xtensor_adaptor of the given stl-like container,
|
|
* with the specified shape and layout_type.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param container the container to adapt
|
|
* @param shape the shape of the xtensor_adaptor
|
|
* @param l the layout_type of the xtensor_adaptor
|
|
*/
|
|
template <
|
|
layout_type L = XTENSOR_DEFAULT_LAYOUT,
|
|
class C,
|
|
class SC,
|
|
XTL_REQUIRES(detail::is_array<std::decay_t<SC>>, detail::not_a_pointer<C>)>
|
|
inline xtensor_adaptor<C, detail::array_size<SC>::value, L>
|
|
adapt(C&& container, const SC& shape, layout_type l = L)
|
|
{
|
|
static_assert(!xtl::is_integral<SC>::value, "shape cannot be a integer");
|
|
constexpr std::size_t N = detail::array_size<SC>::value;
|
|
using return_type = xtensor_adaptor<xtl::closure_type_t<C>, N, L>;
|
|
return return_type(std::forward<C>(container), shape, l);
|
|
}
|
|
|
|
/**
|
|
* Constructs an non-owning xtensor_adaptor from a pointer with the specified shape and layout.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param pointer the pointer to adapt
|
|
* @param shape the shape of the xtensor_adaptor
|
|
* @param l the layout_type of the xtensor_adaptor
|
|
*/
|
|
template <
|
|
layout_type L = XTENSOR_DEFAULT_LAYOUT,
|
|
class C,
|
|
class SC,
|
|
XTL_REQUIRES(detail::is_array<std::decay_t<SC>>, std::is_pointer<std::remove_reference_t<C>>)>
|
|
inline auto adapt(C&& pointer, const SC& shape, layout_type l = L)
|
|
{
|
|
static_assert(!xtl::is_integral<SC>::value, "shape cannot be a integer");
|
|
using buffer_type = xbuffer_adaptor<C, xt::no_ownership, detail::default_allocator_for_ptr_t<C>>;
|
|
constexpr std::size_t N = detail::array_size<SC>::value;
|
|
using return_type = xtensor_adaptor<buffer_type, N, L>;
|
|
return return_type(buffer_type(pointer, compute_size(shape)), shape, l);
|
|
}
|
|
|
|
/**
|
|
* Constructs an xtensor_adaptor of the given stl-like container,
|
|
* with the specified shape and strides.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param container the container to adapt
|
|
* @param shape the shape of the xtensor_adaptor
|
|
* @param strides the strides of the xtensor_adaptor
|
|
*/
|
|
template <
|
|
class C,
|
|
class SC,
|
|
class SS,
|
|
XTL_REQUIRES(detail::is_array<std::decay_t<SC>>, detail::not_a_layout<std::decay_t<SS>>)>
|
|
inline xtensor_adaptor<C, detail::array_size<SC>::value, layout_type::dynamic>
|
|
adapt(C&& container, SC&& shape, SS&& strides)
|
|
{
|
|
static_assert(!xtl::is_integral<std::decay_t<SC>>::value, "shape cannot be a integer");
|
|
constexpr std::size_t N = detail::array_size<SC>::value;
|
|
using return_type = xtensor_adaptor<xtl::closure_type_t<C>, N, layout_type::dynamic>;
|
|
return return_type(
|
|
std::forward<C>(container),
|
|
xtl::forward_sequence<typename return_type::inner_shape_type, SC>(shape),
|
|
xtl::forward_sequence<typename return_type::inner_strides_type, SS>(strides)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Constructs a 1-D xtensor_adaptor of the given dynamically allocated C array,
|
|
* with the specified layout.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param pointer the pointer to the beginning of the dynamic array
|
|
* @param size the size of the dynamic array
|
|
* @param ownership indicates whether the adaptor takes ownership of the array.
|
|
* Possible values are ``no_ownership()`` or ``acquire_ownership()``
|
|
* @param l the layout_type of the xtensor_adaptor
|
|
* @param alloc the allocator used for allocating / deallocating the dynamic array
|
|
*/
|
|
template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class P, class O, class A = detail::default_allocator_for_ptr_t<P>>
|
|
inline xtensor_adaptor<xbuffer_adaptor<xtl::closure_type_t<P>, O, A>, 1, L>
|
|
adapt(P&& pointer, typename A::size_type size, O ownership, layout_type l = L, const A& alloc = A())
|
|
{
|
|
(void) ownership;
|
|
using buffer_type = xbuffer_adaptor<xtl::closure_type_t<P>, O, A>;
|
|
using return_type = xtensor_adaptor<buffer_type, 1, L>;
|
|
buffer_type buf(std::forward<P>(pointer), size, alloc);
|
|
const std::array<typename A::size_type, 1> shape{size};
|
|
return return_type(std::move(buf), shape, l);
|
|
}
|
|
|
|
/**
|
|
* Constructs an xtensor_adaptor of the given dynamically allocated C array,
|
|
* with the specified shape and layout.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param pointer the pointer to the beginning of the dynamic array
|
|
* @param size the size of the dynamic array
|
|
* @param ownership indicates whether the adaptor takes ownership of the array.
|
|
* Possible values are ``no_ownership()`` or ``acquire_ownership()``
|
|
* @param shape the shape of the xtensor_adaptor
|
|
* @param l the layout_type of the xtensor_adaptor
|
|
* @param alloc the allocator used for allocating / deallocating the dynamic array
|
|
*/
|
|
template <
|
|
layout_type L = XTENSOR_DEFAULT_LAYOUT,
|
|
class P,
|
|
class O,
|
|
class SC,
|
|
class A = detail::default_allocator_for_ptr_t<P>,
|
|
XTL_REQUIRES(detail::is_array<std::decay_t<SC>>)>
|
|
inline xtensor_adaptor<xbuffer_adaptor<xtl::closure_type_t<P>, O, A>, detail::array_size<SC>::value, L>
|
|
adapt(
|
|
P&& pointer,
|
|
typename A::size_type size,
|
|
O ownership,
|
|
const SC& shape,
|
|
layout_type l = L,
|
|
const A& alloc = A()
|
|
)
|
|
{
|
|
static_assert(!xtl::is_integral<SC>::value, "shape cannot be a integer");
|
|
(void) ownership;
|
|
using buffer_type = xbuffer_adaptor<xtl::closure_type_t<P>, O, A>;
|
|
constexpr std::size_t N = detail::array_size<SC>::value;
|
|
using return_type = xtensor_adaptor<buffer_type, N, L>;
|
|
buffer_type buf(std::forward<P>(pointer), size, alloc);
|
|
return return_type(std::move(buf), shape, l);
|
|
}
|
|
|
|
/**
|
|
* Constructs an xtensor_adaptor of the given dynamically allocated C array,
|
|
* with the specified shape and strides.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param pointer the pointer to the beginning of the dynamic array
|
|
* @param size the size of the dynamic array
|
|
* @param ownership indicates whether the adaptor takes ownership of the array.
|
|
* Possible values are ``no_ownership()`` or ``acquire_ownership()``
|
|
* @param shape the shape of the xtensor_adaptor
|
|
* @param strides the strides of the xtensor_adaptor
|
|
* @param alloc the allocator used for allocating / deallocating the dynamic array
|
|
*/
|
|
template <
|
|
class P,
|
|
class O,
|
|
class SC,
|
|
class SS,
|
|
class A = detail::default_allocator_for_ptr_t<P>,
|
|
XTL_REQUIRES(detail::is_array<std::decay_t<SC>>, detail::not_a_layout<std::decay_t<SS>>)>
|
|
inline xtensor_adaptor<xbuffer_adaptor<xtl::closure_type_t<P>, O, A>, detail::array_size<SC>::value, layout_type::dynamic>
|
|
adapt(P&& pointer, typename A::size_type size, O ownership, SC&& shape, SS&& strides, const A& alloc = A())
|
|
{
|
|
static_assert(!xtl::is_integral<std::decay_t<SC>>::value, "shape cannot be a integer");
|
|
(void) ownership;
|
|
using buffer_type = xbuffer_adaptor<xtl::closure_type_t<P>, O, A>;
|
|
constexpr std::size_t N = detail::array_size<SC>::value;
|
|
using return_type = xtensor_adaptor<buffer_type, N, layout_type::dynamic>;
|
|
buffer_type buf(std::forward<P>(pointer), size, alloc);
|
|
return return_type(
|
|
std::move(buf),
|
|
xtl::forward_sequence<typename return_type::inner_shape_type, SC>(shape),
|
|
xtl::forward_sequence<typename return_type::inner_strides_type, SS>(strides)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Constructs an xtensor_adaptor of the given C array allocated on the stack, with the
|
|
* specified shape and layout.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param c_array the C array allocated on the stack
|
|
* @param shape the shape of the xarray_adaptor
|
|
* @param l the layout_type of the xarray_adaptor
|
|
*/
|
|
template <
|
|
layout_type L = XTENSOR_DEFAULT_LAYOUT,
|
|
class T,
|
|
std::size_t N,
|
|
class SC,
|
|
XTL_REQUIRES(detail::is_array<std::decay_t<SC>>)>
|
|
inline auto adapt(T (&c_array)[N], const SC& shape, layout_type l = L)
|
|
{
|
|
return adapt(&c_array[0], N, xt::no_ownership(), shape, l);
|
|
}
|
|
|
|
/**
|
|
* Constructs an xtensor_adaptor of the given C array allocated on the stack, with the
|
|
* specified shape and strides.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param c_array the C array allocated on the stack
|
|
* @param shape the shape of the xarray_adaptor
|
|
* @param strides the strides of the xarray_adaptor
|
|
*/
|
|
template <
|
|
class T,
|
|
std::size_t N,
|
|
class SC,
|
|
class SS,
|
|
XTL_REQUIRES(detail::is_array<std::decay_t<SC>>, detail::not_a_layout<std::decay_t<SS>>)>
|
|
inline auto adapt(T (&c_array)[N], SC&& shape, SS&& strides)
|
|
{
|
|
return adapt(&c_array[0], N, xt::no_ownership(), std::forward<SC>(shape), std::forward<SS>(strides));
|
|
}
|
|
|
|
/**
|
|
* Constructs an non-owning xtensor_fixed_adaptor from a pointer with the
|
|
* specified shape and layout.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param pointer the pointer to adapt
|
|
* @param shape the shape of the xtensor_fixed_adaptor
|
|
*/
|
|
template <
|
|
layout_type L = XTENSOR_DEFAULT_LAYOUT,
|
|
class C,
|
|
std::size_t... X,
|
|
XTL_REQUIRES(std::is_pointer<std::remove_reference_t<C>>)>
|
|
inline auto adapt(C&& pointer, const fixed_shape<X...>& /*shape*/)
|
|
{
|
|
using buffer_type = xbuffer_adaptor<C, xt::no_ownership, detail::default_allocator_for_ptr_t<C>>;
|
|
using return_type = xfixed_adaptor<buffer_type, fixed_shape<X...>, L>;
|
|
return return_type(buffer_type(pointer, detail::fixed_compute_size<fixed_shape<X...>>::value));
|
|
}
|
|
|
|
template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class C, class T, std::size_t N>
|
|
inline auto adapt(C&& ptr, const T (&shape)[N])
|
|
{
|
|
using shape_type = std::array<std::size_t, N>;
|
|
return adapt(std::forward<C>(ptr), xtl::forward_sequence<shape_type, decltype(shape)>(shape));
|
|
}
|
|
|
|
#else // IN_DOXYGEN
|
|
|
|
/**
|
|
* Constructs:
|
|
* - an xarray_adaptor if SC is not an array type
|
|
* - an xtensor_adaptor if SC is an array type
|
|
*
|
|
* from the given stl-like container or pointer, with the specified shape and layout.
|
|
* If the adaptor is built from a pointer, it does not take its ownership.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param container the container or pointer to adapt
|
|
* @param shape the shape of the adaptor
|
|
* @param l the layout_type of the adaptor
|
|
*/
|
|
template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class C, class SC>
|
|
inline auto adapt(C&& container, const SC& shape, layout_type l = L);
|
|
|
|
/**
|
|
* Constructs:
|
|
* - an xarray_adaptor if SC is not an array type
|
|
* - an xtensor_adaptor if SC is an array type
|
|
*
|
|
* from the given stl-like container with the specified shape and strides.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param container the container to adapt
|
|
* @param shape the shape of the adaptor
|
|
* @param strides the strides of the adaptor
|
|
*/
|
|
template <class C, class SC, class SS>
|
|
inline auto adapt(C&& container, SC&& shape, SS&& strides);
|
|
|
|
/**
|
|
* Constructs:
|
|
* - an xarray_adaptor if SC is not an array type
|
|
* - an xtensor_adaptor if SC is an array type
|
|
*
|
|
* of the given dynamically allocated C array, with the specified shape and layout.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param pointer the pointer to the beginning of the dynamic array
|
|
* @param size the size of the dynamic array
|
|
* @param ownership indicates whether the adaptor takes ownership of the array.
|
|
* Possible values are ``no_ownership()`` or ``acquire_ownership()``
|
|
* @param shape the shape of the adaptor
|
|
* @param l the layout_type of the adaptor
|
|
* @param alloc the allocator used for allocating / deallocating the dynamic array
|
|
*/
|
|
template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class P, class O, class SC, class A = detail::default_allocator_for_ptr_t<P>>
|
|
inline auto adapt(
|
|
P&& pointer,
|
|
typename A::size_type size,
|
|
O ownership,
|
|
const SC& shape,
|
|
layout_type l = L,
|
|
const A& alloc = A()
|
|
);
|
|
|
|
/**
|
|
* Constructs:
|
|
* - an xarray_adaptor if SC is not an array type
|
|
* - an xtensor_adaptor if SC is an array type
|
|
*
|
|
* of the given dynamically allocated C array, with the specified shape and strides.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param pointer the pointer to the beginning of the dynamic array
|
|
* @param size the size of the dynamic array
|
|
* @param ownership indicates whether the adaptor takes ownership of the array.
|
|
* Possible values are ``no_ownership()`` or ``acquire_ownership()``
|
|
* @param shape the shape of the adaptor
|
|
* @param strides the strides of the adaptor
|
|
* @param alloc the allocator used for allocating / deallocating the dynamic array
|
|
*/
|
|
template <class P, class O, class SC, class SS, class A = detail::default_allocator_for_ptr_t<P>>
|
|
inline auto
|
|
adapt(P&& pointer, typename A::size_type size, O ownership, SC&& shape, SS&& strides, const A& alloc = A());
|
|
|
|
/**
|
|
* Constructs:
|
|
* - an xarray_adaptor if SC is not an array type
|
|
* - an xtensor_adaptor if SC is an array type
|
|
*
|
|
* of the given C array allocated on the stack, with the specified shape and layout.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param c_array the C array allocated on the stack
|
|
* @param shape the shape of the adaptor
|
|
* @param l the layout_type of the adaptor
|
|
*/
|
|
template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class T, std::size_t N, class SC>
|
|
inline auto adapt(T (&c_array)[N], const SC& shape, layout_type l = L);
|
|
|
|
/**
|
|
* Constructs:
|
|
* - an xarray_adaptor if SC is not an array type
|
|
* - an xtensor_adaptor if SC is an array type
|
|
*
|
|
* of the given C array allocated on the stack, with the
|
|
* specified shape and strides.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param c_array the C array allocated on the stack
|
|
* @param shape the shape of the adaptor
|
|
* @param strides the strides of the adaptor
|
|
*/
|
|
template <class T, std::size_t N, class SC, class SS>
|
|
inline auto adapt(T (&c_array)[N], SC&& shape, SS&& strides);
|
|
|
|
/**
|
|
* Constructs an non-owning xtensor_fixed_adaptor from a pointer with the
|
|
* specified shape and layout.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param pointer the pointer to adapt
|
|
* @param shape the shape of the xtensor_fixed_adaptor
|
|
*/
|
|
template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class C, std::size_t... X>
|
|
inline auto adapt(C&& pointer, const fixed_shape<X...>& /*shape*/);
|
|
|
|
/**
|
|
* Constructs a 1-D xtensor_adaptor of the given stl-like container,
|
|
* with the specified layout_type.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param container the container to adapt
|
|
* @param l the layout_type of the xtensor_adaptor
|
|
*/
|
|
template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class C>
|
|
inline xtensor_adaptor<C, 1, L> adapt(C&& container, layout_type l = L);
|
|
|
|
/**
|
|
* Constructs a 1-D xtensor_adaptor of the given dynamically allocated C array,
|
|
* with the specified layout.
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param pointer the pointer to the beginning of the dynamic array
|
|
* @param size the size of the dynamic array
|
|
* @param ownership indicates whether the adaptor takes ownership of the array.
|
|
* Possible values are ``no_ownership()`` or ``acquire_ownership()``
|
|
* @param l the layout_type of the xtensor_adaptor
|
|
* @param alloc the allocator used for allocating / deallocating the dynamic array
|
|
*/
|
|
template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class P, class O, class A = detail::default_allocator_for_ptr_t<P>>
|
|
inline xtensor_adaptor<xbuffer_adaptor<xtl::closure_type_t<P>, O, A>, 1, L>
|
|
adapt(P&& pointer, typename A::size_type size, O ownership, layout_type l = L, const A& alloc = A());
|
|
|
|
#endif // IN_DOXYGEN
|
|
|
|
/*****************************
|
|
* smart_ptr adapter builder *
|
|
*****************************/
|
|
|
|
/**
|
|
* Adapt a smart pointer to a typed memory block (unique_ptr or shared_ptr)
|
|
*
|
|
* @code{.cpp}
|
|
* #include <xtensor/xadapt.hpp>
|
|
* #include <xtensor/xio.hpp>
|
|
*
|
|
* std::shared_ptr<double> sptr(new double[8], std::default_delete<double[]>());
|
|
* sptr.get()[2] = 321.;
|
|
* std::vector<size_t> shape = {4, 2};
|
|
* auto xptr = adapt_smart_ptr(sptr, shape);
|
|
* xptr(1, 3) = 123.;
|
|
* std::cout << xptr;
|
|
* @endcode
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param smart_ptr a smart pointer to a memory block of T[]
|
|
* @param shape The desired shape
|
|
* @param l The desired memory layout
|
|
*
|
|
* @return xarray_adaptor for memory
|
|
*/
|
|
template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class P, class SC, XTL_REQUIRES(detail::not_an_array<std::decay_t<SC>>)>
|
|
auto adapt_smart_ptr(P&& smart_ptr, const SC& shape, layout_type l = L)
|
|
{
|
|
using buffer_adaptor = xbuffer_adaptor<decltype(smart_ptr.get()), smart_ownership, std::decay_t<P>>;
|
|
return xarray_adaptor<buffer_adaptor, L, std::decay_t<SC>>(
|
|
buffer_adaptor(smart_ptr.get(), compute_size(shape), std::forward<P>(smart_ptr)),
|
|
shape,
|
|
l
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Adapt a smart pointer (shared_ptr or unique_ptr)
|
|
*
|
|
* This function allows to automatically adapt a shared or unique pointer to
|
|
* a given shape and operate naturally on it. Memory will be automatically
|
|
* handled by the smart pointer implementation.
|
|
*
|
|
* @code{.cpp}
|
|
* #include <xtensor/xadapt.hpp>
|
|
* #include <xtensor/xio.hpp>
|
|
*
|
|
* struct Buffer {
|
|
* Buffer(std::vector<double>& buf) : m_buf(buf) {}
|
|
* ~Buffer() { std::cout << "deleted" << std::endl; }
|
|
* std::vector<double> m_buf;
|
|
* };
|
|
*
|
|
* auto data = std::vector<double>{1,2,3,4,5,6,7,8};
|
|
* auto shared_buf = std::make_shared<Buffer>(data);
|
|
* auto unique_buf = std::make_unique<Buffer>(data);
|
|
*
|
|
* std::cout << shared_buf.use_count() << std::endl;
|
|
* {
|
|
* std::vector<size_t> shape = {2, 4};
|
|
* auto obj = adapt_smart_ptr(shared_buf.get()->m_buf.data(),
|
|
* shape, shared_buf);
|
|
* // Use count increased to 2
|
|
* std::cout << shared_buf.use_count() << std::endl;
|
|
* std::cout << obj << std::endl;
|
|
* }
|
|
* // Use count reset to 1
|
|
* std::cout << shared_buf.use_count() << std::endl;
|
|
*
|
|
* {
|
|
* std::vector<size_t> shape = {2, 4};
|
|
* auto obj = adapt_smart_ptr(unique_buf.get()->m_buf.data(),
|
|
* shape, std::move(unique_buf));
|
|
* std::cout << obj << std::endl;
|
|
* }
|
|
* @endcode
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param data_ptr A pointer to a typed data block (e.g. double*)
|
|
* @param shape The desired shape
|
|
* @param smart_ptr A smart pointer to move or copy, in order to manage memory
|
|
* @param l The desired memory layout
|
|
*
|
|
* @return xarray_adaptor on the memory
|
|
*/
|
|
template <
|
|
layout_type L = XTENSOR_DEFAULT_LAYOUT,
|
|
class P,
|
|
class SC,
|
|
class D,
|
|
XTL_REQUIRES(detail::not_an_array<std::decay_t<SC>>, detail::not_a_layout<std::decay_t<D>>)>
|
|
auto adapt_smart_ptr(P&& data_ptr, const SC& shape, D&& smart_ptr, layout_type l = L)
|
|
{
|
|
using buffer_adaptor = xbuffer_adaptor<P, smart_ownership, std::decay_t<D>>;
|
|
|
|
return xarray_adaptor<buffer_adaptor, L, std::decay_t<SC>>(
|
|
buffer_adaptor(data_ptr, compute_size(shape), std::forward<D>(smart_ptr)),
|
|
shape,
|
|
l
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Adapt a smart pointer to a typed memory block (unique_ptr or shared_ptr)
|
|
*
|
|
* @code{.cpp}
|
|
* #include <xtensor/xadapt.hpp>
|
|
* #include <xtensor/xio.hpp>
|
|
*
|
|
* std::shared_ptr<double> sptr(new double[8], std::default_delete<double[]>());
|
|
* sptr.get()[2] = 321.;
|
|
* auto xptr = adapt_smart_ptr(sptr, {4, 2});
|
|
* xptr(1, 3) = 123.;
|
|
* std::cout << xptr;
|
|
* @endcode
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param smart_ptr a smart pointer to a memory block of T[]
|
|
* @param shape The desired shape
|
|
* @param l The desired memory layout
|
|
*
|
|
* @return xtensor_adaptor for memory
|
|
*/
|
|
template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class P, class I, std::size_t N>
|
|
auto adapt_smart_ptr(P&& smart_ptr, const I (&shape)[N], layout_type l = L)
|
|
{
|
|
using buffer_adaptor = xbuffer_adaptor<decltype(smart_ptr.get()), smart_ownership, std::decay_t<P>>;
|
|
std::array<std::size_t, N> fshape = xtl::forward_sequence<std::array<std::size_t, N>, decltype(shape)>(
|
|
shape
|
|
);
|
|
return xtensor_adaptor<buffer_adaptor, N, L>(
|
|
buffer_adaptor(smart_ptr.get(), compute_size(fshape), std::forward<P>(smart_ptr)),
|
|
std::move(fshape),
|
|
l
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Adapt a smart pointer (shared_ptr or unique_ptr)
|
|
*
|
|
* This function allows to automatically adapt a shared or unique pointer to
|
|
* a given shape and operate naturally on it. Memory will be automatically
|
|
* handled by the smart pointer implementation.
|
|
*
|
|
* @code{.cpp}
|
|
* #include <xtensor/xadapt.hpp>
|
|
* #include <xtensor/xio.hpp>
|
|
*
|
|
* struct Buffer {
|
|
* Buffer(std::vector<double>& buf) : m_buf(buf) {}
|
|
* ~Buffer() { std::cout << "deleted" << std::endl; }
|
|
* std::vector<double> m_buf;
|
|
* };
|
|
*
|
|
* auto data = std::vector<double>{1,2,3,4,5,6,7,8};
|
|
* auto shared_buf = std::make_shared<Buffer>(data);
|
|
* auto unique_buf = std::make_unique<Buffer>(data);
|
|
*
|
|
* std::cout << shared_buf.use_count() << std::endl;
|
|
* {
|
|
* auto obj = adapt_smart_ptr(shared_buf.get()->m_buf.data(),
|
|
* {2, 4}, shared_buf);
|
|
* // Use count increased to 2
|
|
* std::cout << shared_buf.use_count() << std::endl;
|
|
* std::cout << obj << std::endl;
|
|
* }
|
|
* // Use count reset to 1
|
|
* std::cout << shared_buf.use_count() << std::endl;
|
|
*
|
|
* {
|
|
* auto obj = adapt_smart_ptr(unique_buf.get()->m_buf.data(),
|
|
* {2, 4}, std::move(unique_buf));
|
|
* std::cout << obj << std::endl;
|
|
* }
|
|
* @endcode
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @param data_ptr A pointer to a typed data block (e.g. double*)
|
|
* @param shape The desired shape
|
|
* @param smart_ptr A smart pointer to move or copy, in order to manage memory
|
|
* @param l The desired memory layout
|
|
*
|
|
* @return xtensor_adaptor on the memory
|
|
*/
|
|
template <
|
|
layout_type L = XTENSOR_DEFAULT_LAYOUT,
|
|
class P,
|
|
class I,
|
|
std::size_t N,
|
|
class D,
|
|
XTL_REQUIRES(detail::not_a_layout<std::decay_t<D>>)>
|
|
auto adapt_smart_ptr(P&& data_ptr, const I (&shape)[N], D&& smart_ptr, layout_type l = L)
|
|
{
|
|
using buffer_adaptor = xbuffer_adaptor<P, smart_ownership, std::decay_t<D>>;
|
|
std::array<std::size_t, N> fshape = xtl::forward_sequence<std::array<std::size_t, N>, decltype(shape)>(
|
|
shape
|
|
);
|
|
|
|
return xtensor_adaptor<buffer_adaptor, N, L>(
|
|
buffer_adaptor(data_ptr, compute_size(fshape), std::forward<D>(smart_ptr)),
|
|
std::move(fshape),
|
|
l
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @brief xtensor adaptor for a pointer.
|
|
*
|
|
* Construct for example with:
|
|
*
|
|
* @code{.cpp}
|
|
* #include <xtensor/xadapt.hpp>
|
|
*
|
|
* std::array<size_t, 2> shape = {2, 2};
|
|
* std::vector<double> data = {1, 2, 3, 4};
|
|
*
|
|
* xt::xtensor_pointer<double, 2> a = xt::adapt(data.data(), 4, xt::no_ownership(), shape);
|
|
* @endcode
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @tparam T The data type (e.g. ``double``).
|
|
* @tparam N The number of dimensions.
|
|
* @tparam L The xt::layout_type() of the xtensor.
|
|
*/
|
|
template <class T, std::size_t N, layout_type L = XTENSOR_DEFAULT_LAYOUT>
|
|
using xtensor_pointer = xtensor_adaptor<
|
|
xbuffer_adaptor<xtl::closure_type_t<T*>, xt::no_ownership, detail::default_allocator_for_ptr_t<T>>,
|
|
N,
|
|
L>;
|
|
|
|
/**
|
|
* @brief xarray adaptor for a pointer.
|
|
*
|
|
* Construct for example with:
|
|
*
|
|
* @code{.cpp}
|
|
* #include <xtensor/xadapt.hpp>
|
|
*
|
|
* std::vector<int> data(4, 0);
|
|
* xt::svector<size_t> shape({2, 2});
|
|
*
|
|
* xt::xarray_pointer<int> a = xt::adapt(data.data(), data.size(), xt::no_ownership(), shape);
|
|
* @endcode
|
|
*
|
|
* @ingroup xt_xadapt
|
|
* @tparam T The data type (e.g. ``double``).
|
|
* @tparam L The xt::layout_type() of the xarray.
|
|
* @tparam SC The shape container type (e.g. ``xt::svector<size_t>``). Default matches
|
|
* xt::adapt(P&&, typename A::size_type, O, const SC&, layout_type, const A& alloc)
|
|
*/
|
|
template <
|
|
class T,
|
|
layout_type L = XTENSOR_DEFAULT_LAYOUT,
|
|
class SC = XTENSOR_DEFAULT_SHAPE_CONTAINER(T, std::allocator<std::size_t>, std::allocator<std::size_t>)>
|
|
using xarray_pointer = xarray_adaptor<
|
|
xbuffer_adaptor<xtl::closure_type_t<T*>, xt::no_ownership, detail::default_allocator_for_ptr_t<T>>,
|
|
L,
|
|
SC>;
|
|
}
|
|
|
|
#endif
|