Skip to content

Commit 08d7312

Browse files
committed
initial attempt at switching to zmij for dtoa
1 parent 66bbbbe commit 08d7312

1 file changed

Lines changed: 63 additions & 91 deletions

File tree

src/core/coerce.c

Lines changed: 63 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "moar.h"
22
#include "ryu/ryu.h"
3+
#include "zmij/zmij.c"
34

45
#if defined(_MSC_VER)
56
#define strtoll _strtoi64
@@ -224,40 +225,40 @@ MVMString * MVM_coerce_n_s(MVMThreadContext *tc, MVMnum64 n) {
224225
}
225226
}
226227

227-
char buf[64];
228-
/* What we get back is 0E0, 1E0, 3.14E0, 1E2, ... Infinity.
228+
char buf[25];
229+
/* What we get back is 0e+00, 1e+00, 3.14e+00, 1e+02, ... Infinity.
229230
* What we'd like is the classic "fixed decimal" representation for
230-
* small values, and the exponent as a lower case 'e'. So we do some
231+
* small values. So we do some
231232
* massaging, and handle infinity above. We could leave NaN to fall
232233
* through here, but if so it would hit our "something went wrong" code,
233234
* which somewhat downplays the absolute "this path means a bug". So I think
234235
* that it's still clearer handling it above. */
235-
const int orig_len = d2s_buffered_n(n, buf);
236236
const char *first = buf;
237+
const char *end = zmij_dtoa(n, buf);
238+
const int orig_len = end - first;
237239

238240
/* Take any leading minus away. We put it back at the end. */
239-
int len = orig_len;
241+
int len = end - first;
240242
if (*first == '-') {
241243
++first;
242244
--len;
243245
}
244246

