Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,303 changes: 866 additions & 437 deletions Doxyfile

Large diffs are not rendered by default.

45 changes: 37 additions & 8 deletions include/xvec/detail/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ concept builtin_vectorizable =
|| (complex_number<_Tp> && simple_vectorizable<typename _Tp::value_type>);

/// Trait-based form of vectorization concept.
/// \ingroup cpp29_p2964
template<typename _Tp>
inline constexpr bool disable_vectorization =
std::is_pointer_v<_Tp> ||
Expand Down Expand Up @@ -327,7 +328,6 @@ concept generator_invocable =
for (bool check : checks) if (!check) return false;
return true;
}(std::make_integer_sequence<simd_size_type, _Size>{});
///@}

template<typename Op>
concept mask_operator = any_same_v<Op,
Expand All @@ -342,6 +342,14 @@ template<class T> concept math_floating_point = vec_floating_point<deduced_vec_t

} // namespace detail

/**
* @defgroup cpp26_traits C++26: SIMD type traits
* @brief Form vector and mask types with different element types or element counts.
*
* @see https://eel.is/c++draft/simd.traits
* @{
*/

/// Given a simd type (vec or mask), create a new type which has the same size but a different element.
template<class _Tp, class _Vp> struct rebind {};
template<class _Tp, class _Sp, class _Abi> struct rebind<_Tp, basic_vec<_Sp, _Abi>> {
Expand All @@ -362,12 +370,23 @@ template<simd_size_type _Np, std::size_t _Bytes, class _Abi> struct resize<_Np,
};
template<simd_size_type _Np, class _Vp> using resize_t = typename resize<_Np, _Vp>::type;

/// Shortened aliases for common types.
/// @} cpp26_traits

/// Shortened alias for a vector type.
/// @ingroup cpp26_overview
template<class _Tp, simd_size_type _Np = basic_vec<_Tp>::size()> using vec = basic_vec<_Tp, simd_fixed_size_abi<_Np>>;

/// Shortened alias for a mask type.
/// @ingroup cpp26_mask_overview
template<class _Tp, simd_size_type _Np = basic_mask<sizeof(_Tp)>::size()> using mask = basic_mask<sizeof(_Tp), simd_fixed_size_abi<_Np>>;

///@{
/// flags for controlling the behaviour of simd operations like conversions and memory accesses.
/**
* @defgroup cpp26_flags C++26: Load and store flags
* @brief Flags controlling element conversion and memory alignment.
*
* @see https://eel.is/c++draft/simd.flags
* @{
*/

template <class... _Flags> struct flags {
template <class... _Others>
Expand All @@ -377,31 +396,37 @@ template <class... _Flags> struct flags {
}
};

/// @} cpp26_flags

namespace detail {
class flag_convert {};
class flag_aligned {};
template<size_t _N> class flag_overaligned {};
class flag_unchecked {};

// Add extra flags to the existing flags.
///@{
constexpr auto add_unchecked_flag(auto f) { return f | flags<flag_unchecked>{}; };
constexpr auto add_convert_flag(auto f) { return f | flags<flag_convert>{}; };
///@}

/// @brief Query whether the given flags contains the specified type.
template<typename _F, typename... _Flags>
constexpr bool contains_flag(flags<_Flags...>) { return (std::is_same_v<_F, _Flags> || ...); }
}

/// @addtogroup cpp26_flags
/// @{

/// Standard flags.
///@{
inline constexpr flags<> flag_default{};
inline constexpr flags<detail::flag_convert> flag_convert{};
inline constexpr flags<detail::flag_aligned> flag_aligned{};

template<size_t _N> requires (std::has_single_bit(_N)) inline constexpr flags<detail::flag_overaligned<_N>> flag_overaligned{};
///@}

/// @} cpp26_flags

/// @addtogroup cpp29_p2964
/// @{

