28 using vector_type = simd::Vec128_t<ScalarType>;
31 static_assert(simd::is_quadword_v<vector_type>);
33 static constexpr size_t bytes = 16;
34 static constexpr size_t lanes = bytes /
sizeof(ScalarType);
38 ace Argon(std::array<ScalarType, 4> value_list) : T{
T::Load(value_list.data())} {};
41#ifndef ARGON_PLATFORM_MVE
46 template <simd::is_vector_type
intrinsic_type>
49 template <
typename new_scalar_type>
50 ace Argon<new_scalar_type> As()
const {
51 return simd::reinterpret<simd::Vec128_t<new_scalar_type>>(this->vec_);
54#ifndef ARGON_PLATFORM_MVE
56 return simd::combine(low, high);
59 ace Argon<ScalarType> Reverse() {
60 auto rev_half = this->Reverse64bit();
61 return Combine(rev_half.GetHigh(), rev_half.GetLow());
66 std::is_same_v<U, typename argon::helpers::NextSmaller<ScalarType>::type>
68 return simd::multiply_add_long(this->vec_, b, c);
70 template <
typename U,
typename C>
72 std::is_same_v<C, simd::Vec64_t<argon::helpers::NextSmaller_t<ScalarType>>>
73 ace Argon<ScalarType> MultiplyAddLong(
ArgonHalf<U> b, C c) {
74 return simd::multiply_add_long(this->vec_, b, c);
79 std::is_same_v<U, typename argon::helpers::NextSmaller<ScalarType>::type>
80 ace Argon<ScalarType> MultiplyAddLong(
ArgonHalf<U> b, U c) {
81 return simd::multiply_add_long(this->vec_, b, c);
86 std::is_same_v<U, typename argon::helpers::NextSmaller<ScalarType>::type>
88 return simd::multiply_add_long(this->vec_, b, c.vec(), c.lane());
93 std::is_same_v<U, typename argon::helpers::NextSmaller<ScalarType>::type>
95 return simd::multiply_subtract_long(this->vec_, b, c);
100 std::is_same_v<U, typename argon::helpers::NextSmaller<ScalarType>::type>
101 ace Argon<ScalarType> MultiplySubtractLong(
ArgonHalf<U> b, U c) {
102 return simd::multiply_subtract_long(this->vec_, b, c);
105 template <
typename U>
107 std::is_same_v<U, typename argon::helpers::NextSmaller<ScalarType>::type>
109 return simd::multiply_subtract_long(this->vec_, b, c.vec(), c.lane());
112 ace
auto AddNarrow(Argon<ScalarType> b)
const
115 auto result = simd::add_narrow(this->vec_, b);
119 ace
auto AddRoundNarrow(Argon<ScalarType> b)
const
122 auto result = simd::add_round_narrow(this->vec_, b);
126 ace
auto SubtractNarrow(Argon<ScalarType> b)
const
129 auto result = simd::subtract_narrow(this->vec_, b);
133 ace
auto SubtractRoundNarrow(Argon<ScalarType> b)
const
136 auto result = simd::subtract_round_narrow(this->vec_, b);
142 ace
auto ShiftRightNarrow()
const {
143 auto result = simd::shift_right_narrow<n>(this->vec_);
149 ace
auto ShiftRightSaturateNarrow()
const {
150 auto result = simd::shift_right_saturate_narrow<n>(this->vec_);
156 ace
auto ShiftRightRoundSaturateNarrow()
const {
157 auto result = simd::shift_right_round_saturate_narrow<n>(this->vec_);
163 ace
auto ShiftRightRoundNarrow()
const {
164 auto result = simd::shift_right_round_narrow<n>(this->vec_);
168 ace
auto Narrow()
const
171 auto result = simd::move_narrow(this->vec_);
175 ace
auto SaturateNarrow()
const
178 auto result = simd::move_saturate_narrow(this->vec_);
182 template <
typename NextSmallerType>
184 std::is_same_v<NextSmallerType, argon::helpers::NextSmaller_t<ScalarType>>
186 return neon::multiply_double_add_saturate_long(this->vec_, b, c);
193 template <
typename U>
194 ace Argon<U> ConvertTo()
const {
195 return simd::convert<typename simd::Vec128<U>::type>(this->vec_);
198 template <
typename U,
int fracbits>
199 requires(std::is_same_v<U, uint32_t> || std::is_same_v<U, int32_t> || std::is_same_v<U, float>)
200 ace Argon<U> ConvertTo()
const {
201 if constexpr (std::is_same_v<U, float>) {
202 return simd::convert_n<fracbits>(this->vec_);
203 }
else if constexpr (std::is_unsigned_v<U>) {
204 return simd::convert_n_unsigned<fracbits>(this->vec_);
205 }
else if constexpr (std::is_signed_v<U>) {
206 return simd::convert_n_signed<fracbits>(this->vec_);
210 ace Argon<ScalarType> Reverse()
const {
211 Argon<ScalarType> rev = this->Reverse64bit();
212 return Argon{rev.GetHigh(), rev.GetLow()};
215 template <
typename CommutableOpType>
216 ScalarType Reduce(CommutableOpType op) {
217 auto rev = this->SwapDoublewords();
218 auto sum = op(*
this, rev);
219 if constexpr (lanes == 16) {
220 sum = op(*
this, sum.Reverse16bit());
222 if constexpr (lanes == 8 || lanes == 16) {
223 sum = op(*
this, sum.Reverse32bit());
225 if constexpr (lanes == 4 || lanes == 8 || lanes == 16) {
226 sum = op(*
this, sum.Reverse64bit());
231 ScalarType ReduceAdd() {
233 return simd::reduce_add(this->vec_);
235 return this->Reduce([](
auto a,
auto b) {
return a + b; });
239 ScalarType ReduceMax() {
241 return simd::reduce_max(this->vec_);
243 return this->Reduce([](
auto a,
auto b) {
return std::max(a, b); });
247 ScalarType ReduceMin() {
249 return simd::reduce_min(this->vec_);
252 return std::reduce(arr.begin(), arr.end(), arr[0], [](
auto a,
auto b) { return std::min(a, b); });
256#ifndef ARGON_PLATFORM_MVE
257 ace Argon<ScalarType> SwapDoublewords() {
return Combine(GetHigh(), GetLow()); }