Argon 0.1.0
Loading...
Searching...
No Matches
store_interleaved.hpp
1#pragma once
2#include <ranges>
3#include "argon.hpp"
4#include "arm_simd/helpers/vec128.hpp"
5
6#ifdef __ARM_FEATURE_MVE
7#define simd mve
8#else
9#define simd neon
10#endif
11
12namespace argon::vectorize {
13
14template <typename scalar_type, size_t stride = 2>
15struct store_interleaved : std::ranges::view_interface<store_interleaved<scalar_type, stride>> {
16 using intrinsic_type = simd::Vec128_t<scalar_type>;
17 static constexpr size_t lanes = sizeof(intrinsic_type) / sizeof(scalar_type);
18 static constexpr size_t vectorizeable_size(size_t size) { return size & ~(lanes - 1); }
19
20 static_assert(stride > 1 && stride < 5, "Interleaving Stores can only be performed with a stride of 2, 3, or 4");
21
22 public:
23 struct StoreInterleavedIterator {
24 using difference_type = std::ptrdiff_t;
25 using reference_type = StoreInterleavedIterator&;
26
27 StoreInterleavedIterator() = default;
28 StoreInterleavedIterator(scalar_type* ptr) : ptr_{ptr} {}
29
30 std::array<Argon<scalar_type>, stride>& operator*() { return vecs_; }
31
32 StoreInterleavedIterator& operator++() {
33 argon::store_interleaved(ptr_, vecs_);
34 ptr_ += lanes * stride;
35 vecs_ = {};
36 return *this;
37 }
38
39 StoreInterleavedIterator operator++(int) {
40 StoreInterleavedIterator tmp = *this;
41 ++(*this);
42 return tmp;
43 }
44
45 StoreInterleavedIterator& operator--() {
46 ptr_ -= lanes * stride;
47 vecs_ = {};
48 return *this;
49 }
50
51 StoreInterleavedIterator operator--(int) {
52 StoreInterleavedIterator tmp = *this;
53 --(*this);
54 return tmp;
55 }
56
57 difference_type operator-(const StoreInterleavedIterator& other) const { return ptr_ - other.ptr_; }
58
59 friend bool operator==(const StoreInterleavedIterator& a, const StoreInterleavedIterator& b) {
60 return a.ptr_ == b.ptr_;
61 }
62 friend bool operator==(const StoreInterleavedIterator& a, const scalar_type* ptr) { return a.ptr_ == ptr; }
63 friend bool operator!=(const StoreInterleavedIterator& a, const StoreInterleavedIterator& b) {
64 return a.ptr_ != b.ptr_;
65 }
66 friend bool operator!=(const StoreInterleavedIterator& a, const scalar_type* ptr) { return a.ptr_ != ptr; }
67 friend auto operator<=>(const StoreInterleavedIterator& a, const StoreInterleavedIterator& b) {
68 return a.ptr_ <=> b.ptr_;
69 }
70
71 private:
72 std::array<Argon<scalar_type>, stride> vecs_;
73 scalar_type* ptr_;
74 };
75 static_assert(std::sized_sentinel_for<StoreInterleavedIterator, StoreInterleavedIterator>);
76 static_assert(std::output_iterator<StoreInterleavedIterator, std::array<Argon<scalar_type>, stride>>);
77
78 using iterator = StoreInterleavedIterator;
79
80 iterator begin() { return start_; }
81 scalar_type* end() { return start_ + size_; }
82 size_t size() const { return size_ / (lanes * stride); }
83
84 template <std::ranges::contiguous_range R>
85 store_interleaved(R&& r) : start_{&*std::ranges::begin(r)}, size_{vectorizeable_size(std::ranges::size(r))} {}
86
87 private:
88 scalar_type* start_;
89 size_t size_;
90};
91
92static_assert(std::ranges::range<store_interleaved<int32_t, 2>>);
93static_assert(std::ranges::view<store_interleaved<int32_t, 2>>);
94
95template <std::ranges::contiguous_range R, size_t stride = 2>
97
98} // namespace argon::vectorize
99#undef simd
Lane deconstruction feature.
Definition argon_full.hpp:302
Definition ptr.hpp:74
Definition store_interleaved.hpp:15