Applies the `len`-byte bitmask `mask` to `buf`, in 16-byte chunks if able, otherwise, falls back to 8-byte chunks and possibly 1-byte chunks.
| 140 | // Applies the `len`-byte bitmask `mask` to `buf`, in 16-byte chunks if able, |
| 141 | // otherwise, falls back to 8-byte chunks and possibly 1-byte chunks. |
| 142 | static inline void MaskBytes(uint8_t *buf, uint8_t const *mask, |
| 143 | const size_t len) { |
| 144 | if (len <= sizeof(uint64_t)) { |
| 145 | return MaskBytes64(buf, mask, len); |
| 146 | } |
| 147 | |
| 148 | // AVX2? |
| 149 | size_t n = len / sizeof(__m128i); |
| 150 | size_t leftover = len - n * sizeof(__m128i); |
| 151 | __m128i *buf128 = reinterpret_cast<__m128i *>(buf); |
| 152 | const __m128i *mask128 = reinterpret_cast<const __m128i *>(mask); |
| 153 | for (size_t i = 0; i < n; i++) { |
| 154 | __m128i a = _mm_loadu_si128(buf128 + i); |
| 155 | __m128i b = _mm_loadu_si128(mask128 + i); |
| 156 | _mm_storeu_si128(buf128 + i, _mm_and_si128(a, b)); |
| 157 | } |
| 158 | |
| 159 | buf = reinterpret_cast<uint8_t *>(buf128 + n); |
| 160 | mask = reinterpret_cast<uint8_t const *>(mask128 + n); |
| 161 | if (leftover >= sizeof(uint64_t)) { |
| 162 | MaskBytes64(buf, mask, leftover); |
| 163 | } else { |
| 164 | MaskBytesSmall(buf, mask, leftover); |
| 165 | } |
| 166 | } |
| 167 | |
| 168 | // Dangerous Helper! Use SetBitsHigh<T>() and SetBitsLow<T>() instead. |
| 169 | template <typename T, typename = std::enable_if<std::is_integral<T>::value>> |