1 | static inline __m128i |
2 | enc_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 | |