ATLAS Offline Software
vec.h
Go to the documentation of this file.
1 // This file's extension implies that it's C, but it's really -*- C++ -*-.
2 /*
3  * Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration.
4  */
128 #ifndef CXXUTILS_VEC_H
129 #define CXXUTILS_VEC_H
130 
131 #include "CxxUtils/features.h"
132 #include "CxxUtils/inline_hints.h"
133 #include <cstdlib>
134 #include <cstring>
135 #include <type_traits>
136 
137 
138 // Define @c WANT_VECTOR_FALLBACK prior to including this file to
139 // make the fallback class @c vec_fb visible, even if we support the
140 // built-in type.
141 // Intended for testing.
142 #ifndef WANT_VECTOR_FALLBACK
143 # define WANT_VECTOR_FALLBACK 0
144 #endif
145 
146 #if (!HAVE_VECTOR_SIZE_ATTRIBUTE) || WANT_VECTOR_FALLBACK!=0
147 #include "CxxUtils/vec_fb.h"
148 #endif // !HAVE_VECTOR_SIZE_ATTRIBUTE || WANT_VECTOR_FALLBACK
149 
150 namespace CxxUtils {
151 
152 namespace vecDetail {
158 template <typename T, size_t N>
159 struct vec_typedef {
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");
162 
163 #if HAVE_VECTOR_SIZE_ATTRIBUTE
164  using type __attribute__((vector_size(N * sizeof(T)))) = T;
165 #else
166  using type vec_fb<T, N>;
167 #endif
168 };
169 
173 template <class VEC>
174 struct vec_type {
175  static auto elt(const VEC& v) -> decltype(v[0]);
176  typedef typename std::invoke_result<decltype(elt), const VEC&>::type type1;
177  typedef std::remove_cv_t<std::remove_reference_t<type1>> type;
178 };
179 
184 template <class VEC>
186  static auto maskt(const VEC& v1, const VEC& v2) -> decltype(v1 < v2);
187  typedef typename std::invoke_result<decltype(maskt), const VEC&, const VEC&>::type type1;
188  typedef std::remove_cv_t<std::remove_reference_t<type1>> type;
189 };
190 
194 namespace bool_pack_helper {
195 template <bool...>
196 struct bool_pack;
197 template <bool... bs>
198 using all_true = std::is_same<bool_pack<bs..., true>, bool_pack<true, bs...>>;
199 } // namespace bool_pack_helper
200 
201 } // namespace vecDetail
202 
206 template <typename T, size_t N>
208 
212 template<class VEC>
214 
218 template<class VEC>
220 
224 template<class VEC>
226 constexpr size_t
228 {
229  typedef vec_type_t<VEC> ELT;
230  return sizeof(VEC) / sizeof(ELT);
231 }
232 
236 template<class VEC>
238 constexpr size_t
239 vec_size(const VEC&)
240 {
241  typedef vec_type_t<VEC> ELT;
242  return sizeof(VEC) / sizeof(ELT);
243 }
244 
248 template<typename VEC, typename T>
250 void
251 vbroadcast(VEC& v, T x)
252 {
253 #if !HAVE_VECTOR_SIZE_ATTRIBUTE || WANT_VECTOR_FALLBACK
254  constexpr size_t N = CxxUtils::vec_size<VEC>();
255  for (size_t i = 0; i < N; ++i) {
256  v[i] = x;
257  }
258 #else
259  // using - to avoid sign conversions.
260  v = x - VEC{ 0 };
261 #endif
262 }
263 
264 /*
265  * @brief load elements from memory address src (C-array)
266  * to a vectorized type dst.
267  * Used memcpy to avoid alignment issues
268  */
269 template<typename VEC>
271 void
272 vload(VEC& dst, vec_type_t<VEC> const* src)
273 {
274  std::memcpy(&dst, src, sizeof(VEC));
275 }
276 
277 /*
278  * @brief store elements from a vectorized type src to
279  * to a memory address dst (C-array).
280  * Uses memcpy to avoid alignment issues
281  */
282 template<typename VEC>
284 void
285 vstore(vec_type_t<VEC>* dst, const VEC& src)
286 {
287  std::memcpy(dst, &src, sizeof(VEC));
288 }
289 
290 /*
291  * @brief select elements based on a mask
292  * Fill dst according to
293  * dst[i] = mask[i] ? a[i] : b[i]
294  */
295 template <typename VEC>
297 void vselect(VEC& dst, const VEC& a, const VEC& b, const vec_mask_type_t<VEC>& mask) {
298 #if !HAVE_VECTOR_SIZE_ATTRIBUTE || WANT_VECTOR_FALLBACK
299  constexpr size_t N = vec_size<VEC>();
300  for (size_t i = 0; i < N; ++i) {
301  dst[i] = mask[i] ? a[i] : b[i];
302  }
303 #else
304  dst = mask ? a : b;
305 #endif
306 }
307 
308 /*
309  * @brief vectorized min.
310  * copies to @c dst[i] the min(a[i],b[i])
311  */
312 template<typename VEC>
314 void
315 vmin(VEC& dst, const VEC& a, const VEC& b)
316 {
317 #if !HAVE_VECTOR_SIZE_ATTRIBUTE || WANT_VECTOR_FALLBACK
318  constexpr size_t N = vec_size<VEC>();
319  for (size_t i = 0; i < N; ++i) {
320  dst[i] = a[i] < b[i] ? a[i] : b[i];
321  }
322 #else
323  dst = a < b ? a : b;
324 #endif
325 }
326 
327 /*
328  * @brief vectorized max.
329  * copies to @c dst[i] the max(a[i],b[i])
330  */
331 template<typename VEC>
333 void
334 vmax(VEC& dst, const VEC& a, const VEC& b)
335 {
336 #if !HAVE_VECTOR_SIZE_ATTRIBUTE || WANT_VECTOR_FALLBACK
337  constexpr size_t N = vec_size<VEC>();
338  for (size_t i = 0; i < N; ++i) {
339  dst[i] = a[i] > b[i] ? a[i] : b[i];
340  }
341 #else
342  dst = a > b ? a : b;
343 #endif
344 }
345 
346 /*
347  * @brief Returns true if at least
348  * one value in mask is true.
349  */
350 template<typename VEC>
352 bool
353 vany(const VEC& mask){
354  static_assert(std::is_integral<vec_type_t<VEC>>::value,
355  "vec elements must be of integral type. Aka vec must be "
356  "compatible with a mask");
357  VEC zero;
359  return std::memcmp(&mask, &zero, sizeof(VEC)) != 0;
360 }
361 
362 /*
363  * @brief Returns true if
364  * all values in mask are false
365  */
366 template<typename VEC>
368 bool
369 vnone(const VEC& mask){
370  static_assert(std::is_integral<vec_type_t<VEC>>::value,
371  "vec elements must be of integral type. Aka vec must be "
372  "compatible with a mask");
373  VEC zero;
375  return std::memcmp(&mask, &zero, sizeof(VEC)) == 0;
376 }
377 
378 /*
379  * @brief Returns true if
380  * all values in mask are false
381  */
382 template<typename VEC>
384 bool
385 vall(const VEC& mask){
386  static_assert(std::is_integral<vec_type_t<VEC>>::value,
387  "vec elements must be of integral type. Aka vec must be "
388  "compatible with a mask");
389  VEC alltrue;
390 #if !HAVE_VECTOR_SIZE_ATTRIBUTE || WANT_VECTOR_FALLBACK
391  // fallback compares to 0 when false
392  // and 1 when is true
393  vbroadcast(alltrue, vec_type_t<VEC>{1});
394 #else
395  // For the gnu vector extensions
396  // Vectors are compared element-wise producing 0 when comparison is false
397  // and -1 (constant of the appropriate type where all bits are set) otherwise.
398  vbroadcast(alltrue, vec_type_t<VEC>{-1});
399 #endif
400  return std::memcmp(&mask, &alltrue, sizeof(VEC)) == 0;
401 }
402 
403 
404 template<typename VEC1, typename VEC2>
406 void
407 vconvert(VEC1& dst, const VEC2& src)
408 {
409  static_assert((vec_size<VEC1>() == vec_size<VEC2>()),
410  "vconvert dst and src have different number of elements");
411 
412 #if !HAVE_CONVERT_VECTOR || WANT_VECTOR_FALLBACK
413  typedef vec_type_t<VEC1> ELT;
414  constexpr size_t N = vec_size<VEC1>();
415  for (size_t i = 0; i < N; ++i) {
416  dst[i] = static_cast<ELT>(src[i]);
417  }
418 #else
419  dst = __builtin_convertvector(src, VEC1);
420 #endif
421 }
422 
428 template<size_t... Indices, typename VEC, typename VEC1>
430 vpermute(VEC1& dst, const VEC& src)
431 {
432 
433  static_assert((sizeof...(Indices) == vec_size<VEC1>()),
434  "vpermute number of indices different than return vector size");
435  static_assert(std::is_same<vec_type_t<VEC>, vec_type_t<VEC1>>::value,
436  "vpermute type of input and output vector elements differ");
438  Indices >= 0 && Indices < vec_size<VEC>())...>::value,
439  "vpermute value of a mask index is outside the allowed range");
440 
441 #if !HAVE_VECTOR_SIZE_ATTRIBUTE || WANT_VECTOR_FALLBACK
442  dst = VEC1{ src[Indices]... };
443 #else
444  dst = __builtin_shufflevector(src, src, Indices...);
445 #endif
446 }
447 
453 template<size_t... Indices, typename VEC, typename VEC1>
455 vpermute2(VEC1& dst, const VEC& src1, const VEC& src2)
456 {
457  static_assert(
458  (sizeof...(Indices) == vec_size<VEC1>()),
459  "vpermute2 number of indices different than return vector size");
460  static_assert(std::is_same<vec_type_t<VEC>, vec_type_t<VEC1>>::value,
461  "vpermute2 type of input and output vector elements differ");
462  constexpr size_t N = vec_size<VEC>();
464  Indices >= 0 && Indices < 2 * N)...>::value,
465  "vpermute2 value of a mask index is outside the allowed range");
466 
467 #if !HAVE_VECTOR_SIZE_ATTRIBUTE || WANT_VECTOR_FALLBACK
468  VEC1 tmp;
469  size_t pos{0};
470  for (auto index: { Indices... }) {
471  if (index < N) {
472  tmp[pos] = src1[index];
473  } else {
474  tmp[pos] = src2[index - N];
475  }
476  ++pos;
477  }
478  dst = tmp;
479 #else
480  dst = __builtin_shufflevector(src1, src2, Indices...);
481 #endif
482 }
483 
484 } // namespace CxxUtils
485 
486 #endif // not CXXUTILS_VEC_H
features.h
Some additional feature test macros.
inline_hints.h
CxxUtils::vnone
ATH_ALWAYS_INLINE bool vnone(const VEC &mask)
Definition: vec.h:369
CxxUtils::vmax
ATH_ALWAYS_INLINE void vmax(VEC &dst, const VEC &a, const VEC &b)
Definition: vec.h:334
WriteCellNoiseToCool.src
src
Definition: WriteCellNoiseToCool.py:513
index
Definition: index.py:1
CxxUtils::vec_size
constexpr ATH_ALWAYS_INLINE size_t vec_size()
Return the number of elements in a vectorized type.
Definition: vec.h:227
CxxUtils::vecDetail::vec_type
Deduce the element type from a vectorized type.
Definition: vec.h:174
CxxUtils::vpermute
ATH_ALWAYS_INLINE void vpermute(VEC1 &dst, const VEC &src)
vpermute function.
Definition: vec.h:430
ATH_ALWAYS_INLINE
#define ATH_ALWAYS_INLINE
Definition: inline_hints.h:53
athena.value
value
Definition: athena.py:122
JetTiledMap::N
@ N
Definition: TiledEtaPhiMap.h:44
CxxUtils::vec_fb
Definition: vec_fb.h:31
CxxUtils::vstore
ATH_ALWAYS_INLINE void vstore(vec_type_t< VEC > *dst, const VEC &src)
Definition: vec.h:285
CxxUtils::vec_mask_type_t
typename vecDetail::vec_mask_type< VEC >::type vec_mask_type_t
Define a nice alias for the mask type for a vectorized type.
Definition: vec.h:219
x
#define x
CxxUtils::vall
ATH_ALWAYS_INLINE bool vall(const VEC &mask)
Definition: vec.h:385
CxxUtils::vconvert
ATH_ALWAYS_INLINE void vconvert(VEC1 &dst, const VEC2 &src)
Definition: vec.h:407
python.utils.AtlRunQueryLookup.mask
string mask
Definition: AtlRunQueryLookup.py:460
CxxUtils::vecDetail::vec_mask_type::maskt
static auto maskt(const VEC &v1, const VEC &v2) -> decltype(v1< v2)
CxxUtils::vec
typename vecDetail::vec_typedef< T, N >::type vec
Define a nice alias for the vectorized type.
Definition: vec.h:207
CxxUtils::vpermute2
ATH_ALWAYS_INLINE void vpermute2(VEC1 &dst, const VEC &src1, const VEC &src2)
vpermute2 function.
Definition: vec.h:455
CxxUtils::vecDetail::vec_typedef
check the type and the size of the vector.
Definition: vec.h:159
lumiFormat.i
int i
Definition: lumiFormat.py:92
CxxUtils::vecDetail::vec_mask_type::type
std::remove_cv_t< std::remove_reference_t< type1 > > type
Definition: vec.h:188
CxxUtils
Definition: aligned_vector.h:29
CxxUtils::vecDetail::vec_type::type
std::remove_cv_t< std::remove_reference_t< type1 > > type
Definition: vec.h:177
DeMoUpdate.tmp
string tmp
Definition: DeMoUpdate.py:1167
CxxUtils::vecDetail::vec_type::type1
std::invoke_result< decltype(elt), const VEC & >::type type1
Definition: vec.h:176
CxxUtils::vmin
ATH_ALWAYS_INLINE void vmin(VEC &dst, const VEC &a, const VEC &b)
Definition: vec.h:315
CxxUtils::vecDetail::vec_type::elt
static auto elt(const VEC &v) -> decltype(v[0])
CxxUtils::vload
ATH_ALWAYS_INLINE void vload(VEC &dst, vec_type_t< VEC > const *src)
Definition: vec.h:272
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
CxxUtils::vselect
ATH_ALWAYS_INLINE void vselect(VEC &dst, const VEC &a, const VEC &b, const vec_mask_type_t< VEC > &mask)
Definition: vec.h:297
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
ReadCellNoiseFromCoolCompare.v2
v2
Definition: ReadCellNoiseFromCoolCompare.py:364
python.PyAthena.v
v
Definition: PyAthena.py:157
CxxUtils::vecDetail::vec_mask_type
Deduce the type of the mask returned by relational operations, for a vectorized type.
Definition: vec.h:185
DeMoScan.index
string index
Definition: DeMoScan.py:362
__attribute__
__attribute__((always_inline)) inline uint16_t TileCalibDrawerBase
Definition: TileCalibDrawerBase.h:190
a
TList * a
Definition: liststreamerinfos.cxx:10
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
CxxUtils::vec_type_t
typename vecDetail::vec_type< VEC >::type vec_type_t
Define a nice alias for the element type of a vectorized type.
Definition: vec.h:213
CxxUtils::vbroadcast
ATH_ALWAYS_INLINE void vbroadcast(VEC &v, T x)
Copy a scalar to each element of a vectorized type.
Definition: vec.h:251
CxxUtils::vecDetail::bool_pack_helper::bool_pack
Definition: vec.h:196
CxxUtils::vany
ATH_ALWAYS_INLINE bool vany(const VEC &mask)
Definition: vec.h:353
vec_fb.h
Fallback vectorized class.
CxxUtils::vecDetail::bool_pack_helper::all_true
std::is_same< bool_pack< bs..., true >, bool_pack< true, bs... > > all_true
Definition: vec.h:198
beamspotCoolDiff.bs
bs
Definition: beamspotCoolDiff.py:148
CxxUtils::vecDetail::vec_mask_type::type1
std::invoke_result< decltype(maskt), const VEC &, const VEC & >::type type1
Definition: vec.h:187
zero
void zero(TH2 *h)
zero the contents of a 2d histogram
Definition: comparitor.cxx:435