245-
if (len < 3 || !(first[1] == '.' || first[1] == 'E')) {
247+
if (len < 3 || !(first[1] == '.' || first[1] == 'e')) {
246248
/* Well, this shouldn't be possible. */
247249
}
248250
else {
249-
const char *end = first + len;
250251
const char *E = NULL;
251-
if (end[-2] == 'E') {
252+
if (end[-2] == 'e') {
252253
E = end - 2;
253254
}
254-
else if (end[-3] == 'E') {
255+
else if (end[-3] == 'e') {
255256
E = end - 3;
256257
}
257-
else if (len >= 4 && end[-4] == 'E') {
258+
else if (len >= 4 && end[-4] == 'e') {
258259
E = end - 4;
259260
}
260-
else if (len > 4 && end[-5] == 'E') {
261+
else if (len > 4 && end[-5] == 'e') {
261262
E = end - 5;
262263
}
263264

@@ -270,24 +271,10 @@ MVMString * MVM_coerce_n_s(MVMThreadContext *tc, MVMnum64 n) {
270271
if (E) {
271272
MVMGrapheme8 *blob;
272273
size_t e_len = end - (E + 1);
273-
if (e_len == 2 && E[1] == '-') {
274-
/* 1E-1 etc to 1E-9 etc */
275-
if (E[2] > '4') {
276-
/* 1E-5 etc to 1E-9 etc. Need to add a zero. */
277-
len = orig_len + 1;
278-
blob = MVM_malloc(len);
279-
/* Using buf here, not first, means that we copy any '-'
280-
* too. */
281-
size_t new_e = E - buf;
282-
memcpy(blob, buf, new_e);
283-
blob[new_e] = 'e';
284-
blob[new_e + 1] = '-';
285-
blob[new_e + 2] = '0';
286-
blob[new_e + 3] = E[2];
287-
}
288-
else {
274+
/* 1e-01 etc to 1e-04 etc */
275+
if (e_len == 3 && E[1] == '-' && E[2] == '0' && E[3] <= '4') {
289276
/* Convert to fixed format, value < 1 */
290-
unsigned int zeros = E[2] - '0' - 1;
277+
unsigned int zeros = E[3] - '0' - 1;
291278
size_t dec_len;
292279
if (E == first + 1) {
293280
/* No trailing decimals */
@@ -326,75 +313,60 @@ MVMString * MVM_coerce_n_s(MVMThreadContext *tc, MVMnum64 n) {
326313
memcpy(pos, first + 2, dec_len);
327314
}
328315
}
329-
}
330-
else if (e_len == 1 || (e_len == 2 && E[1] == '1' && E[2] < '5')) {
331-
/* 1E0 etc to 1E14 etc.
332-
* Convert to fixed format, possibly needing padding,
333-
* possibly with trailing decimals, possibly neither. */
334-
unsigned int exp = e_len == 1 ? E[1] - '0' : 10 + E[2] - '0';
335-
size_t dec_len;
336-
if (E == first + 1) {
337-
/* No trailing decimals */
338-
dec_len = 0;
339-
}
340-
else {
341-
dec_len = E - (first + 2);
342-
}
343-
size_t padding = exp > dec_len ? exp - dec_len : 0;
344-
size_t before_dp = exp > dec_len ? dec_len : exp;
345-
int has_dp = dec_len > exp;
346-
347-
len = 1 + padding + dec_len + has_dp;
348-
349-
MVMGrapheme8 *pos;
350-
if (first == buf) {
351-
blob = MVM_malloc(len);
352-
pos = blob;
353-
} else {
354-
++len;
355-
blob = MVM_malloc(len);
356-
pos = blob;
357-
*pos++ = '-';
358-
}
316+
/* 1e+00 etc to 1e+14 etc. */
317+
else if (e_len == 3 && (E[2] == '0' || (E[2] == '1' && E[3] < '5'))) {
318+
/* Convert to fixed format, possibly needing padding,
319+
* possibly with trailing decimals, possibly neither. */
320+
unsigned int exp = (10 * (E[2] - '0')) + (E[3] - '0');
321+
size_t dec_len;
322+
if (E == first + 1) {
323+
/* No trailing decimals */
324+
dec_len = 0;
325+
}
326+
else {
327+
dec_len = E - (first + 2);
328+
}
329+
size_t padding = exp > dec_len ? exp - dec_len : 0;
330+
size_t before_dp = exp > dec_len ? dec_len : exp;
331+
int has_dp = dec_len > exp;
359332

360-
*pos++ = *first;
333+
len = 1 + padding + dec_len + has_dp;
361334

362-
if (before_dp) {
363-
memcpy(pos, first + 2, before_dp);
364-
pos += before_dp;
365-
}
335+
MVMGrapheme8 *pos;
336+
if (first == buf) {
337+
blob = MVM_malloc(len);
338+
pos = blob;
339+
} else {
340+
++len;
341+
blob = MVM_malloc(len);
342+
pos = blob;
343+
*pos++ = '-';
344+
}
366345

367-
if (has_dp) {
368-
/* In this case, we never need to pad with zeros. */
369-
*pos++ = '.';
370-
memcpy(pos, first + 2 + before_dp, dec_len - exp);
371-
}
372-
else {
373-
/* In this case, we might need to pad with zeros. */
374-
while (padding) {
375-
*pos++ = '0';
376-
--padding;
346+
*pos++ = *first;
347+
348+
if (before_dp) {
349+
memcpy(pos, first + 2, before_dp);
350+
pos += before_dp;
351+
}
352+
353+
if (has_dp) {
354+
/* In this case, we never need to pad with zeros. */
355+
*pos++ = '.';
356+
memcpy(pos, first + 2 + before_dp, dec_len - exp);
357+
}
358+
else {
359+
/* In this case, we might need to pad with zeros. */
360+
while (padding) {
361+
*pos++ = '0';
362+
--padding;
363+
}
377364
}
378-
}
379-
}
380-
else if (E[1] == '-') {
381-
/* Stays in scientific notation, but need to change to 'e'. */
382-
len = orig_len;
383-
blob = MVM_malloc(len);
384-
size_t new_e = E - buf;
385-
memcpy(blob, buf, new_e);
386-
blob[new_e] = 'e';
387-
memcpy(blob + new_e + 1, E + 1, e_len);
388365
} else {
389-
/* Stays in scientific notation, but need to change to 'e'
390-
* and add a + */
391-
len = orig_len + 1;
366+
/* Stays in scientific notation. */
367+
len = orig_len;
392368
blob = MVM_malloc(len);
393-
size_t new_e = E - buf;
394-
memcpy(blob, buf, new_e);
395-
blob[new_e] = 'e';
396-
blob[new_e + 1] = '+';
397-
memcpy(blob + new_e + 2, E + 1, e_len);
369+
memcpy(blob, buf, len);
398370
}
399371
return MVM_string_ascii_from_buf_nocheck(tc, blob, len);
400372
}

0 commit comments

Comments
 (0)