Anurag Bhat 86b4fc623c
Merge numpy to pocketpy (#303)
* Merge numpy to pocketpy

* Add CI

* Fix CI
2024-09-02 16:22:41 +08:00

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