35#ifndef NEKTAR_LIB_LIBUTILITES_SIMDLIB_SVE_H
36#define NEKTAR_LIB_LIBUTILITES_SIMDLIB_SVE_H
38#if defined(__ARM_FEATURE_SVE)
49template <
typename scalarType,
int w
idth = 0>
struct sve
58#if __ARM_FEATURE_SVE_BITS > 0 && defined(NEKTAR_ENABLE_SIMD_SVE)
66typedef svfloat64_t svfloat64_vlst_t
67 __attribute__((arm_sve_vector_bits(__ARM_FEATURE_SVE_BITS)));
68typedef svint64_t svint64_vlst_t
69 __attribute__((arm_sve_vector_bits(__ARM_FEATURE_SVE_BITS)));
70typedef svuint64_t svuint64_vlst_t
71 __attribute__((arm_sve_vector_bits(__ARM_FEATURE_SVE_BITS)));
72typedef svfloat32_t svfloat32_vlst_t
73 __attribute__((arm_sve_vector_bits(__ARM_FEATURE_SVE_BITS)));
74typedef svint32_t svint32_vlst_t
75 __attribute__((arm_sve_vector_bits(__ARM_FEATURE_SVE_BITS)));
76typedef svuint32_t svuint32_vlst_t
77 __attribute__((arm_sve_vector_bits(__ARM_FEATURE_SVE_BITS)));
78typedef svbool_t svbool_vlst_t
79 __attribute__((arm_sve_vector_bits(__ARM_FEATURE_SVE_BITS)));
82template <
typename T>
struct sveInt64;
83template <
typename T>
struct sveInt32;
93template <>
struct sve<double>
95 using type = sveFloat64;
97template <>
struct sve<float>
99 using type = sveFloat32;
105 using type = sveInt64<std::int64_t>;
109 using type = sveInt64<std::uint64_t>;
113 using type = sveInt32<std::int32_t>;
117 using type = sveInt32<std::uint32_t>;
120template <>
struct sve<
std::
int64_t, __ARM_FEATURE_SVE_BITS / 64>
122 using type = sveInt64<std::int64_t>;
124template <>
struct sve<
std::
uint64_t, __ARM_FEATURE_SVE_BITS / 64>
126 using type = sveInt64<std::uint64_t>;
131template <>
struct sve<
std::
int32_t, __ARM_FEATURE_SVE_BITS / 64>
133 using type = sveInt64<std::int64_t>;
135template <>
struct sve<
std::
uint32_t, __ARM_FEATURE_SVE_BITS / 64>
137 using type = sveInt64<std::uint64_t>;
139template <>
struct sve<
std::
int32_t, __ARM_FEATURE_SVE_BITS / 32>
141 using type = sveInt32<std::int32_t>;
143template <>
struct sve<
std::
uint32_t, __ARM_FEATURE_SVE_BITS / 32>
145 using type = sveInt32<std::uint32_t>;
148template <>
struct sve<bool, __ARM_FEATURE_SVE_BITS / 64>
150 using type = sveMask64;
152template <>
struct sve<bool, __ARM_FEATURE_SVE_BITS / 32>
154 using type = sveMask32;
160template <
typename T>
struct sveInt32
162 static_assert(std::is_integral_v<T> &&
sizeof(T) == 4,
163 "4 bytes Integral required.");
165 static constexpr unsigned int alignment =
166 __ARM_FEATURE_SVE_BITS /
sizeof(T);
167 static constexpr unsigned int width = alignment / 8;
169 using scalarType = T;
171 typename std::conditional<std::is_signed_v<T>, svint32_vlst_t,
172 svuint32_vlst_t>::type;
173 using scalarArray = scalarType[width];
179 inline sveInt32() =
default;
180 inline sveInt32(
const sveInt32 &rhs) =
default;
181 inline sveInt32(
const vectorType &rhs) : _data(rhs)
184 inline sveInt32(
const scalarType rhs)
186 _data = svdup_s32(rhs);
188 explicit inline sveInt32(scalarArray &rhs)
190 _data = svld1(svptrue_b32(), rhs);
194 inline void store(scalarType *p)
const
196 svst1(svptrue_b32(), p, _data);
201 template <
typename TAG,
202 typename std::enable_if<is_load_tag_v<TAG>,
bool>::type = 0>
203 inline void store(scalarType *p, TAG)
const
205 svst1(svptrue_b32(), p, _data);
209 inline void load(
const scalarType *p)
211 _data = svld1(svptrue_b32(), p);
216 template <
typename TAG,
217 typename std::enable_if<is_load_tag_v<TAG>,
bool>::type = 0>
218 inline void load(
const scalarType *p, TAG)
220 _data = svld1(svptrue_b32(), p);
224 inline void broadcast(
const scalarType rhs)
232 inline scalarType operator[](
size_t i)
const
234 alignas(alignment) scalarArray tmp;
235 store(tmp, is_aligned);
239 inline scalarType &operator[](
size_t i)
241 scalarType *tmp =
reinterpret_cast<scalarType *
>(&_data);
246 inline void operator+=(sveInt32 rhs)
248 if constexpr (std::is_signed_v<T>)
250 _data = svadd_s32_x(svptrue_b32(), _data, rhs._data);
254 _data = svadd_u32_x(svptrue_b32(), _data, rhs._data);
258 inline void operator-=(sveInt32 rhs)
260 _data = svsub_x(svptrue_b32(), _data, rhs._data);
263 inline void operator*=(sveInt32 rhs)
265 _data = svmul_x(svptrue_b32(), _data, rhs._data);
268 inline void operator/=(sveInt32 rhs)
270 _data = svdiv_x(svptrue_b32(), _data, rhs._data);
275inline sveInt32<T>
operator+(sveInt32<T> lhs, sveInt32<T> rhs)
277 if constexpr (std::is_signed_v<T>)
279 return svadd_s32_x(svptrue_b32(), lhs._data, rhs._data);
283 return svadd_u32_x(svptrue_b32(), lhs._data, rhs._data);
287template <
typename T>
inline sveInt32<T>
operator+(sveInt32<T> lhs, T rhs)
289 if constexpr (std::is_signed_v<T>)
291 return svadd_s32_x(svptrue_b32(), lhs._data, sveInt32<T>(rhs)._data);
295 return svadd_u32_x(svptrue_b32(), lhs._data, sveInt32<T>(rhs)._data);
300inline sveInt32<T>
operator-(sveInt32<T> lhs, sveInt32<T> rhs)
302 return svsub_x(svptrue_b32(), lhs._data, rhs._data);
306inline sveInt32<T>
operator*(sveInt32<T> lhs, sveInt32<T> rhs)
308 return svmul_x(svptrue_b32(), lhs._data, rhs._data);
312inline sveInt32<T>
operator/(sveInt32<T> lhs, sveInt32<T> rhs)
314 return svdiv_x(svptrue_b32(), lhs._data, rhs._data);
317template <
typename T>
inline sveInt32<T>
abs(sveInt32<T> in)
319 return svabs_x(svptrue_b32(), in._data);
324template <
typename T>
struct sveInt64
326 static_assert(std::is_integral_v<T> &&
sizeof(T) == 8,
327 "8 bytes Integral required.");
329 static constexpr unsigned int alignment =
330 __ARM_FEATURE_SVE_BITS /
sizeof(T);
331 static constexpr unsigned int width = alignment / 8;
333 using scalarType = T;
335 typename std::conditional<std::is_signed_v<T>, svint64_vlst_t,
336 svuint64_vlst_t>::type;
337 using scalarArray = scalarType[width];
343 inline sveInt64() =
default;
344 inline sveInt64(
const sveInt64 &rhs) =
default;
345 inline sveInt64(
const vectorType &rhs) : _data(rhs)
348 inline sveInt64(
const scalarType rhs)
350 _data = svdup_s64(rhs);
352 explicit inline sveInt64(scalarArray &rhs)
354 _data = svld1(svptrue_b64(), rhs);
358 inline void store(scalarType *p)
const
360 svst1(svptrue_b64(), p, _data);
365 template <
typename TAG,
366 typename std::enable_if<is_load_tag_v<TAG>,
bool>::type = 0>
367 inline void store(scalarType *p, TAG)
const
369 svst1(svptrue_b64(), p, _data);
373 inline void load(
const scalarType *p)
375 _data = svld1(svptrue_b64(), p);
380 template <
typename TAG,
381 typename std::enable_if<is_load_tag_v<TAG>,
bool>::type = 0>
382 inline void load(
const scalarType *p, TAG)
384 _data = svld1(svptrue_b64(), p);
388 template <
typename I32,
389 typename std::enable_if<std::is_integral_v<I32> &&
390 std::is_signed_v<scalarType> &&
393 inline void load(
const I32 *p)
395 _data = svld1sw_s64(svptrue_b64(), p);
397 template <
typename I32,
398 typename std::enable_if<std::is_integral_v<I32> &&
399 !std::is_signed_v<scalarType> &&
402 inline void load(
const I32 *p)
404 _data = svld1uw_s64(svptrue_b64(), p);
406 template <
typename I32,
typename TAG,
407 typename std::enable_if<
408 is_load_tag_v<TAG> && std::is_integral_v<I32> &&
409 std::is_signed_v<scalarType> &&
sizeof(I32) == 4,
411 inline void load(
const I32 *p, TAG)
413 _data = svld1sw_s64(svptrue_b64(), p);
415 template <
typename I32,
typename TAG,
416 typename std::enable_if<
417 is_load_tag_v<TAG> && std::is_integral_v<I32> &&
418 !std::is_signed_v<scalarType> &&
sizeof(I32) == 4,
420 inline void load(
const I32 *p, TAG)
422 _data = svld1uw_s64(svptrue_b64(), p);
426 inline void broadcast(
const scalarType rhs)
434 inline scalarType operator[](
size_t i)
const
436 alignas(alignment) scalarArray tmp;
437 store(tmp, is_aligned);
442 inline void operator+=(sveInt64 rhs)
444 if constexpr (std::is_signed_v<T>)
446 _data = svadd_s64_x(svptrue_b64(), _data, rhs._data);
450 _data = svadd_u64_x(svptrue_b64(), _data, rhs._data);
454 inline void operator-=(sveInt64 rhs)
456 if constexpr (std::is_signed_v<T>)
458 _data = svsub_s64_x(svptrue_b64(), _data, rhs._data);
462 _data = svsub_u64_x(svptrue_b64(), _data, rhs._data);
466 inline void operator*=(sveInt64 rhs)
468 if constexpr (std::is_signed_v<T>)
470 _data = svmul_s64_x(svptrue_b64(), _data, rhs._data);
474 _data = svmul_u64_x(svptrue_b64(), _data, rhs._data);
478 inline void operator/=(sveInt64 rhs)
480 if constexpr (std::is_signed_v<T>)
482 _data = svdiv_s64_x(svptrue_b64(), _data, rhs._data);
486 _data = svdiv_u64_x(svptrue_b64(), _data, rhs._data);
492inline sveInt64<T>
operator+(sveInt64<T> lhs, sveInt64<T> rhs)
494 if constexpr (std::is_signed_v<T>)
496 return svadd_s64_x(svptrue_b64(), lhs._data, rhs._data);
500 return svadd_u64_x(svptrue_b64(), lhs._data, rhs._data);
504template <
typename T>
inline sveInt64<T>
operator+(sveInt64<T> lhs, T rhs)
506 if constexpr (std::is_signed_v<T>)
508 return svadd_s64_x(svptrue_b64(), lhs._data, sveInt64<T>(rhs)._data);
512 return svadd_u64_x(svptrue_b64(), lhs._data, sveInt64<T>(rhs)._data);
517inline sveInt64<T>
operator-(sveInt64<T> lhs, sveInt64<T> rhs)
519 if constexpr (std::is_signed_v<T>)
521 return svsub_s64_x(svptrue_b64(), lhs._data, rhs._data);
525 return svsub_u64_x(svptrue_b64(), lhs._data, rhs._data);
530inline sveInt64<T>
operator*(sveInt64<T> lhs, sveInt64<T> rhs)
532 if constexpr (std::is_signed_v<T>)
534 return svmul_s64_x(svptrue_b64(), lhs._data, rhs._data);
538 return svmul_u64_x(svptrue_b64(), lhs._data, rhs._data);
543inline sveInt64<T>
operator/(sveInt64<T> lhs, sveInt64<T> rhs)
545 if constexpr (std::is_signed_v<T>)
547 return svdiv_s64_x(svptrue_b64(), lhs._data, rhs._data);
551 return svdiv_u64_x(svptrue_b64(), lhs._data, rhs._data);
555template <
typename T>
inline sveInt64<T>
abs(sveInt64<T> in)
557 if constexpr (std::is_signed_v<T>)
559 return svabs_s64_x(svptrue_b64(), in._data);
563 return svabs_u64_x(svptrue_b64(), in._data);
571 static constexpr unsigned int alignment =
572 __ARM_FEATURE_SVE_BITS /
sizeof(float);
573 static constexpr unsigned int width = alignment / 8;
575 using scalarType = float;
576 using scalarIndexType = std::uint32_t;
577 using vectorType = svfloat32_vlst_t;
578 using scalarArray = scalarType[width];
584 inline sveFloat32() =
default;
585 inline sveFloat32(
const sveFloat32 &rhs) =
default;
586 inline sveFloat32(
const vectorType &rhs) : _data(rhs)
589 inline sveFloat32(
const scalarType rhs)
591 _data = svdup_f32(rhs);
595 inline void store(scalarType *p)
const
597 svst1_f32(svptrue_b32(), p, _data);
602 template <
typename T,
603 typename std::enable_if<is_load_tag_v<T>,
bool>::type = 0>
604 inline void store(scalarType *p, T)
const
606 svst1_f32(svptrue_b32(), p, _data);
610 inline void load(
const scalarType *p)
612 _data = svld1_f32(svptrue_b32(), p);
617 template <
typename T,
618 typename std::enable_if<is_load_tag_v<T>,
bool>::type = 0>
619 inline void load(
const scalarType *p, T)
621 _data = svld1_f32(svptrue_b32(), p);
625 inline void broadcast(
const scalarType rhs)
627 _data = svdup_f32(rhs);
631 template <
typename T>
632 inline void gather(scalarType
const *p,
const sveInt32<T> &indices)
634 if constexpr (std::is_signed_v<T>)
636 _data = svld1_gather_s32index_f32(svptrue_b32(), p, indices._data);
640 _data = svld1_gather_u32index_f32(svptrue_b32(), p, indices._data);
644 template <
typename T>
645 inline void scatter(scalarType *out,
const sveInt32<T> &indices)
const
647 if constexpr (std::is_signed_v<T>)
649 svst1_scatter_s32index_f32(svptrue_b32(), out, indices._data,
654 svst1_scatter_u32index_f32(svptrue_b32(), out, indices._data,
661 inline void fma(
const sveFloat32 &a,
const sveFloat32 &b)
663 _data = svmad_f32_x(svptrue_b32(), a._data, b._data, _data);
669 inline scalarType operator[](
size_t i)
const
671 alignas(alignment) scalarArray tmp;
676 inline scalarType &operator[](
size_t i)
678 scalarType *tmp =
reinterpret_cast<scalarType *
>(&_data);
683 inline void operator+=(sveFloat32 rhs)
685 _data = svadd_f32_x(svptrue_b32(), _data, rhs._data);
688 inline void operator-=(sveFloat32 rhs)
690 _data = svsub_f32_x(svptrue_b32(), _data, rhs._data);
693 inline void operator*=(sveFloat32 rhs)
695 _data = svmul_f32_x(svptrue_b32(), _data, rhs._data);
698 inline void operator/=(sveFloat32 rhs)
700 _data = svdiv_f32_x(svptrue_b32(), _data, rhs._data);
704inline sveFloat32
operator+(sveFloat32 lhs, sveFloat32 rhs)
706 return svadd_f32_x(svptrue_b32(), lhs._data, rhs._data);
709inline sveFloat32
operator-(sveFloat32 lhs, sveFloat32 rhs)
711 return svsub_f32_x(svptrue_b32(), lhs._data, rhs._data);
714inline sveFloat32
operator-(sveFloat32 in)
716 return svsub_f32_x(svptrue_b32(), svdup_f32(-0.0), in._data);
720inline sveFloat32
operator*(sveFloat32 lhs, sveFloat32 rhs)
722 return svmul_f32_x(svptrue_b32(), lhs._data, rhs._data);
725inline sveFloat32
operator/(sveFloat32 lhs, sveFloat32 rhs)
727 return svdiv_f32_x(svptrue_b32(), lhs._data, rhs._data);
730inline sveFloat32
sqrt(sveFloat32 in)
732 return svsqrt_f32_x(svptrue_b32(), in._data);
735inline sveFloat32
abs(sveFloat32 in)
737 return svabs_f32_x(svptrue_b32(), in._data);
740inline sveFloat32
min(sveFloat32 lhs, sveFloat32 rhs)
742 return svmin_f32_x(svptrue_b32(), lhs._data, rhs._data);
745inline sveFloat32
max(sveFloat32 lhs, sveFloat32 rhs)
747 return svmax_f32_x(svptrue_b32(), lhs._data, rhs._data);
750inline sveFloat32
log(sveFloat32 in)
754 alignas(sveFloat32::alignment) sveFloat32::scalarArray tmp;
756 for (
size_t i = 0; i < sveFloat32::width; ++i)
758 tmp[i] = std::log(tmp[i]);
766 const double *in,
const std::uint32_t dataLen,
767 std::vector<sveFloat32, allocator<sveFloat32>> &out)
769 alignas(sveFloat32::alignment) sveFloat32::scalarArray tmp;
770 for (
size_t i = 0; i < dataLen; ++i)
772 for (
size_t j = 0; j < sveFloat32::width; ++j)
774 tmp[j] = in[i + j * dataLen];
781 const double *in,
const std::uint32_t dataLen,
const std::uint32_t nPads,
782 std::vector<sveFloat32, allocator<sveFloat32>> &out)
784 alignas(sveFloat32::alignment) sveFloat32::scalarArray tmp;
785 const size_t nData = sveFloat32::width - nPads;
786 for (
size_t i = 0; i < dataLen; ++i)
788 for (
size_t j = 0; j < nData; ++j)
790 tmp[j] = in[i + j * dataLen];
792 for (
size_t j = nData; j < sveFloat32::width; ++j)
801 std::vector<sveFloat32, allocator<sveFloat32>> &out)
804 alignas(sveFloat32::alignment)
805 sveFloat32::scalarIndexType tmp[sveFloat32::width] = {};
809 for (
size_t i = 0; i < sveFloat32::width; ++i)
811 tmp[i] = i * dataLen;
814 using index_t = sveInt32<sveFloat32::scalarIndexType>;
816 index_t index1 = index0 + 1u;
819 size_t nBlocks = dataLen / 2;
820 for (
size_t i = 0; i < nBlocks; ++i)
822 out[2 * i + 0].gather(in, index0);
823 out[2 * i + 1].gather(in, index1);
824 index0 = index0 + 2u;
825 index1 = index1 + 2u;
829 for (
size_t i = 2 * nBlocks; i < dataLen; ++i)
831 out[i].gather(in, index0);
832 index0 = index0 + 1u;
837 const std::vector<sveFloat32, allocator<sveFloat32>> &in,
838 const std::uint32_t dataLen,
double *out)
840 alignas(sveFloat32::alignment) sveFloat32::scalarArray tmp;
841 for (
size_t i = 0; i < dataLen; ++i)
844 for (
size_t j = 0; j < sveFloat32::width; ++j)
846 out[i + j * dataLen] = tmp[j];
852 const std::vector<sveFloat32, allocator<sveFloat32>> &in,
853 const std::uint32_t dataLen,
const std::uint32_t nPads,
double *out)
855 alignas(sveFloat32::alignment) sveFloat32::scalarArray tmp;
856 const size_t nData = sveFloat32::width - nPads;
857 for (
size_t i = 0; i < dataLen; ++i)
860 for (
size_t j = 0; j < nData; ++j)
862 out[i + j * dataLen] = tmp[j];
868 const std::vector<sveFloat32, allocator<sveFloat32>> &in,
869 std::uint32_t dataLen,
float *out)
871 alignas(sveFloat32::alignment)
872 sveFloat32::scalarIndexType tmp[sveFloat32::width] = {};
876 for (
size_t i = 0; i < sveFloat32::width; ++i)
878 tmp[i] = i * dataLen;
881 using index_t = sveInt32<sveFloat32::scalarIndexType>;
884 for (
size_t i = 0; i < dataLen; ++i)
886 in[i].scatter(out, index0);
887 index0 = index0 + 1u;
895 static constexpr unsigned int alignment =
896 __ARM_FEATURE_SVE_BITS /
sizeof(double);
897 static constexpr unsigned int width = alignment / 8;
899 using scalarType = double;
900 using scalarIndexType = std::uint64_t;
901 using vectorType = svfloat64_vlst_t;
902 using scalarArray = scalarType[width];
908 inline sveFloat64() =
default;
909 inline sveFloat64(
const sveFloat64 &rhs) =
default;
910 inline sveFloat64(
const vectorType &rhs) : _data(rhs)
913 inline sveFloat64(
const scalarType rhs)
915 _data = svdup_f64(rhs);
919 inline void store(scalarType *p)
const
921 svst1_f64(svptrue_b64(), p, _data);
926 template <
typename T,
927 typename std::enable_if<is_load_tag_v<T>,
bool>::type = 0>
928 inline void store(scalarType *p, T)
const
930 svst1_f64(svptrue_b64(), p, _data);
934 inline void load(
const scalarType *p)
936 _data = svld1_f64(svptrue_b64(), p);
941 template <
typename T,
942 typename std::enable_if<is_load_tag_v<T>,
bool>::type = 0>
943 inline void load(
const scalarType *p, T)
945 _data = svld1_f64(svptrue_b64(), p);
949 inline void broadcast(
const scalarType rhs)
951 _data = svdup_f64(rhs);
955 template <
typename T>
956 inline void gather(scalarType
const *p,
const sveInt64<T> &indices)
958 if constexpr (std::is_signed_v<T>)
960 _data = svld1_gather_s64index_f64(svptrue_b64(), p, indices._data);
964 _data = svld1_gather_u64index_f64(svptrue_b64(), p, indices._data);
968 template <
typename T>
969 inline void scatter(scalarType *out,
const sveInt64<T> &indices)
const
971 if constexpr (std::is_signed_v<T>)
973 svst1_scatter_s64index_f64(svptrue_b64(), out, indices._data,
978 svst1_scatter_u64index_f64(svptrue_b64(), out, indices._data,
985 inline void fma(
const sveFloat64 &a,
const sveFloat64 &b)
987 _data = svmad_f64_x(svptrue_b64(), a._data, b._data, _data);
993 inline scalarType operator[](
size_t i)
const
995 alignas(alignment) scalarArray tmp;
996 store(tmp, is_aligned);
1000 inline scalarType &operator[](
size_t i)
1002 scalarType *tmp =
reinterpret_cast<scalarType *
>(&_data);
1007 inline void operator+=(sveFloat64 rhs)
1009 _data = svadd_f64_x(svptrue_b64(), _data, rhs._data);
1012 inline void operator-=(sveFloat64 rhs)
1014 _data = svsub_f64_x(svptrue_b64(), _data, rhs._data);
1017 inline void operator*=(sveFloat64 rhs)
1019 _data = svmul_f64_x(svptrue_b64(), _data, rhs._data);
1022 inline void operator/=(sveFloat64 rhs)
1024 _data = svdiv_f64_x(svptrue_b64(), _data, rhs._data);
1028inline sveFloat64
operator+(sveFloat64 lhs, sveFloat64 rhs)
1030 return svadd_f64_x(svptrue_b64(), lhs._data, rhs._data);
1033inline sveFloat64
operator-(sveFloat64 lhs, sveFloat64 rhs)
1035 return svsub_f64_x(svptrue_b64(), lhs._data, rhs._data);
1038inline sveFloat64
operator-(sveFloat64 in)
1040 return svsub_f64_x(svptrue_b64(), svdup_f64(-0.0), in._data);
1044inline sveFloat64
operator*(sveFloat64 lhs, sveFloat64 rhs)
1046 return svmul_f64_x(svptrue_b64(), lhs._data, rhs._data);
1049inline sveFloat64
operator/(sveFloat64 lhs, sveFloat64 rhs)
1051 return svdiv_f64_x(svptrue_b64(), lhs._data, rhs._data);
1054inline sveFloat64
sqrt(sveFloat64 in)
1056 return svsqrt_f64_x(svptrue_b64(), in._data);
1059inline sveFloat64
abs(sveFloat64 in)
1061 return svabs_f64_x(svptrue_b64(), in._data);
1064inline sveFloat64
min(sveFloat64 lhs, sveFloat64 rhs)
1066 return svmin_f64_x(svptrue_b64(), lhs._data, rhs._data);
1069inline sveFloat64
max(sveFloat64 lhs, sveFloat64 rhs)
1071 return svmax_f64_x(svptrue_b64(), lhs._data, rhs._data);
1074inline sveFloat64
log(sveFloat64 in)
1078 alignas(sveFloat64::alignment) sveFloat64::scalarArray tmp;
1080 for (
size_t i = 0; i < sveFloat64::width; ++i)
1082 tmp[i] = std::log(tmp[i]);
1090 const double *in,
const std::uint32_t dataLen,
1091 std::vector<sveFloat64, allocator<sveFloat64>> &out)
1093 alignas(sveFloat64::alignment) sveFloat64::scalarArray tmp;
1094 for (
size_t i = 0; i < dataLen; ++i)
1096 for (
size_t j = 0; j < sveFloat64::width; ++j)
1098 tmp[j] = in[i + j * dataLen];
1105 const double *in,
const std::uint32_t dataLen,
const std::uint32_t nPads,
1106 std::vector<sveFloat64, allocator<sveFloat64>> &out)
1108 alignas(sveFloat64::alignment) sveFloat64::scalarArray tmp;
1109 const size_t nData = sveFloat64::width - nPads;
1110 for (
size_t i = 0; i < dataLen; ++i)
1112 for (
size_t j = 0; j < nData; ++j)
1114 tmp[j] = in[i + j * dataLen];
1116 for (
size_t j = nData; j < sveFloat64::width; ++j)
1125 std::vector<sveFloat64, allocator<sveFloat64>> &out)
1128 alignas(sveFloat64::alignment)
size_t tmp[sveFloat64::width] = {};
1132 for (
size_t i = 0; i < sveFloat64::width; ++i)
1134 tmp[i] = i * dataLen;
1137 using index_t = sveInt64<size_t>;
1138 index_t index0(tmp);
1139 index_t index1 = index0 + 1ul;
1142 size_t nBlocks = dataLen / 2;
1143 for (
size_t i = 0; i < nBlocks; ++i)
1145 out[2 * i + 0].gather(in, index0);
1146 out[2 * i + 1].gather(in, index1);
1147 index0 = index0 + 2ul;
1148 index1 = index1 + 2ul;
1152 for (
size_t i = 2 * nBlocks; i < dataLen; ++i)
1154 out[i].gather(in, index0);
1155 index0 = index0 + 1ul;
1160 const std::vector<sveFloat64, allocator<sveFloat64>> &in,
1161 const std::uint32_t dataLen,
double *out)
1163 alignas(sveFloat64::alignment) sveFloat64::scalarArray tmp;
1164 for (
size_t i = 0; i < dataLen; ++i)
1167 for (
size_t j = 0; j < sveFloat64::width; ++j)
1169 out[i + j * dataLen] = tmp[j];
1175 const std::vector<sveFloat64, allocator<sveFloat64>> &in,
1176 const std::uint32_t dataLen,
const std::uint32_t nPads,
double *out)
1178 alignas(sveFloat64::alignment) sveFloat64::scalarArray tmp;
1179 const size_t nData = sveFloat64::width - nPads;
1180 for (
size_t i = 0; i < dataLen; ++i)
1183 for (
size_t j = 0; j < nData; ++j)
1185 out[i + j * dataLen] = tmp[j];
1191 const std::vector<sveFloat64, allocator<sveFloat64>> &in,
1192 std::uint32_t dataLen,
double *out)
1194 alignas(sveFloat64::alignment)
size_t tmp[sveFloat64::width] = {};
1198 for (
size_t i = 0; i < sveFloat64::width; ++i)
1200 tmp[i] = i * dataLen;
1203 using index_t = sveInt64<size_t>;
1204 index_t index0(tmp);
1206 for (
size_t i = 0; i < dataLen; ++i)
1208 in[i].scatter(out, index0);
1209 index0 = index0 + 1ul;
1222struct sveMask64 : sveInt64<std::uint64_t>
1225 using sveInt64::sveInt64;
1227 static constexpr scalarType true_v = -1;
1228 static constexpr scalarType false_v = 0;
1231inline sveMask64
operator>(sveFloat64 lhs, sveFloat64 rhs)
1234 svbool_vlst_t mask = svcmpgt(svptrue_b64(), lhs._data, rhs._data);
1236 sveMask64::vectorType sveTrue_v = svdup_u64(sveMask64::true_v);
1237 return svand_u64_z(mask, sveTrue_v, sveTrue_v);
1241inline bool operator&&(sveMask64 lhs,
bool rhs)
1244 sveMask64::vectorType sveFalse_v = svdup_u64(sveMask64::false_v);
1245 svbool_vlst_t mask = svcmpne_u64(svptrue_b64(), lhs._data, sveFalse_v);
1247 bool tmp = svptest_any(svptrue_b64(), mask);
1253struct sveMask32 : sveInt32<std::uint32_t>
1256 using sveInt32::sveInt32;
1258 static constexpr scalarType true_v = -1;
1259 static constexpr scalarType false_v = 0;
1262inline sveMask32
operator>(sveFloat32 lhs, sveFloat32 rhs)
1265 svbool_vlst_t mask = svcmpgt(svptrue_b32(), lhs._data, rhs._data);
1267 sveMask32::vectorType sveTrue_v = svdup_u32(sveMask32::true_v);
1268 return svand_u32_z(mask, sveTrue_v, sveTrue_v);
1272inline bool operator&&(sveMask32 lhs,
bool rhs)
1275 sveMask32::vectorType sveFalse_v = svdup_u32(sveMask32::false_v);
1276 svbool_vlst_t mask = svcmpne_u32(svptrue_b32(), lhs._data, sveFalse_v);
1278 bool tmp = svptest_any(svptrue_b32(), mask);
void load_interleave(const T *in, const size_t dataLen, std::vector< scalarT< T >, allocator< scalarT< T > > > &out)
scalarT< T > abs(scalarT< T > in)
void deinterleave_unalign_store(const std::vector< scalarT< T >, allocator< scalarT< T > > > &in, const size_t dataLen, T *out)
static constexpr struct tinysimd::is_aligned_t is_aligned
scalarT< T > operator-(scalarT< T > lhs, scalarT< T > rhs)
scalarT< T > operator/(scalarT< T > lhs, scalarT< T > rhs)
scalarT< T > max(scalarT< T > lhs, scalarT< T > rhs)
scalarT< T > log(scalarT< T > in)
scalarT< T > operator*(scalarT< T > lhs, scalarT< T > rhs)
scalarMask operator>(scalarT< double > lhs, scalarT< double > rhs)
bool operator&&(scalarMask lhs, bool rhs)
void load_unalign_interleave(const T *in, const size_t dataLen, std::vector< scalarT< T >, allocator< scalarT< T > > > &out)
void deinterleave_store(const std::vector< scalarT< T >, allocator< scalarT< T > > > &in, const size_t dataLen, T *out)
scalarT< T > min(scalarT< T > lhs, scalarT< T > rhs)
void deinterleave_unalign_store_skipPads(const std::vector< scalarT< T >, allocator< scalarT< T > > > &in, const size_t dataLen, const size_t skipPads, T *out)
scalarT< T > sqrt(scalarT< T > in)
void load_unalign_interleave_skipPads(const T *in, const size_t dataLen, const size_t skipPads, std::vector< scalarT< T >, allocator< scalarT< T > > > &out)
scalarT< T > operator+(scalarT< T > lhs, scalarT< T > rhs)