4#ifndef ARGON_PLATFORM_MVE
6#define ace [[gnu::always_inline]] constexpr
8#define ace [[gnu::always_inline]] inline
10template <
typename ScalarType>
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>> {
19 using vector_type = neon::Vec64_t<ScalarType>;
22 static_assert(neon::is_doubleword_v<vector_type>);
24 static constexpr size_t bytes = 8;
25 static constexpr size_t lanes = bytes /
sizeof(ScalarType);
29 ace ArgonHalf(
const ArgonHalf&) =
default;
30 ace ArgonHalf(ArgonHalf&&) =
default;
31 ace ArgonHalf& operator=(
const ArgonHalf&) =
default;
32 ace ArgonHalf& operator=(ArgonHalf&&) =
default;
36 ace
static ArgonHalf<ScalarType>
Create(uint64_t a) {
return neon::create<vector_type>(a); }
40 template <
typename NewScalarType>
41 ace ArgonHalf<NewScalarType>
As()
const {
42 return neon::reinterpret<neon::Vec64_t<NewScalarType>>(this->vec_);
46 ace ArgonHalf<ScalarType> TableExtension(ArgonHalf<ScalarType> b, ArgonHalf<ScalarType> idx) {
47 return neon::table_extension1(this->vec_, b, idx);
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);
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");
59 using multivec_type = neon::MultiVector_t<vector_type, NumTables>;
61 multivec_type multivector = *(multivec_type*)b;
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);
73 ace ArgonHalf<U> ConvertTo() {
74 return neon::convert<typename neon::Vec64<U>::type>(this->vec_);
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_);
88 ace Argon<ScalarType> CombineWith(ArgonHalf<ScalarType> high)
const {
return neon::combine(this->vec_, high); }
90 ace ArgonHalf<ScalarType> Reverse()
const {
return this->Reverse64bit(); }
93template <argon::helpers::has_larger ScalarType>
95 using T = argon::Vector<neon::Vec64_t<ScalarType>>;
97 using argon_next_larger = Argon<next_larger>;
100 using vector_type = neon::Vec64_t<ScalarType>;
101 using lane_type =
const argon::Lane<vector_type>;
103 static_assert(neon::is_doubleword_v<vector_type>);
105 static constexpr size_t bytes = 8;
106 static constexpr size_t lanes = bytes /
sizeof(ScalarType);
112 ace
static ArgonHalf<ScalarType>
Create(uint64_t a) {
return neon::create<vector_type>(a); }
116 template <
typename NewScalarType>
117 ace ArgonHalf<NewScalarType>
As()
const {
118 return neon::reinterpret<neon::Vec64_t<NewScalarType>>(this->vec_);
122 ace argon_next_larger
AddLong(ArgonHalf<ScalarType> b)
const {
return neon::add_long(this->vec_, b); }
124 ace argon_next_larger MultiplyLong(
ArgonHalf<ScalarType> b)
const {
return neon::multiply_long(this->vec_, b); }
126 ace argon_next_larger MultiplyLong(ScalarType b)
const {
return neon::multiply_long(this->vec_, b); }
128 ace argon_next_larger MultiplyLong(lane_type b)
const {
129 return neon::multiply_long_lane(this->vec_, b.vec(), b.lane());
132 ace argon_next_larger MultiplyAddLong(ArgonHalf<ScalarType> b)
const {
133 return neon::multiply_add_long(this->vec_, b);
136 ace argon_next_larger MultiplyAddLong(ScalarType b)
const {
return neon::multiply_add_long(this->vec_, b); }
138 ace argon_next_larger MultiplyAddLong(lane_type b)
const {
139 return neon::multiply_add_long_lane(this->vec_, b.vec(), b.lane());
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>)
145 return neon::multiply_double_saturate_long(this->vec_, b);
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>)
151 return neon::multiply_double_saturate_long(this->vec_, b);
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>)
157 return neon::multiply_double_saturate_long_lane(this->vec_, b.vec(), b.lane());
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>)
163 return neon::multiply_double_add_saturate_long(this->vec_, b);
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>)
169 return neon::multiply_double_add_saturate_long(this->vec_, b);
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>)
175 return neon::multiply_double_add_saturate_long_lane(this->vec_, b.vec(), b.lane());
178 ace argon_next_larger SubtractLong(ArgonHalf<ScalarType> b)
const {
return neon::subtract_long(this->vec_, b); }
180 ace argon_next_larger SubtractAbsoluteLong(ArgonHalf<ScalarType> b)
const {
181 return neon::subtract_absolute_long(this->vec_, b);
184 ace argon_next_larger PairwiseAddLong()
const {
return neon::pairwise_add_long(this->vec_); }
186 ace argon_next_larger PairwiseAddLong(ArgonHalf<
typename argon::helpers::NextSmaller<ScalarType>> b)
const {
187 return neon::pairwise_add_long(this->vec_, b);
190 ace argon_next_larger Widen()
const {
return neon::move_long(this->vec_); }
193 ace argon_next_larger ShiftLeftLong() {
194 return neon::shift_left_long<n>(this->vec_);
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);
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);
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");
211 using multivec_type = neon::MultiVector_t<vector_type, NumTables>;
213 multivec_type multivector = *(multivec_type*)b;
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);
224 template <
typename U>
225 ace ArgonHalf<U> ConvertTo() {
226 return neon::convert<typename neon::Vec64<U>::type>(this->vec_);
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_);
241 ace Argon<ScalarType> CombineWith(ArgonHalf<ScalarType> high)
const {
return neon::combine(this->vec_, high); }
243 ace ArgonHalf<ScalarType> Reverse()
const {
return this->Reverse64bit(); }
246template <
class... ArgTypes>
247 requires(
sizeof...(ArgTypes) > 1)
251 requires std::is_scalar_v<V>
257 requires std::is_scalar_v<V>
263 requires std::is_scalar_v<V>
265 return b.Multiply(a);
269 requires std::is_scalar_v<V>
279template <
size_t Index,
typename T>
281 static_assert(Index < ArgonHalf<T>::lanes);
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