blob: 501745386c577a9934059d7a2eedc4915f193ffb [file] [log] [blame]
Nigel Tao2a7e1ed2020-07-07 21:50:06 +10001// After editing this file, run "go generate" in the parent directory.
2
3// Copyright 2020 The Wuffs Authors.
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// https://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17// ---------------- IEEE 754 Floating Point
18
19#define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE 2047
20#define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION 800
21
22// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL is the largest N
23// such that ((10 << N) < (1 << 64)).
24#define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL 60
25
26// wuffs_base__private_implementation__high_prec_dec (abbreviated as HPD) is a
27// fixed precision floating point decimal number, augmented with ±infinity
28// values, but it cannot represent NaN (Not a Number).
29//
30// "High precision" means that the mantissa holds 800 decimal digits. 800 is
31// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION.
32//
33// An HPD isn't for general purpose arithmetic, only for conversions to and
34// from IEEE 754 double-precision floating point, where the largest and
35// smallest positive, finite values are approximately 1.8e+308 and 4.9e-324.
36// HPD exponents above +2047 mean infinity, below -2047 mean zero. The ±2047
37// bounds are further away from zero than ±(324 + 800), where 800 and 2047 is
38// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION and
39// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE.
40//
41// digits[.. num_digits] are the number's digits in big-endian order. The
42// uint8_t values are in the range [0 ..= 9], not ['0' ..= '9'], where e.g. '7'
43// is the ASCII value 0x37.
44//
45// decimal_point is the index (within digits) of the decimal point. It may be
46// negative or be larger than num_digits, in which case the explicit digits are
47// padded with implicit zeroes.
48//
49// For example, if num_digits is 3 and digits is "\x07\x08\x09":
50// - A decimal_point of -2 means ".00789"
51// - A decimal_point of -1 means ".0789"
52// - A decimal_point of +0 means ".789"
53// - A decimal_point of +1 means "7.89"
54// - A decimal_point of +2 means "78.9"
55// - A decimal_point of +3 means "789."
56// - A decimal_point of +4 means "7890."
57// - A decimal_point of +5 means "78900."
58//
59// As above, a decimal_point higher than +2047 means that the overall value is
60// infinity, lower than -2047 means zero.
61//
62// negative is a sign bit. An HPD can distinguish positive and negative zero.
63//
64// truncated is whether there are more than
65// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION digits, and at
66// least one of those extra digits are non-zero. The existence of long-tail
67// digits can affect rounding.
68//
69// The "all fields are zero" value is valid, and represents the number +0.
70typedef struct {
71 uint32_t num_digits;
72 int32_t decimal_point;
73 bool negative;
74 bool truncated;
75 uint8_t digits[WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION];
76} wuffs_base__private_implementation__high_prec_dec;
77
78// wuffs_base__private_implementation__high_prec_dec__trim trims trailing
79// zeroes from the h->digits[.. h->num_digits] slice. They have no benefit,
80// since we explicitly track h->decimal_point.
81//
82// Preconditions:
83// - h is non-NULL.
84static inline void //
85wuffs_base__private_implementation__high_prec_dec__trim(
86 wuffs_base__private_implementation__high_prec_dec* h) {
87 while ((h->num_digits > 0) && (h->digits[h->num_digits - 1] == 0)) {
88 h->num_digits--;
89 }
90}
91
92// wuffs_base__private_implementation__high_prec_dec__assign sets h to
93// represent the number x.
94//
95// Preconditions:
96// - h is non-NULL.
97static void //
98wuffs_base__private_implementation__high_prec_dec__assign(
99 wuffs_base__private_implementation__high_prec_dec* h,
100 uint64_t x,
101 bool negative) {
102 uint32_t n = 0;
103
104 // Set h->digits.
105 if (x > 0) {
106 // Calculate the digits, working right-to-left. After we determine n (how
107 // many digits there are), copy from buf to h->digits.
108 //
109 // UINT64_MAX, 18446744073709551615, is 20 digits long. It can be faster to
110 // copy a constant number of bytes than a variable number (20 instead of
111 // n). Make buf large enough (and start writing to it from the middle) so
112 // that can we always copy 20 bytes: the slice buf[(20-n) .. (40-n)].
113 uint8_t buf[40] = {0};
114 uint8_t* ptr = &buf[20];
115 do {
116 uint64_t remaining = x / 10;
117 x -= remaining * 10;
118 ptr--;
119 *ptr = (uint8_t)x;
120 n++;
121 x = remaining;
122 } while (x > 0);
123 memcpy(h->digits, ptr, 20);
124 }
125
126 // Set h's other fields.
127 h->num_digits = n;
128 h->decimal_point = (int32_t)n;
129 h->negative = negative;
130 h->truncated = false;
131 wuffs_base__private_implementation__high_prec_dec__trim(h);
132}
133
134static wuffs_base__status //
135wuffs_base__private_implementation__high_prec_dec__parse(
136 wuffs_base__private_implementation__high_prec_dec* h,
Nigel Taoe0c5de92020-07-11 11:48:17 +1000137 wuffs_base__slice_u8 s,
138 uint32_t options) {
Nigel Tao2a7e1ed2020-07-07 21:50:06 +1000139 if (!h) {
140 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
141 }
142 h->num_digits = 0;
143 h->decimal_point = 0;
144 h->negative = false;
145 h->truncated = false;
146
147 uint8_t* p = s.ptr;
148 uint8_t* q = s.ptr + s.len;
149
150 for (;; p++) {
151 if (p >= q) {
152 return wuffs_base__make_status(wuffs_base__error__bad_argument);
153 } else if (*p != '_') {
154 break;
155 }
156 }
157
158 // Parse sign.
159 do {
160 if (*p == '+') {
161 p++;
162 } else if (*p == '-') {
163 h->negative = true;
164 p++;
165 } else {
166 break;
167 }
168 for (;; p++) {
169 if (p >= q) {
170 return wuffs_base__make_status(wuffs_base__error__bad_argument);
171 } else if (*p != '_') {
172 break;
173 }
174 }
175 } while (0);
176
177 // Parse digits, up to (and including) a '.', 'E' or 'e'. Examples for each
178 // limb in this if-else chain:
179 // - "0.789"
180 // - "1002.789"
181 // - ".789"
182 // - Other (invalid input).
183 uint32_t nd = 0;
184 int32_t dp = 0;
185 bool no_digits_before_separator = false;
186 if ('0' == *p) {
187 p++;
188 for (;; p++) {
189 if (p >= q) {
190 goto after_all;
Nigel Taoe0c5de92020-07-11 11:48:17 +1000191 } else if (*p ==
192 ((options &
193 WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA)
194 ? ','
195 : '.')) {
Nigel Tao2a7e1ed2020-07-07 21:50:06 +1000196 p++;
197 goto after_sep;
198 } else if ((*p == 'E') || (*p == 'e')) {
199 p++;
200 goto after_exp;
201 } else if (*p != '_') {
202 return wuffs_base__make_status(wuffs_base__error__bad_argument);
203 }
204 }
205
206 } else if (('0' < *p) && (*p <= '9')) {
207 h->digits[nd++] = (uint8_t)(*p - '0');
208 dp = (int32_t)nd;
209 p++;
210 for (;; p++) {
211 if (p >= q) {
212 goto after_all;
213 } else if (('0' <= *p) && (*p <= '9')) {
214 if (nd < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {
215 h->digits[nd++] = (uint8_t)(*p - '0');
216 dp = (int32_t)nd;
217 } else if ('0' != *p) {
218 // Long-tail non-zeroes set the truncated bit.
219 h->truncated = true;
220 }
Nigel Taoe0c5de92020-07-11 11:48:17 +1000221 } else if (*p ==
222 ((options &
223 WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA)
224 ? ','
225 : '.')) {
Nigel Tao2a7e1ed2020-07-07 21:50:06 +1000226 p++;
227 goto after_sep;
228 } else if ((*p == 'E') || (*p == 'e')) {
229 p++;
230 goto after_exp;
231 } else if (*p != '_') {
232 return wuffs_base__make_status(wuffs_base__error__bad_argument);
233 }
234 }
235
Nigel Taoe0c5de92020-07-11 11:48:17 +1000236 } else if (*p == ((options &
237 WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA)
238 ? ','
239 : '.')) {
Nigel Tao2a7e1ed2020-07-07 21:50:06 +1000240 p++;
241 no_digits_before_separator = true;
242
243 } else {
244 return wuffs_base__make_status(wuffs_base__error__bad_argument);
245 }
246
247after_sep:
248 for (;; p++) {
249 if (p >= q) {
250 goto after_all;
251 } else if ('0' == *p) {
252 if (nd == 0) {
253 // Track leading zeroes implicitly.
254 dp--;
255 } else if (nd <
256 WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {
257 h->digits[nd++] = (uint8_t)(*p - '0');
258 }
259 } else if (('0' < *p) && (*p <= '9')) {
260 if (nd < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {
261 h->digits[nd++] = (uint8_t)(*p - '0');
262 } else {
263 // Long-tail non-zeroes set the truncated bit.
264 h->truncated = true;
265 }
266 } else if ((*p == 'E') || (*p == 'e')) {
267 p++;
268 goto after_exp;
269 } else if (*p != '_') {
270 return wuffs_base__make_status(wuffs_base__error__bad_argument);
271 }
272 }
273
274after_exp:
275 do {
276 for (;; p++) {
277 if (p >= q) {
278 return wuffs_base__make_status(wuffs_base__error__bad_argument);
279 } else if (*p != '_') {
280 break;
281 }
282 }
283
284 int32_t exp_sign = +1;
285 if (*p == '+') {
286 p++;
287 } else if (*p == '-') {
288 exp_sign = -1;
289 p++;
290 }
291
292 int32_t exp = 0;
293 const int32_t exp_large =
294 WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE +
295 WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION;
296 bool saw_exp_digits = false;
297 for (; p < q; p++) {
298 if (*p == '_') {
299 // No-op.
300 } else if (('0' <= *p) && (*p <= '9')) {
301 saw_exp_digits = true;
302 if (exp < exp_large) {
303 exp = (10 * exp) + ((int32_t)(*p - '0'));
304 }
305 } else {
306 break;
307 }
308 }
309 if (!saw_exp_digits) {
310 return wuffs_base__make_status(wuffs_base__error__bad_argument);
311 }
312 dp += exp_sign * exp;
313 } while (0);
314
315after_all:
316 if (p != q) {
317 return wuffs_base__make_status(wuffs_base__error__bad_argument);
318 }
319 h->num_digits = nd;
320 if (nd == 0) {
321 if (no_digits_before_separator) {
322 return wuffs_base__make_status(wuffs_base__error__bad_argument);
323 }
324 h->decimal_point = 0;
325 } else if (dp <
326 -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) {
327 h->decimal_point =
328 -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE - 1;
329 } else if (dp >
330 +WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) {
331 h->decimal_point =
332 +WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE + 1;
333 } else {
334 h->decimal_point = dp;
335 }
336 wuffs_base__private_implementation__high_prec_dec__trim(h);
337 return wuffs_base__make_status(NULL);
338}
339
340// --------
341
342// wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits
343// returns the number of additional decimal digits when left-shifting by shift.
344//
345// See below for preconditions.
346static uint32_t //
347wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits(
348 wuffs_base__private_implementation__high_prec_dec* h,
349 uint32_t shift) {
350 // Masking with 0x3F should be unnecessary (assuming the preconditions) but
351 // it's cheap and ensures that we don't overflow the
352 // wuffs_base__private_implementation__hpd_left_shift array.
353 shift &= 63;
354
355 uint32_t x_a = wuffs_base__private_implementation__hpd_left_shift[shift];
356 uint32_t x_b = wuffs_base__private_implementation__hpd_left_shift[shift + 1];
357 uint32_t num_new_digits = x_a >> 11;
358 uint32_t pow5_a = 0x7FF & x_a;
359 uint32_t pow5_b = 0x7FF & x_b;
360
361 const uint8_t* pow5 =
362 &wuffs_base__private_implementation__powers_of_5[pow5_a];
363 uint32_t i = 0;
364 uint32_t n = pow5_b - pow5_a;
365 for (; i < n; i++) {
366 if (i >= h->num_digits) {
367 return num_new_digits - 1;
368 } else if (h->digits[i] == pow5[i]) {
369 continue;
370 } else if (h->digits[i] < pow5[i]) {
371 return num_new_digits - 1;
372 } else {
373 return num_new_digits;
374 }
375 }
376 return num_new_digits;
377}
378
379// --------
380
381// wuffs_base__private_implementation__high_prec_dec__rounded_integer returns
382// the integral (non-fractional) part of h, provided that it is 18 or fewer
383// decimal digits. For 19 or more digits, it returns UINT64_MAX. Note that:
384// - (1 << 53) is 9007199254740992, which has 16 decimal digits.
385// - (1 << 56) is 72057594037927936, which has 17 decimal digits.
386// - (1 << 59) is 576460752303423488, which has 18 decimal digits.
387// - (1 << 63) is 9223372036854775808, which has 19 decimal digits.
388// and that IEEE 754 double precision has 52 mantissa bits.
389//
390// That integral part is rounded-to-even: rounding 7.5 or 8.5 both give 8.
391//
392// h's negative bit is ignored: rounding -8.6 returns 9.
393//
394// See below for preconditions.
395static uint64_t //
396wuffs_base__private_implementation__high_prec_dec__rounded_integer(
397 wuffs_base__private_implementation__high_prec_dec* h) {
398 if ((h->num_digits == 0) || (h->decimal_point < 0)) {
399 return 0;
400 } else if (h->decimal_point > 18) {
401 return UINT64_MAX;
402 }
403
404 uint32_t dp = (uint32_t)(h->decimal_point);
405 uint64_t n = 0;
406 uint32_t i = 0;
407 for (; i < dp; i++) {
408 n = (10 * n) + ((i < h->num_digits) ? h->digits[i] : 0);
409 }
410
411 bool round_up = false;
412 if (dp < h->num_digits) {
413 round_up = h->digits[dp] >= 5;
414 if ((h->digits[dp] == 5) && (dp + 1 == h->num_digits)) {
415 // We are exactly halfway. If we're truncated, round up, otherwise round
416 // to even.
417 round_up = h->truncated || //
418 ((dp > 0) && (1 & h->digits[dp - 1]));
419 }
420 }
421 if (round_up) {
422 n++;
423 }
424
425 return n;
426}
427
428// wuffs_base__private_implementation__high_prec_dec__small_xshift shifts h's
429// number (where 'x' is 'l' or 'r' for left or right) by a small shift value.
430//
431// Preconditions:
432// - h is non-NULL.
433// - h->decimal_point is "not extreme".
434// - shift is non-zero.
435// - shift is "a small shift".
436//
437// "Not extreme" means within
438// ±WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE.
439//
440// "A small shift" means not more than
441// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL.
442//
443// wuffs_base__private_implementation__high_prec_dec__rounded_integer and
444// wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits
445// have the same preconditions.
446//
447// wuffs_base__private_implementation__high_prec_dec__lshift keeps the first
448// two preconditions but not the last two. Its shift argument is signed and
449// does not need to be "small": zero is a no-op, positive means left shift and
450// negative means right shift.
451
452static void //
453wuffs_base__private_implementation__high_prec_dec__small_lshift(
454 wuffs_base__private_implementation__high_prec_dec* h,
455 uint32_t shift) {
456 if (h->num_digits == 0) {
457 return;
458 }
459 uint32_t num_new_digits =
460 wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits(
461 h, shift);
462 uint32_t rx = h->num_digits - 1; // Read index.
463 uint32_t wx = h->num_digits - 1 + num_new_digits; // Write index.
464 uint64_t n = 0;
465
466 // Repeat: pick up a digit, put down a digit, right to left.
467 while (((int32_t)rx) >= 0) {
468 n += ((uint64_t)(h->digits[rx])) << shift;
469 uint64_t quo = n / 10;
470 uint64_t rem = n - (10 * quo);
471 if (wx < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {
472 h->digits[wx] = (uint8_t)rem;
473 } else if (rem > 0) {
474 h->truncated = true;
475 }
476 n = quo;
477 wx--;
478 rx--;
479 }
480
481 // Put down leading digits, right to left.
482 while (n > 0) {
483 uint64_t quo = n / 10;
484 uint64_t rem = n - (10 * quo);
485 if (wx < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {
486 h->digits[wx] = (uint8_t)rem;
487 } else if (rem > 0) {
488 h->truncated = true;
489 }
490 n = quo;
491 wx--;
492 }
493
494 // Finish.
495 h->num_digits += num_new_digits;
496 if (h->num_digits >
497 WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {
498 h->num_digits = WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION;
499 }
500 h->decimal_point += (int32_t)num_new_digits;
501 wuffs_base__private_implementation__high_prec_dec__trim(h);
502}
503
504static void //
505wuffs_base__private_implementation__high_prec_dec__small_rshift(
506 wuffs_base__private_implementation__high_prec_dec* h,
507 uint32_t shift) {
508 uint32_t rx = 0; // Read index.
509 uint32_t wx = 0; // Write index.
510 uint64_t n = 0;
511
512 // Pick up enough leading digits to cover the first shift.
513 while ((n >> shift) == 0) {
514 if (rx < h->num_digits) {
515 // Read a digit.
516 n = (10 * n) + h->digits[rx++];
517 } else if (n == 0) {
518 // h's number used to be zero and remains zero.
519 return;
520 } else {
521 // Read sufficient implicit trailing zeroes.
522 while ((n >> shift) == 0) {
523 n = 10 * n;
524 rx++;
525 }
526 break;
527 }
528 }
529 h->decimal_point -= ((int32_t)(rx - 1));
530 if (h->decimal_point <
531 -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) {
532 // After the shift, h's number is effectively zero.
533 h->num_digits = 0;
534 h->decimal_point = 0;
535 h->negative = false;
536 h->truncated = false;
537 return;
538 }
539
540 // Repeat: pick up a digit, put down a digit, left to right.
541 uint64_t mask = (((uint64_t)(1)) << shift) - 1;
542 while (rx < h->num_digits) {
543 uint8_t new_digit = ((uint8_t)(n >> shift));
544 n = (10 * (n & mask)) + h->digits[rx++];
545 h->digits[wx++] = new_digit;
546 }
547
548 // Put down trailing digits, left to right.
549 while (n > 0) {
550 uint8_t new_digit = ((uint8_t)(n >> shift));
551 n = 10 * (n & mask);
552 if (wx < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {
553 h->digits[wx++] = new_digit;
554 } else if (new_digit > 0) {
555 h->truncated = true;
556 }
557 }
558
559 // Finish.
560 h->num_digits = wx;
561 wuffs_base__private_implementation__high_prec_dec__trim(h);
562}
563
564static void //
565wuffs_base__private_implementation__high_prec_dec__lshift(
566 wuffs_base__private_implementation__high_prec_dec* h,
567 int32_t shift) {
568 if (shift > 0) {
569 while (shift > +WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL) {
570 wuffs_base__private_implementation__high_prec_dec__small_lshift(
571 h, WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL);
572 shift -= WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL;
573 }
574 wuffs_base__private_implementation__high_prec_dec__small_lshift(
575 h, ((uint32_t)(+shift)));
576 } else if (shift < 0) {
577 while (shift < -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL) {
578 wuffs_base__private_implementation__high_prec_dec__small_rshift(
579 h, WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL);
580 shift += WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL;
581 }
582 wuffs_base__private_implementation__high_prec_dec__small_rshift(
583 h, ((uint32_t)(-shift)));
584 }
585}
586
587// --------
588
589// wuffs_base__private_implementation__high_prec_dec__round_etc rounds h's
590// number. For those functions that take an n argument, rounding produces at
591// most n digits (which is not necessarily at most n decimal places). Negative
592// n values are ignored, as well as any n greater than or equal to h's number
593// of digits. The etc__round_just_enough function implicitly chooses an n to
594// implement WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION.
595//
596// Preconditions:
597// - h is non-NULL.
598// - h->decimal_point is "not extreme".
599//
600// "Not extreme" means within
601// ±WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE.
602
603static void //
604wuffs_base__private_implementation__high_prec_dec__round_down(
605 wuffs_base__private_implementation__high_prec_dec* h,
606 int32_t n) {
607 if ((n < 0) || (h->num_digits <= (uint32_t)n)) {
608 return;
609 }
610 h->num_digits = (uint32_t)(n);
611 wuffs_base__private_implementation__high_prec_dec__trim(h);
612}
613
614static void //
615wuffs_base__private_implementation__high_prec_dec__round_up(
616 wuffs_base__private_implementation__high_prec_dec* h,
617 int32_t n) {
618 if ((n < 0) || (h->num_digits <= (uint32_t)n)) {
619 return;
620 }
621
622 for (n--; n >= 0; n--) {
623 if (h->digits[n] < 9) {
624 h->digits[n]++;
625 h->num_digits = (uint32_t)(n + 1);
626 return;
627 }
628 }
629
630 // The number is all 9s. Change to a single 1 and adjust the decimal point.
631 h->digits[0] = 1;
632 h->num_digits = 1;
633 h->decimal_point++;
634}
635
636static void //
637wuffs_base__private_implementation__high_prec_dec__round_nearest(
638 wuffs_base__private_implementation__high_prec_dec* h,
639 int32_t n) {
640 if ((n < 0) || (h->num_digits <= (uint32_t)n)) {
641 return;
642 }
643 bool up = h->digits[n] >= 5;
644 if ((h->digits[n] == 5) && ((n + 1) == ((int32_t)(h->num_digits)))) {
645 up = h->truncated || //
646 ((n > 0) && ((h->digits[n - 1] & 1) != 0));
647 }
648
649 if (up) {
650 wuffs_base__private_implementation__high_prec_dec__round_up(h, n);
651 } else {
652 wuffs_base__private_implementation__high_prec_dec__round_down(h, n);
653 }
654}
655
656static void //
657wuffs_base__private_implementation__high_prec_dec__round_just_enough(
658 wuffs_base__private_implementation__high_prec_dec* h,
659 int32_t exp2,
660 uint64_t mantissa) {
661 // The magic numbers 52 and 53 in this function are because IEEE 754 double
662 // precision has 52 mantissa bits.
663 //
664 // Let f be the floating point number represented by exp2 and mantissa (and
665 // also the number in h): the number (mantissa * (2 ** (exp2 - 52))).
666 //
667 // If f is zero or a small integer, we can return early.
668 if ((mantissa == 0) ||
669 ((exp2 < 53) && (h->decimal_point >= ((int32_t)(h->num_digits))))) {
670 return;
671 }
672
673 // The smallest normal f has an exp2 of -1022 and a mantissa of (1 << 52).
674 // Subnormal numbers have the same exp2 but a smaller mantissa.
675 static const int32_t min_incl_normal_exp2 = -1022;
676 static const uint64_t min_incl_normal_mantissa = 0x0010000000000000ul;
677
678 // Compute lower and upper bounds such that any number between them (possibly
679 // inclusive) will round to f. First, the lower bound. Our number f is:
680 // ((mantissa + 0) * (2 ** ( exp2 - 52)))
681 //
682 // The next lowest floating point number is:
683 // ((mantissa - 1) * (2 ** ( exp2 - 52)))
684 // unless (mantissa - 1) drops the (1 << 52) bit and exp2 is not the
685 // min_incl_normal_exp2. Either way, call it:
686 // ((l_mantissa) * (2 ** (l_exp2 - 52)))
687 //
688 // The lower bound is halfway between them (noting that 52 became 53):
689 // (((2 * l_mantissa) + 1) * (2 ** (l_exp2 - 53)))
690 int32_t l_exp2 = exp2;
691 uint64_t l_mantissa = mantissa - 1;
692 if ((exp2 > min_incl_normal_exp2) && (mantissa <= min_incl_normal_mantissa)) {
693 l_exp2 = exp2 - 1;
694 l_mantissa = (2 * mantissa) - 1;
695 }
696 wuffs_base__private_implementation__high_prec_dec lower;
697 wuffs_base__private_implementation__high_prec_dec__assign(
698 &lower, (2 * l_mantissa) + 1, false);
699 wuffs_base__private_implementation__high_prec_dec__lshift(&lower,
700 l_exp2 - 53);
701
702 // Next, the upper bound. Our number f is:
703 // ((mantissa + 0) * (2 ** (exp2 - 52)))
704 //
705 // The next highest floating point number is:
706 // ((mantissa + 1) * (2 ** (exp2 - 52)))
707 //
708 // The upper bound is halfway between them (noting that 52 became 53):
709 // (((2 * mantissa) + 1) * (2 ** (exp2 - 53)))
710 wuffs_base__private_implementation__high_prec_dec upper;
711 wuffs_base__private_implementation__high_prec_dec__assign(
712 &upper, (2 * mantissa) + 1, false);
713 wuffs_base__private_implementation__high_prec_dec__lshift(&upper, exp2 - 53);
714
715 // The lower and upper bounds are possible outputs only if the original
716 // mantissa is even, so that IEEE round-to-even would round to the original
717 // mantissa and not its neighbors.
718 bool inclusive = (mantissa & 1) == 0;
719
720 // As we walk the digits, we want to know whether rounding up would fall
721 // within the upper bound. This is tracked by upper_delta:
722 // - When -1, the digits of h and upper are the same so far.
723 // - When +0, we saw a difference of 1 between h and upper on a previous
724 // digit and subsequently only 9s for h and 0s for upper. Thus, rounding
725 // up may fall outside of the bound if !inclusive.
726 // - When +1, the difference is greater than 1 and we know that rounding up
727 // falls within the bound.
728 //
729 // This is a state machine with three states. The numerical value for each
730 // state (-1, +0 or +1) isn't important, other than their order.
731 int upper_delta = -1;
732
733 // We can now figure out the shortest number of digits required. Walk the
734 // digits until h has distinguished itself from lower or upper.
735 //
736 // The zi and zd variables are indexes and digits, for z in l (lower), h (the
737 // number) and u (upper).
738 //
739 // The lower, h and upper numbers may have their decimal points at different
740 // places. In this case, upper is the longest, so we iterate ui starting from
741 // 0 and iterate li and hi starting from either 0 or -1.
742 int32_t ui = 0;
743 for (;; ui++) {
744 // Calculate hd, the middle number's digit.
745 int32_t hi = ui - upper.decimal_point + h->decimal_point;
746 if (hi >= ((int32_t)(h->num_digits))) {
747 break;
748 }
749 uint8_t hd = (((uint32_t)hi) < h->num_digits) ? h->digits[hi] : 0;
750
751 // Calculate ld, the lower bound's digit.
752 int32_t li = ui - upper.decimal_point + lower.decimal_point;
753 uint8_t ld = (((uint32_t)li) < lower.num_digits) ? lower.digits[li] : 0;
754
755 // We can round down (truncate) if lower has a different digit than h or if
756 // lower is inclusive and is exactly the result of rounding down (i.e. we
757 // have reached the final digit of lower).
758 bool can_round_down =
759 (ld != hd) || //
760 (inclusive && ((li + 1) == ((int32_t)(lower.num_digits))));
761
762 // Calculate ud, the upper bound's digit, and update upper_delta.
763 uint8_t ud = (((uint32_t)ui) < upper.num_digits) ? upper.digits[ui] : 0;
764 if (upper_delta < 0) {
765 if ((hd + 1) < ud) {
766 // For example:
767 // h = 12345???
768 // upper = 12347???
769 upper_delta = +1;
770 } else if (hd != ud) {
771 // For example:
772 // h = 12345???
773 // upper = 12346???
774 upper_delta = +0;
775 }
776 } else if (upper_delta == 0) {
777 if ((hd != 9) || (ud != 0)) {
778 // For example:
779 // h = 1234598?
780 // upper = 1234600?
781 upper_delta = +1;
782 }
783 }
784
785 // We can round up if upper has a different digit than h and either upper
786 // is inclusive or upper is bigger than the result of rounding up.
787 bool can_round_up =
788 (upper_delta > 0) || //
789 ((upper_delta == 0) && //
790 (inclusive || ((ui + 1) < ((int32_t)(upper.num_digits)))));
791
792 // If we can round either way, round to nearest. If we can round only one
793 // way, do it. If we can't round, continue the loop.
794 if (can_round_down) {
795 if (can_round_up) {
796 wuffs_base__private_implementation__high_prec_dec__round_nearest(
797 h, hi + 1);
798 return;
799 } else {
800 wuffs_base__private_implementation__high_prec_dec__round_down(h,
801 hi + 1);
802 return;
803 }
804 } else {
805 if (can_round_up) {
806 wuffs_base__private_implementation__high_prec_dec__round_up(h, hi + 1);
807 return;
808 }
809 }
810 }
811}
812
813// --------
814
815// wuffs_base__private_implementation__parse_number_f64_eisel produces the IEEE
Nigel Taob15a0fc2020-07-08 10:50:14 +1000816// 754 double-precision value for an exact mantissa and base-10 exponent. For
817// example:
818// - when parsing "12345.678e+02", man is 12345678 and exp10 is -1.
819// - when parsing "-12", man is 12 and exp10 is 0. Processing the leading
820// minus sign is the responsibility of the caller, not this function.
Nigel Tao2a7e1ed2020-07-07 21:50:06 +1000821//
822// On success, it returns a non-negative int64_t such that the low 63 bits hold
823// the 11-bit exponent and 52-bit mantissa.
824//
825// On failure, it returns a negative value.
826//
827// The algorithm is based on an original idea by Michael Eisel. See
828// https://lemire.me/blog/2020/03/10/fast-float-parsing-in-practice/
829//
830// Preconditions:
831// - man is non-zero.
832// - exp10 is in the range -326 ..= 310, the same range of the
833// wuffs_base__private_implementation__powers_of_10 array.
834static int64_t //
835wuffs_base__private_implementation__parse_number_f64_eisel(uint64_t man,
836 int32_t exp10) {
837 // Look up the (possibly truncated) base-2 representation of (10 ** exp10).
838 // The look-up table was constructed so that it is already normalized: the
839 // table entry's mantissa's MSB (most significant bit) is on.
840 const uint32_t* po10 =
841 &wuffs_base__private_implementation__powers_of_10[5 * (exp10 + 326)];
842
843 // Normalize the man argument. The (man != 0) precondition means that a
844 // non-zero bit exists.
845 uint32_t clz = wuffs_base__count_leading_zeroes_u64(man);
846 man <<= clz;
847
848 // Calculate the return value's base-2 exponent. We might tweak it by ±1
849 // later, but its initial value comes from the look-up table and clz.
850 uint64_t ret_exp2 = ((uint64_t)po10[4]) - ((uint64_t)clz);
851
852 // Multiply the two mantissas. Normalization means that both mantissas are at
853 // least (1<<63), so the 128-bit product must be at least (1<<126). The high
Nigel Tao74d4af62020-07-10 11:27:17 +1000854 // 64 bits of the product, x_hi, must therefore be at least (1<<62).
Nigel Tao2a7e1ed2020-07-07 21:50:06 +1000855 //
Nigel Tao74d4af62020-07-10 11:27:17 +1000856 // As a consequence, x_hi has either 0 or 1 leading zeroes. Shifting x_hi
857 // right by either 9 or 10 bits (depending on x_hi's MSB) will therefore
Nigel Tao2a7e1ed2020-07-07 21:50:06 +1000858 // leave the top 10 MSBs (bits 54 ..= 63) off and the 11th MSB (bit 53) on.
Nigel Taoe722bb02020-07-10 20:33:09 +1000859#if defined(__SIZEOF_INT128__)
Nigel Taobff01d72020-07-10 12:15:09 +1000860 // See commit 18449ad75d582dd015c236abc85a16f333b796f3 "Optimize 128-bit muls
861 // in parse_number_f64_eisel" for benchmark numbers.
Nigel Tao18449ad2020-07-10 11:48:52 +1000862 __uint128_t x =
863 ((__uint128_t)man) * (((uint64_t)po10[2]) | (((uint64_t)po10[3]) << 32));
864 uint64_t x_hi = ((uint64_t)(x >> 64));
865 uint64_t x_lo = ((uint64_t)(x));
866#else
Nigel Tao2a7e1ed2020-07-07 21:50:06 +1000867 wuffs_base__multiply_u64__output x = wuffs_base__multiply_u64(
868 man, ((uint64_t)po10[2]) | (((uint64_t)po10[3]) << 32));
Nigel Tao74d4af62020-07-10 11:27:17 +1000869 uint64_t x_hi = x.hi;
870 uint64_t x_lo = x.lo;
Nigel Tao18449ad2020-07-10 11:48:52 +1000871#endif
Nigel Tao2a7e1ed2020-07-07 21:50:06 +1000872
873 // Before we shift right by at least 9 bits, recall that the look-up table
874 // entry was possibly truncated. We have so far only calculated a lower bound
875 // for the product (man * e), where e is (10 ** exp10). The upper bound would
876 // add a further (man * 1) to the 128-bit product, which overflows the lower
Nigel Tao74d4af62020-07-10 11:27:17 +1000877 // 64-bit limb if ((x_lo + man) < man).
Nigel Tao2a7e1ed2020-07-07 21:50:06 +1000878 //
Nigel Tao74d4af62020-07-10 11:27:17 +1000879 // If overflow occurs, that adds 1 to x_hi. Since we're about to shift right
Nigel Tao2a7e1ed2020-07-07 21:50:06 +1000880 // by at least 9 bits, that carried 1 can be ignored unless the higher 64-bit
881 // limb's low 9 bits are all on.
Nigel Tao74d4af62020-07-10 11:27:17 +1000882 if (((x_hi & 0x1FF) == 0x1FF) && ((x_lo + man) < man)) {
Nigel Tao2a7e1ed2020-07-07 21:50:06 +1000883 // Refine our calculation of (man * e). Before, our approximation of e used
884 // a "low resolution" 64-bit mantissa. Now use a "high resolution" 128-bit
885 // mantissa. We've already calculated x = (man * bits_0_to_63_incl_of_e).
886 // Now calculate y = (man * bits_64_to_127_incl_of_e).
Nigel Taoe722bb02020-07-10 20:33:09 +1000887#if defined(__SIZEOF_INT128__)
Nigel Taobff01d72020-07-10 12:15:09 +1000888 // See commit 18449ad75d582dd015c236abc85a16f333b796f3 "Optimize 128-bit
889 // muls in parse_number_f64_eisel" for benchmark numbers.
Nigel Tao18449ad2020-07-10 11:48:52 +1000890 __uint128_t y = ((__uint128_t)man) *
891 (((uint64_t)po10[0]) | (((uint64_t)po10[1]) << 32));
892 uint64_t y_hi = ((uint64_t)(y >> 64));
893 uint64_t y_lo = ((uint64_t)(y));
894#else
Nigel Tao2a7e1ed2020-07-07 21:50:06 +1000895 wuffs_base__multiply_u64__output y = wuffs_base__multiply_u64(
896 man, ((uint64_t)po10[0]) | (((uint64_t)po10[1]) << 32));
Nigel Tao74d4af62020-07-10 11:27:17 +1000897 uint64_t y_hi = y.hi;
898 uint64_t y_lo = y.lo;
Nigel Tao18449ad2020-07-10 11:48:52 +1000899#endif
Nigel Tao2a7e1ed2020-07-07 21:50:06 +1000900
901 // Merge the 128-bit x and 128-bit y, which overlap by 64 bits, to
902 // calculate the 192-bit product of the 64-bit man by the 128-bit e.
903 // As we exit this if-block, we only care about the high 128 bits
904 // (merged_hi and merged_lo) of that 192-bit product.
Nigel Tao74d4af62020-07-10 11:27:17 +1000905 uint64_t merged_hi = x_hi;
906 uint64_t merged_lo = x_lo + y_hi;
907 if (merged_lo < x_lo) {
Nigel Tao2a7e1ed2020-07-07 21:50:06 +1000908 merged_hi++; // Carry the overflow bit.
909 }
910
911 // The "high resolution" approximation of e is still a lower bound. Once
912 // again, see if the upper bound is large enough to produce a different
913 // result. This time, if it does, give up instead of reaching for an even
914 // more precise approximation to e.
915 //
916 // This three-part check is similar to the two-part check that guarded the
917 // if block that we're now in, but it has an extra term for the middle 64
918 // bits (checking that adding 1 to merged_lo would overflow).
919 if (((merged_hi & 0x1FF) == 0x1FF) && ((merged_lo + 1) == 0) &&
Nigel Tao74d4af62020-07-10 11:27:17 +1000920 (y_lo + man < man)) {
Nigel Tao2a7e1ed2020-07-07 21:50:06 +1000921 return -1;
922 }
923
924 // Replace the 128-bit x with merged.
Nigel Tao74d4af62020-07-10 11:27:17 +1000925 x_hi = merged_hi;
926 x_lo = merged_lo;
Nigel Tao2a7e1ed2020-07-07 21:50:06 +1000927 }
928
Nigel Tao74d4af62020-07-10 11:27:17 +1000929 // As mentioned above, shifting x_hi right by either 9 or 10 bits will leave
Nigel Tao2a7e1ed2020-07-07 21:50:06 +1000930 // the top 10 MSBs (bits 54 ..= 63) off and the 11th MSB (bit 53) on. If the
931 // MSB (before shifting) was on, adjust ret_exp2 for the larger shift.
932 //
933 // Having bit 53 on (and higher bits off) means that ret_mantissa is a 54-bit
934 // number.
Nigel Tao74d4af62020-07-10 11:27:17 +1000935 uint64_t msb = x_hi >> 63;
936 uint64_t ret_mantissa = x_hi >> (msb + 9);
Nigel Tao2a7e1ed2020-07-07 21:50:06 +1000937 ret_exp2 -= 1 ^ msb;
938
939 // IEEE 754 rounds to-nearest with ties rounded to-even. Rounding to-even can
940 // be tricky. If we're half-way between two exactly representable numbers
941 // (x's low 73 bits are zero and the next 2 bits that matter are "01"), give
942 // up instead of trying to pick the winner.
943 //
944 // Technically, we could tighten the condition by changing "73" to "73 or 74,
945 // depending on msb", but a flat "73" is simpler.
Nigel Tao74d4af62020-07-10 11:27:17 +1000946 if ((x_lo == 0) && ((x_hi & 0x1FF) == 0) && ((ret_mantissa & 3) == 1)) {
Nigel Tao2a7e1ed2020-07-07 21:50:06 +1000947 return -1;
948 }
949
950 // If we're not halfway then it's rounding to-nearest. Starting with a 54-bit
951 // number, carry the lowest bit (bit 0) up if it's on. Regardless of whether
952 // it was on or off, shifting right by one then produces a 53-bit number. If
953 // carrying up overflowed, shift again.
954 ret_mantissa += ret_mantissa & 1;
955 ret_mantissa >>= 1;
956 if ((ret_mantissa >> 53) > 0) {
957 ret_mantissa >>= 1;
958 ret_exp2++;
959 }
960
961 // Starting with a 53-bit number, IEEE 754 double-precision normal numbers
962 // have an implicit mantissa bit. Mask that away and keep the low 52 bits.
963 ret_mantissa &= 0x000FFFFFFFFFFFFF;
964
965 // IEEE 754 double-precision floating point has 11 exponent bits. All off (0)
966 // means subnormal numbers. All on (2047) means infinity or NaN.
967 if ((ret_exp2 <= 0) || (2047 <= ret_exp2)) {
968 return -1;
969 }
970
971 // Pack the bits and return.
972 return ((int64_t)(ret_mantissa | (ret_exp2 << 52)));
973}
974
975// --------
976
977static wuffs_base__result_f64 //
Nigel Taoe0c5de92020-07-11 11:48:17 +1000978wuffs_base__private_implementation__parse_number_f64_special(
979 wuffs_base__slice_u8 s,
Nigel Tao4d61a052020-07-11 12:34:40 +1000980 uint32_t options) {
Nigel Tao2a7e1ed2020-07-07 21:50:06 +1000981 do {
Nigel Tao4d61a052020-07-11 12:34:40 +1000982 if (options & WUFFS_BASE__PARSE_NUMBER_FXX__REJECT_INF_AND_NAN) {
983 goto fail;
984 }
985
Nigel Tao2a7e1ed2020-07-07 21:50:06 +1000986 uint8_t* p = s.ptr;
987 uint8_t* q = s.ptr + s.len;
988
989 for (; (p < q) && (*p == '_'); p++) {
990 }
991 if (p >= q) {
Nigel Tao4d61a052020-07-11 12:34:40 +1000992 goto fail;
Nigel Tao2a7e1ed2020-07-07 21:50:06 +1000993 }
994
995 // Parse sign.
996 bool negative = false;
997 do {
998 if (*p == '+') {
999 p++;
1000 } else if (*p == '-') {
1001 negative = true;
1002 p++;
1003 } else {
1004 break;
1005 }
1006 for (; (p < q) && (*p == '_'); p++) {
1007 }
1008 } while (0);
1009 if (p >= q) {
Nigel Tao4d61a052020-07-11 12:34:40 +10001010 goto fail;
Nigel Tao2a7e1ed2020-07-07 21:50:06 +10001011 }
1012
1013 bool nan = false;
1014 switch (p[0]) {
1015 case 'I':
1016 case 'i':
1017 if (((q - p) < 3) || //
1018 ((p[1] != 'N') && (p[1] != 'n')) || //
1019 ((p[2] != 'F') && (p[2] != 'f'))) {
Nigel Tao4d61a052020-07-11 12:34:40 +10001020 goto fail;
Nigel Tao2a7e1ed2020-07-07 21:50:06 +10001021 }
1022 p += 3;
1023
1024 if ((p >= q) || (*p == '_')) {
1025 break;
1026 } else if (((q - p) < 5) || //
1027 ((p[0] != 'I') && (p[0] != 'i')) || //
1028 ((p[1] != 'N') && (p[1] != 'n')) || //
1029 ((p[2] != 'I') && (p[2] != 'i')) || //
1030 ((p[3] != 'T') && (p[3] != 't')) || //
1031 ((p[4] != 'Y') && (p[4] != 'y'))) {
Nigel Tao4d61a052020-07-11 12:34:40 +10001032 goto fail;
Nigel Tao2a7e1ed2020-07-07 21:50:06 +10001033 }
1034 p += 5;
1035
1036 if ((p >= q) || (*p == '_')) {
1037 break;
1038 }
Nigel Tao4d61a052020-07-11 12:34:40 +10001039 goto fail;
Nigel Tao2a7e1ed2020-07-07 21:50:06 +10001040
1041 case 'N':
1042 case 'n':
1043 if (((q - p) < 3) || //
1044 ((p[1] != 'A') && (p[1] != 'a')) || //
1045 ((p[2] != 'N') && (p[2] != 'n'))) {
Nigel Tao4d61a052020-07-11 12:34:40 +10001046 goto fail;
Nigel Tao2a7e1ed2020-07-07 21:50:06 +10001047 }
1048 p += 3;
1049
1050 if ((p >= q) || (*p == '_')) {
1051 nan = true;
1052 break;
1053 }
Nigel Tao4d61a052020-07-11 12:34:40 +10001054 goto fail;
Nigel Tao2a7e1ed2020-07-07 21:50:06 +10001055
1056 default:
Nigel Tao4d61a052020-07-11 12:34:40 +10001057 goto fail;
Nigel Tao2a7e1ed2020-07-07 21:50:06 +10001058 }
1059
1060 // Finish.
1061 for (; (p < q) && (*p == '_'); p++) {
1062 }
1063 if (p != q) {
Nigel Tao4d61a052020-07-11 12:34:40 +10001064 goto fail;
Nigel Tao2a7e1ed2020-07-07 21:50:06 +10001065 }
1066 wuffs_base__result_f64 ret;
1067 ret.status.repr = NULL;
1068 ret.value = wuffs_base__ieee_754_bit_representation__to_f64(
1069 (nan ? 0x7FFFFFFFFFFFFFFF : 0x7FF0000000000000) |
1070 (negative ? 0x8000000000000000 : 0));
1071 return ret;
1072 } while (0);
1073
Nigel Tao4d61a052020-07-11 12:34:40 +10001074fail:
Nigel Tao2a7e1ed2020-07-07 21:50:06 +10001075 do {
1076 wuffs_base__result_f64 ret;
Nigel Tao4d61a052020-07-11 12:34:40 +10001077 ret.status.repr = wuffs_base__error__bad_argument;
Nigel Tao2a7e1ed2020-07-07 21:50:06 +10001078 ret.value = 0;
1079 return ret;
1080 } while (0);
1081}
1082
1083WUFFS_BASE__MAYBE_STATIC wuffs_base__result_f64 //
Nigel Taoe0c5de92020-07-11 11:48:17 +10001084wuffs_base__private_implementation__high_prec_dec__to_f64(
Nigel Tao4d61a052020-07-11 12:34:40 +10001085 wuffs_base__private_implementation__high_prec_dec* h,
1086 uint32_t options) {
Nigel Tao2a7e1ed2020-07-07 21:50:06 +10001087 do {
1088 // powers converts decimal powers of 10 to binary powers of 2. For example,
1089 // (10000 >> 13) is 1. It stops before the elements exceed 60, also known
1090 // as WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL.
1091 static const uint32_t num_powers = 19;
1092 static const uint8_t powers[19] = {
1093 0, 3, 6, 9, 13, 16, 19, 23, 26, 29, //
1094 33, 36, 39, 43, 46, 49, 53, 56, 59, //
1095 };
1096
1097 // Handle zero and obvious extremes. The largest and smallest positive
1098 // finite f64 values are approximately 1.8e+308 and 4.9e-324.
1099 if ((h->num_digits == 0) || (h->decimal_point < -326)) {
1100 goto zero;
1101 } else if (h->decimal_point > 310) {
1102 goto infinity;
1103 }
1104
1105 // Try the fast Eisel algorithm again. Calculating the (man, exp10) pair
1106 // from the high_prec_dec h is more correct but slower than the approach
1107 // taken in wuffs_base__parse_number_f64. The latter is optimized for the
1108 // common cases (e.g. assuming no underscores or a leading '+' sign) rather
1109 // than the full set of cases allowed by the Wuffs API.
1110 if (h->num_digits <= 19) {
1111 uint64_t man = 0;
1112 uint32_t i;
1113 for (i = 0; i < h->num_digits; i++) {
1114 man = (10 * man) + h->digits[i];
1115 }
1116 int32_t exp10 = h->decimal_point - ((int32_t)(h->num_digits));
1117 if ((man != 0) && (-326 <= exp10) && (exp10 <= 310)) {
1118 int64_t r = wuffs_base__private_implementation__parse_number_f64_eisel(
1119 man, exp10);
1120 if (r >= 0) {
1121 wuffs_base__result_f64 ret;
1122 ret.status.repr = NULL;
1123 ret.value = wuffs_base__ieee_754_bit_representation__to_f64(
1124 ((uint64_t)r) | (((uint64_t)(h->negative)) << 63));
1125 return ret;
1126 }
1127 }
1128 }
1129
1130 // Scale by powers of 2 until we're in the range [½ .. 1], which gives us
1131 // our exponent (in base-2). First we shift right, possibly a little too
1132 // far, ending with a value certainly below 1 and possibly below ½...
1133 const int32_t f64_bias = -1023;
1134 int32_t exp2 = 0;
1135 while (h->decimal_point > 0) {
1136 uint32_t n = (uint32_t)(+h->decimal_point);
1137 uint32_t shift =
1138 (n < num_powers)
1139 ? powers[n]
1140 : WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL;
1141
1142 wuffs_base__private_implementation__high_prec_dec__small_rshift(h, shift);
1143 if (h->decimal_point <
1144 -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) {
1145 goto zero;
1146 }
1147 exp2 += (int32_t)shift;
1148 }
1149 // ...then we shift left, putting us in [½ .. 1].
1150 while (h->decimal_point <= 0) {
1151 uint32_t shift;
1152 if (h->decimal_point == 0) {
1153 if (h->digits[0] >= 5) {
1154 break;
1155 }
1156 shift = (h->digits[0] <= 2) ? 2 : 1;
1157 } else {
1158 uint32_t n = (uint32_t)(-h->decimal_point);
1159 shift = (n < num_powers)
1160 ? powers[n]
1161 : WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL;
1162 }
1163
1164 wuffs_base__private_implementation__high_prec_dec__small_lshift(h, shift);
1165 if (h->decimal_point >
1166 +WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) {
1167 goto infinity;
1168 }
1169 exp2 -= (int32_t)shift;
1170 }
1171
1172 // We're in the range [½ .. 1] but f64 uses [1 .. 2].
1173 exp2--;
1174
1175 // The minimum normal exponent is (f64_bias + 1).
1176 while ((f64_bias + 1) > exp2) {
1177 uint32_t n = (uint32_t)((f64_bias + 1) - exp2);
1178 if (n > WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL) {
1179 n = WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL;
1180 }
1181 wuffs_base__private_implementation__high_prec_dec__small_rshift(h, n);
1182 exp2 += (int32_t)n;
1183 }
1184
1185 // Check for overflow.
1186 if ((exp2 - f64_bias) >= 0x07FF) { // (1 << 11) - 1.
1187 goto infinity;
1188 }
1189
1190 // Extract 53 bits for the mantissa (in base-2).
1191 wuffs_base__private_implementation__high_prec_dec__small_lshift(h, 53);
1192 uint64_t man2 =
1193 wuffs_base__private_implementation__high_prec_dec__rounded_integer(h);
1194
1195 // Rounding might have added one bit. If so, shift and re-check overflow.
1196 if ((man2 >> 53) != 0) {
1197 man2 >>= 1;
1198 exp2++;
1199 if ((exp2 - f64_bias) >= 0x07FF) { // (1 << 11) - 1.
1200 goto infinity;
1201 }
1202 }
1203
1204 // Handle subnormal numbers.
1205 if ((man2 >> 52) == 0) {
1206 exp2 = f64_bias;
1207 }
1208
1209 // Pack the bits and return.
1210 uint64_t exp2_bits =
1211 (uint64_t)((exp2 - f64_bias) & 0x07FF); // (1 << 11) - 1.
1212 uint64_t bits = (man2 & 0x000FFFFFFFFFFFFF) | // (1 << 52) - 1.
1213 (exp2_bits << 52) | //
1214 (h->negative ? 0x8000000000000000 : 0); // (1 << 63).
1215
1216 wuffs_base__result_f64 ret;
1217 ret.status.repr = NULL;
1218 ret.value = wuffs_base__ieee_754_bit_representation__to_f64(bits);
1219 return ret;
1220 } while (0);
1221
1222zero:
1223 do {
1224 uint64_t bits = h->negative ? 0x8000000000000000 : 0;
1225
1226 wuffs_base__result_f64 ret;
1227 ret.status.repr = NULL;
1228 ret.value = wuffs_base__ieee_754_bit_representation__to_f64(bits);
1229 return ret;
1230 } while (0);
1231
1232infinity:
1233 do {
Nigel Tao4d61a052020-07-11 12:34:40 +10001234 if (options & WUFFS_BASE__PARSE_NUMBER_FXX__REJECT_INF_AND_NAN) {
1235 wuffs_base__result_f64 ret;
1236 ret.status.repr = wuffs_base__error__bad_argument;
1237 ret.value = 0;
1238 return ret;
1239 }
1240
Nigel Tao2a7e1ed2020-07-07 21:50:06 +10001241 uint64_t bits = h->negative ? 0xFFF0000000000000 : 0x7FF0000000000000;
1242
1243 wuffs_base__result_f64 ret;
1244 ret.status.repr = NULL;
1245 ret.value = wuffs_base__ieee_754_bit_representation__to_f64(bits);
1246 return ret;
1247 } while (0);
1248}
1249
1250static inline bool //
1251wuffs_base__private_implementation__is_decimal_digit(uint8_t c) {
1252 return ('0' <= c) && (c <= '9');
1253}
1254
1255WUFFS_BASE__MAYBE_STATIC wuffs_base__result_f64 //
1256wuffs_base__parse_number_f64(wuffs_base__slice_u8 s, uint32_t options) {
1257 // In practice, almost all "dd.ddddE±xxx" numbers can be represented
1258 // losslessly by a uint64_t mantissa "dddddd" and an int32_t base-10
1259 // exponent, adjusting "xxx" for the position (if present) of the decimal
1260 // separator '.' or ','.
1261 //
1262 // This (u64 man, i32 exp10) data structure is superficially similar to the
1263 // "Do It Yourself Floating Point" type from Loitsch (†), but the exponent
1264 // here is base-10, not base-2.
1265 //
1266 // If s's number fits in a (man, exp10), parse that pair with the Eisel
1267 // algorithm. If not, or if Eisel fails, parsing s with the fallback
1268 // algorithm is slower but comprehensive.
1269 //
1270 // † "Printing Floating-Point Numbers Quickly and Accurately with Integers"
1271 // (https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf).
1272 // Florian Loitsch is also the primary contributor to
1273 // https://github.com/google/double-conversion
1274 do {
1275 // Calculating that (man, exp10) pair needs to stay within s's bounds.
1276 // Provided that s isn't extremely long, work on a NUL-terminated copy of
1277 // s's contents. The NUL byte isn't a valid part of "±dd.ddddE±xxx".
1278 //
1279 // As the pointer p walks the contents, it's faster to repeatedly check "is
1280 // *p a valid digit" than "is p within bounds and *p a valid digit".
1281 if (s.len >= 256) {
1282 goto fallback;
1283 }
1284 uint8_t z[256];
1285 memcpy(&z[0], s.ptr, s.len);
1286 z[s.len] = 0;
1287 const uint8_t* p = &z[0];
1288
1289 // Look for a leading minus sign. Technically, we could also look for an
1290 // optional plus sign, but the "script/process-json-numbers.c with -p"
1291 // benchmark is noticably slower if we do. It's optional and, in practice,
1292 // usually absent. Let the fallback catch it.
1293 bool negative = (*p == '-');
1294 if (negative) {
1295 p++;
1296 }
1297
1298 // After walking "dd.dddd", comparing p later with p now will produce the
1299 // number of "d"s and "."s.
1300 const uint8_t* const start_of_digits_ptr = p;
1301
1302 // Walk the "d"s before a '.', 'E', NUL byte, etc. If it starts with '0',
1303 // it must be a single '0'. If it starts with a non-zero decimal digit, it
1304 // can be a sequence of decimal digits.
1305 //
1306 // Update the man variable during the walk. It's OK if man overflows now.
1307 // We'll detect that later.
1308 uint64_t man;
1309 if (*p == '0') {
1310 man = 0;
1311 p++;
1312 if (wuffs_base__private_implementation__is_decimal_digit(*p)) {
1313 goto fallback;
1314 }
1315 } else if (wuffs_base__private_implementation__is_decimal_digit(*p)) {
1316 man = ((uint8_t)(*p - '0'));
1317 p++;
1318 for (; wuffs_base__private_implementation__is_decimal_digit(*p); p++) {
1319 man = (10 * man) + ((uint8_t)(*p - '0'));
1320 }
1321 } else {
1322 goto fallback;
1323 }
1324
1325 // Walk the "d"s after the optional decimal separator ('.' or ','),
1326 // updating the man and exp10 variables.
1327 int32_t exp10 = 0;
Nigel Taoe0c5de92020-07-11 11:48:17 +10001328 if (*p ==
1329 ((options & WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA)
1330 ? ','
1331 : '.')) {
Nigel Tao2a7e1ed2020-07-07 21:50:06 +10001332 p++;
1333 const uint8_t* first_after_separator_ptr = p;
1334 if (!wuffs_base__private_implementation__is_decimal_digit(*p)) {
1335 goto fallback;
1336 }
1337 man = (10 * man) + ((uint8_t)(*p - '0'));
1338 p++;
1339 for (; wuffs_base__private_implementation__is_decimal_digit(*p); p++) {
1340 man = (10 * man) + ((uint8_t)(*p - '0'));
1341 }
1342 exp10 = ((int32_t)(first_after_separator_ptr - p));
1343 }
1344
1345 // Count the number of digits:
1346 // - for an input of "314159", digit_count is 6.
1347 // - for an input of "3.14159", digit_count is 7.
1348 //
1349 // This is off-by-one if there is a decimal separator. That's OK for now.
1350 // We'll correct for that later. The "script/process-json-numbers.c with
1351 // -p" benchmark is noticably slower if we try to correct for that now.
1352 uint32_t digit_count = (uint32_t)(p - start_of_digits_ptr);
1353
1354 // Update exp10 for the optional exponent, starting with 'E' or 'e'.
1355 if ((*p | 0x20) == 'e') {
1356 p++;
1357 int32_t exp_sign = +1;
1358 if (*p == '-') {
1359 p++;
1360 exp_sign = -1;
1361 } else if (*p == '+') {
1362 p++;
1363 }
1364 if (!wuffs_base__private_implementation__is_decimal_digit(*p)) {
1365 goto fallback;
1366 }
1367 int32_t exp_num = ((uint8_t)(*p - '0'));
1368 p++;
1369 // The rest of the exp_num walking has a peculiar control flow but, once
1370 // again, the "script/process-json-numbers.c with -p" benchmark is
1371 // sensitive to alternative formulations.
1372 if (wuffs_base__private_implementation__is_decimal_digit(*p)) {
1373 exp_num = (10 * exp_num) + ((uint8_t)(*p - '0'));
1374 p++;
1375 }
1376 if (wuffs_base__private_implementation__is_decimal_digit(*p)) {
1377 exp_num = (10 * exp_num) + ((uint8_t)(*p - '0'));
1378 p++;
1379 }
1380 while (wuffs_base__private_implementation__is_decimal_digit(*p)) {
1381 if (exp_num > 0x1000000) {
1382 goto fallback;
1383 }
1384 exp_num = (10 * exp_num) + ((uint8_t)(*p - '0'));
1385 p++;
1386 }
1387 exp10 += exp_sign * exp_num;
1388 }
1389
1390 // The Wuffs API is that the original slice has no trailing data. It also
1391 // allows underscores, which we don't catch here but the fallback should.
1392 if (p != &z[s.len]) {
1393 goto fallback;
1394 }
1395
1396 // Check that the uint64_t typed man variable has not overflowed, based on
1397 // digit_count.
1398 //
1399 // For reference:
1400 // - (1 << 63) is 9223372036854775808, which has 19 decimal digits.
1401 // - (1 << 64) is 18446744073709551616, which has 20 decimal digits.
1402 // - 19 nines, 9999999999999999999, is 0x8AC7230489E7FFFF, which has 64
1403 // bits and 16 hexadecimal digits.
1404 // - 20 nines, 99999999999999999999, is 0x56BC75E2D630FFFFF, which has 67
1405 // bits and 17 hexadecimal digits.
1406 if (digit_count > 19) {
1407 // Even if we have more than 19 pseudo-digits, it's not yet definitely an
1408 // overflow. Recall that digit_count might be off-by-one (too large) if
1409 // there's a decimal separator. It will also over-report the number of
1410 // meaningful digits if the input looks something like "0.000dddExxx".
1411 //
1412 // We adjust by the number of leading '0's and '.'s and re-compare to 19.
1413 // Once again, technically, we could skip ','s too, but that perturbs the
1414 // "script/process-json-numbers.c with -p" benchmark.
1415 const uint8_t* q = start_of_digits_ptr;
1416 for (; (*q == '0') || (*q == '.'); q++) {
1417 }
1418 digit_count -= (uint32_t)(q - start_of_digits_ptr);
1419 if (digit_count > 19) {
1420 goto fallback;
1421 }
1422 }
1423
1424 // The wuffs_base__private_implementation__parse_number_f64_eisel
1425 // preconditions include that exp10 is in the range -326 ..= 310.
1426 if ((exp10 < -326) || (310 < exp10)) {
1427 goto fallback;
1428 }
1429
1430 // If man and exp10 are small enough, all three of (man), (10 ** exp10) and
1431 // (man ** (10 ** exp10)) are exactly representable by a double. We don't
1432 // need to run the Eisel algorithm.
1433 if ((-22 <= exp10) && (exp10 <= 22) && ((man >> 53) == 0)) {
1434 double d = (double)man;
1435 if (exp10 >= 0) {
1436 d *= wuffs_base__private_implementation__f64_powers_of_10[+exp10];
1437 } else {
1438 d /= wuffs_base__private_implementation__f64_powers_of_10[-exp10];
1439 }
1440 wuffs_base__result_f64 ret;
1441 ret.status.repr = NULL;
1442 ret.value = negative ? -d : +d;
1443 return ret;
1444 }
1445
1446 // The wuffs_base__private_implementation__parse_number_f64_eisel
1447 // preconditions include that man is non-zero. Parsing "0" should be caught
1448 // by the "If man and exp10 are small enough" above, but "0e99" might not.
1449 if (man == 0) {
1450 goto fallback;
1451 }
1452
1453 // Our man and exp10 are in range. Run the Eisel algorithm.
1454 int64_t r =
1455 wuffs_base__private_implementation__parse_number_f64_eisel(man, exp10);
1456 if (r < 0) {
1457 goto fallback;
1458 }
1459 wuffs_base__result_f64 ret;
1460 ret.status.repr = NULL;
1461 ret.value = wuffs_base__ieee_754_bit_representation__to_f64(
1462 ((uint64_t)r) | (((uint64_t)negative) << 63));
1463 return ret;
1464 } while (0);
1465
1466fallback:
1467 do {
1468 wuffs_base__private_implementation__high_prec_dec h;
1469 wuffs_base__status status =
Nigel Taoe0c5de92020-07-11 11:48:17 +10001470 wuffs_base__private_implementation__high_prec_dec__parse(&h, s,
1471 options);
Nigel Tao2a7e1ed2020-07-07 21:50:06 +10001472 if (status.repr) {
Nigel Taoe0c5de92020-07-11 11:48:17 +10001473 return wuffs_base__private_implementation__parse_number_f64_special(
Nigel Tao4d61a052020-07-11 12:34:40 +10001474 s, options);
Nigel Tao2a7e1ed2020-07-07 21:50:06 +10001475 }
Nigel Tao4d61a052020-07-11 12:34:40 +10001476 return wuffs_base__private_implementation__high_prec_dec__to_f64(&h,
1477 options);
Nigel Tao2a7e1ed2020-07-07 21:50:06 +10001478 } while (0);
1479}
1480
1481// --------
1482
1483static inline size_t //
1484wuffs_base__private_implementation__render_inf(wuffs_base__slice_u8 dst,
1485 bool neg,
1486 uint32_t options) {
1487 if (neg) {
1488 if (dst.len < 4) {
1489 return 0;
1490 }
1491 wuffs_base__store_u32le__no_bounds_check(dst.ptr, 0x666E492D); // '-Inf'le.
1492 return 4;
1493 }
1494
1495 if (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN) {
1496 if (dst.len < 4) {
1497 return 0;
1498 }
1499 wuffs_base__store_u32le__no_bounds_check(dst.ptr, 0x666E492B); // '+Inf'le.
1500 return 4;
1501 }
1502
1503 if (dst.len < 3) {
1504 return 0;
1505 }
1506 wuffs_base__store_u24le__no_bounds_check(dst.ptr, 0x666E49); // 'Inf'le.
1507 return 3;
1508}
1509
1510static inline size_t //
1511wuffs_base__private_implementation__render_nan(wuffs_base__slice_u8 dst) {
1512 if (dst.len < 3) {
1513 return 0;
1514 }
1515 wuffs_base__store_u24le__no_bounds_check(dst.ptr, 0x4E614E); // 'NaN'le.
1516 return 3;
1517}
1518
1519static size_t //
1520wuffs_base__private_implementation__high_prec_dec__render_exponent_absent(
1521 wuffs_base__slice_u8 dst,
1522 wuffs_base__private_implementation__high_prec_dec* h,
1523 uint32_t precision,
1524 uint32_t options) {
1525 size_t n = (h->negative ||
1526 (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN))
1527 ? 1
1528 : 0;
1529 if (h->decimal_point <= 0) {
1530 n += 1;
1531 } else {
1532 n += (size_t)(h->decimal_point);
1533 }
1534 if (precision > 0) {
1535 n += precision + 1; // +1 for the '.'.
1536 }
1537
1538 // Don't modify dst if the formatted number won't fit.
1539 if (n > dst.len) {
1540 return 0;
1541 }
1542
1543 // Align-left or align-right.
1544 uint8_t* ptr = (options & WUFFS_BASE__RENDER_NUMBER_XXX__ALIGN_RIGHT)
1545 ? &dst.ptr[dst.len - n]
1546 : &dst.ptr[0];
1547
1548 // Leading "±".
1549 if (h->negative) {
1550 *ptr++ = '-';
1551 } else if (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN) {
1552 *ptr++ = '+';
1553 }
1554
1555 // Integral digits.
1556 if (h->decimal_point <= 0) {
1557 *ptr++ = '0';
1558 } else {
1559 uint32_t m =
1560 wuffs_base__u32__min(h->num_digits, (uint32_t)(h->decimal_point));
1561 uint32_t i = 0;
1562 for (; i < m; i++) {
1563 *ptr++ = (uint8_t)('0' | h->digits[i]);
1564 }
1565 for (; i < (uint32_t)(h->decimal_point); i++) {
1566 *ptr++ = '0';
1567 }
1568 }
1569
1570 // Separator and then fractional digits.
1571 if (precision > 0) {
1572 *ptr++ =
1573 (options & WUFFS_BASE__RENDER_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA)
1574 ? ','
1575 : '.';
1576 uint32_t i = 0;
1577 for (; i < precision; i++) {
1578 uint32_t j = ((uint32_t)(h->decimal_point)) + i;
1579 *ptr++ = (uint8_t)('0' | ((j < h->num_digits) ? h->digits[j] : 0));
1580 }
1581 }
1582
1583 return n;
1584}
1585
1586static size_t //
1587wuffs_base__private_implementation__high_prec_dec__render_exponent_present(
1588 wuffs_base__slice_u8 dst,
1589 wuffs_base__private_implementation__high_prec_dec* h,
1590 uint32_t precision,
1591 uint32_t options) {
1592 int32_t exp = 0;
1593 if (h->num_digits > 0) {
1594 exp = h->decimal_point - 1;
1595 }
1596 bool negative_exp = exp < 0;
1597 if (negative_exp) {
1598 exp = -exp;
1599 }
1600
1601 size_t n = (h->negative ||
1602 (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN))
1603 ? 4
1604 : 3; // Mininum 3 bytes: first digit and then "e±".
1605 if (precision > 0) {
1606 n += precision + 1; // +1 for the '.'.
1607 }
1608 n += (exp < 100) ? 2 : 3;
1609
1610 // Don't modify dst if the formatted number won't fit.
1611 if (n > dst.len) {
1612 return 0;
1613 }
1614
1615 // Align-left or align-right.
1616 uint8_t* ptr = (options & WUFFS_BASE__RENDER_NUMBER_XXX__ALIGN_RIGHT)
1617 ? &dst.ptr[dst.len - n]
1618 : &dst.ptr[0];
1619
1620 // Leading "±".
1621 if (h->negative) {
1622 *ptr++ = '-';
1623 } else if (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN) {
1624 *ptr++ = '+';
1625 }
1626
1627 // Integral digit.
1628 if (h->num_digits > 0) {
1629 *ptr++ = (uint8_t)('0' | h->digits[0]);
1630 } else {
1631 *ptr++ = '0';
1632 }
1633
1634 // Separator and then fractional digits.
1635 if (precision > 0) {
1636 *ptr++ =
1637 (options & WUFFS_BASE__RENDER_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA)
1638 ? ','
1639 : '.';
1640 uint32_t i = 1;
1641 uint32_t j = wuffs_base__u32__min(h->num_digits, precision + 1);
1642 for (; i < j; i++) {
1643 *ptr++ = (uint8_t)('0' | h->digits[i]);
1644 }
1645 for (; i <= precision; i++) {
1646 *ptr++ = '0';
1647 }
1648 }
1649
1650 // Exponent: "e±" and then 2 or 3 digits.
1651 *ptr++ = 'e';
1652 *ptr++ = negative_exp ? '-' : '+';
1653 if (exp < 10) {
1654 *ptr++ = '0';
1655 *ptr++ = (uint8_t)('0' | exp);
1656 } else if (exp < 100) {
1657 *ptr++ = (uint8_t)('0' | (exp / 10));
1658 *ptr++ = (uint8_t)('0' | (exp % 10));
1659 } else {
1660 int32_t e = exp / 100;
1661 exp -= e * 100;
1662 *ptr++ = (uint8_t)('0' | e);
1663 *ptr++ = (uint8_t)('0' | (exp / 10));
1664 *ptr++ = (uint8_t)('0' | (exp % 10));
1665 }
1666
1667 return n;
1668}
1669
1670WUFFS_BASE__MAYBE_STATIC size_t //
1671wuffs_base__render_number_f64(wuffs_base__slice_u8 dst,
1672 double x,
1673 uint32_t precision,
1674 uint32_t options) {
1675 // Decompose x (64 bits) into negativity (1 bit), base-2 exponent (11 bits
1676 // with a -1023 bias) and mantissa (52 bits).
1677 uint64_t bits = wuffs_base__ieee_754_bit_representation__from_f64(x);
1678 bool neg = (bits >> 63) != 0;
1679 int32_t exp2 = ((int32_t)(bits >> 52)) & 0x7FF;
1680 uint64_t man = bits & 0x000FFFFFFFFFFFFFul;
1681
1682 // Apply the exponent bias and set the implicit top bit of the mantissa,
1683 // unless x is subnormal. Also take care of Inf and NaN.
1684 if (exp2 == 0x7FF) {
1685 if (man != 0) {
1686 return wuffs_base__private_implementation__render_nan(dst);
1687 }
1688 return wuffs_base__private_implementation__render_inf(dst, neg, options);
1689 } else if (exp2 == 0) {
1690 exp2 = -1022;
1691 } else {
1692 exp2 -= 1023;
1693 man |= 0x0010000000000000ul;
1694 }
1695
1696 // Ensure that precision isn't too large.
1697 if (precision > 4095) {
1698 precision = 4095;
1699 }
1700
1701 // Convert from the (neg, exp2, man) tuple to an HPD.
1702 wuffs_base__private_implementation__high_prec_dec h;
1703 wuffs_base__private_implementation__high_prec_dec__assign(&h, man, neg);
1704 if (h.num_digits > 0) {
1705 wuffs_base__private_implementation__high_prec_dec__lshift(
1706 &h, exp2 - 52); // 52 mantissa bits.
1707 }
1708
1709 // Handle the "%e" and "%f" formats.
1710 switch (options & (WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_ABSENT |
1711 WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_PRESENT)) {
1712 case WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_ABSENT: // The "%"f" format.
1713 if (options & WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION) {
1714 wuffs_base__private_implementation__high_prec_dec__round_just_enough(
1715 &h, exp2, man);
1716 int32_t p = ((int32_t)(h.num_digits)) - h.decimal_point;
1717 precision = ((uint32_t)(wuffs_base__i32__max(0, p)));
1718 } else {
1719 wuffs_base__private_implementation__high_prec_dec__round_nearest(
1720 &h, ((int32_t)precision) + h.decimal_point);
1721 }
1722 return wuffs_base__private_implementation__high_prec_dec__render_exponent_absent(
1723 dst, &h, precision, options);
1724
1725 case WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_PRESENT: // The "%e" format.
1726 if (options & WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION) {
1727 wuffs_base__private_implementation__high_prec_dec__round_just_enough(
1728 &h, exp2, man);
1729 precision = (h.num_digits > 0) ? (h.num_digits - 1) : 0;
1730 } else {
1731 wuffs_base__private_implementation__high_prec_dec__round_nearest(
1732 &h, ((int32_t)precision) + 1);
1733 }
1734 return wuffs_base__private_implementation__high_prec_dec__render_exponent_present(
1735 dst, &h, precision, options);
1736 }
1737
1738 // We have the "%g" format and so precision means the number of significant
1739 // digits, not the number of digits after the decimal separator. Perform
1740 // rounding and determine whether to use "%e" or "%f".
1741 int32_t e_threshold = 0;
1742 if (options & WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION) {
1743 wuffs_base__private_implementation__high_prec_dec__round_just_enough(
1744 &h, exp2, man);
1745 precision = h.num_digits;
1746 e_threshold = 6;
1747 } else {
1748 if (precision == 0) {
1749 precision = 1;
1750 }
1751 wuffs_base__private_implementation__high_prec_dec__round_nearest(
1752 &h, ((int32_t)precision));
1753 e_threshold = ((int32_t)precision);
1754 int32_t nd = ((int32_t)(h.num_digits));
1755 if ((e_threshold > nd) && (nd >= h.decimal_point)) {
1756 e_threshold = nd;
1757 }
1758 }
1759
1760 // Use the "%e" format if the exponent is large.
1761 int32_t e = h.decimal_point - 1;
1762 if ((e < -4) || (e_threshold <= e)) {
1763 uint32_t p = wuffs_base__u32__min(precision, h.num_digits);
1764 return wuffs_base__private_implementation__high_prec_dec__render_exponent_present(
1765 dst, &h, (p > 0) ? (p - 1) : 0, options);
1766 }
1767
1768 // Use the "%f" format otherwise.
1769 int32_t p = ((int32_t)precision);
1770 if (p > h.decimal_point) {
1771 p = ((int32_t)(h.num_digits));
1772 }
1773 precision = ((uint32_t)(wuffs_base__i32__max(0, p - h.decimal_point)));
1774 return wuffs_base__private_implementation__high_prec_dec__render_exponent_absent(
1775 dst, &h, precision, options);
1776}