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