Argon 0.1.0
Loading...
Searching...
No Matches
argon_half.hpp
1#pragma once
2#include "vector.hpp"
3
4#ifndef ARGON_PLATFORM_MVE
5#ifdef __clang__
6#define ace [[gnu::always_inline]] constexpr
7#else
8#define ace [[gnu::always_inline]] inline
9#endif
10template <typename ScalarType>
12
13template <typename ScalarType>
14 requires std::same_as<ScalarType, double> || std::same_as<ScalarType, uint64_t> || std::same_as<ScalarType, int64_t>
15class ArgonHalf<ScalarType> : public argon::Vector<neon::Vec64_t<ScalarType>> {
17
18 public:
19 using vector_type = neon::Vec64_t<ScalarType>;
20 using lane_type = const argon::Lane<vector_type>;
21
22 static_assert(neon::is_doubleword_v<vector_type>);
23
24 static constexpr size_t bytes = 8;
25 static constexpr size_t lanes = bytes / sizeof(ScalarType);
26
27 using T::T;
28 ace ArgonHalf(argon::Vector<vector_type> vec) : T{std::move(vec)} {};
29 ace ArgonHalf(const ArgonHalf&) = default;
30 ace ArgonHalf(ArgonHalf&&) = default;
31 ace ArgonHalf& operator=(const ArgonHalf&) = default;
32 ace ArgonHalf& operator=(ArgonHalf&&) = default;
33
36 ace static ArgonHalf<ScalarType> Create(uint64_t a) { return neon::create<vector_type>(a); }
37
40 template <typename NewScalarType>
41 ace ArgonHalf<NewScalarType> As() const {
42 return neon::reinterpret<neon::Vec64_t<NewScalarType>>(this->vec_);
43 }
44
45 ace ArgonHalf<ScalarType> TableLookup(ArgonHalf<ScalarType> idx) { return neon::table_lookup1(this->vec_, idx); }
46 ace ArgonHalf<ScalarType> TableExtension(ArgonHalf<ScalarType> b, ArgonHalf<ScalarType> idx) {
47 return neon::table_extension1(this->vec_, b, idx);
48 }
49
50 template <size_t NumTables>
51 ace ArgonHalf<ScalarType> TableExtension(std::array<ArgonHalf<ScalarType>, NumTables> b, ArgonHalf<ScalarType> idx) {
52 return TableExtension<NumTables>((vector_type*)b.data(), idx);
53 }
54
55 template <size_t NumTables>
56 ace ArgonHalf<ScalarType> TableExtension(vector_type* b, ArgonHalf<ScalarType> idx) {
57 static_assert(NumTables > 1 && NumTables < 5, "Table Extension can only be performed with 1, 2, 3, or 4 tables");
58
59 using multivec_type = neon::MultiVector_t<vector_type, NumTables>;
60
61 multivec_type multivector = *(multivec_type*)b;
62
63 if constexpr (NumTables == 2) {
64 return neon::table_extension2(this->vec_, multivector, idx);
65 } else if constexpr (NumTables == 3) {
66 return neon::table_extension3(this->vec_, multivector, idx);
67 } else if constexpr (NumTables == 4) {
68 return neon::table_extension4(this->vec_, multivector, idx);
69 }
70 }
71
72 template <typename U>
73 ace ArgonHalf<U> ConvertTo() {
74 return neon::convert<typename neon::Vec64<U>::type>(this->vec_);
75 }
76 template <typename U, int fracbits>
77 requires(std::is_same_v<U, uint32_t> || std::is_same_v<U, int32_t> || std::is_same_v<U, float>)
78 ace ArgonHalf<U> ConvertTo() {
79 if constexpr (std::is_same_v<U, float>) {
80 return neon::convert_n<fracbits>(this->vec_);
81 } else if constexpr (std::is_unsigned_v<U>) {
82 return neon::convert_n_unsigned<fracbits>(this->vec_);
83 } else if constexpr (std::is_signed_v<U>) {
84 return neon::convert_n_signed<fracbits>(this->vec_);
85 }
86 }
87
88 ace Argon<ScalarType> CombineWith(ArgonHalf<ScalarType> high) const { return neon::combine(this->vec_, high); }
89
90 ace ArgonHalf<ScalarType> Reverse() const { return this->Reverse64bit(); }
91};
92
93template <argon::helpers::has_larger ScalarType>
94class ArgonHalf<ScalarType> : public argon::Vector<neon::Vec64_t<ScalarType>> {
95 using T = argon::Vector<neon::Vec64_t<ScalarType>>;
96 using next_larger = typename argon::helpers::NextLarger_t<ScalarType>;
97 using argon_next_larger = Argon<next_larger>;
98
99 public:
100 using vector_type = neon::Vec64_t<ScalarType>;
101 using lane_type = const argon::Lane<vector_type>;
102
103 static_assert(neon::is_doubleword_v<vector_type>);
104
105 static constexpr size_t bytes = 8;
106 static constexpr size_t lanes = bytes / sizeof(ScalarType);
107
108 using T::T;
109
112 ace static ArgonHalf<ScalarType> Create(uint64_t a) { return neon::create<vector_type>(a); }
113
116 template <typename NewScalarType>
117 ace ArgonHalf<NewScalarType> As() const {
118 return neon::reinterpret<neon::Vec64_t<NewScalarType>>(this->vec_);
119 }
120
122 ace argon_next_larger AddLong(ArgonHalf<ScalarType> b) const { return neon::add_long(this->vec_, b); }
123
124 ace argon_next_larger MultiplyLong(ArgonHalf<ScalarType> b) const { return neon::multiply_long(this->vec_, b); }
125
126 ace argon_next_larger MultiplyLong(ScalarType b) const { return neon::multiply_long(this->vec_, b); }
127
128 ace argon_next_larger MultiplyLong(lane_type b) const {
129 return neon::multiply_long_lane(this->vec_, b.vec(), b.lane());
130 }
131
132 ace argon_next_larger MultiplyAddLong(ArgonHalf<ScalarType> b) const {
133 return neon::multiply_add_long(this->vec_, b);
134 }
135
136 ace argon_next_larger MultiplyAddLong(ScalarType b) const { return neon::multiply_add_long(this->vec_, b); }
137
138 ace argon_next_larger MultiplyAddLong(lane_type b) const {
139 return neon::multiply_add_long_lane(this->vec_, b.vec(), b.lane());
140 }
141
142 ace argon_next_larger MultiplyDoubleSaturateLong(ArgonHalf<ScalarType> b) const
143 requires(std::is_same_v<vector_type, int16x4_t> || std::is_same_v<vector_type, int32x2_t>)
144 {
145 return neon::multiply_double_saturate_long(this->vec_, b);
146 }
147
148 ace argon_next_larger MultiplyDoubleSaturateLong(ScalarType b) const
149 requires(std::is_same_v<vector_type, int16x4_t> || std::is_same_v<vector_type, int32x2_t>)
150 {
151 return neon::multiply_double_saturate_long(this->vec_, b);
152 }
153
154 ace argon_next_larger MultiplyDoubleSaturateLong(lane_type b) const
155 requires(std::is_same_v<vector_type, int16x4_t> || std::is_same_v<vector_type, int32x2_t>)
156 {
157 return neon::multiply_double_saturate_long_lane(this->vec_, b.vec(), b.lane());
158 }
159
160 ace argon_next_larger MultiplyDoubleAddSaturateLong(ArgonHalf<ScalarType> b) const
161 requires(std::is_same_v<vector_type, int16x4_t> || std::is_same_v<vector_type, int32x2_t>)
162 {
163 return neon::multiply_double_add_saturate_long(this->vec_, b);
164 }
165
166 ace argon_next_larger MultiplyDoubleAddSaturateLong(ScalarType b) const
167 requires(std::is_same_v<vector_type, int16x4_t> || std::is_same_v<vector_type, int32x2_t>)
168 {
169 return neon::multiply_double_add_saturate_long(this->vec_, b);
170 }
171
172 ace argon_next_larger MultiplyDoubleAddSaturateLong(lane_type b) const
173 requires(std::is_same_v<vector_type, int16x4_t> || std::is_same_v<vector_type, int32x2_t>)
174 {
175 return neon::multiply_double_add_saturate_long_lane(this->vec_, b.vec(), b.lane());
176 }
177
178 ace argon_next_larger SubtractLong(ArgonHalf<ScalarType> b) const { return neon::subtract_long(this->vec_, b); }
179
180 ace argon_next_larger SubtractAbsoluteLong(ArgonHalf<ScalarType> b) const {
181 return neon::subtract_absolute_long(this->vec_, b);
182 }
183
184 ace argon_next_larger PairwiseAddLong() const { return neon::pairwise_add_long(this->vec_); }
185
186 ace argon_next_larger PairwiseAddLong(ArgonHalf<typename argon::helpers::NextSmaller<ScalarType>> b) const {
187 return neon::pairwise_add_long(this->vec_, b);
188 }
189
190 ace argon_next_larger Widen() const { return neon::move_long(this->vec_); }
191
192 template <size_t n>
193 ace argon_next_larger ShiftLeftLong() {
194 return neon::shift_left_long<n>(this->vec_);
195 }
196
197 ace ArgonHalf<ScalarType> TableLookup(ArgonHalf<ScalarType> idx) { return neon::table_lookup1(this->vec_, idx); }
198 ace ArgonHalf<ScalarType> TableExtension(ArgonHalf<ScalarType> b, ArgonHalf<ScalarType> idx) {
199 return neon::table_extension1(this->vec_, b, idx);
200 }
201
202 template <size_t NumTables>
203 ace ArgonHalf<ScalarType> TableExtension(std::array<ArgonHalf<ScalarType>, NumTables> b, ArgonHalf<ScalarType> idx) {
204 return TableExtension<NumTables>((vector_type*)b.data(), idx);
205 }
206
207 template <size_t NumTables>
208 ace ArgonHalf<ScalarType> TableExtension(vector_type* b, ArgonHalf<ScalarType> idx) {
209 static_assert(NumTables > 1 && NumTables < 5, "Table Extension can only be performed with 1, 2, 3, or 4 tables");
210
211 using multivec_type = neon::MultiVector_t<vector_type, NumTables>;
212
213 multivec_type multivector = *(multivec_type*)b;
214
215 if constexpr (NumTables == 2) {
216 return neon::table_extension2(this->vec_, multivector, idx);
217 } else if constexpr (NumTables == 3) {
218 return neon::table_extension3(this->vec_, multivector, idx);
219 } else if constexpr (NumTables == 4) {
220 return neon::table_extension4(this->vec_, multivector, idx);
221 }
222 }
223
224 template <typename U>
225 ace ArgonHalf<U> ConvertTo() {
226 return neon::convert<typename neon::Vec64<U>::type>(this->vec_);
227 }
228
229 template <typename U, int fracbits>
230 requires(std::is_same_v<U, uint32_t> || std::is_same_v<U, int32_t> || std::is_same_v<U, float>)
231 ace ArgonHalf<U> ConvertTo() {
232 if constexpr (std::is_same_v<U, float>) {
233 return neon::convert_n<fracbits>(this->vec_);
234 } else if constexpr (std::is_unsigned_v<U>) {
235 return neon::convert_n_unsigned<fracbits>(this->vec_);
236 } else if constexpr (std::is_signed_v<U>) {
237 return neon::convert_n_signed<fracbits>(this->vec_);
238 }
239 }
240
241 ace Argon<ScalarType> CombineWith(ArgonHalf<ScalarType> high) const { return neon::combine(this->vec_, high); }
242
243 ace ArgonHalf<ScalarType> Reverse() const { return this->Reverse64bit(); }
244};
245
246template <class... ArgTypes>
247 requires(sizeof...(ArgTypes) > 1)
248ArgonHalf(ArgTypes...) -> ArgonHalf<std::tuple_element_t<0, std::tuple<ArgTypes...>>>;
249
250template <typename V>
251 requires std::is_scalar_v<V>
252ace ArgonHalf<V> operator+(const V a, const ArgonHalf<V> b) {
253 return b.Add(a);
254}
255
256template <typename V>
257 requires std::is_scalar_v<V>
258ace ArgonHalf<V> operator-(const V a, const ArgonHalf<V> b) {
259 return ArgonHalf<V>{a}.Subtract(b);
260}
261
262template <typename V>
263 requires std::is_scalar_v<V>
264ace ArgonHalf<V> operator*(const V a, const ArgonHalf<V> b) {
265 return b.Multiply(a);
266}
267
268template <typename V>
269 requires std::is_scalar_v<V>
270ace ArgonHalf<V> operator/(const V a, const ArgonHalf<V> b) {
271 return ArgonHalf<V>{a}.Divide(b);
272}
273
274namespace std {
275template <typename T>
276struct tuple_size<ArgonHalf<T>> {
277 static constexpr size_t value = ArgonHalf<T>::lanes;
278};
279template <size_t Index, typename T>
280struct tuple_element<Index, ArgonHalf<T>> {
281 static_assert(Index < ArgonHalf<T>::lanes);
283};
284} // namespace std
285#endif
286#undef ace
static ace ArgonHalf< ScalarType > Create(uint64_t a)
Create a new ArgonHalf from a raw 64-bit value.
Definition argon_half.hpp:36
ace argon_next_larger AddLong(ArgonHalf< ScalarType > b) const
Add, widening.
Definition argon_half.hpp:122
ace ArgonHalf< NewScalarType > As() const
reinterpret an ArgonHalf to a different type
Definition argon_half.hpp:41
Definition argon_half.hpp:11
Represents a single lane of a SIMD vector.
Definition lane.hpp:102
Represents a SIMD vector with various operations.
Definition vector.hpp:50
constexpr neon::Vec64_t< ScalarType > vec() const
Definition vector.hpp:268
NextLarger< T >::type NextLarger_t
Helper alias to get the next larger type for a given type.
Definition helpers.hpp:75
Lane deconstruction feature.
Definition argon_full.hpp:302