/src/simdjson/include/simdjson/icelake/numberparsing_defs.h
Line | Count | Source |
1 | | #ifndef SIMDJSON_ICELAKE_NUMBERPARSING_DEFS_H |
2 | | #define SIMDJSON_ICELAKE_NUMBERPARSING_DEFS_H |
3 | | |
4 | | #ifndef SIMDJSON_CONDITIONAL_INCLUDE |
5 | | #include "simdjson/icelake/base.h" |
6 | | #include "simdjson/icelake/intrinsics.h" |
7 | | #include "simdjson/internal/numberparsing_tables.h" |
8 | | #endif // SIMDJSON_CONDITIONAL_INCLUDE |
9 | | |
10 | | namespace simdjson { |
11 | | namespace icelake { |
12 | | namespace numberparsing { |
13 | | |
14 | 0 | static simdjson_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars) { |
15 | | // this actually computes *16* values so we are being wasteful. |
16 | 0 | const __m128i ascii0 = _mm_set1_epi8('0'); |
17 | 0 | const __m128i mul_1_10 = |
18 | 0 | _mm_setr_epi8(10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1); |
19 | 0 | const __m128i mul_1_100 = _mm_setr_epi16(100, 1, 100, 1, 100, 1, 100, 1); |
20 | 0 | const __m128i mul_1_10000 = |
21 | 0 | _mm_setr_epi16(10000, 1, 10000, 1, 10000, 1, 10000, 1); |
22 | 0 | const __m128i input = _mm_sub_epi8( |
23 | 0 | _mm_loadu_si128(reinterpret_cast<const __m128i *>(chars)), ascii0); |
24 | 0 | const __m128i t1 = _mm_maddubs_epi16(input, mul_1_10); |
25 | 0 | const __m128i t2 = _mm_madd_epi16(t1, mul_1_100); |
26 | 0 | const __m128i t3 = _mm_packus_epi32(t2, t2); |
27 | 0 | const __m128i t4 = _mm_madd_epi16(t3, mul_1_10000); |
28 | 0 | return _mm_cvtsi128_si32( |
29 | 0 | t4); // only captures the sum of the first 8 digits, drop the rest |
30 | 0 | } |
31 | | |
32 | | /** @private */ |
33 | 0 | simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t value2) { |
34 | 0 | internal::value128 answer; |
35 | | #if SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS |
36 | | #if SIMDJSON_IS_ARM64 |
37 | | // ARM64 has native support for 64-bit multiplications, no need to emultate |
38 | | answer.high = __umulh(value1, value2); |
39 | | answer.low = value1 * value2; |
40 | | #else |
41 | | answer.low = _umul128(value1, value2, &answer.high); // _umul128 not available on ARM64 |
42 | | #endif // SIMDJSON_IS_ARM64 |
43 | | #else // SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS |
44 | 0 | __uint128_t r = (static_cast<__uint128_t>(value1)) * value2; |
45 | 0 | answer.low = uint64_t(r); |
46 | 0 | answer.high = uint64_t(r >> 64); |
47 | 0 | #endif |
48 | 0 | return answer; |
49 | 0 | } |
50 | | |
51 | | } // namespace numberparsing |
52 | | } // namespace icelake |
53 | | } // namespace simdjson |
54 | | |
55 | | #define SIMDJSON_SWAR_NUMBER_PARSING 1 |
56 | | |
57 | | #endif // SIMDJSON_ICELAKE_NUMBERPARSING_DEFS_H |