LCOV - code coverage report
Current view: top level - ballet/hex - fd_hex.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 98 98 100.0 %
Date: 2026-05-19 08:05:42 Functions: 7 7 100.0 %

          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 : }

Generated by: LCOV version 1.14