Skip to content

Instantly share code, notes, and snippets.

@dgrr
Created September 26, 2022 14:12
Show Gist options
  • Save dgrr/33d52255653aaaf4774f35d7c8815080 to your computer and use it in GitHub Desktop.
Save dgrr/33d52255653aaaf4774f35d7c8815080 to your computer and use it in GitHub Desktop.
#include <immintrin.h>
#include <string>
static const unsigned char __hex_chars[16] = {'0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'a', 'b',
'c', 'd', 'e', 'f'};
static const unsigned char __blend_table[32] = {
0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128,
0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128};
static const unsigned char __dup_index[16] = {0, 0, 1, 1, 2, 2, 3, 3,
4, 4, 5, 5, 6, 6, 7, 7};
class hex
{
std::string r_;
__m128i table_;
__m128i mask_;
__m128i dup_index_;
public:
hex()
{
table_ = _mm_loadu_si128((__m128i const*) &__hex_chars[0]);
mask_ = _mm_loadu_si128((__m128i const*) &__blend_table[0]);
dup_index_ = _mm_loadu_si128((__m128i const*) &__dup_index[0]);
}
hex& clear()
{
r_.clear();
return *this;
}
hex& encode(const unsigned char* data, size_t size)
{
__m128i _s = _mm_set1_epi8(15);
size_t r_index = r_.size();
r_.resize(r_.size() + size * 2);
size_t i = 0;
for (; size >= 8; i += 8, r_index += 16, size -= 8)
{
__m128i _r, _dh, _dl; // result
__m128i _data = _mm_loadu_si64((void const*) &data[i]); // data
_dh = _mm_srli_epi16(_data, 4); // shift right 4 bits
_dh = _mm_and_si128(_dh, _s); // remove higher bits
_dh = _mm_shuffle_epi8(table_, _dh); // search in table
_dl = _mm_and_si128(_data, _s); // remove higher bits
_dl = _mm_shuffle_epi8(table_, _dl); // search in table
_dh = _mm_shuffle_epi8(_dh, dup_index_); // duplicate first
_dl = _mm_shuffle_epi8(_dl, dup_index_); // duplicate second
_r = _mm_blendv_epi8(_dh, _dl, mask_); // blend
_mm_storeu_si128((__m128i*) &r_[r_index], _r); // store in r_
}
while (size > 0)
{
r_[r_index++] = __hex_chars[data[i] >> 4];
r_[r_index++] = __hex_chars[data[i++] & 15];
size--;
}
return *this;
}
const std::string& final() const
{
return r_;
}
};
// requires sse4.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment