LCOV - code coverage report
Current view: top level - ballet/hex - fd_hex.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 98 0.0 %
Date: 2026-10-22 18:10:43 Functions: 0 7 0.0 %

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

Generated by: LCOV version 1.14