Skip to content

Instantly share code, notes, and snippets.

@0x1F9F1
Created December 9, 2018 19:56
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 0x1F9F1/cba054c667c4e8525d9b12c99fdab7fb to your computer and use it in GitHub Desktop.
Save 0x1F9F1/cba054c667c4e8525d9b12c99fdab7fb to your computer and use it in GitHub Desktop.
SIMD Accelerated bytes to hex string
#include <immintrin.h> // SSE
#include <emmintrin.h> // SSE2
#include <tmmintrin.h> // SSSE3
alignas(16) static constexpr const char hex_chars[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
void bin2hex(const byte* src, char* dst, size_t num) noexcept
{
if (num >= 8)
{
const __m128i mask = _mm_set1_epi8(0xF);
#if 1 // SSSE3
const __m128i chars = _mm_load_si128(reinterpret_cast<const __m128i*>(hex_chars));
#else // SSE2
const __m128i mask1 = _mm_set1_epi8(0x9);
const __m128i mask2 = _mm_set1_epi8('A' - '0' - 0xA);
const __m128i mask3 = _mm_set1_epi8('0');
#endif
do
{
__m128i value = _mm_loadu_si64(src);
num -= 8;
src += 8;
value = _mm_and_si128(_mm_unpacklo_epi8(_mm_srli_epi64(value, 4), value), mask);
#if 1 // SSSE3
value = _mm_shuffle_epi8(chars, value);
#else // SSE2
value = _mm_add_epi8(_mm_add_epi8(value, mask3), _mm_and_si128(_mm_cmpgt_epi8(value, mask1), mask2));
#endif
_mm_storeu_si128(reinterpret_cast<__m128i*>(dst), value);
dst += 16;
} while (num >= 8);
}
while (num != 0)
{
--num;
byte value = *src++;
*dst++ = hex_chars[size_t(value >> 4)];
*dst++ = hex_chars[size_t(value & 0xF)];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment