1 | #ifndef SIMDJSON_HASWELL_NUMBERPARSING_H |
2 | #define SIMDJSON_HASWELL_NUMBERPARSING_H |
3 | |
4 | #ifdef IS_X86_64 |
5 | |
6 | #include "simdjson/common_defs.h" |
7 | #include "simdjson/portability.h" |
8 | #include "westmere/intrinsics.h" |
9 | #include "simdjson/parsedjson.h" |
10 | #include "jsoncharutils.h" |
11 | #include <cmath> |
12 | #include <limits> |
13 | |
14 | |
15 | #ifdef JSON_TEST_NUMBERS // for unit testing |
16 | void found_invalid_number(const uint8_t *buf); |
17 | void found_integer(int64_t result, const uint8_t *buf); |
18 | void found_unsigned_integer(uint64_t result, const uint8_t *buf); |
19 | void found_float(double result, const uint8_t *buf); |
20 | #endif |
21 | |
22 | TARGET_HASWELL |
23 | namespace simdjson::haswell { |
24 | static inline uint32_t parse_eight_digits_unrolled(const char *chars) { |
25 | // this actually computes *16* values so we are being wasteful. |
26 | const __m128i ascii0 = _mm_set1_epi8('0'); |
27 | const __m128i mul_1_10 = |
28 | _mm_setr_epi8(10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1); |
29 | const __m128i mul_1_100 = _mm_setr_epi16(100, 1, 100, 1, 100, 1, 100, 1); |
30 | const __m128i mul_1_10000 = |
31 | _mm_setr_epi16(10000, 1, 10000, 1, 10000, 1, 10000, 1); |
32 | const __m128i input = _mm_sub_epi8( |
33 | _mm_loadu_si128(reinterpret_cast<const __m128i *>(chars)), ascii0); |
34 | const __m128i t1 = _mm_maddubs_epi16(input, mul_1_10); |
35 | const __m128i t2 = _mm_madd_epi16(t1, mul_1_100); |
36 | const __m128i t3 = _mm_packus_epi32(t2, t2); |
37 | const __m128i t4 = _mm_madd_epi16(t3, mul_1_10000); |
38 | return _mm_cvtsi128_si32( |
39 | t4); // only captures the sum of the first 8 digits, drop the rest |
40 | } |
41 | |
42 | #define SWAR_NUMBER_PARSING |
43 | |
44 | #include "generic/numberparsing.h" |
45 | |
46 | } // namespace simdjson::haswell |
47 | UNTARGET_REGION |
48 | |
49 | |
50 | |
51 | |
52 | #endif // IS_X86_64 |
53 | |
54 | |
55 | #endif // SIMDJSON_HASWELL_NUMBERPARSING_H |
56 | |