Created
September 26, 2022 14:12
-
-
Save dgrr/33d52255653aaaf4774f35d7c8815080 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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