38# include <emmintrin.h>
42static const char *bc_count_digits(
const char *str,
const char *
end)
46 const __m128i
offset = _mm_set1_epi8((
signed char) (SCHAR_MIN -
'0'));
48 const __m128i threshold = _mm_set1_epi8(SCHAR_MIN + (
'9' + 1 -
'0'));
50 while (str +
sizeof(__m128i) <=
end) {
51 __m128i bytes = _mm_loadu_si128((
const __m128i *) str);
54 bytes = _mm_add_epi8(bytes,
offset);
56 bytes = _mm_cmplt_epi8(bytes, threshold);
58 int mask = _mm_movemask_epi8(bytes);
61#ifdef PHP_HAVE_BUILTIN_CTZL
62 return str + __builtin_ctz(~mask);
68 str +=
sizeof(__m128i);
72 while (*str >=
'0' && *str <=
'9') {
79static inline const char *bc_skip_zero_reverse(
const char *scanner,
const char *stop)
83 const __m128i c_zero_repeat = _mm_set1_epi8(
'0');
84 while (scanner -
sizeof(__m128i) >= stop) {
85 scanner -=
sizeof(__m128i);
86 __m128i bytes = _mm_loadu_si128((
const __m128i *) scanner);
88 bytes = _mm_cmpeq_epi8(bytes, c_zero_repeat);
90 int mask = _mm_movemask_epi8(bytes);
94 scanner +=
sizeof(__m128i);
101 while (scanner - 1 >= stop && scanner[-1] ==
'0') {
109bool bc_str2num(
bc_num *num,
const char *str,
const char *
end,
size_t scale,
size_t *full_scale,
bool auto_scale)
111 size_t str_scale = 0;
112 const char *
ptr = str;
113 const char *fractional_ptr =
NULL;
114 const char *fractional_end =
NULL;
115 bool zero_int =
false;
120 if ((*
ptr ==
'+') || (*
ptr ==
'-')) {
125 while (*
ptr ==
'0') {
128 const char *integer_ptr =
ptr;
131 size_t digits =
ptr - integer_ptr;
133 const char *decimal_point = (*
ptr ==
'.') ?
ptr :
NULL;
143 fractional_ptr = fractional_end = decimal_point + 1;
149 goto after_fractional;
153 fractional_end = bc_count_digits(fractional_ptr,
end);
160 *full_scale = fractional_end - fractional_ptr;
164 fractional_end = bc_skip_zero_reverse(fractional_end, fractional_ptr);
167 str_scale = fractional_end - fractional_ptr;
173 if (str_scale > scale && !auto_scale) {
174 fractional_end -= str_scale - scale;
182 const char *fractional_new_end = bc_skip_zero_reverse(fractional_end, fractional_ptr);
183 str_scale -= fractional_end - fractional_new_end;
194 if (digits + str_scale == 0) {
204 (*num)->n_sign = *str ==
'-' ?
MINUS :
PLUS;
205 char *nptr = (*num)->n_value;
215 const char *integer_end = integer_ptr + digits;
struct bc_struct * bc_num
#define bc_new_num_nonzeroed(length, scale)
char * bc_copy_and_toggle_bcd(char *restrict dest, const char *source, const char *source_end)
unsigned const char * end
bool bc_str2num(bc_num *num, const char *str, const char *end, size_t scale, size_t *full_scale, bool auto_scale)
#define EXPECTED(condition)
#define UNEXPECTED(condition)