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