enc_translate.c 1.2 KB

12345678910111213141516171819202122232425262728293031
  1. static inline __m256i
  2. enc_translate (const __m256i in)
  3. {
  4. // A lookup table containing the absolute offsets for all ranges:
  5. const __m256i lut = _mm256_setr_epi8(
  6. 65, 71, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -19, -16, 0, 0,
  7. 65, 71, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -19, -16, 0, 0);
  8. // Translate values 0..63 to the Base64 alphabet. There are five sets:
  9. // # From To Abs Index Characters
  10. // 0 [0..25] [65..90] +65 0 ABCDEFGHIJKLMNOPQRSTUVWXYZ
  11. // 1 [26..51] [97..122] +71 1 abcdefghijklmnopqrstuvwxyz
  12. // 2 [52..61] [48..57] -4 [2..11] 0123456789
  13. // 3 [62] [43] -19 12 +
  14. // 4 [63] [47] -16 13 /
  15. // Create LUT indices from the input. The index for range #0 is right,
  16. // others are 1 less than expected:
  17. __m256i indices = _mm256_subs_epu8(in, _mm256_set1_epi8(51));
  18. // mask is 0xFF (-1) for range #[1..4] and 0x00 for range #0:
  19. const __m256i mask = _mm256_cmpgt_epi8(in, _mm256_set1_epi8(25));
  20. // Subtract -1, so add 1 to indices for range #[1..4]. All indices are
  21. // now correct:
  22. indices = _mm256_sub_epi8(indices, mask);
  23. // Add offsets to input values:
  24. return _mm256_add_epi8(in, _mm256_shuffle_epi8(lut, indices));
  25. }