mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 19:40:18 +00:00
1099 lines
33 KiB
C++
1099 lines
33 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_SCALAR_HPP
|
|
#define XTENSOR_SCALAR_HPP
|
|
|
|
#include <array>
|
|
#include <cstddef>
|
|
#include <utility>
|
|
|
|
#include <xtl/xtype_traits.hpp>
|
|
|
|
#include "xaccessible.hpp"
|
|
#include "xexpression.hpp"
|
|
#include "xiterable.hpp"
|
|
#include "xlayout.hpp"
|
|
#include "xtensor_simd.hpp"
|
|
|
|
namespace xt
|
|
{
|
|
|
|
/*********************
|
|
* xscalar extension *
|
|
*********************/
|
|
|
|
namespace extension
|
|
{
|
|
template <class Tag, class CT>
|
|
struct xscalar_base_impl;
|
|
|
|
template <class CT>
|
|
struct xscalar_base_impl<xtensor_expression_tag, CT>
|
|
{
|
|
using type = xtensor_empty_base;
|
|
};
|
|
|
|
template <class CT>
|
|
struct xscalar_base : xscalar_base_impl<get_expression_tag_t<std::decay_t<CT>>, CT>
|
|
{
|
|
};
|
|
|
|
template <class CT>
|
|
using xscalar_base_t = typename xscalar_base<CT>::type;
|
|
}
|
|
|
|
/***********
|
|
* xscalar *
|
|
***********/
|
|
|
|
// xscalar is a cheap wrapper for a scalar value as an xexpression.
|
|
template <class CT>
|
|
class xscalar;
|
|
|
|
template <bool is_const, class CT>
|
|
class xscalar_stepper;
|
|
|
|
template <bool is_const, class CT>
|
|
class xdummy_iterator;
|
|
|
|
template <class CT>
|
|
struct xiterable_inner_types<xscalar<CT>>
|
|
{
|
|
using value_type = std::decay_t<CT>;
|
|
using inner_shape_type = std::array<std::size_t, 0>;
|
|
using shape_type = inner_shape_type;
|
|
using const_stepper = xscalar_stepper<true, CT>;
|
|
using stepper = xscalar_stepper<false, CT>;
|
|
};
|
|
|
|
template <class CT>
|
|
struct xcontainer_inner_types<xscalar<CT>>
|
|
{
|
|
using value_type = std::decay_t<CT>;
|
|
using reference = value_type&;
|
|
using const_reference = const value_type&;
|
|
using size_type = std::size_t;
|
|
};
|
|
|
|
template <class CT>
|
|
class xscalar : public xsharable_expression<xscalar<CT>>,
|
|
private xiterable<xscalar<CT>>,
|
|
private xaccessible<xscalar<CT>>,
|
|
public extension::xscalar_base_t<CT>
|
|
{
|
|
public:
|
|
|
|
using self_type = xscalar<CT>;
|
|
using xexpression_type = std::decay_t<CT>;
|
|
using extension_base = extension::xscalar_base_t<CT>;
|
|
using accessible_base = xaccessible<self_type>;
|
|
using expression_tag = typename extension_base::expression_tag;
|
|
using inner_types = xcontainer_inner_types<self_type>;
|
|
|
|
using value_type = typename inner_types::value_type;
|
|
using reference = typename inner_types::reference;
|
|
using const_reference = typename inner_types::const_reference;
|
|
using pointer = value_type*;
|
|
using const_pointer = const value_type*;
|
|
using size_type = typename inner_types::size_type;
|
|
using difference_type = std::ptrdiff_t;
|
|
using simd_value_type = xt_simd::simd_type<value_type>;
|
|
using bool_load_type = xt::bool_load_type<value_type>;
|
|
|
|
using iterable_base = xiterable<self_type>;
|
|
using inner_shape_type = typename iterable_base::inner_shape_type;
|
|
using shape_type = inner_shape_type;
|
|
|
|
using stepper = typename iterable_base::stepper;
|
|
using const_stepper = typename iterable_base::const_stepper;
|
|
|
|
template <layout_type L>
|
|
using layout_iterator = typename iterable_base::template layout_iterator<L>;
|
|
template <layout_type L>
|
|
using const_layout_iterator = typename iterable_base::template const_layout_iterator<L>;
|
|
|
|
template <layout_type L>
|
|
using reverse_layout_iterator = typename iterable_base::template reverse_layout_iterator<L>;
|
|
template <layout_type L>
|
|
using const_reverse_layout_iterator = typename iterable_base::template const_reverse_layout_iterator<L>;
|
|
|
|
template <class S, layout_type L>
|
|
using broadcast_iterator = typename iterable_base::template broadcast_iterator<S, L>;
|
|
template <class S, layout_type L>
|
|
using const_broadcast_iterator = typename iterable_base::template const_broadcast_iterator<S, L>;
|
|
|
|
template <class S, layout_type L>
|
|
using reverse_broadcast_iterator = typename iterable_base::template reverse_broadcast_iterator<S, L>;
|
|
template <class S, layout_type L>
|
|
using const_reverse_broadcast_iterator = typename iterable_base::template const_reverse_broadcast_iterator<S, L>;
|
|
|
|
using iterator = value_type*;
|
|
using const_iterator = const value_type*;
|
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
|
|
|
using dummy_iterator = xdummy_iterator<false, CT>;
|
|
using const_dummy_iterator = xdummy_iterator<true, CT>;
|
|
|
|
static constexpr layout_type static_layout = layout_type::any;
|
|
static constexpr bool contiguous_layout = true;
|
|
|
|
xscalar() noexcept;
|
|
xscalar(CT value) noexcept;
|
|
|
|
operator value_type&() noexcept;
|
|
operator const value_type&() const noexcept;
|
|
|
|
size_type size() const noexcept;
|
|
const shape_type& shape() const noexcept;
|
|
size_type shape(size_type i) const noexcept;
|
|
layout_type layout() const noexcept;
|
|
bool is_contiguous() const noexcept;
|
|
using accessible_base::dimension;
|
|
using accessible_base::shape;
|
|
|
|
template <class... Args>
|
|
reference operator()(Args...) noexcept;
|
|
template <class... Args>
|
|
reference unchecked(Args...) noexcept;
|
|
|
|
template <class... Args>
|
|
const_reference operator()(Args...) const noexcept;
|
|
template <class... Args>
|
|
const_reference unchecked(Args...) const noexcept;
|
|
|
|
using accessible_base::at;
|
|
using accessible_base::operator[];
|
|
using accessible_base::back;
|
|
using accessible_base::front;
|
|
using accessible_base::in_bounds;
|
|
using accessible_base::periodic;
|
|
|
|
template <class It>
|
|
reference element(It, It) noexcept;
|
|
|
|
template <class It>
|
|
const_reference element(It, It) const noexcept;
|
|
|
|
xexpression_type& expression() noexcept;
|
|
const xexpression_type& expression() const noexcept;
|
|
|
|
template <class S>
|
|
bool broadcast_shape(S& shape, bool reuse_cache = false) const noexcept;
|
|
|
|
template <class S>
|
|
bool has_linear_assign(const S& strides) const noexcept;
|
|
|
|
template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
|
|
iterator begin() noexcept;
|
|
template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
|
|
iterator end() noexcept;
|
|
|
|
template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
|
|
const_iterator begin() const noexcept;
|
|
template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
|
|
const_iterator end() const noexcept;
|
|
template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
|
|
const_iterator cbegin() const noexcept;
|
|
template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
|
|
const_iterator cend() const noexcept;
|
|
|
|
template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
|
|
reverse_iterator rbegin() noexcept;
|
|
template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
|
|
reverse_iterator rend() noexcept;
|
|
|
|
template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
|
|
const_reverse_iterator rbegin() const noexcept;
|
|
template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
|
|
const_reverse_iterator rend() const noexcept;
|
|
template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
|
|
const_reverse_iterator crbegin() const noexcept;
|
|
template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
|
|
const_reverse_iterator crend() const noexcept;
|
|
|
|
template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
|
|
broadcast_iterator<S, L> begin(const S& shape) noexcept;
|
|
template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
|
|
broadcast_iterator<S, L> end(const S& shape) noexcept;
|
|
|
|
template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
|
|
const_broadcast_iterator<S, L> begin(const S& shape) const noexcept;
|
|
template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
|
|
const_broadcast_iterator<S, L> end(const S& shape) const noexcept;
|
|
template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
|
|
const_broadcast_iterator<S, L> cbegin(const S& shape) const noexcept;
|
|
template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
|
|
const_broadcast_iterator<S, L> cend(const S& shape) const noexcept;
|
|
|
|
|
|
template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
|
|
reverse_broadcast_iterator<S, L> rbegin(const S& shape) noexcept;
|
|
template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
|
|
reverse_broadcast_iterator<S, L> rend(const S& shape) noexcept;
|
|
|
|
template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
|
|
const_reverse_broadcast_iterator<S, L> rbegin(const S& shape) const noexcept;
|
|
template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
|
|
const_reverse_broadcast_iterator<S, L> rend(const S& shape) const noexcept;
|
|
template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
|
|
const_reverse_broadcast_iterator<S, L> crbegin(const S& shape) const noexcept;
|
|
template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
|
|
const_reverse_broadcast_iterator<S, L> crend(const S& shape) const noexcept;
|
|
|
|
iterator linear_begin() noexcept;
|
|
iterator linear_end() noexcept;
|
|
|
|
const_iterator linear_begin() const noexcept;
|
|
const_iterator linear_end() const noexcept;
|
|
const_iterator linear_cbegin() const noexcept;
|
|
const_iterator linear_cend() const noexcept;
|
|
|
|
reverse_iterator linear_rbegin() noexcept;
|
|
reverse_iterator linear_rend() noexcept;
|
|
|
|
const_reverse_iterator linear_rbegin() const noexcept;
|
|
const_reverse_iterator linear_rend() const noexcept;
|
|
const_reverse_iterator linear_crbegin() const noexcept;
|
|
const_reverse_iterator linear_crend() const noexcept;
|
|
|
|
template <class S>
|
|
stepper stepper_begin(const S& shape) noexcept;
|
|
template <class S>
|
|
stepper stepper_end(const S& shape, layout_type l) noexcept;
|
|
|
|
template <class S>
|
|
const_stepper stepper_begin(const S& shape) const noexcept;
|
|
template <class S>
|
|
const_stepper stepper_end(const S& shape, layout_type l) const noexcept;
|
|
|
|
dummy_iterator dummy_begin() noexcept;
|
|
dummy_iterator dummy_end() noexcept;
|
|
|
|
const_dummy_iterator dummy_begin() const noexcept;
|
|
const_dummy_iterator dummy_end() const noexcept;
|
|
|
|
reference data_element(size_type i) noexcept;
|
|
const_reference data_element(size_type i) const noexcept;
|
|
|
|
reference flat(size_type i) noexcept;
|
|
const_reference flat(size_type i) const noexcept;
|
|
|
|
template <class align, class simd = simd_value_type>
|
|
void store_simd(size_type i, const simd& e);
|
|
template <class align, class requested_type = value_type, std::size_t N = xt_simd::simd_traits<requested_type>::size>
|
|
xt_simd::simd_return_type<value_type, requested_type> load_simd(size_type i) const;
|
|
|
|
private:
|
|
|
|
CT m_value;
|
|
|
|
friend class xconst_iterable<self_type>;
|
|
friend class xiterable<self_type>;
|
|
friend class xaccessible<self_type>;
|
|
friend class xconst_accessible<self_type>;
|
|
};
|
|
|
|
namespace detail
|
|
{
|
|
template <class E>
|
|
struct is_xscalar_impl : std::false_type
|
|
{
|
|
};
|
|
|
|
template <class E>
|
|
struct is_xscalar_impl<xscalar<E>> : std::true_type
|
|
{
|
|
};
|
|
}
|
|
|
|
template <class E>
|
|
using is_xscalar = detail::is_xscalar_impl<E>;
|
|
|
|
namespace detail
|
|
{
|
|
template <class... E>
|
|
struct all_xscalar
|
|
{
|
|
static constexpr bool value = xtl::conjunction<is_xscalar<std::decay_t<E>>...>::value;
|
|
};
|
|
}
|
|
|
|
// Note: MSVC bug workaround. Cannot just define
|
|
// template <class... E>
|
|
// using all_xscalar = xtl::conjunction<is_xscalar<std::decay_t<E>>...>;
|
|
|
|
template <class... E>
|
|
using all_xscalar = detail::all_xscalar<E...>;
|
|
|
|
/******************
|
|
* xref and xcref *
|
|
******************/
|
|
|
|
template <class T>
|
|
xscalar<T&> xref(T& t);
|
|
|
|
template <class T>
|
|
xscalar<const T&> xcref(T& t);
|
|
|
|
/*******************
|
|
* xscalar_stepper *
|
|
*******************/
|
|
|
|
template <bool is_const, class CT>
|
|
class xscalar_stepper
|
|
{
|
|
public:
|
|
|
|
using self_type = xscalar_stepper<is_const, CT>;
|
|
using storage_type = std::conditional_t<is_const, const xscalar<CT>, xscalar<CT>>;
|
|
|
|
using value_type = typename storage_type::value_type;
|
|
using reference = std::
|
|
conditional_t<is_const, typename storage_type::const_reference, typename storage_type::reference>;
|
|
using pointer = std::conditional_t<is_const, typename storage_type::const_pointer, typename storage_type::pointer>;
|
|
using size_type = typename storage_type::size_type;
|
|
using difference_type = typename storage_type::difference_type;
|
|
using shape_type = typename storage_type::shape_type;
|
|
|
|
template <class requested_type>
|
|
using simd_return_type = xt_simd::simd_return_type<value_type, requested_type>;
|
|
|
|
xscalar_stepper(storage_type* c) noexcept;
|
|
|
|
reference operator*() const noexcept;
|
|
|
|
void step(size_type dim, size_type n = 1) noexcept;
|
|
void step_back(size_type dim, size_type n = 1) noexcept;
|
|
void reset(size_type dim) noexcept;
|
|
void reset_back(size_type dim) noexcept;
|
|
|
|
void to_begin() noexcept;
|
|
void to_end(layout_type l) noexcept;
|
|
|
|
template <class T>
|
|
simd_return_type<T> step_simd();
|
|
|
|
void step_leading();
|
|
|
|
private:
|
|
|
|
storage_type* p_c;
|
|
};
|
|
|
|
/*******************
|
|
* xdummy_iterator *
|
|
*******************/
|
|
|
|
namespace detail
|
|
{
|
|
template <bool is_const, class CT>
|
|
using dummy_reference_t = std::
|
|
conditional_t<is_const, typename xscalar<CT>::const_reference, typename xscalar<CT>::reference>;
|
|
|
|
template <bool is_const, class CT>
|
|
using dummy_pointer_t = std::
|
|
conditional_t<is_const, typename xscalar<CT>::const_pointer, typename xscalar<CT>::pointer>;
|
|
}
|
|
|
|
template <bool is_const, class CT>
|
|
class xdummy_iterator : public xtl::xrandom_access_iterator_base<
|
|
xdummy_iterator<is_const, CT>,
|
|
typename xscalar<CT>::value_type,
|
|
typename xscalar<CT>::difference_type,
|
|
detail::dummy_pointer_t<is_const, CT>,
|
|
detail::dummy_reference_t<is_const, CT>>
|
|
{
|
|
public:
|
|
|
|
using self_type = xdummy_iterator<is_const, CT>;
|
|
using storage_type = std::conditional_t<is_const, const xscalar<CT>, xscalar<CT>>;
|
|
|
|
using value_type = typename storage_type::value_type;
|
|
using reference = detail::dummy_reference_t<is_const, CT>;
|
|
using pointer = detail::dummy_pointer_t<is_const, CT>;
|
|
using difference_type = typename storage_type::difference_type;
|
|
using iterator_category = std::random_access_iterator_tag;
|
|
|
|
explicit xdummy_iterator(storage_type* c) noexcept;
|
|
|
|
self_type& operator++() noexcept;
|
|
self_type& operator--() noexcept;
|
|
|
|
self_type& operator+=(difference_type n) noexcept;
|
|
self_type& operator-=(difference_type n) noexcept;
|
|
|
|
difference_type operator-(const self_type& rhs) const noexcept;
|
|
|
|
reference operator*() const noexcept;
|
|
|
|
bool equal(const self_type& rhs) const noexcept;
|
|
bool less_than(const self_type& rhs) const noexcept;
|
|
|
|
private:
|
|
|
|
storage_type* p_c;
|
|
};
|
|
|
|
template <bool is_const, class CT>
|
|
bool
|
|
operator==(const xdummy_iterator<is_const, CT>& lhs, const xdummy_iterator<is_const, CT>& rhs) noexcept;
|
|
|
|
template <bool is_const, class CT>
|
|
bool operator<(const xdummy_iterator<is_const, CT>& lhs, const xdummy_iterator<is_const, CT>& rhs) noexcept;
|
|
|
|
template <class T>
|
|
struct is_not_xdummy_iterator : std::true_type
|
|
{
|
|
};
|
|
|
|
template <bool is_const, class CT>
|
|
struct is_not_xdummy_iterator<xdummy_iterator<is_const, CT>> : std::false_type
|
|
{
|
|
};
|
|
|
|
/*****************************
|
|
* linear_begin / linear_end *
|
|
*****************************/
|
|
|
|
template <class CT>
|
|
XTENSOR_CONSTEXPR_RETURN auto linear_begin(xscalar<CT>& c) noexcept -> decltype(c.dummy_begin())
|
|
{
|
|
return c.dummy_begin();
|
|
}
|
|
|
|
template <class CT>
|
|
XTENSOR_CONSTEXPR_RETURN auto linear_end(xscalar<CT>& c) noexcept -> decltype(c.dummy_end())
|
|
{
|
|
return c.dummy_end();
|
|
}
|
|
|
|
template <class CT>
|
|
XTENSOR_CONSTEXPR_RETURN auto linear_begin(const xscalar<CT>& c) noexcept -> decltype(c.dummy_begin())
|
|
{
|
|
return c.dummy_begin();
|
|
}
|
|
|
|
template <class CT>
|
|
XTENSOR_CONSTEXPR_RETURN auto linear_end(const xscalar<CT>& c) noexcept -> decltype(c.dummy_end())
|
|
{
|
|
return c.dummy_end();
|
|
}
|
|
|
|
/**************************
|
|
* xscalar implementation *
|
|
**************************/
|
|
|
|
// This constructor will not compile when CT is a reference type.
|
|
template <class CT>
|
|
inline xscalar<CT>::xscalar() noexcept
|
|
: m_value()
|
|
{
|
|
}
|
|
|
|
template <class CT>
|
|
inline xscalar<CT>::xscalar(CT value) noexcept
|
|
: m_value(value)
|
|
{
|
|
}
|
|
|
|
template <class CT>
|
|
inline xscalar<CT>::operator value_type&() noexcept
|
|
{
|
|
return m_value;
|
|
}
|
|
|
|
template <class CT>
|
|
inline xscalar<CT>::operator const value_type&() const noexcept
|
|
{
|
|
return m_value;
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::size() const noexcept -> size_type
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::shape() const noexcept -> const shape_type&
|
|
{
|
|
static std::array<size_type, 0> zero_shape;
|
|
return zero_shape;
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::shape(size_type) const noexcept -> size_type
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
template <class CT>
|
|
inline layout_type xscalar<CT>::layout() const noexcept
|
|
{
|
|
return static_layout;
|
|
}
|
|
|
|
template <class CT>
|
|
inline bool xscalar<CT>::is_contiguous() const noexcept
|
|
{
|
|
return true;
|
|
}
|
|
|
|
template <class CT>
|
|
template <class... Args>
|
|
inline auto xscalar<CT>::operator()(Args...) noexcept -> reference
|
|
{
|
|
XTENSOR_CHECK_DIMENSION((std::array<int, 0>()), Args()...);
|
|
return m_value;
|
|
}
|
|
|
|
template <class CT>
|
|
template <class... Args>
|
|
inline auto xscalar<CT>::unchecked(Args...) noexcept -> reference
|
|
{
|
|
return m_value;
|
|
}
|
|
|
|
template <class CT>
|
|
template <class... Args>
|
|
inline auto xscalar<CT>::operator()(Args...) const noexcept -> const_reference
|
|
{
|
|
XTENSOR_CHECK_DIMENSION((std::array<int, 0>()), Args()...);
|
|
return m_value;
|
|
}
|
|
|
|
template <class CT>
|
|
template <class... Args>
|
|
inline auto xscalar<CT>::unchecked(Args...) const noexcept -> const_reference
|
|
{
|
|
return m_value;
|
|
}
|
|
|
|
template <class CT>
|
|
template <class It>
|
|
inline auto xscalar<CT>::element(It, It) noexcept -> reference
|
|
{
|
|
return m_value;
|
|
}
|
|
|
|
template <class CT>
|
|
template <class It>
|
|
inline auto xscalar<CT>::element(It, It) const noexcept -> const_reference
|
|
{
|
|
return m_value;
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::expression() noexcept -> xexpression_type&
|
|
{
|
|
return m_value;
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::expression() const noexcept -> const xexpression_type&
|
|
{
|
|
return m_value;
|
|
}
|
|
|
|
template <class CT>
|
|
template <class S>
|
|
inline bool xscalar<CT>::broadcast_shape(S&, bool) const noexcept
|
|
{
|
|
return true;
|
|
}
|
|
|
|
template <class CT>
|
|
template <class S>
|
|
inline bool xscalar<CT>::has_linear_assign(const S&) const noexcept
|
|
{
|
|
return true;
|
|
}
|
|
|
|
template <class CT>
|
|
template <layout_type L>
|
|
inline auto xscalar<CT>::begin() noexcept -> iterator
|
|
{
|
|
return &m_value;
|
|
}
|
|
|
|
template <class CT>
|
|
template <layout_type L>
|
|
inline auto xscalar<CT>::end() noexcept -> iterator
|
|
{
|
|
return &m_value + 1;
|
|
}
|
|
|
|
template <class CT>
|
|
template <layout_type L>
|
|
inline auto xscalar<CT>::begin() const noexcept -> const_iterator
|
|
{
|
|
return &m_value;
|
|
}
|
|
|
|
template <class CT>
|
|
template <layout_type L>
|
|
inline auto xscalar<CT>::end() const noexcept -> const_iterator
|
|
{
|
|
return &m_value + 1;
|
|
}
|
|
|
|
template <class CT>
|
|
template <layout_type L>
|
|
inline auto xscalar<CT>::cbegin() const noexcept -> const_iterator
|
|
{
|
|
return &m_value;
|
|
}
|
|
|
|
template <class CT>
|
|
template <layout_type L>
|
|
inline auto xscalar<CT>::cend() const noexcept -> const_iterator
|
|
{
|
|
return &m_value + 1;
|
|
}
|
|
|
|
template <class CT>
|
|
template <layout_type L>
|
|
inline auto xscalar<CT>::rbegin() noexcept -> reverse_iterator
|
|
{
|
|
return reverse_iterator(end());
|
|
}
|
|
|
|
template <class CT>
|
|
template <layout_type L>
|
|
inline auto xscalar<CT>::rend() noexcept -> reverse_iterator
|
|
{
|
|
return reverse_iterator(begin());
|
|
}
|
|
|
|
template <class CT>
|
|
template <layout_type L>
|
|
inline auto xscalar<CT>::rbegin() const noexcept -> const_reverse_iterator
|
|
{
|
|
return crbegin();
|
|
}
|
|
|
|
template <class CT>
|
|
template <layout_type L>
|
|
inline auto xscalar<CT>::rend() const noexcept -> const_reverse_iterator
|
|
{
|
|
return crend();
|
|
}
|
|
|
|
template <class CT>
|
|
template <layout_type L>
|
|
inline auto xscalar<CT>::crbegin() const noexcept -> const_reverse_iterator
|
|
{
|
|
return const_reverse_iterator(cend());
|
|
}
|
|
|
|
template <class CT>
|
|
template <layout_type L>
|
|
inline auto xscalar<CT>::crend() const noexcept -> const_reverse_iterator
|
|
{
|
|
return const_reverse_iterator(cbegin());
|
|
}
|
|
|
|
/*****************************
|
|
* Broadcasting iterator api *
|
|
*****************************/
|
|
|
|
template <class CT>
|
|
template <class S, layout_type L>
|
|
inline auto xscalar<CT>::begin(const S& shape) noexcept -> broadcast_iterator<S, L>
|
|
{
|
|
return iterable_base::template begin<S, L>(shape);
|
|
}
|
|
|
|
template <class CT>
|
|
template <class S, layout_type L>
|
|
inline auto xscalar<CT>::end(const S& shape) noexcept -> broadcast_iterator<S, L>
|
|
{
|
|
return iterable_base::template end<S, L>(shape);
|
|
}
|
|
|
|
template <class CT>
|
|
template <class S, layout_type L>
|
|
inline auto xscalar<CT>::begin(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
|
|
{
|
|
return iterable_base::template begin<S, L>(shape);
|
|
}
|
|
|
|
template <class CT>
|
|
template <class S, layout_type L>
|
|
inline auto xscalar<CT>::end(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
|
|
{
|
|
return iterable_base::template end<S, L>(shape);
|
|
}
|
|
|
|
template <class CT>
|
|
template <class S, layout_type L>
|
|
inline auto xscalar<CT>::cbegin(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
|
|
{
|
|
return iterable_base::template cbegin<S, L>(shape);
|
|
}
|
|
|
|
template <class CT>
|
|
template <class S, layout_type L>
|
|
inline auto xscalar<CT>::cend(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
|
|
{
|
|
return iterable_base::template cend<S, L>(shape);
|
|
}
|
|
|
|
template <class CT>
|
|
template <class S, layout_type L>
|
|
inline auto xscalar<CT>::rbegin(const S& shape) noexcept -> reverse_broadcast_iterator<S, L>
|
|
{
|
|
return iterable_base::template rbegin<S, L>(shape);
|
|
}
|
|
|
|
template <class CT>
|
|
template <class S, layout_type L>
|
|
inline auto xscalar<CT>::rend(const S& shape) noexcept -> reverse_broadcast_iterator<S, L>
|
|
{
|
|
return iterable_base::template rend<S, L>(shape);
|
|
}
|
|
|
|
template <class CT>
|
|
template <class S, layout_type L>
|
|
inline auto xscalar<CT>::rbegin(const S& shape) const noexcept -> const_reverse_broadcast_iterator<S, L>
|
|
{
|
|
return iterable_base::template rbegin<S, L>(shape);
|
|
}
|
|
|
|
template <class CT>
|
|
template <class S, layout_type L>
|
|
inline auto xscalar<CT>::rend(const S& shape) const noexcept -> const_reverse_broadcast_iterator<S, L>
|
|
{
|
|
return iterable_base::template rend<S, L>(shape);
|
|
}
|
|
|
|
template <class CT>
|
|
template <class S, layout_type L>
|
|
inline auto xscalar<CT>::crbegin(const S& shape) const noexcept -> const_reverse_broadcast_iterator<S, L>
|
|
{
|
|
return iterable_base::template crbegin<S, L>(shape);
|
|
}
|
|
|
|
template <class CT>
|
|
template <class S, layout_type L>
|
|
inline auto xscalar<CT>::crend(const S& shape) const noexcept -> const_reverse_broadcast_iterator<S, L>
|
|
{
|
|
return iterable_base::template crend<S, L>(shape);
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::linear_begin() noexcept -> iterator
|
|
{
|
|
return this->template begin<XTENSOR_DEFAULT_LAYOUT>();
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::linear_end() noexcept -> iterator
|
|
{
|
|
return this->template end<XTENSOR_DEFAULT_LAYOUT>();
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::linear_begin() const noexcept -> const_iterator
|
|
{
|
|
return this->template begin<XTENSOR_DEFAULT_LAYOUT>();
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::linear_end() const noexcept -> const_iterator
|
|
{
|
|
return this->template end<XTENSOR_DEFAULT_LAYOUT>();
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::linear_cbegin() const noexcept -> const_iterator
|
|
{
|
|
return this->template cbegin<XTENSOR_DEFAULT_LAYOUT>();
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::linear_cend() const noexcept -> const_iterator
|
|
{
|
|
return this->template cend<XTENSOR_DEFAULT_LAYOUT>();
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::linear_rbegin() noexcept -> reverse_iterator
|
|
{
|
|
return this->template rbegin<XTENSOR_DEFAULT_LAYOUT>();
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::linear_rend() noexcept -> reverse_iterator
|
|
{
|
|
return this->template rend<XTENSOR_DEFAULT_LAYOUT>();
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::linear_rbegin() const noexcept -> const_reverse_iterator
|
|
{
|
|
return this->template rbegin<XTENSOR_DEFAULT_LAYOUT>();
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::linear_rend() const noexcept -> const_reverse_iterator
|
|
{
|
|
return this->template rend<XTENSOR_DEFAULT_LAYOUT>();
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::linear_crbegin() const noexcept -> const_reverse_iterator
|
|
{
|
|
return this->template crbegin<XTENSOR_DEFAULT_LAYOUT>();
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::linear_crend() const noexcept -> const_reverse_iterator
|
|
{
|
|
return this->template crend<XTENSOR_DEFAULT_LAYOUT>();
|
|
}
|
|
|
|
template <class CT>
|
|
template <class S>
|
|
inline auto xscalar<CT>::stepper_begin(const S&) noexcept -> stepper
|
|
{
|
|
return stepper(this, false);
|
|
}
|
|
|
|
template <class CT>
|
|
template <class S>
|
|
inline auto xscalar<CT>::stepper_end(const S&, layout_type) noexcept -> stepper
|
|
{
|
|
return stepper(this);
|
|
}
|
|
|
|
template <class CT>
|
|
template <class S>
|
|
inline auto xscalar<CT>::stepper_begin(const S&) const noexcept -> const_stepper
|
|
{
|
|
return const_stepper(this);
|
|
}
|
|
|
|
template <class CT>
|
|
template <class S>
|
|
inline auto xscalar<CT>::stepper_end(const S&, layout_type) const noexcept -> const_stepper
|
|
{
|
|
return const_stepper(this);
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::dummy_begin() noexcept -> dummy_iterator
|
|
{
|
|
return dummy_iterator(this);
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::dummy_end() noexcept -> dummy_iterator
|
|
{
|
|
return dummy_iterator(this);
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::dummy_begin() const noexcept -> const_dummy_iterator
|
|
{
|
|
return const_dummy_iterator(this);
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::dummy_end() const noexcept -> const_dummy_iterator
|
|
{
|
|
return const_dummy_iterator(this);
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::data_element(size_type) noexcept -> reference
|
|
{
|
|
return m_value;
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::data_element(size_type) const noexcept -> const_reference
|
|
{
|
|
return m_value;
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::flat(size_type) noexcept -> reference
|
|
{
|
|
return m_value;
|
|
}
|
|
|
|
template <class CT>
|
|
inline auto xscalar<CT>::flat(size_type) const noexcept -> const_reference
|
|
{
|
|
return m_value;
|
|
}
|
|
|
|
template <class CT>
|
|
template <class align, class simd>
|
|
inline void xscalar<CT>::store_simd(size_type, const simd& e)
|
|
{
|
|
m_value = static_cast<value_type>(e[0]);
|
|
}
|
|
|
|
template <class CT>
|
|
template <class align, class requested_type, std::size_t N>
|
|
inline auto xscalar<CT>::load_simd(size_type) const
|
|
-> xt_simd::simd_return_type<value_type, requested_type>
|
|
{
|
|
return xt_simd::broadcast_as<requested_type>(m_value);
|
|
}
|
|
|
|
template <class T>
|
|
inline xscalar<T&> xref(T& t)
|
|
{
|
|
return xscalar<T&>(t);
|
|
}
|
|
|
|
template <class T>
|
|
inline xscalar<const T&> xcref(T& t)
|
|
{
|
|
return xscalar<const T&>(t);
|
|
}
|
|
|
|
/**********************************
|
|
* xscalar_stepper implementation *
|
|
**********************************/
|
|
|
|
template <bool is_const, class CT>
|
|
inline xscalar_stepper<is_const, CT>::xscalar_stepper(storage_type* c) noexcept
|
|
: p_c(c)
|
|
{
|
|
}
|
|
|
|
template <bool is_const, class CT>
|
|
inline auto xscalar_stepper<is_const, CT>::operator*() const noexcept -> reference
|
|
{
|
|
return p_c->operator()();
|
|
}
|
|
|
|
template <bool is_const, class CT>
|
|
inline void xscalar_stepper<is_const, CT>::step(size_type /*dim*/, size_type /*n*/) noexcept
|
|
{
|
|
}
|
|
|
|
template <bool is_const, class CT>
|
|
inline void xscalar_stepper<is_const, CT>::step_back(size_type /*dim*/, size_type /*n*/) noexcept
|
|
{
|
|
}
|
|
|
|
template <bool is_const, class CT>
|
|
inline void xscalar_stepper<is_const, CT>::reset(size_type /*dim*/) noexcept
|
|
{
|
|
}
|
|
|
|
template <bool is_const, class CT>
|
|
inline void xscalar_stepper<is_const, CT>::reset_back(size_type /*dim*/) noexcept
|
|
{
|
|
}
|
|
|
|
template <bool is_const, class CT>
|
|
inline void xscalar_stepper<is_const, CT>::to_begin() noexcept
|
|
{
|
|
}
|
|
|
|
template <bool is_const, class CT>
|
|
inline void xscalar_stepper<is_const, CT>::to_end(layout_type /*l*/) noexcept
|
|
{
|
|
}
|
|
|
|
template <bool is_const, class CT>
|
|
template <class T>
|
|
inline auto xscalar_stepper<is_const, CT>::step_simd() -> simd_return_type<T>
|
|
{
|
|
return simd_return_type<T>(p_c->operator()());
|
|
}
|
|
|
|
template <bool is_const, class CT>
|
|
inline void xscalar_stepper<is_const, CT>::step_leading()
|
|
{
|
|
}
|
|
|
|
/**********************************
|
|
* xdummy_iterator implementation *
|
|
**********************************/
|
|
|
|
template <bool is_const, class CT>
|
|
inline xdummy_iterator<is_const, CT>::xdummy_iterator(storage_type* c) noexcept
|
|
: p_c(c)
|
|
{
|
|
}
|
|
|
|
template <bool is_const, class CT>
|
|
inline auto xdummy_iterator<is_const, CT>::operator++() noexcept -> self_type&
|
|
{
|
|
return *this;
|
|
}
|
|
|
|
template <bool is_const, class CT>
|
|
inline auto xdummy_iterator<is_const, CT>::operator--() noexcept -> self_type&
|
|
{
|
|
return *this;
|
|
}
|
|
|
|
template <bool is_const, class CT>
|
|
inline auto xdummy_iterator<is_const, CT>::operator+=(difference_type) noexcept -> self_type&
|
|
{
|
|
return *this;
|
|
}
|
|
|
|
template <bool is_const, class CT>
|
|
inline auto xdummy_iterator<is_const, CT>::operator-=(difference_type) noexcept -> self_type&
|
|
{
|
|
return *this;
|
|
}
|
|
|
|
template <bool is_const, class CT>
|
|
inline auto xdummy_iterator<is_const, CT>::operator-(const self_type&) const noexcept -> difference_type
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
template <bool is_const, class CT>
|
|
inline auto xdummy_iterator<is_const, CT>::operator*() const noexcept -> reference
|
|
{
|
|
return p_c->operator()();
|
|
}
|
|
|
|
template <bool is_const, class CT>
|
|
inline bool xdummy_iterator<is_const, CT>::equal(const self_type& rhs) const noexcept
|
|
{
|
|
return p_c == rhs.p_c;
|
|
}
|
|
|
|
template <bool is_const, class CT>
|
|
inline bool xdummy_iterator<is_const, CT>::less_than(const self_type& rhs) const noexcept
|
|
{
|
|
return p_c < rhs.p_c;
|
|
}
|
|
|
|
template <bool is_const, class CT>
|
|
inline bool
|
|
operator==(const xdummy_iterator<is_const, CT>& lhs, const xdummy_iterator<is_const, CT>& rhs) noexcept
|
|
{
|
|
return lhs.equal(rhs);
|
|
}
|
|
|
|
template <bool is_const, class CT>
|
|
inline bool
|
|
operator<(const xdummy_iterator<is_const, CT>& lhs, const xdummy_iterator<is_const, CT>& rhs) noexcept
|
|
{
|
|
return lhs.less_than(rhs);
|
|
}
|
|
}
|
|
|
|
#endif
|