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
16void found_invalid_number(const uint8_t *buf);
17void found_integer(int64_t result, const uint8_t *buf);
18void found_unsigned_integer(uint64_t result, const uint8_t *buf);
19void found_float(double result, const uint8_t *buf);
20#endif
21
22TARGET_HASWELL
23namespace simdjson::haswell {
24static 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
47UNTARGET_REGION
48
49
50
51
52#endif // IS_X86_64
53
54
55#endif // SIMDJSON_HASWELL_NUMBERPARSING_H
56