Line data Source code
1 : #include "fd_hex.h"
2 :
3 : static inline int
4 0 : fd_hex_unhex( int c ) {
5 0 : if( c>='0' && c<='9' ) return c-'0';
6 0 : if( c>='a' && c<='f' ) return c-'a'+0xa;
7 0 : if( c>='A' && c<='F' ) return c-'A'+0xa;
8 0 : return -1;
9 0 : }
10 :
11 : #if FD_HAS_AVX
12 : #include "../../util/simd/fd_sse.h"
13 : #include "../../util/simd/fd_avx.h"
14 :
15 : static inline wb_t
16 : decode_32( wb_t c,
17 0 : uint * invalid ) {
18 0 : wb_t lower = wb_or( c, wb_bcast( 0x20 ) );
19 0 : wb_t alpha = wb_and( wb_gt( lower, wb_bcast( '`' ) ), wb_gt( wb_bcast( 'g' ), lower ) );
20 0 : wb_t digit = wb_and( wb_gt( c, wb_bcast( '/' ) ), wb_gt( wb_bcast( ':' ), c ) );
21 0 : wb_t valid = wb_or( digit, alpha );
22 0 : wb_t nibbles = wb_add( wb_and( c, wb_bcast( 0x0f ) ), wb_notczero( alpha, wb_bcast( 9 ) ) );
23 0 : wb_t pairs = _mm256_maddubs_epi16( nibbles, wh_bcast( 0x0110 ) );
24 0 : wb_t compressed = _mm256_shuffle_epi8( pairs, wb_bcast_hex( 0x00,0x02,0x04,0x06,0x08,0x0A,0x0C,0x0E,
25 0 : 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ) );
26 :
27 0 : *invalid = (uint)_mm256_movemask_epi8( wb_lnot( valid ) );
28 0 : return _mm256_permute4x64_epi64( compressed, 0xd8 );
29 0 : }
30 :
31 : static inline wb_t
32 0 : encode_16( vb_t x ) {
33 0 : wb_t expanded = _mm256_cvtepu8_epi16( x );
34 0 : wb_t nibbles = wb_and( wb_or( wh_shr( expanded, 4 ), wh_shl( expanded, 8 ) ), wb_bcast( 0x0f ) );
35 0 : wb_t adjust = wb_notczero( wb_gt( nibbles, wb_bcast( 9 ) ), wb_bcast( 39 ) );
36 0 : return wb_add( wb_add( nibbles, adjust ), wb_bcast( '0' ) );
37 0 : }
38 :
39 : #endif
40 :
41 : #if FD_HAS_AVX512
42 : #include "../../util/simd/fd_avx512.h"
43 :
44 : static inline wb_t
45 : decode_64( wwb_t c,
46 0 : ulong * invalid ) {
47 0 : wwb_t lower = wwb_or( c, wwb_bcast( 0x20 ) );
48 0 : ulong alpha = wwb_gt( lower, wwb_bcast( '`' ) ) & wwb_gt( wwb_bcast( 'g' ), lower );
49 0 : ulong digit = wwb_gt( c, wwb_bcast( '/' ) ) & wwb_gt( wwb_bcast( ':' ), c );
50 0 : ulong valid = digit | alpha;
51 0 : wwb_t nibbles = wwb_add( wwb_and( c, wwb_bcast( 0x0f ) ), _mm512_maskz_set1_epi8( alpha, 9 ) );
52 0 : wwb_t pairs = _mm512_maddubs_epi16( nibbles, wwh_bcast( 0x0110 ) );
53 0 : wwb_t compressed = _mm512_shuffle_epi8( pairs, wwb_bcast_hex( 0x00,0x02,0x04,0x06,0x08,0x0A,0x0C,0x0E,
54 0 : 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ) );
55 :
56 0 : *invalid = ~valid;
57 0 : return _mm512_castsi512_si256( _mm512_maskz_compress_epi64( (__mmask8)0x55, compressed ) );
58 0 : }
59 :
60 : static inline wwb_t
61 0 : encode_32( wb_t x ) {
62 0 : wwb_t expanded = _mm512_cvtepu8_epi16( x );
63 0 : wwb_t nibbles = wwb_and( wwb_or( wwh_shr( expanded, 4 ), wwh_shl( expanded, 8 ) ), wwb_bcast( 0x0f ) );
64 0 : wwb_t adjust = _mm512_maskz_set1_epi8( wwb_gt( nibbles, wwb_bcast( 9 ) ), 39 );
65 0 : return wwb_add( wwb_add( nibbles, adjust ), wwb_bcast( '0' ) );
66 0 : }
67 :
68 : #endif
69 :
70 : ulong
71 : fd_hex_decode( void * _dst,
72 : char const * hex,
73 0 : ulong sz ) {
74 0 : uchar const * src = (uchar const *)hex;
75 0 : uchar * dst = _dst;
76 :
77 0 : ulong i=0UL;
78 0 : #if FD_HAS_AVX512
79 0 : for( ; i+32UL<=sz; i+=32UL ) {
80 0 : ulong invalid;
81 0 : wb_t bytes = decode_64( wwb_ldu( src + 2UL*i ), &invalid );
82 0 : if( FD_UNLIKELY( invalid ) ) return i + (ulong)fd_ulong_find_lsb( invalid )/2UL;
83 0 : wb_stu( fd_type_pun( dst + i ), bytes );
84 0 : }
85 0 : #endif
86 0 : #if FD_HAS_AVX
87 0 : for( ; i+16UL<=sz; i+=16UL ) {
88 0 : uint invalid;
89 0 : wb_t bytes = decode_32( wb_ldu( src + 2UL*i ), &invalid );
90 0 : if( FD_UNLIKELY( invalid ) ) return i + (ulong)fd_uint_find_lsb( invalid )/2UL;
91 0 : vb_stu( fd_type_pun( dst + i ), _mm256_castsi256_si128( bytes ) );
92 0 : }
93 0 : #endif
94 :
95 0 : src += 2UL*i;
96 0 : dst += i;
97 :
98 0 : for( ; i<sz; i++ ) {
99 0 : int hi = fd_hex_unhex( *src++ );
100 0 : int lo = fd_hex_unhex( *src++ );
101 0 : if( FD_UNLIKELY( (hi<0) | (lo<0) ) ) return i;
102 0 : *dst++ = (uchar)( ((uint)hi<<4) | (uint)lo );
103 0 : }
104 :
105 0 : return i;
106 0 : }
107 :
108 : char *
109 : fd_hex_encode( char * dst,
110 : void const * _src,
111 0 : ulong sz ) {
112 :
113 0 : uchar const * src = (uchar const *)_src;
114 0 : ulong j=0UL;
115 0 : #if FD_HAS_AVX512
116 0 : for( ; j+32UL<=sz; j+=32UL ) {
117 0 : wwb_t out = encode_32( wb_ldu( src + j ) );
118 0 : wwb_stu( fd_type_pun( dst + 2UL*j ), out );
119 0 : }
120 0 : #endif
121 0 : #if FD_HAS_AVX
122 0 : for( ; j+16UL<=sz; j+=16UL ) {
123 0 : wb_t out = encode_16( vb_ldu( fd_type_pun_const( src + j ) ) );
124 0 : wb_stu( fd_type_pun( dst + 2UL*j ), out );
125 0 : }
126 0 : #endif
127 :
128 0 : src += j;
129 0 : dst += 2UL*j;
130 0 : sz -= j;
131 :
132 0 : static char const lut[ 16 ] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
133 0 : for( ulong j=0UL; j<sz; j++ ) {
134 0 : ulong c = src[j];
135 0 : *dst++ = lut[ c >> 4UL ];
136 0 : *dst++ = lut[ c & 0xfUL ];
137 0 : }
138 0 : return dst;
139 0 : }
|