/src/glaze/include/glaze/util/bit.hpp
Line | Count | Source |
1 | | // Glaze Library |
2 | | // For the license information refer to glaze.hpp |
3 | | |
4 | | #pragma once |
5 | | |
6 | | #include <bit> |
7 | | #include <cstdint> |
8 | | |
9 | | #include "glaze/util/inline.hpp" |
10 | | |
11 | | namespace glz |
12 | | { |
13 | | // std::countr_zero uses another branch check whether the input is zero, |
14 | | // we use this function when we know that x > 0 |
15 | | GLZ_ALWAYS_INLINE auto countr_zero(const uint32_t x) noexcept |
16 | 33.4M | { |
17 | | #ifdef _MSC_VER |
18 | | return std::countr_zero(x); |
19 | | #else |
20 | 33.4M | #if __has_builtin(__builtin_ctzl) |
21 | 33.4M | return __builtin_ctzl(x); |
22 | | #else |
23 | | return std::countr_zero(x); |
24 | | #endif |
25 | 33.4M | #endif |
26 | 33.4M | } |
27 | | |
28 | | GLZ_ALWAYS_INLINE auto countr_zero(const uint64_t x) noexcept |
29 | 9.49M | { |
30 | | #ifdef _MSC_VER |
31 | | return std::countr_zero(x); |
32 | | #else |
33 | 9.49M | #if __has_builtin(__builtin_ctzll) |
34 | 9.49M | return __builtin_ctzll(x); |
35 | | #else |
36 | | return std::countr_zero(x); |
37 | | #endif |
38 | 9.49M | #endif |
39 | 9.49M | } |
40 | | |
41 | | #if defined(__SIZEOF_INT128__) |
42 | | GLZ_ALWAYS_INLINE auto countr_zero(__uint128_t x) noexcept |
43 | 0 | { |
44 | 0 | uint64_t low = uint64_t(x); |
45 | 0 | if (low != 0) { |
46 | 0 | return countr_zero(low); |
47 | 0 | } |
48 | 0 | else { |
49 | 0 | uint64_t high = uint64_t(x >> 64); |
50 | 0 | return countr_zero(high) + 64; |
51 | 0 | } |
52 | 0 | } |
53 | | #endif |
54 | | |
55 | | // std::countl_zero uses another branch check whether the input is zero, |
56 | | // we use this function when we know that x > 0 |
57 | | GLZ_ALWAYS_INLINE constexpr auto countl_zero(const uint32_t x) noexcept |
58 | 0 | { |
59 | 0 | #ifdef _MSC_VER |
60 | 0 | return std::countl_zero(x); |
61 | 0 | #else |
62 | 0 | #if __has_builtin(__builtin_clz) |
63 | 0 | return __builtin_clz(x); |
64 | 0 | #else |
65 | 0 | return std::countl_zero(x); |
66 | 0 | #endif |
67 | 0 | #endif |
68 | 0 | } |
69 | | |
70 | 0 | constexpr int int_log2(uint32_t x) noexcept { return 31 - glz::countl_zero(x | 1); } |
71 | | |
72 | | consteval uint32_t repeat_byte4(const auto repeat) { return uint32_t(0x01010101u) * uint8_t(repeat); } |
73 | | |
74 | | consteval uint64_t repeat_byte8(const uint8_t repeat) { return 0x0101010101010101ull * repeat; } |
75 | | |
76 | | // Byte-granular tests over a word, the SWAR technique from Mycroft's bit twiddling notes: a |
77 | | // byte that matches becomes zero after the xor, and a zero byte is the only one that borrows |
78 | | // into its own high bit. The result marks the low bit group of every match, so the first match |
79 | | // is the lowest set bit however many bytes matched. |
80 | | GLZ_ALWAYS_INLINE constexpr uint64_t has_zero(const uint64_t chunk) noexcept |
81 | 155M | { |
82 | 155M | return (((chunk - 0x0101010101010101ull) & ~chunk) & 0x8080808080808080ull); |
83 | 155M | } |
84 | | |
85 | | GLZ_ALWAYS_INLINE constexpr uint64_t has_quote(const uint64_t chunk) noexcept |
86 | 89.5M | { |
87 | 89.5M | return has_zero(chunk ^ repeat_byte8('"')); |
88 | 89.5M | } |
89 | | |
90 | | GLZ_ALWAYS_INLINE constexpr uint64_t has_escape(const uint64_t chunk) noexcept |
91 | 0 | { |
92 | 0 | return has_zero(chunk ^ repeat_byte8('\\')); |
93 | 0 | } |
94 | | |
95 | | GLZ_ALWAYS_INLINE constexpr uint64_t has_space(const uint64_t chunk) noexcept |
96 | 0 | { |
97 | 0 | return has_zero(chunk ^ repeat_byte8(' ')); |
98 | 0 | } |
99 | | |
100 | | template <char Char> |
101 | | GLZ_ALWAYS_INLINE constexpr uint64_t has_char(const uint64_t chunk) noexcept |
102 | 65.9M | { |
103 | 65.9M | return has_zero(chunk ^ repeat_byte8(Char)); |
104 | 65.9M | } unsigned long glz::has_char<(char)123>(unsigned long) Line | Count | Source | 102 | 23.5M | { | 103 | 23.5M | return has_zero(chunk ^ repeat_byte8(Char)); | 104 | 23.5M | } |
unsigned long glz::has_char<(char)125>(unsigned long) Line | Count | Source | 102 | 23.5M | { | 103 | 23.5M | return has_zero(chunk ^ repeat_byte8(Char)); | 104 | 23.5M | } |
unsigned long glz::has_char<(char)91>(unsigned long) Line | Count | Source | 102 | 9.43M | { | 103 | 9.43M | return has_zero(chunk ^ repeat_byte8(Char)); | 104 | 9.43M | } |
unsigned long glz::has_char<(char)93>(unsigned long) Line | Count | Source | 102 | 9.43M | { | 103 | 9.43M | return has_zero(chunk ^ repeat_byte8(Char)); | 104 | 9.43M | } |
Unexecuted instantiation: unsigned long glz::has_char<(char)47>(unsigned long) Unexecuted instantiation: unsigned long glz::has_char<(char)34>(unsigned long) |
105 | | } |