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