simdjson  3.11.0
Ridiculously Fast JSON
numberparsing_defs.h
1 #ifndef SIMDJSON_FALLBACK_NUMBERPARSING_DEFS_H
2 #define SIMDJSON_FALLBACK_NUMBERPARSING_DEFS_H
3 
4 #ifndef SIMDJSON_CONDITIONAL_INCLUDE
5 #include "simdjson/fallback/base.h"
6 #include "simdjson/internal/numberparsing_tables.h"
7 #endif // SIMDJSON_CONDITIONAL_INCLUDE
8 
9 #include <cstring>
10 
11 #ifdef JSON_TEST_NUMBERS // for unit testing
12 void found_invalid_number(const uint8_t *buf);
13 void found_integer(int64_t result, const uint8_t *buf);
14 void found_unsigned_integer(uint64_t result, const uint8_t *buf);
15 void found_float(double result, const uint8_t *buf);
16 #endif
17 
18 namespace simdjson {
19 namespace fallback {
20 namespace numberparsing {
21 
22 // credit: https://johnnylee-sde.github.io/Fast-numeric-string-to-int/
24 static simdjson_inline uint32_t parse_eight_digits_unrolled(const char *chars) {
25  uint64_t val;
26  memcpy(&val, chars, sizeof(uint64_t));
27  val = (val & 0x0F0F0F0F0F0F0F0F) * 2561 >> 8;
28  val = (val & 0x00FF00FF00FF00FF) * 6553601 >> 16;
29  return uint32_t((val & 0x0000FFFF0000FFFF) * 42949672960001 >> 32);
30 }
31 
33 static simdjson_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars) {
34  return parse_eight_digits_unrolled(reinterpret_cast<const char *>(chars));
35 }
36 
37 #if SIMDJSON_IS_32BITS // _umul128 for x86, arm
38 // this is a slow emulation routine for 32-bit
39 //
40 static simdjson_inline uint64_t __emulu(uint32_t x, uint32_t y) {
41  return x * (uint64_t)y;
42 }
43 static simdjson_inline uint64_t _umul128(uint64_t ab, uint64_t cd, uint64_t *hi) {
44  uint64_t ad = __emulu((uint32_t)(ab >> 32), (uint32_t)cd);
45  uint64_t bd = __emulu((uint32_t)ab, (uint32_t)cd);
46  uint64_t adbc = ad + __emulu((uint32_t)ab, (uint32_t)(cd >> 32));
47  uint64_t adbc_carry = !!(adbc < ad);
48  uint64_t lo = bd + (adbc << 32);
49  *hi = __emulu((uint32_t)(ab >> 32), (uint32_t)(cd >> 32)) + (adbc >> 32) +
50  (adbc_carry << 32) + !!(lo < bd);
51  return lo;
52 }
53 #endif
54 
56 simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t value2) {
57  internal::value128 answer;
58 #if SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
59 #if SIMDJSON_IS_ARM64
60  // ARM64 has native support for 64-bit multiplications, no need to emultate
61  answer.high = __umulh(value1, value2);
62  answer.low = value1 * value2;
63 #else
64  answer.low = _umul128(value1, value2, &answer.high); // _umul128 not available on ARM64
65 #endif // SIMDJSON_IS_ARM64
66 #else // SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
67  __uint128_t r = (static_cast<__uint128_t>(value1)) * value2;
68  answer.low = uint64_t(r);
69  answer.high = uint64_t(r >> 64);
70 #endif
71  return answer;
72 }
73 
74 } // namespace numberparsing
75 } // namespace fallback
76 } // namespace simdjson
77 
78 #ifndef SIMDJSON_SWAR_NUMBER_PARSING
79 #if SIMDJSON_IS_BIG_ENDIAN
80 #define SIMDJSON_SWAR_NUMBER_PARSING 0
81 #else
82 #define SIMDJSON_SWAR_NUMBER_PARSING 1
83 #endif
84 #endif
85 
86 #endif // SIMDJSON_FALLBACK_NUMBERPARSING_DEFS_H
The top level simdjson namespace, containing everything the library provides.
Definition: base.h:8