Argon 0.1.0
Loading...
Searching...
No Matches
lane.hpp
1#pragma once
2#include "arm_simd.hpp"
3#include "arm_simd/helpers/scalar.hpp"
4#include "arm_simd/helpers/vec64.hpp"
5#include "features.h"
6#include "helpers/argon_for.hpp"
7
8#ifdef __ARM_FEATURE_MVE
9#define simd mve
10#else
11#define simd neon
12#endif
13
14#ifdef ARGON_PLATFORM_SIMDE
15#define ace [[gnu::always_inline]] inline
16#elifdef __clang__
17#define ace [[gnu::always_inline]] constexpr
18#else
19#define ace [[gnu::always_inline]] inline
20#endif
21
22namespace argon {
23template <typename T>
24class Vector;
25
26#ifdef ARGON_PLATFORM_MVE
27
28// MVE does not support lane manipulators, so we use the scalar type directly
29// for the lane type.
30
31template <size_t, typename VectorType>
32using ConstLane = simd::Scalar_t<VectorType>;
33
34template <typename VectorType>
35using Lane = simd::Scalar_t<VectorType>;
36
37#else
38
45template <size_t LaneIndex, typename VectorType>
46class ConstLane {
47 using scalar_type = simd::Scalar_t<VectorType>;
49 using argon_type = helpers::ArgonFor_t<VectorType>;
50
51 public:
53 ace ConstLane(VectorType& vec) : vec_{vec} {}
55 ace operator scalar_type() const { return Get(); }
57 ace argon_type operator=(const scalar_type b) { return vec_ = Set(b); }
60 ace argon_type Load(const scalar_type* ptr) {
61#ifdef ARGON_PLATFORM_MVE
62 return vec_ = Set(*ptr);
63#else
64 if constexpr (simd::is_quadword_v<VectorType>) {
65 return vec_ = argon_type{simd::load1_lane_quad<LaneIndex>(ptr, vec_)};
66 } else {
67 return vec_ = argon_type{simd::load1_lane<LaneIndex>(ptr, vec_)};
68 }
69#endif
70 }
71
72 ace argon_type Set(const scalar_type b) { return argon_type{simd::set_lane<LaneIndex>(b, vec_)}; }
74 ace scalar_type Get() const { return simd::get_lane<LaneIndex>(vec_); }
75
76#if __ARM_ARCH >= 8
78 ace VectorType vec() { return vec_; }
80 ace const int lane() { return LaneIndex; }
81#else
83 ace neon::Vec64_t<scalar_type> vec() {
84 if constexpr (simd::is_doubleword_v<VectorType>) {
85 return vec_;
86 } else if constexpr (simd::is_quadword_v<VectorType>) {
87 if constexpr (LaneIndex >= ArgonHalf<scalar_type>::lanes) {
88 return simd::get_high(vec_);
89 } else {
90 return simd::get_low(vec_);
91 }
92 }
93 }
94
95 ace int lane() {
96 if constexpr (simd::is_doubleword_v<VectorType>) {
97 return LaneIndex;
98 } else if constexpr (simd::is_quadword_v<VectorType>) {
99 if (LaneIndex >= ArgonHalf<scalar_type>::lanes) {
100 return (LaneIndex - ArgonHalf<scalar_type>::lanes);
101 } else {
102 return LaneIndex;
103 }
104 }
105 }
106#endif
107 private:
108 VectorType& vec_;
109};
110
116template <typename VectorType>
117class Lane {
118 using scalar_type = simd::Scalar_t<VectorType>;
119 using type = Lane<VectorType>;
120 using argon_type = helpers::ArgonFor_t<VectorType>;
121
122 public:
124 ace Lane(VectorType& vec, const int lane) : vec_{vec}, lane_{lane} {}
126 ace argon_type operator=(const scalar_type b) { return vec_ = Set(b); }
129 ace argon_type Load(const scalar_type* ptr) {
130#ifdef ARGON_PLATFORM_MVE
131 return vec_ = Set(*ptr);
132#else
133 return vec_ = argon_type{simd::load1_lane(vec_, lane_, ptr)};
134#endif
135 }
136
137 ace argon_type Set(const scalar_type b) { return argon_type{simd::set_lane(vec_, lane_, b)}; }
139 ace scalar_type Get() const { return simd::get_lane(vec_, lane_); }
141 ace operator scalar_type() const { return Get(); }
142
143#if __ARM_ARCH >= 8
145 ace VectorType vec() { return vec_; }
147 ace const int lane() { return lane_; }
148#else
150 ace neon::Vec64_t<scalar_type> vec() {
151 if constexpr (simd::is_doubleword_v<VectorType>) {
152 return vec_;
153 } else if constexpr (simd::is_quadword_v<VectorType>) {
154 if (lane_ >= ArgonHalf<scalar_type>::lanes) {
155 return simd::get_high(vec_);
156 } else {
157 return simd::get_low(vec_);
158 }
159 }
160 }
161
162 ace int lane() {
163 if constexpr (simd::is_doubleword_v<VectorType>) {
164 return lane_;
165 } else if constexpr (simd::is_quadword_v<VectorType>) {
166 if (lane_ >= ArgonHalf<scalar_type>::lanes) {
167 return (lane_ - ArgonHalf<scalar_type>::lanes);
168 } else {
169 return lane_;
170 }
171 }
172 }
173#endif
174
175 private:
176 VectorType& vec_;
177 int lane_;
178
179 // friend class Vector<VectorType>;
180};
181#endif
182} // namespace argon
Definition argon_half.hpp:11
Represents a single lane of a SIMD vector with the lane index known at compile time.
Definition lane.hpp:46
ace int lane()
On ARM32, return the local lane index within the 64-bit half-register returned by vec().
Definition lane.hpp:95
ace argon_type Set(const scalar_type b)
Set this lane to b and return the updated vector.
Definition lane.hpp:72
ace argon_type operator=(const scalar_type b)
Write a scalar value into this lane and return the updated vector.
Definition lane.hpp:57
ace neon::Vec64_t< scalar_type > vec()
On ARM32, return the 64-bit half-register that contains this lane.
Definition lane.hpp:83
ace ConstLane(VectorType &vec)
Construct a lane accessor bound to vec.
Definition lane.hpp:53
ace scalar_type Get() const
Get the scalar value of this lane.
Definition lane.hpp:74
ace argon_type Load(const scalar_type *ptr)
Load a scalar from ptr into this lane and return the updated vector.
Definition lane.hpp:60
Represents a single lane of a SIMD vector with a runtime-determined index.
Definition lane.hpp:117
ace argon_type Set(const scalar_type b)
Set this lane to b and return the updated vector.
Definition lane.hpp:137
ace argon_type Load(const scalar_type *ptr)
Load a scalar from ptr into this lane and return the updated vector.
Definition lane.hpp:129
ace int lane()
Definition lane.hpp:162
ace Lane(VectorType &vec, const int lane)
Construct a lane accessor bound to vec at runtime index lane.
Definition lane.hpp:124
ace neon::Vec64_t< scalar_type > vec()
Definition lane.hpp:150
ace scalar_type Get() const
Get the scalar value of this lane.
Definition lane.hpp:139
ace argon_type operator=(const scalar_type b)
Write a scalar value into this lane and return the updated vector.
Definition lane.hpp:126
Represents a SIMD vector with various operations.
Definition vector.hpp:50
Header file for SIMD features and platform detection.
typename ArgonFor< std::remove_cv_t< T > >::type ArgonFor_t
Helper alias to get the Argon type for a given vector type.
Definition argon_for.hpp:45