@@ -313,39 +313,63 @@ inline int count_digits( char const* p ) noexcept
313313
314314// parse_unsigned
315315
316+ inline
317+ uint64_t
318+ parse_four_digits (void const * p) noexcept
319+ {
320+ #ifdef BOOST_JSON_USE_SSE2
321+ auto const c0 = _mm_cvtsi32_si128 (0x0F0F0F0F );
322+ auto v0 = _mm_and_si128 (_mm_loadu_si32 (p), c0);
323+
324+ // auto const c1 = _mm_cvtsi64_si128(0x0001'000A'0064'03E8);
325+ auto const c1 = _mm_setr_epi16 (1000 , 100 , 10 , 1 , 0 , 0 , 0 , 0 );
326+
327+ auto v1 = _mm_unpacklo_epi8 ( v0, _mm_setzero_si128 () );
328+ auto v2 = _mm_madd_epi16 (v1, c1);
329+ auto v3 = _mm_srli_epi64 (v2, 32 );
330+ auto v4 = _mm_add_epi32 (v2, v3);
331+ return static_cast <uint32_t >( _mm_cvtsi128_si32 (v4) );
332+ #else // BOOST_JSON_USE_SSE2
333+ uint32_t v;
334+ std::memcpy ( &v, p, 4 );
335+ endian::native_to_little_inplace (v);
336+ v = (v & 0x0F0F0F0F ) * 2561 >> 8 ;
337+ v = (v & 0x00FF00FF ) * 6553601 >> 16 ;
338+ return v;
339+ #endif // BOOST_JSON_USE_SSE2
340+ }
341+
316342inline uint64_t parse_unsigned ( uint64_t r, char const * p, std::size_t n ) noexcept
317343{
318- char const * e = p + n;
344+ auto const e = p + n;
319345
320- if ( n & 1 )
346+ if (n & 2 )
321347 {
322- r = r * 10 + p[0 ] - ' 0' ;
323- ++p;
348+ uint32_t v0 = 0 ;
349+ std::memcpy ( &v0, p, 2 );
350+ endian::native_to_little_inplace (v0);
351+ v0 = v0 & 0x0F0F ;
352+ r = (r * 100 ) + ((v0 & 0xFF ) * 10 ) + (v0 >> 8 );
353+ p += 2 ;
324354 }
325- if ( n & 2 )
355+ if (n & 1 )
326356 {
327- r = r * 10 + p[0 ] - ' 0' ;
328- r = r * 10 + p[1 ] - ' 0' ;
329- p += 2 ;
357+ r = (r * 10 ) + (p[0 ] & 0x0F );
358+ p += 1 ;
330359 }
331- #if BOOST_JSON_ARCH == 64
360+
361+ #if defined(BOOST_JSON_USE_SSE2) || (BOOST_JSON_ARCH == 64)
362+ while (p < e)
363+ #else // !defined(BOOST_JSON_USE_SSE2) && (BOOST_JSON_ARCH == 32)
332364 if ( n & 4 )
333- #else
334- while ( p != e )
335365#endif
336366 {
337- uint32_t v;
338- std::memcpy ( &v, p, 4 );
339- endian::native_to_little_inplace (v);
340- v = (v & 0x0F0F0F0F ) * 2561 >> 8 ;
341- v = (v & 0x00FF00FF ) * 6553601 >> 16 ;
342-
343- r = r * 10000 + v;
367+ r = r * 10000 + parse_four_digits (p);
344368 p += 4 ;
345369 }
346370
347371#if BOOST_JSON_ARCH == 64
348- while ( p != e )
372+ while ( p < e )
349373 {
350374 uint64_t v;
351375 std::memcpy ( &v, p, 8 );
0 commit comments