128#ifndef CXXUTILS_VEC_H
129#define CXXUTILS_VEC_H
135#include <type_traits>
142#ifndef WANT_VECTOR_FALLBACK
143# define WANT_VECTOR_FALLBACK 0
146#if (!HAVE_VECTOR_SIZE_ATTRIBUTE) || WANT_VECTOR_FALLBACK!=0
158template <
typename T,
size_t N>
160 static_assert((N & (N - 1)) == 0,
"N must be a power of 2.");
161 static_assert(std::is_arithmetic_v<T>,
"T not an arithmetic type");
163#if HAVE_VECTOR_SIZE_ATTRIBUTE
175 static auto elt(
const VEC& v) ->
decltype(v[0]);
177 typedef std::remove_cv_t<std::remove_reference_t<type1>>
type;
186 static auto maskt(
const VEC& v1,
const VEC& v2) ->
decltype(v1 < v2);
188 typedef std::remove_cv_t<std::remove_reference_t<type1>>
type;
206template <
typename T,
size_t N>
230 return sizeof(VEC) /
sizeof(ELT);
242 return sizeof(VEC) /
sizeof(ELT);
248template<
typename VEC,
typename T>
253#if !HAVE_VECTOR_SIZE_ATTRIBUTE || WANT_VECTOR_FALLBACK
255 for (
size_t i = 0; i < N; ++i) {
269template<
typename VEC>
275#if !HAVE_VECTOR_SIZE_ATTRIBUTE || WANT_VECTOR_FALLBACK
276 std::memcpy(dst.m_arr, src,
sizeof(VEC));
278 std::memcpy(&dst, src,
sizeof(VEC));
287template<
typename VEC>
292#if !HAVE_VECTOR_SIZE_ATTRIBUTE || WANT_VECTOR_FALLBACK
293 std::memcpy(dst, src.m_arr,
sizeof(VEC));
295 std::memcpy(dst, &src,
sizeof(VEC));
304template <
typename VEC>
307#if !HAVE_VECTOR_SIZE_ATTRIBUTE || WANT_VECTOR_FALLBACK
309 for (
size_t i = 0; i < N; ++i) {
310 dst[i] = mask[i] ?
a[i] : b[i];
321template<
typename VEC>
324vmin(VEC& dst,
const VEC&
a,
const VEC& b)
326#if !HAVE_VECTOR_SIZE_ATTRIBUTE || WANT_VECTOR_FALLBACK
328 for (
size_t i = 0; i < N; ++i) {
329 dst[i] =
a[i] < b[i] ?
a[i] : b[i];
340template<
typename VEC>
343vmax(VEC& dst,
const VEC&
a,
const VEC& b)
345#if !HAVE_VECTOR_SIZE_ATTRIBUTE || WANT_VECTOR_FALLBACK
347 for (
size_t i = 0; i < N; ++i) {
348 dst[i] =
a[i] > b[i] ?
a[i] : b[i];
359template<
typename VEC>
363 static_assert(std::is_integral<vec_type_t<VEC>>::value,
364 "vec elements must be of integral type. Aka vec must be "
365 "compatible with a mask");
368#if !HAVE_VECTOR_SIZE_ATTRIBUTE || WANT_VECTOR_FALLBACK
369 return std::memcmp(mask.m_arr,
zero.m_arr,
sizeof(VEC)) != 0;
371 return std::memcmp(&mask, &
zero,
sizeof(VEC)) != 0;
379template<
typename VEC>
383 static_assert(std::is_integral<vec_type_t<VEC>>::value,
384 "vec elements must be of integral type. Aka vec must be "
385 "compatible with a mask");
388#if !HAVE_VECTOR_SIZE_ATTRIBUTE || WANT_VECTOR_FALLBACK
389 return std::memcmp(mask.m_arr,
zero.m_arr,
sizeof(VEC)) == 0;
391 return std::memcmp(&mask, &
zero,
sizeof(VEC)) == 0;
399template<
typename VEC>
403 static_assert(std::is_integral<vec_type_t<VEC>>::value,
404 "vec elements must be of integral type. Aka vec must be "
405 "compatible with a mask");
407#if !HAVE_VECTOR_SIZE_ATTRIBUTE || WANT_VECTOR_FALLBACK
411 return std::memcmp(mask.m_arr, alltrue.m_arr,
sizeof(VEC)) == 0;
417 return std::memcmp(&mask, &alltrue,
sizeof(VEC)) == 0;
425template<
typename VEC1,
typename VEC2>
431 "vconvert dst and src have different number of elements");
433#if !HAVE_CONVERT_VECTOR || WANT_VECTOR_FALLBACK
436 for (
size_t i = 0; i < N; ++i) {
437 dst[i] =
static_cast<ELT
>(src[i]);
440 dst = __builtin_convertvector(src, VEC1);
449template<
size_t... Indices,
typename VEC,
typename VEC1>
455 "vpermute number of indices different than return vector size");
457 "vpermute type of input and output vector elements differ");
459 Indices >= 0 && Indices < vec_size<VEC>())...>::value,
460 "vpermute value of a mask index is outside the allowed range");
462#if !HAVE_VECTOR_SIZE_ATTRIBUTE || WANT_VECTOR_FALLBACK
463 dst = VEC1{ src[Indices]... };
465 dst = __builtin_shufflevector(src, src, Indices...);
474template<
size_t... Indices,
typename VEC,
typename VEC1>
480 "vpermute2 number of indices different than return vector size");
482 "vpermute2 type of input and output vector elements differ");
485 Indices >= 0 && Indices < 2 * N)...>::value,
486 "vpermute2 value of a mask index is outside the allowed range");
488#if !HAVE_VECTOR_SIZE_ATTRIBUTE || WANT_VECTOR_FALLBACK
491 for (
auto index: { Indices... }) {
493 tmp[pos] = src1[
index];
495 tmp[pos] = src2[
index - N];
501 dst = __builtin_shufflevector(src1, src2, Indices...);
__attribute__((always_inline)) inline uint16_t TileCalibDrawerBase
void zero(TH2 *h)
zero the contents of a 2d histogram
Some additional feature test macros.
#define ATH_ALWAYS_INLINE
Helper for static asserts for argument packs.
std::is_same< bool_pack< bs..., true >, bool_pack< true, bs... > > all_true
ATH_ALWAYS_INLINE constexpr size_t vec_size()
Return the number of elements in a vectorized type.
typename vecDetail::vec_typedef< T, N >::type vec
Define a nice alias for the vectorized type.
ATH_ALWAYS_INLINE void vmax(VEC &dst, const VEC &a, const VEC &b)
ATH_ALWAYS_INLINE void vconvert(VEC1 &dst, const VEC2 &src)
performs dst is the result of a static cast of each element of src
ATH_ALWAYS_INLINE void vselect(VEC &dst, const VEC &a, const VEC &b, const vec_mask_type_t< VEC > &mask)
ATH_ALWAYS_INLINE bool vany(const VEC &mask)
typename vecDetail::vec_mask_type< VEC >::type vec_mask_type_t
Define a nice alias for the mask type for a vectorized type.
ATH_ALWAYS_INLINE bool vnone(const VEC &mask)
ATH_ALWAYS_INLINE void vstore(vec_type_t< VEC > *dst, const VEC &src)
ATH_ALWAYS_INLINE bool vall(const VEC &mask)
ATH_ALWAYS_INLINE void vmin(VEC &dst, const VEC &a, const VEC &b)
ATH_ALWAYS_INLINE void vpermute(VEC1 &dst, const VEC &src)
vpermute function.
typename vecDetail::vec_type< VEC >::type vec_type_t
Define a nice alias for the element type of a vectorized type.
ATH_ALWAYS_INLINE void vbroadcast(VEC &v, T x)
Copy a scalar to each element of a vectorized type.
ATH_ALWAYS_INLINE void vload(VEC &dst, vec_type_t< VEC > const *src)
ATH_ALWAYS_INLINE void vpermute2(VEC1 &dst, const VEC &src1, const VEC &src2)
vpermute2 function.
Deduce the type of the mask returned by relational operations, for a vectorized type.
static auto maskt(const VEC &v1, const VEC &v2) -> decltype(v1< v2)
std::remove_cv_t< std::remove_reference_t< type1 > > type
std::invoke_result< decltype(maskt), constVEC &, constVEC & >::type type1
Deduce the element type from a vectorized type.
std::invoke_result< decltype(elt), constVEC & >::type type1
std::remove_cv_t< std::remove_reference_t< type1 > > type
static auto elt(const VEC &v) -> decltype(v[0])
check the type and the size of the vector.
Fallback vectorized class.