/// Conversion flag, used to pass destination type to a simd_convert customisation point.
template<typename _Tp>
Expand All @@ -412,10 +437,13 @@ struct convert_to_t {

template<class _Tp> inline constexpr convert_to_t<_Tp> convert_to{};

/// @} cpp29_p2964

namespace detail
{

/// Traits for standard builtin vector types.
/// @internal
template<typename _Vendor, typename _Tp, simd_size_type _Np>
struct vec_traits
{
Expand Down Expand Up @@ -490,6 +518,7 @@ struct vec_traits
};

/// Traits for generic mask types which use a standard vector register to represent the mask.
/// @internal
template<typename _Vendor, std::size_t _Bytes, simd_size_type _Np>
struct mask_traits
{
Expand Down
24 changes: 24 additions & 0 deletions include/xvec/detail/invoke.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,28 @@ inline constexpr bool are_all_sizes_equal = (... && (Size == Sizes));

} // End namespace detail

/**
* @defgroup cpp29_p2929 Chunked invocation
* @brief Invoke a callable on corresponding chunks of vectors or masks.
*
* Proposed in P2929, "chunked_invoke", previously named simd_invoke.
*
* @see https://wg21.link/P2929
* @{
*/

/// @brief Invoke a callable on corresponding vector or mask chunks.
/// @tparam _SuggestedN Chunk size, or zero to deduce a common native width.
/// @tparam _Fn The callable type.
/// @tparam _Arg0 The first vector or mask argument type.
/// @tparam _Args The remaining vector or mask argument types.
/// @param fn The callable invoked on each set of corresponding chunks.
/// @param arg0 The first vector or mask argument.
/// @param args The remaining vector or mask arguments.
/// @return Concatenated vector or mask results, or void for a void-returning callable.
/// @details All arguments must have equal element counts. The final chunk may
/// be smaller than the selected chunk size. The callable may accept a trailing
/// argument giving the beginning index of the chunk.
template<simd_size_type _SuggestedN = 0, typename _Fn, vec_or_mask_type _Arg0, vec_or_mask_type... _Args>
constexpr auto chunked_invoke(_Fn fn, const _Arg0& arg0, const _Args&... args)
{
Expand Down Expand Up @@ -93,4 +115,6 @@ constexpr auto chunked_invoke(_Fn fn, const _Arg0& arg0, const _Args&... args)

}

/// @} cpp29_p2929

} // namespace _XVEC_NAMESPACE::simd
45 changes: 44 additions & 1 deletion include/xvec/detail/iterator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,27 @@
namespace _XVEC_NAMESPACE::simd
{

/**
* @defgroup cpp26_iterator C++26: SIMD iteration
* @brief Random-access iteration over vector and mask elements.
*
* @see https://eel.is/c++draft/simd.iterator
* @{
*/

/// @brief xvec implementation of the exposition-only SIMD iterator.
/// @tparam _Simd The vector or mask type being traversed.
template <vec_or_mask_type _Simd>
class simd_iterator
{
public:

/// The simd object over which iteration is happening.
/// @internal
_Simd* data = nullptr;

/// The current position of the iterator within the simd being iterated.
/// @internal
simd_size_type index = 0;

// Traits
Expand All @@ -34,29 +46,42 @@ class simd_iterator
using iterator_concept = std::random_access_iterator_tag;
using difference_type = simd_size_type;

/// Default-construct an iterator.
constexpr simd_iterator() = default;

/// Copy an iterator.
constexpr simd_iterator(const simd_iterator&) = default;

/// Construct an iterator at element x of s.
constexpr simd_iterator(_Simd& s, simd_size_type x) : data(std::addressof(s)), index(x) {}

/// Copy-assign an iterator.
constexpr simd_iterator& operator=(const simd_iterator&) = default;

/// Convert a mutable iterator to a const iterator.
constexpr simd_iterator(const simd_iterator<std::remove_const_t<_Simd>>& i)
requires std::is_const_v<_Simd> : data(i.data), index(i.index) {}

// Dereference the iterator to get the simd element.
/// Return the current element.
constexpr value_type operator*() const { return (*data)[index]; }
/// Return the element at the specified relative offset.
constexpr value_type operator[](difference_type i) const { return (*data)[index + i]; }

/// Advance to the next element.
constexpr simd_iterator& operator++() { index += 1; return *this; }

/// Move to the previous element.
constexpr simd_iterator& operator--() { index -= 1; return *this; }

/// Advance to the next element, returning the original iterator.
constexpr simd_iterator operator++(int)
{
simd_iterator i = *this;
index += 1;
return i;
}

/// Move to the previous element, returning the original iterator.
constexpr simd_iterator
operator--(int)
{
Expand All @@ -65,24 +90,42 @@ class simd_iterator
return i;
}

/// Return the distance from another iterator.
constexpr difference_type operator-(simd_iterator rhs) const { return index - rhs.index; }

/// Return an iterator advanced by the specified offset.
friend constexpr simd_iterator operator+(difference_type x, const simd_iterator& it) { return simd_iterator(*it.data, it.index + x); }

/// Return an iterator advanced by the specified offset.
friend constexpr simd_iterator operator+(const simd_iterator& it, difference_type x) { return simd_iterator(*it.data, it.index + x); }

/// Return an iterator moved backward by the specified offset.
friend constexpr simd_iterator operator-(const simd_iterator& it, difference_type x) { return simd_iterator(*it.data, it.index - x); }

/// Advance by the specified offset.
constexpr simd_iterator& operator+=(difference_type x) { index += x; return *this; }

/// Move backward by the specified offset.
constexpr simd_iterator& operator-=(difference_type x) { index -= x; return *this; }

/// Compare iterator positions.
friend constexpr auto operator<=>(simd_iterator a, simd_iterator b) { return a.index <=> b.index; }

/// Test iterator equality.
friend constexpr bool operator==(simd_iterator a, simd_iterator b) = default;

/// Test whether the iterator has reached the end.
friend constexpr bool operator==(simd_iterator a, std::default_sentinel_t) noexcept
{ return a.index == static_cast<difference_type>(_Simd::size()); }

/// Return the signed distance from the end sentinel.
friend constexpr difference_type operator-(simd_iterator a, std::default_sentinel_t) noexcept
{ return a.index - static_cast<difference_type>(_Simd::size()); }
/// Return the number of elements remaining before the end sentinel.
friend constexpr difference_type operator-(std::default_sentinel_t, simd_iterator a) noexcept
{ return static_cast<difference_type>(_Simd::size()) - a.index; }
};

/// @} cpp26_iterator

}
Loading
Loading