65 lines
1.7 KiB
C++
65 lines
1.7 KiB
C++
module;
|
|
|
|
#include <simd>
|
|
|
|
module tricks;
|
|
|
|
import std;
|
|
|
|
namespace brc {
|
|
|
|
std::size_t find_delim(std::string_view string, char target) {
|
|
constexpr auto width = std::simd::vec<std::uint8_t>::size();
|
|
const auto needle = std::simd::vec<std::uint8_t>(static_cast<std::uint8_t>(target));
|
|
|
|
auto i = std::size_t(0);
|
|
for (; i + width <= string.size(); i += width) {
|
|
const auto chunk = std::simd::vec<std::uint8_t>(
|
|
std::span<const std::uint8_t, width>(reinterpret_cast<const std::uint8_t*>(string.data() + i), width));
|
|
|
|
const auto mask = chunk == needle;
|
|
if (const auto bits = mask.to_bitset(); bits.any()) {
|
|
return i + std::countr_zero(bits.to_ullong());
|
|
}
|
|
}
|
|
|
|
for (; i < string.size(); ++i) {
|
|
if (string[i] == target) return i;
|
|
}
|
|
return string.size();
|
|
}
|
|
|
|
std::inplace_vector<std::size_t, 4> find_delim_batch(std::string_view string, char target) {
|
|
constexpr auto BatchSize = 4;
|
|
auto sizes = std::inplace_vector<std::size_t, BatchSize>();
|
|
|
|
constexpr auto width = std::simd::vec<std::uint8_t>::size();
|
|
const auto needle = std::simd::vec<std::uint8_t>(static_cast<std::uint8_t>(target));
|
|
|
|
std::size_t i = 0;
|
|
|
|
for (; i + width <= string.size() && sizes.size() < BatchSize; i += width) {
|
|
const auto chunk = std::simd::vec<std::uint8_t>(
|
|
std::span<const std::uint8_t, width>(reinterpret_cast<const std::uint8_t*>(string.data() + i), width));
|
|
|
|
const auto mask = chunk == needle;
|
|
auto bits = mask.to_bitset().to_ullong();
|
|
|
|
while (bits != 0 && sizes.size() < BatchSize) {
|
|
const auto bit_pos = std::countr_zero(bits);
|
|
sizes.push_back(i + bit_pos);
|
|
bits &= bits - 1;
|
|
}
|
|
}
|
|
|
|
for (; i < string.size() && sizes.size() < BatchSize; ++i) {
|
|
if (string[i] == target) {
|
|
sizes.push_back(i);
|
|
}
|
|
}
|
|
|
|
return sizes;
|
|
}
|
|
|
|
} // namespace brc
|