mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-03 15:38:22 +00:00
parent
6fa049c9c7
commit
cfd453d125
5 changed files with 283 additions and 134 deletions
143
libc/fmt/fmt.c
143
libc/fmt/fmt.c
|
@ -23,12 +23,23 @@
|
||||||
#include "libc/fmt/fmt.h"
|
#include "libc/fmt/fmt.h"
|
||||||
#include "libc/fmt/fmts.h"
|
#include "libc/fmt/fmts.h"
|
||||||
#include "libc/fmt/internal.h"
|
#include "libc/fmt/internal.h"
|
||||||
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
|
#include "libc/nexgen32e/bsr.h"
|
||||||
#include "libc/runtime/internal.h"
|
#include "libc/runtime/internal.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "third_party/gdtoa/gdtoa.h"
|
#include "third_party/gdtoa/gdtoa.h"
|
||||||
|
|
||||||
|
#define PUT(C) \
|
||||||
|
do { \
|
||||||
|
if (out(C, arg) == -1) { \
|
||||||
|
return -1; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
static const char kSpecialFloats[2][2][4] = {{"INF", "inf"}, {"NAN", "nan"}};
|
||||||
|
|
||||||
static int __fmt_atoi(const char **str) {
|
static int __fmt_atoi(const char **str) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; '0' <= **str && **str <= '9'; ++*str) {
|
for (i = 0; '0' <= **str && **str <= '9'; ++*str) {
|
||||||
|
@ -107,11 +118,10 @@ static int __fmt_atoi(const char **str) {
|
||||||
hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
||||||
union {
|
union {
|
||||||
double d;
|
double d;
|
||||||
unsigned int u[2];
|
uint32_t u[2];
|
||||||
|
uint64_t q;
|
||||||
} pun;
|
} pun;
|
||||||
void *p;
|
void *p;
|
||||||
char qchar;
|
|
||||||
char *s, *se;
|
|
||||||
bool longdouble;
|
bool longdouble;
|
||||||
long double ldbl;
|
long double ldbl;
|
||||||
wchar_t charbuf[1];
|
wchar_t charbuf[1];
|
||||||
|
@ -119,6 +129,7 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
||||||
int (*out)(long, void *);
|
int (*out)(long, void *);
|
||||||
unsigned char signbit, log2base;
|
unsigned char signbit, log2base;
|
||||||
int c, d, k, w, i1, ui, bw, bex;
|
int c, d, k, w, i1, ui, bw, bex;
|
||||||
|
char *s, *q, *se, qchar, special[8];
|
||||||
int sgn, alt, sign, prec, prec1, flags, width, decpt, lasterr;
|
int sgn, alt, sign, prec, prec1, flags, width, decpt, lasterr;
|
||||||
|
|
||||||
lasterr = errno;
|
lasterr = errno;
|
||||||
|
@ -128,7 +139,7 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
||||||
/* %[flags][width][.prec][length] */
|
/* %[flags][width][.prec][length] */
|
||||||
if (*format != '%') {
|
if (*format != '%') {
|
||||||
/* no */
|
/* no */
|
||||||
if (out(*format, arg) == -1) return -1;
|
PUT(*format);
|
||||||
format++;
|
format++;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
|
@ -308,6 +319,7 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'F':
|
||||||
case 'f':
|
case 'f':
|
||||||
if (!(flags & FLAGS_PRECISION)) prec = 6;
|
if (!(flags & FLAGS_PRECISION)) prec = 6;
|
||||||
if (longdouble) {
|
if (longdouble) {
|
||||||
|
@ -317,19 +329,25 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
||||||
}
|
}
|
||||||
FormatDtoa:
|
FormatDtoa:
|
||||||
if (!weaken(__fmt_dtoa)) {
|
if (!weaken(__fmt_dtoa)) {
|
||||||
p = "nan";
|
p = "?";
|
||||||
goto FormatString;
|
goto FormatThatThing;
|
||||||
}
|
}
|
||||||
s = weaken(__fmt_dtoa)(pun.d, 3, prec, &decpt, &sgn, &se);
|
s = weaken(__fmt_dtoa)(pun.d, 3, prec, &decpt, &sgn, &se);
|
||||||
if (decpt == 9999) {
|
if (decpt == 9999) {
|
||||||
Format9999:
|
Format9999:
|
||||||
prec = alt = 0;
|
p = q = memset(special, 0, sizeof(special));
|
||||||
flags &= ~FLAGS_PRECISION;
|
if (sgn) {
|
||||||
if (*s == 'N') {
|
*q++ = '-';
|
||||||
p = s;
|
} else if (flags & FLAGS_PLUS) {
|
||||||
goto FormatString;
|
*q++ = '+';
|
||||||
|
} else if (flags & FLAGS_SPACE) {
|
||||||
|
*q++ = ' ';
|
||||||
}
|
}
|
||||||
decpt = strlen(s);
|
memcpy(q, kSpecialFloats[*s == 'N'][d >= 'a'], 4);
|
||||||
|
FormatThatThing:
|
||||||
|
prec = alt = 0;
|
||||||
|
flags &= ~(FLAGS_PRECISION | FLAGS_PLUS | FLAGS_SPACE);
|
||||||
|
goto FormatString;
|
||||||
}
|
}
|
||||||
FormatReal:
|
FormatReal:
|
||||||
if (sgn) sign = '-';
|
if (sgn) sign = '-';
|
||||||
|
@ -347,20 +365,21 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
||||||
}
|
}
|
||||||
if (width > 0 && !(flags & FLAGS_LEFT)) {
|
if (width > 0 && !(flags & FLAGS_LEFT)) {
|
||||||
if (flags & FLAGS_ZEROPAD) {
|
if (flags & FLAGS_ZEROPAD) {
|
||||||
if (sign) out(sign, arg);
|
if (sign) PUT(sign);
|
||||||
sign = 0;
|
sign = 0;
|
||||||
do out('0', arg);
|
do PUT('0');
|
||||||
while (--width > 0);
|
while (--width > 0);
|
||||||
} else
|
} else {
|
||||||
do out(' ', arg);
|
do PUT(' ');
|
||||||
while (--width > 0);
|
while (--width > 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (sign) out(sign, arg);
|
if (sign) PUT(sign);
|
||||||
if (decpt <= 0) {
|
if (decpt <= 0) {
|
||||||
out('0', arg);
|
PUT('0');
|
||||||
if (prec > 0 || alt) out('.', arg);
|
if (prec > 0 || alt) PUT('.');
|
||||||
while (decpt < 0) {
|
while (decpt < 0) {
|
||||||
out('0', arg);
|
PUT('0');
|
||||||
prec--;
|
prec--;
|
||||||
decpt++;
|
decpt++;
|
||||||
}
|
}
|
||||||
|
@ -371,9 +390,9 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
||||||
} else {
|
} else {
|
||||||
c = '0';
|
c = '0';
|
||||||
}
|
}
|
||||||
out(c, arg);
|
PUT(c);
|
||||||
} while (--decpt > 0);
|
} while (--decpt > 0);
|
||||||
if (prec > 0 || alt) out('.', arg);
|
if (prec > 0 || alt) PUT('.');
|
||||||
}
|
}
|
||||||
while (--prec >= 0) {
|
while (--prec >= 0) {
|
||||||
if ((c = *s)) {
|
if ((c = *s)) {
|
||||||
|
@ -381,10 +400,10 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
||||||
} else {
|
} else {
|
||||||
c = '0';
|
c = '0';
|
||||||
}
|
}
|
||||||
out(c, arg);
|
PUT(c);
|
||||||
}
|
}
|
||||||
while (--width >= 0) {
|
while (--width >= 0) {
|
||||||
out(' ', arg);
|
PUT(' ');
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -398,8 +417,8 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
||||||
}
|
}
|
||||||
if (prec < 0) prec = 0;
|
if (prec < 0) prec = 0;
|
||||||
if (!weaken(__fmt_dtoa)) {
|
if (!weaken(__fmt_dtoa)) {
|
||||||
p = "nan";
|
p = "?";
|
||||||
goto FormatString;
|
goto FormatThatThing;
|
||||||
}
|
}
|
||||||
s = weaken(__fmt_dtoa)(pun.d, prec ? 2 : 0, prec, &decpt, &sgn, &se);
|
s = weaken(__fmt_dtoa)(pun.d, prec ? 2 : 0, prec, &decpt, &sgn, &se);
|
||||||
if (decpt == 9999) goto Format9999;
|
if (decpt == 9999) goto Format9999;
|
||||||
|
@ -408,7 +427,6 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
||||||
if (!prec) {
|
if (!prec) {
|
||||||
prec = c;
|
prec = c;
|
||||||
prec1 = c + (s[1] || alt ? 5 : 4);
|
prec1 = c + (s[1] || alt ? 5 : 4);
|
||||||
/* %.0g gives 10 rather than 1e1 */
|
|
||||||
}
|
}
|
||||||
if (decpt > -4 && decpt <= prec1) {
|
if (decpt > -4 && decpt <= prec1) {
|
||||||
if (alt) {
|
if (alt) {
|
||||||
|
@ -434,8 +452,8 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
||||||
}
|
}
|
||||||
if (prec < 0) prec = 0;
|
if (prec < 0) prec = 0;
|
||||||
if (!weaken(__fmt_dtoa)) {
|
if (!weaken(__fmt_dtoa)) {
|
||||||
p = "nan";
|
p = "?";
|
||||||
goto FormatString;
|
goto FormatThatThing;
|
||||||
}
|
}
|
||||||
s = weaken(__fmt_dtoa)(pun.d, 2, prec + 1, &decpt, &sgn, &se);
|
s = weaken(__fmt_dtoa)(pun.d, 2, prec + 1, &decpt, &sgn, &se);
|
||||||
if (decpt == 9999) goto Format9999;
|
if (decpt == 9999) goto Format9999;
|
||||||
|
@ -452,44 +470,44 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
||||||
}
|
}
|
||||||
if (width > 0 && !(flags & FLAGS_LEFT)) {
|
if (width > 0 && !(flags & FLAGS_LEFT)) {
|
||||||
if (flags & FLAGS_ZEROPAD) {
|
if (flags & FLAGS_ZEROPAD) {
|
||||||
if (sign) out(sign, arg);
|
if (sign) PUT(sign);
|
||||||
sign = 0;
|
sign = 0;
|
||||||
do out('0', arg);
|
do PUT('0');
|
||||||
while (--width > 0);
|
while (--width > 0);
|
||||||
} else {
|
} else {
|
||||||
do out(' ', arg);
|
do PUT(' ');
|
||||||
while (--width > 0);
|
while (--width > 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sign) out(sign, arg);
|
if (sign) PUT(sign);
|
||||||
out(*s++, arg);
|
PUT(*s++);
|
||||||
if (prec || alt) out('.', arg);
|
if (prec || alt) PUT('.');
|
||||||
while (--prec >= 0) {
|
while (--prec >= 0) {
|
||||||
if ((c = *s)) {
|
if ((c = *s)) {
|
||||||
s++;
|
s++;
|
||||||
} else {
|
} else {
|
||||||
c = '0';
|
c = '0';
|
||||||
}
|
}
|
||||||
out(c, arg);
|
PUT(c);
|
||||||
}
|
}
|
||||||
out(d, arg);
|
PUT(d);
|
||||||
if (decpt < 0) {
|
if (decpt < 0) {
|
||||||
out('-', arg);
|
PUT('-');
|
||||||
decpt = -decpt;
|
decpt = -decpt;
|
||||||
} else {
|
} else {
|
||||||
out('+', arg);
|
PUT('+');
|
||||||
}
|
}
|
||||||
for (c = 2, k = 10; 10 * k <= decpt; c++, k *= 10) {
|
for (c = 2, k = 10; 10 * k <= decpt; c++, k *= 10) {
|
||||||
}
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
i1 = decpt / k;
|
i1 = decpt / k;
|
||||||
out(i1 + '0', arg);
|
PUT(i1 + '0');
|
||||||
if (--c <= 0) break;
|
if (--c <= 0) break;
|
||||||
decpt -= i1 * k;
|
decpt -= i1 * k;
|
||||||
decpt *= 10;
|
decpt *= 10;
|
||||||
}
|
}
|
||||||
while (--width >= 0) {
|
while (--width >= 0) {
|
||||||
out(' ', arg);
|
PUT(' ');
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -507,12 +525,12 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
||||||
if ((pun.u[1] & 0x7ff00000) == 0x7ff00000) {
|
if ((pun.u[1] & 0x7ff00000) == 0x7ff00000) {
|
||||||
goto FormatDtoa;
|
goto FormatDtoa;
|
||||||
}
|
}
|
||||||
|
if (pun.u[1] & 0x80000000) {
|
||||||
|
sign = '-';
|
||||||
|
pun.u[1] &= 0x7fffffff;
|
||||||
|
}
|
||||||
if (pun.d) {
|
if (pun.d) {
|
||||||
c = '1';
|
c = '1';
|
||||||
if (pun.u[1] & 0x80000000) {
|
|
||||||
sign = '-';
|
|
||||||
pun.u[1] &= 0x7fffffff;
|
|
||||||
}
|
|
||||||
bex = (pun.u[1] >> 20) - 1023;
|
bex = (pun.u[1] >> 20) - 1023;
|
||||||
pun.u[1] &= 0xfffff;
|
pun.u[1] &= 0xfffff;
|
||||||
if (bex == -1023) {
|
if (bex == -1023) {
|
||||||
|
@ -595,49 +613,52 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
||||||
if (sign) --width;
|
if (sign) --width;
|
||||||
if (prec || alt) --width;
|
if (prec || alt) --width;
|
||||||
}
|
}
|
||||||
|
if (pun.q && prec > 0) {
|
||||||
|
width -= ROUNDUP(bsrl(pun.q) + 1, 4) >> 2;
|
||||||
|
}
|
||||||
if (width > 0 && !(flags & FLAGS_LEFT)) {
|
if (width > 0 && !(flags & FLAGS_LEFT)) {
|
||||||
if (flags & FLAGS_ZEROPAD) {
|
if (flags & FLAGS_ZEROPAD) {
|
||||||
if (sign) {
|
if (sign) {
|
||||||
out(sign, arg);
|
PUT(sign);
|
||||||
sign = 0;
|
sign = 0;
|
||||||
}
|
}
|
||||||
do out('0', arg);
|
do PUT('0');
|
||||||
while (--width > 0);
|
while (--width > 0);
|
||||||
} else {
|
} else {
|
||||||
do out(' ', arg);
|
do PUT(' ');
|
||||||
while (--width > 0);
|
while (--width > 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sign) out(sign, arg);
|
if (sign) PUT(sign);
|
||||||
out('0', arg);
|
PUT('0');
|
||||||
out(alphabet[17], arg);
|
PUT(alphabet[17]);
|
||||||
out(c, arg);
|
PUT(c);
|
||||||
if (prec > 0 || alt) out('.', arg);
|
if (prec > 0 || alt) PUT('.');
|
||||||
if (prec > 0) {
|
if (prec > 0) {
|
||||||
if ((i1 = prec) > 5) i1 = 5;
|
if ((i1 = prec) > 5) i1 = 5;
|
||||||
prec -= i1;
|
prec -= i1;
|
||||||
do {
|
do {
|
||||||
out(alphabet[(pun.u[1] >> 16) & 0xf], arg);
|
PUT(alphabet[(pun.u[1] >> 16) & 0xf]);
|
||||||
pun.u[1] <<= 4;
|
pun.u[1] <<= 4;
|
||||||
} while (--i1 > 0);
|
} while (--i1 > 0);
|
||||||
while (prec > 0) {
|
while (prec > 0) {
|
||||||
--prec;
|
--prec;
|
||||||
out(alphabet[(pun.u[0] >> 28) & 0xf], arg);
|
PUT(alphabet[(pun.u[0] >> 28) & 0xf]);
|
||||||
pun.u[0] <<= 4;
|
pun.u[0] <<= 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out(alphabet[16], arg);
|
PUT(alphabet[16]);
|
||||||
if (bex < 0) {
|
if (bex < 0) {
|
||||||
out('-', arg);
|
PUT('-');
|
||||||
bex = -bex;
|
bex = -bex;
|
||||||
} else {
|
} else {
|
||||||
out('+', arg);
|
PUT('+');
|
||||||
}
|
}
|
||||||
for (c = 1; 10 * c <= bex; c *= 10) {
|
for (c = 1; 10 * c <= bex; c *= 10) {
|
||||||
}
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
i1 = bex / c;
|
i1 = bex / c;
|
||||||
out('0' + i1, arg);
|
PUT('0' + i1);
|
||||||
if (!--bw) break;
|
if (!--bw) break;
|
||||||
bex -= i1 * c;
|
bex -= i1 * c;
|
||||||
bex *= 10;
|
bex *= 10;
|
||||||
|
@ -645,11 +666,11 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case '%':
|
case '%':
|
||||||
if (out('%', arg) == -1) return -1;
|
PUT('%');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (out(format[-1], arg) == -1) return -1;
|
PUT(format[-1]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,6 @@
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
int Printf(const char *, ...);
|
|
||||||
int Sprintf(char *, const char *, ...);
|
|
||||||
|
|
||||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||||
│ cosmopolitan § standard i/o ─╬─│┼
|
│ cosmopolitan § standard i/o ─╬─│┼
|
||||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||||
|
|
199
test/libc/fmt/fmt_test.c
Normal file
199
test/libc/fmt/fmt_test.c
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/fmt/fmt.h"
|
||||||
|
#include "libc/math.h"
|
||||||
|
#include "libc/runtime/gc.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
|
#include "libc/testlib/testlib.h"
|
||||||
|
#include "libc/x/x.h"
|
||||||
|
|
||||||
|
TEST(RealFormatting, g) {
|
||||||
|
EXPECT_STREQ("1", gc(xasprintf("%g", 1.)));
|
||||||
|
EXPECT_STREQ("-1", gc(xasprintf("%g", -1.)));
|
||||||
|
EXPECT_STREQ("10", gc(xasprintf("%g", 10.)));
|
||||||
|
EXPECT_STREQ("10", gc(xasprintf("%.0g", 10.)));
|
||||||
|
EXPECT_STREQ("-10", gc(xasprintf("%g", -10.)));
|
||||||
|
EXPECT_STREQ("-10", gc(xasprintf("%.0g", -10.)));
|
||||||
|
EXPECT_STREQ("1e+100", gc(xasprintf("%g", 1e100)));
|
||||||
|
EXPECT_STREQ("1e-100", gc(xasprintf("%g", 1e-100)));
|
||||||
|
EXPECT_STREQ("-1e-100", gc(xasprintf("%g", -1e-100)));
|
||||||
|
EXPECT_STREQ("3.14159", gc(xasprintf("%g", 0x1.921fb54442d1846ap+1)));
|
||||||
|
EXPECT_STREQ("0", gc(xasprintf("%g", 0.)));
|
||||||
|
EXPECT_STREQ("-0", gc(xasprintf("%g", -0.)));
|
||||||
|
EXPECT_STREQ("nan", gc(xasprintf("%g", NAN)));
|
||||||
|
EXPECT_STREQ("-nan", gc(xasprintf("%g", -NAN)));
|
||||||
|
EXPECT_STREQ("inf", gc(xasprintf("%g", INFINITY)));
|
||||||
|
EXPECT_STREQ("-inf", gc(xasprintf("%g", -INFINITY)));
|
||||||
|
EXPECT_STREQ("2.22507e-308", gc(xasprintf("%g", __DBL_MIN__)));
|
||||||
|
EXPECT_STREQ("1.79769e+308", gc(xasprintf("%g", __DBL_MAX__)));
|
||||||
|
EXPECT_STREQ("0", gc(xasprintf("%G", 0.)));
|
||||||
|
EXPECT_STREQ("-0", gc(xasprintf("%G", -0.)));
|
||||||
|
EXPECT_STREQ("NAN", gc(xasprintf("%G", NAN)));
|
||||||
|
EXPECT_STREQ("-NAN", gc(xasprintf("%G", -NAN)));
|
||||||
|
EXPECT_STREQ("INF", gc(xasprintf("%G", INFINITY)));
|
||||||
|
EXPECT_STREQ("-INF", gc(xasprintf("%G", -INFINITY)));
|
||||||
|
EXPECT_STREQ("2.22507E-308", gc(xasprintf("%G", __DBL_MIN__)));
|
||||||
|
EXPECT_STREQ("1.79769E+308", gc(xasprintf("%G", __DBL_MAX__)));
|
||||||
|
EXPECT_STREQ(" 0", gc(xasprintf("%13g", 0.)));
|
||||||
|
EXPECT_STREQ(" -0", gc(xasprintf("%13g", -0.)));
|
||||||
|
EXPECT_STREQ(" nan", gc(xasprintf("%13g", NAN)));
|
||||||
|
EXPECT_STREQ(" -nan", gc(xasprintf("%13g", -NAN)));
|
||||||
|
EXPECT_STREQ(" inf", gc(xasprintf("%13g", INFINITY)));
|
||||||
|
EXPECT_STREQ(" -inf", gc(xasprintf("%13g", -INFINITY)));
|
||||||
|
EXPECT_STREQ(" 2.22507e-308", gc(xasprintf("%13g", __DBL_MIN__)));
|
||||||
|
EXPECT_STREQ(" 1.79769e+308", gc(xasprintf("%13g", __DBL_MAX__)));
|
||||||
|
EXPECT_STREQ(" 0", gc(xasprintf("%13G", 0.)));
|
||||||
|
EXPECT_STREQ(" -0", gc(xasprintf("%13G", -0.)));
|
||||||
|
EXPECT_STREQ(" NAN", gc(xasprintf("%13G", NAN)));
|
||||||
|
EXPECT_STREQ(" -NAN", gc(xasprintf("%13G", -NAN)));
|
||||||
|
EXPECT_STREQ(" INF", gc(xasprintf("%13G", INFINITY)));
|
||||||
|
EXPECT_STREQ(" -INF", gc(xasprintf("%13G", -INFINITY)));
|
||||||
|
EXPECT_STREQ(" 2.22507E-308", gc(xasprintf("%13G", __DBL_MIN__)));
|
||||||
|
EXPECT_STREQ(" 1.79769E+308", gc(xasprintf("%13G", __DBL_MAX__)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(RealFormatting, f) {
|
||||||
|
EXPECT_STREQ("3.141593", gc(xasprintf("%f", 0x1.921fb54442d1846ap+1)));
|
||||||
|
EXPECT_STREQ("3.1415926535897931",
|
||||||
|
gc(xasprintf("%.16f", 0x1.921fb54442d1846ap+1)));
|
||||||
|
EXPECT_STREQ("100000000000000001590289110975991804683608085639452813"
|
||||||
|
"89781327557747838772170381060813469985856815104.000000",
|
||||||
|
gc(xasprintf("%f", 1e100)));
|
||||||
|
EXPECT_STREQ("0.000000", gc(xasprintf("%f", 0.)));
|
||||||
|
EXPECT_STREQ("-0.000000", gc(xasprintf("%f", -0.)));
|
||||||
|
EXPECT_STREQ("nan", gc(xasprintf("%f", NAN)));
|
||||||
|
EXPECT_STREQ("-nan", gc(xasprintf("%f", -NAN)));
|
||||||
|
EXPECT_STREQ("inf", gc(xasprintf("%f", INFINITY)));
|
||||||
|
EXPECT_STREQ("-inf", gc(xasprintf("%f", -INFINITY)));
|
||||||
|
EXPECT_STREQ("0.000000", gc(xasprintf("%f", __DBL_MIN__)));
|
||||||
|
EXPECT_STREQ(
|
||||||
|
"179769313486231570814527423731704356798070567525844996598917476803157260"
|
||||||
|
"780028538760589558632766878171540458953514382464234321326889464182768467"
|
||||||
|
"546703537516986049910576551282076245490090389328944075868508455133942304"
|
||||||
|
"583236903222948165808559332123348274797826204144723168738177180919299881"
|
||||||
|
"250404026184124858368.000000",
|
||||||
|
gc(xasprintf("%f", __DBL_MAX__)));
|
||||||
|
EXPECT_STREQ("0.000000", gc(xasprintf("%F", 0.)));
|
||||||
|
EXPECT_STREQ("-0.000000", gc(xasprintf("%F", -0.)));
|
||||||
|
EXPECT_STREQ("NAN", gc(xasprintf("%F", NAN)));
|
||||||
|
EXPECT_STREQ("-NAN", gc(xasprintf("%F", -NAN)));
|
||||||
|
EXPECT_STREQ("INF", gc(xasprintf("%F", INFINITY)));
|
||||||
|
EXPECT_STREQ("-INF", gc(xasprintf("%F", -INFINITY)));
|
||||||
|
EXPECT_STREQ("0.000000", gc(xasprintf("%F", __DBL_MIN__)));
|
||||||
|
EXPECT_STREQ(
|
||||||
|
"179769313486231570814527423731704356798070567525844996598917476803157260"
|
||||||
|
"780028538760589558632766878171540458953514382464234321326889464182768467"
|
||||||
|
"546703537516986049910576551282076245490090389328944075868508455133942304"
|
||||||
|
"583236903222948165808559332123348274797826204144723168738177180919299881"
|
||||||
|
"250404026184124858368.000000",
|
||||||
|
gc(xasprintf("%F", __DBL_MAX__)));
|
||||||
|
EXPECT_STREQ(" 0.000000", gc(xasprintf("%10f", 0.)));
|
||||||
|
EXPECT_STREQ(" -0.000000", gc(xasprintf("%10f", -0.)));
|
||||||
|
EXPECT_STREQ(" nan", gc(xasprintf("%10f", NAN)));
|
||||||
|
EXPECT_STREQ(" -nan", gc(xasprintf("%10f", -NAN)));
|
||||||
|
EXPECT_STREQ(" inf", gc(xasprintf("%10f", INFINITY)));
|
||||||
|
EXPECT_STREQ(" -inf", gc(xasprintf("%10f", -INFINITY)));
|
||||||
|
EXPECT_STREQ(" 0.000000", gc(xasprintf("%10f", __DBL_MIN__)));
|
||||||
|
EXPECT_STREQ(
|
||||||
|
"179769313486231570814527423731704356798070567525844996598917476803157260"
|
||||||
|
"780028538760589558632766878171540458953514382464234321326889464182768467"
|
||||||
|
"546703537516986049910576551282076245490090389328944075868508455133942304"
|
||||||
|
"583236903222948165808559332123348274797826204144723168738177180919299881"
|
||||||
|
"250404026184124858368.000000",
|
||||||
|
gc(xasprintf("%10f", __DBL_MAX__)));
|
||||||
|
EXPECT_STREQ(" 0.000000", gc(xasprintf("%10F", 0.)));
|
||||||
|
EXPECT_STREQ(" -0.000000", gc(xasprintf("%10F", -0.)));
|
||||||
|
EXPECT_STREQ(" NAN", gc(xasprintf("%10F", NAN)));
|
||||||
|
EXPECT_STREQ(" -NAN", gc(xasprintf("%10F", -NAN)));
|
||||||
|
EXPECT_STREQ(" INF", gc(xasprintf("%10F", INFINITY)));
|
||||||
|
EXPECT_STREQ(" -INF", gc(xasprintf("%10F", -INFINITY)));
|
||||||
|
EXPECT_STREQ(" 0.000000", gc(xasprintf("%10F", __DBL_MIN__)));
|
||||||
|
EXPECT_STREQ(
|
||||||
|
"179769313486231570814527423731704356798070567525844996598917476803157260"
|
||||||
|
"780028538760589558632766878171540458953514382464234321326889464182768467"
|
||||||
|
"546703537516986049910576551282076245490090389328944075868508455133942304"
|
||||||
|
"583236903222948165808559332123348274797826204144723168738177180919299881"
|
||||||
|
"250404026184124858368.000000",
|
||||||
|
gc(xasprintf("%10F", __DBL_MAX__)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(RealFormatting, e) {
|
||||||
|
EXPECT_STREQ("3.14159", gc(xasprintf("%g", 0x1.921fb54442d1846ap+1)));
|
||||||
|
EXPECT_STREQ("3.141592653589793",
|
||||||
|
gc(xasprintf("%.16g", 0x1.921fb54442d1846ap+1)));
|
||||||
|
EXPECT_STREQ("1.000000e+100", gc(xasprintf("%e", 1e100)));
|
||||||
|
EXPECT_STREQ("1.000000E+100", gc(xasprintf("%E", 1e100)));
|
||||||
|
EXPECT_STREQ(" 0.000000e+00", gc(xasprintf("%24e", 0.)));
|
||||||
|
EXPECT_STREQ(" -0.000000e+00", gc(xasprintf("%24e", -0.)));
|
||||||
|
EXPECT_STREQ(" nan", gc(xasprintf("%24e", NAN)));
|
||||||
|
EXPECT_STREQ(" -nan", gc(xasprintf("%24e", -NAN)));
|
||||||
|
EXPECT_STREQ(" inf", gc(xasprintf("%24e", INFINITY)));
|
||||||
|
EXPECT_STREQ(" -inf", gc(xasprintf("%24e", -INFINITY)));
|
||||||
|
EXPECT_STREQ(" 2.225074e-308", gc(xasprintf("%24e", __DBL_MIN__)));
|
||||||
|
EXPECT_STREQ(" 1.797693e+308", gc(xasprintf("%24e", __DBL_MAX__)));
|
||||||
|
EXPECT_STREQ(" 0.000000E+00", gc(xasprintf("%24E", 0.)));
|
||||||
|
EXPECT_STREQ(" -0.000000E+00", gc(xasprintf("%24E", -0.)));
|
||||||
|
EXPECT_STREQ(" NAN", gc(xasprintf("%24E", NAN)));
|
||||||
|
EXPECT_STREQ(" -NAN", gc(xasprintf("%24E", -NAN)));
|
||||||
|
EXPECT_STREQ(" INF", gc(xasprintf("%24E", INFINITY)));
|
||||||
|
EXPECT_STREQ(" -INF", gc(xasprintf("%24E", -INFINITY)));
|
||||||
|
EXPECT_STREQ(" 2.225074E-308", gc(xasprintf("%24E", __DBL_MIN__)));
|
||||||
|
EXPECT_STREQ(" 1.797693E+308", gc(xasprintf("%24E", __DBL_MAX__)));
|
||||||
|
EXPECT_STREQ(" +0.000000e+00", gc(xasprintf("%+24e", 0.)));
|
||||||
|
EXPECT_STREQ(" -0.000000e+00", gc(xasprintf("%+24e", -0.)));
|
||||||
|
EXPECT_STREQ(" +nan", gc(xasprintf("%+24e", NAN)));
|
||||||
|
EXPECT_STREQ(" -nan", gc(xasprintf("%+24e", -NAN)));
|
||||||
|
EXPECT_STREQ(" +inf", gc(xasprintf("%+24e", INFINITY)));
|
||||||
|
EXPECT_STREQ(" -inf", gc(xasprintf("%+24e", -INFINITY)));
|
||||||
|
EXPECT_STREQ(" +2.225074e-308", gc(xasprintf("%+24e", __DBL_MIN__)));
|
||||||
|
EXPECT_STREQ(" +1.797693e+308", gc(xasprintf("%+24e", __DBL_MAX__)));
|
||||||
|
EXPECT_STREQ(" +0.000000E+00", gc(xasprintf("%+24E", 0.)));
|
||||||
|
EXPECT_STREQ(" -0.000000E+00", gc(xasprintf("%+24E", -0.)));
|
||||||
|
EXPECT_STREQ(" +NAN", gc(xasprintf("%+24E", NAN)));
|
||||||
|
EXPECT_STREQ(" -NAN", gc(xasprintf("%+24E", -NAN)));
|
||||||
|
EXPECT_STREQ(" +INF", gc(xasprintf("%+24E", INFINITY)));
|
||||||
|
EXPECT_STREQ(" -INF", gc(xasprintf("%+24E", -INFINITY)));
|
||||||
|
EXPECT_STREQ(" +2.225074E-308", gc(xasprintf("%+24E", __DBL_MIN__)));
|
||||||
|
EXPECT_STREQ(" +1.797693E+308", gc(xasprintf("%+24E", __DBL_MAX__)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(RealFormatting, a) {
|
||||||
|
EXPECT_STREQ("0x1.921fb54442d18p+1",
|
||||||
|
gc(xasprintf("%a", 0x1.921fb54442d1846ap+1)));
|
||||||
|
EXPECT_STREQ("0X1.921FB54442D18P+1",
|
||||||
|
gc(xasprintf("%A", 0x1.921fb54442d1846ap+1)));
|
||||||
|
EXPECT_STREQ(" 0x0p+0", gc(xasprintf("%24a", 0.)));
|
||||||
|
EXPECT_STREQ(" -0x0p+0", gc(xasprintf("%24a", -0.)));
|
||||||
|
EXPECT_STREQ(" nan", gc(xasprintf("%24a", NAN)));
|
||||||
|
EXPECT_STREQ(" -nan", gc(xasprintf("%24a", -NAN)));
|
||||||
|
EXPECT_STREQ(" inf", gc(xasprintf("%24a", INFINITY)));
|
||||||
|
EXPECT_STREQ(" -inf", gc(xasprintf("%24a", -INFINITY)));
|
||||||
|
EXPECT_STREQ(" 0x1p-1022", gc(xasprintf("%24a", __DBL_MIN__)));
|
||||||
|
EXPECT_STREQ(" 0x1.fffffffffffffp+1023", gc(xasprintf("%24a", __DBL_MAX__)));
|
||||||
|
EXPECT_STREQ(" 0X0P+0", gc(xasprintf("%24A", 0.)));
|
||||||
|
EXPECT_STREQ(" -0X0P+0", gc(xasprintf("%24A", -0.)));
|
||||||
|
EXPECT_STREQ(" NAN", gc(xasprintf("%24A", NAN)));
|
||||||
|
EXPECT_STREQ(" -NAN", gc(xasprintf("%24A", -NAN)));
|
||||||
|
EXPECT_STREQ(" INF", gc(xasprintf("%24A", INFINITY)));
|
||||||
|
EXPECT_STREQ(" -INF", gc(xasprintf("%24A", -INFINITY)));
|
||||||
|
EXPECT_STREQ(" 0X1P-1022", gc(xasprintf("%24A", __DBL_MIN__)));
|
||||||
|
EXPECT_STREQ(" 0X1.FFFFFFFFFFFFFP+1023", gc(xasprintf("%24A", __DBL_MAX__)));
|
||||||
|
EXPECT_STREQ(" 0X1.E9A488E8A71DEP+14", gc(xasprintf("%24A", 31337.1337)));
|
||||||
|
EXPECT_STREQ(" -0X1.E9A488E8A71DEP+14", gc(xasprintf("%24A", -31337.1337)));
|
||||||
|
}
|
|
@ -1,68 +0,0 @@
|
||||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
|
||||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
|
||||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
|
||||||
│ │
|
|
||||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
|
||||||
│ any purpose with or without fee is hereby granted, provided that the │
|
|
||||||
│ above copyright notice and this permission notice appear in all copies. │
|
|
||||||
│ │
|
|
||||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
|
||||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
|
||||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
|
||||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
|
||||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
|
||||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
|
||||||
#include "libc/fmt/fmt.h"
|
|
||||||
#include "libc/math.h"
|
|
||||||
#include "libc/runtime/gc.h"
|
|
||||||
#include "libc/testlib/testlib.h"
|
|
||||||
#include "libc/x/x.h"
|
|
||||||
|
|
||||||
TEST(RealFormatting, g) {
|
|
||||||
EXPECT_STREQ("nan", gc(xasprintf("%g", NAN)));
|
|
||||||
EXPECT_STREQ("-nan", gc(xasprintf("%g", -NAN)));
|
|
||||||
EXPECT_STREQ("inf", gc(xasprintf("%g", INFINITY)));
|
|
||||||
EXPECT_STREQ("-inf", gc(xasprintf("%g", -INFINITY)));
|
|
||||||
EXPECT_STREQ("0", gc(xasprintf("%g", 0.)));
|
|
||||||
EXPECT_STREQ("-0", gc(xasprintf("%g", -0.)));
|
|
||||||
EXPECT_STREQ("1", gc(xasprintf("%g", 1.)));
|
|
||||||
EXPECT_STREQ("-1", gc(xasprintf("%g", -1.)));
|
|
||||||
EXPECT_STREQ("10", gc(xasprintf("%g", 10.)));
|
|
||||||
EXPECT_STREQ("10", gc(xasprintf("%.0g", 10.)));
|
|
||||||
EXPECT_STREQ("-10", gc(xasprintf("%g", -10.)));
|
|
||||||
EXPECT_STREQ("-10", gc(xasprintf("%.0g", -10.)));
|
|
||||||
EXPECT_STREQ(" -10", gc(xasprintf("%10g", -10.)));
|
|
||||||
EXPECT_STREQ(" -10", gc(xasprintf("%*g", 10, -10.)));
|
|
||||||
EXPECT_STREQ("1e+100", gc(xasprintf("%g", 1e100)));
|
|
||||||
EXPECT_STREQ("1e-100", gc(xasprintf("%g", 1e-100)));
|
|
||||||
EXPECT_STREQ("-1e-100", gc(xasprintf("%g", -1e-100)));
|
|
||||||
EXPECT_STREQ("3.14159", gc(xasprintf("%g", 0x1.921fb54442d1846ap+1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(RealFormatting, f) {
|
|
||||||
EXPECT_STREQ("3.141593", gc(xasprintf("%f", 0x1.921fb54442d1846ap+1)));
|
|
||||||
EXPECT_STREQ("3.1415926535897931",
|
|
||||||
gc(xasprintf("%.16f", 0x1.921fb54442d1846ap+1)));
|
|
||||||
EXPECT_STREQ("100000000000000001590289110975991804683608085639452813"
|
|
||||||
"89781327557747838772170381060813469985856815104.000000",
|
|
||||||
gc(xasprintf("%f", 1e100)));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(RealFormatting, e) {
|
|
||||||
EXPECT_STREQ("3.14159", gc(xasprintf("%g", 0x1.921fb54442d1846ap+1)));
|
|
||||||
EXPECT_STREQ("3.141592653589793",
|
|
||||||
gc(xasprintf("%.16g", 0x1.921fb54442d1846ap+1)));
|
|
||||||
EXPECT_STREQ("1.000000e+100", gc(xasprintf("%e", 1e100)));
|
|
||||||
EXPECT_STREQ("1.000000E+100", gc(xasprintf("%E", 1e100)));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(RealFormatting, a) {
|
|
||||||
EXPECT_STREQ("0x1.921fb54442d18p+1",
|
|
||||||
gc(xasprintf("%a", 0x1.921fb54442d1846ap+1)));
|
|
||||||
EXPECT_STREQ("0X1.921FB54442D18P+1",
|
|
||||||
gc(xasprintf("%A", 0x1.921fb54442d1846ap+1)));
|
|
||||||
}
|
|
4
third_party/gdtoa/dtoa.c
vendored
4
third_party/gdtoa/dtoa.c
vendored
|
@ -168,9 +168,9 @@ dtoa(double d0, int mode, int ndigits, int *decpt, int *sign, char **rve)
|
||||||
*decpt = 9999;
|
*decpt = 9999;
|
||||||
#ifdef IEEE_Arith
|
#ifdef IEEE_Arith
|
||||||
if (!word1(&d) && !(word0(&d) & 0xfffff))
|
if (!word1(&d) && !(word0(&d) & 0xfffff))
|
||||||
return nrv_alloc("inf", rve, 8 MTb);
|
return nrv_alloc("Infinity", rve, 8 MTb);
|
||||||
#endif
|
#endif
|
||||||
return nrv_alloc("nan", rve, 3 MTb);
|
return nrv_alloc("NaN", rve, 3 MTb);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef IBM
|
#ifdef IBM
|
||||||
|
|
Loading…
Add table
Reference in a new issue