ATLAS Offline Software
bitscan.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
17 #ifndef CXXUTILS_BITSCAN_H
18 #define CXXUTILS_BITSCAN_H
19 
20 #include "CxxUtils/features.h"
21 #include <climits>
22 #include <cstdint>
23 #include <type_traits>
24 
25 namespace CxxUtils {
26 
32  namespace detail {
33 
34  template <typename T>
35  inline constexpr unsigned ctz_portable(T x) {
36  static_assert(std::is_integral<T>::value, "An integer type is required.");
37  unsigned n(0);
38  if (x!=0) {
39  for (;(x & 0x1) == 0; ++n, x >>= 1);
40  }
41  return n;
42  }
43 
44  template <typename T>
45  inline constexpr unsigned clz_portable(T x) {
46  static_assert(std::is_integral<T>::value, "An integer type is required.");
47  if (x==0) return sizeof(T)*8;
48  unsigned n(0);
49  T msb = static_cast<T>(1) << (sizeof(T)*8-1);
50  for (n = 0; (x & msb) == 0; ++n, x <<= 1);
51  return n;
52  }
53 
54  template <typename T>
55  inline constexpr unsigned popcount_portable(T x) {
56  static_assert(std::is_integral<T>::value, "An integer type is required.");
57  unsigned n = 0;
58  while (x != 0) {
59  n += (x&1);
60  x >>= 1;
61  }
62  return n;
63  }
64  }
65 
72  inline constexpr unsigned count_trailing_zeros(unsigned x) {
73 #if HAVE_BITCOUNT_INTRINSICS
74  return (x!=0 ? __builtin_ctz(x) : 0);
75 #else
76  return detail::ctz_portable(x);
77 #endif
78  }
79 
80  inline constexpr unsigned count_trailing_zeros(unsigned long x) {
81 #if HAVE_BITCOUNT_INTRINSICS
82  return (x!=0 ? __builtin_ctzl(x) : 0);
83 #else
84  return detail::ctz_portable(x);
85 #endif
86  }
87 
88  inline constexpr unsigned count_trailing_zeros(unsigned long long x) {
89 #if HAVE_BITCOUNT_INTRINSICS
90  return (x!=0 ? __builtin_ctzll(x) : 0);
91 #else
92  return detail::ctz_portable(x);
93 #endif
94  }
95 
102  inline constexpr unsigned count_leading_zeros(unsigned x) {
103 #if HAVE_BITCOUNT_INTRINSICS
104  return (x!=0 ? __builtin_clz(x) : sizeof(x)*CHAR_BIT);
105 #else
106  return detail::clz_portable(x);
107 #endif
108  }
109 
110  inline constexpr unsigned count_leading_zeros(unsigned long x) {
111 #if HAVE_BITCOUNT_INTRINSICS
112  return (x!=0 ? __builtin_clzl(x) : sizeof(x)*CHAR_BIT);
113 #else
114  return detail::clz_portable(x);
115 #endif
116  }
117 
118  inline constexpr unsigned count_leading_zeros(unsigned long long x) {
119 #if HAVE_BITCOUNT_INTRINSICS
120  return (x!=0 ? __builtin_clzll(x) : sizeof(x)*CHAR_BIT);
121 #else
122  return detail::clz_portable(x);
123 #endif
124  }
125 
126 
133 #if defined(__x86_64__) && HAVE_TARGET_CLONES
134  // We want to use the popcnt instruction for this if it's available.
135  // However, we're still compiling for a Model-T x86_64 by default.
136  // Use the target attribute and function multiversioning to use
137  // this instruction if it is in fact available.
138  // clang has intrinsics for popcount but not target_clones.
139  [[gnu::target_clones("popcnt,default")]]
140 #endif
141  inline constexpr unsigned count_ones(unsigned x) {
142 #if HAVE_BITCOUNT_INTRINSICS
143  return __builtin_popcount(x);
144 #else
146 #endif
147  }
148 
149 #if defined(__x86_64__) && HAVE_TARGET_CLONES
150  [[gnu::target_clones("popcnt,default")]]
151 #endif
152  inline constexpr unsigned count_ones(unsigned long x) {
153 #if HAVE_BITCOUNT_INTRINSICS
154  return __builtin_popcountl(x);
155 #else
157 #endif
158  }
159 
160 
161 #if defined(__x86_64__) && HAVE_TARGET_CLONES
162  [[gnu::target_clones("popcnt,default")]]
163 #endif
164  inline constexpr unsigned count_ones(unsigned long long x) {
165 #if HAVE_BITCOUNT_INTRINSICS
166  return __builtin_popcountll(x);
167 #else
169 #endif
170  }
174  template<typename T> constexpr int maxSetBit(const T x) {
175  return x != 0 ? sizeof(T) * 8 - count_leading_zeros(x) - 1 : -1;
176  }
177 }
178 #endif // CXXUTILS_BITSCAN_H
features.h
Some additional feature test macros.
athena.value
value
Definition: athena.py:122
detail
Definition: extract_histogram_tag.cxx:14
x
#define x
CxxUtils::count_leading_zeros
constexpr unsigned count_leading_zeros(unsigned x)
Count number of leading zeros.
Definition: bitscan.h:102
CxxUtils::detail::ctz_portable
constexpr unsigned ctz_portable(T x)
Definition: bitscan.h:35
CxxUtils::detail::clz_portable
constexpr unsigned clz_portable(T x)
Definition: bitscan.h:45
beamspotman.n
n
Definition: beamspotman.py:731
CxxUtils
Definition: aligned_vector.h:29
CxxUtils::count_ones
constexpr unsigned count_ones(unsigned x)
Count number of set bits.
Definition: bitscan.h:141
CxxUtils::count_trailing_zeros
constexpr unsigned count_trailing_zeros(unsigned x)
Count number of trailing zeros.
Definition: bitscan.h:72
CxxUtils::maxSetBit
constexpr int maxSetBit(const T x)
Returns the position (counting from least-significant-bit=0) of the most significant set bit.
Definition: bitscan.h:174
CxxUtils::detail::popcount_portable
constexpr unsigned popcount_portable(T x)
Definition: bitscan.h:55