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