bad floats for printf

This commit is contained in:
bumbread 2022-07-19 08:27:37 +11:00
parent e96c840ce4
commit 8f0bf83f0b
11 changed files with 168 additions and 23 deletions

3
.gitmodules vendored
View File

@ -1,6 +1,3 @@
[submodule "unicope"]
path = unicope
url = https://github.com/bumbread/unicope.git
[submodule "ryu"]
path = ryu
url = https://github.com/bumbread/ryu.git

25
bake.py
View File

@ -1,9 +1,29 @@
import os
import sys
import subprocess
import runpy
from pathlib import Path
for arg in sys.argv[1:]:
if arg == 'test':
test = os.getenv('test');
if test == None:
test = 'assert'
test_file = 'test/test_' + test + '.c'
subprocess.run([
'clang',
test_file,
'-Iinc',
'-g',
'-luser32',
'-lkernel32',
'-lshell32',
'-lDbghelp',
'-lciabatta.lib',
])
sys.exit(0)
# Build dependencies rq
if not Path("ryu/ryu.lib").exists():
os.chdir('ryu')
@ -23,7 +43,8 @@ do_cuik = False
inc_folders = [
'inc',
os.path.join('unicope', 'inc'),
'unicope/inc',
'ryu',
]
definitions = [
@ -101,5 +122,5 @@ compile(os.path.normpath('src/code'), compile_map)
for dir, _, f in os.walk('bin'):
if len(f) != 0:
obj_paths.append(os.path.join(dir, '*.obj'))
subprocess.run(['llvm-ar', 'rc', 'ciabatta.lib'] + obj_paths)
subprocess.run(['lib', '/out:ciabatta.lib'] + obj_paths)
print('*.obj => ciabatta.lib')

View File

@ -3,7 +3,11 @@
#include <stdlib.h>
#include <inttypes.h>
#include <limits.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <ryu/ryu.h>
typedef int (pfx(cbfn))(void *ctx, ctype ch);
@ -42,6 +46,24 @@ static inline int pfx(_dtoh)(
int width,
int flags
);
static inline int pfx(_dtoa)(
int w,
void *ctx,
pfx(cbfn) cb,
double value,
int prec,
int width,
int flags
);
static inline int pfx(_etoa)(
int w,
void *ctx,
pfx(cbfn) cb,
double value,
int prec,
int width,
int flags
);
static inline int pfx(_infnantoa)(
int w,
void *ctx,
@ -229,7 +251,38 @@ static int pfx(vprintfcb)(
case 'F':
case 'g':
case 'G':
if(*fmt == 'E' || *fmt == 'F' || *fmt == 'G') flags |= FLAG_UPPER;
char conv = tolower(*fmt);
++fmt;
double value = va_arg(va, double);
if(conv == 'f') {
w = pfx(_dtoa)(w, ctx, cb, value, prec, width, flags);
}
else if(conv == 'e') {
w = pfx(_etoa)(w, ctx, cb, value, prec, width, flags);
}
else {
int P = prec;
if(!(flags & FLAG_PREC)) P = 6;
if(prec == 0) P = 1;
union {
uint64_t bits;
double value;
} _ = {.value = value};
uint64_t bits = _.bits;
int E = (int)((bits >> 52) & 0x7ff) - 1023;
int class = fpclassify(value);
if(class == FP_SUBNORMAL || class == FP_ZERO) {
E = 0;
}
if(P > E && E >= -4) {
w = pfx(_dtoa)(w, ctx, cb, value, P-(E+1), width, flags);
}
else {
w = pfx(_etoa)(w, ctx, cb, value, P-1, width, flags);
}
}
if(w < 0) return -1;
break;
}
}
@ -516,4 +569,78 @@ static inline int pfx(_dtoh)(
return w;
}
static inline int pfx(_dtoa)(
int w,
void *ctx,
pfx(cbfn) cb,
double value,
int prec,
int width,
int flags
) {
int class = fpclassify(value);
if(class == FP_INFINITE || class == FP_NAN) {
return pfx(_infnantoa)(w, ctx, cb, value, prec, width, flags);
}
// This guy does memory allocation which makes it pretty cringe
if(!(flags & FLAG_PREC)) prec = 6;
char *buf = d2fixed(value, prec);
int len = (int)strlen(buf);
int pad = width - len;
// Left pad
if(!(flags & FLAG_LEFT) && !(flags & FLAG_ZERO)) while(pad-- > 0) {
out(' ');
}
{
char *str = buf;
while(*str) {
out(*str);
++str;
}
}
free(buf);
// Right pad
if(flags & FLAG_LEFT) while(pad-- > 0) {
out(' ');
}
return w;
}
static inline int pfx(_etoa)(
int w,
void *ctx,
pfx(cbfn) cb,
double value,
int prec,
int width,
int flags
) {
int class = fpclassify(value);
if(class == FP_INFINITE || class == FP_NAN) {
return pfx(_infnantoa)(w, ctx, cb, value, prec, width, flags);
}
// This guy does memory allocation which makes it pretty cringe
if(!(flags & FLAG_PREC)) prec = 6;
char *buf = d2exp(value, prec);
int len = (int)strlen(buf);
int pad = width - len;
// Left pad
if(!(flags & FLAG_LEFT) && !(flags & FLAG_ZERO)) while(pad-- > 0) {
out(' ');
}
{
char *str = buf;
while(*str) {
out(*str);
++str;
}
}
free(buf);
// Right pad
if(flags & FLAG_LEFT) while(pad-- > 0) {
out(' ');
}
return w;
}
#undef out

View File

@ -9,9 +9,9 @@ dname = os.path.dirname(abspath)
os.chdir(dname)
data=[
('cordic_dataf.c', 'float', 'f', 32),
('cordic_data.c', 'double', '', 64),
('cordic_datal.c', 'long double', 'l', 64),
('cordic_dataf.h', 'float', 'f', 32),
('cordic_data.h', 'double', '', 64),
('cordic_datal.h', 'long double', 'l', 64),
]
for f in data:

View File

@ -14,21 +14,21 @@ static double LOG2E = 1.442695040888963407359924681001892;
#define ftype float
#define suffix(name) name ## f
#include "cordic/cordic_dataf.c"
#include "cordic/cordic_dataf.h"
#include "gen_math.h"
#undef ftype
#undef suffix
#define ftype double
#define suffix(name) name
#include "cordic/cordic_data.c"
#include "cordic/cordic_data.h"
#include "gen_math.h"
#undef ftype
#undef suffix
#define ftype long double
#define suffix(name) name ## l
#include "cordic/cordic_datal.c"
#include "cordic/cordic_datal.h"
#include "gen_math.h"
#undef ftype
#undef suffix

View File

@ -64,7 +64,8 @@ void free(void *ptr) {
}
void *malloc(size_t size) {
return aligned_alloc(8, size);
if(size == 0) return NULL;
return HeapAlloc(heap_handle, 0, size);
}
void *realloc(void *ptr, size_t size) {

View File

@ -4,14 +4,7 @@
#include <limits.h>
int main() {
printf("%a\n", 0.0);
printf("%a\n", 2.0);
printf("%#a\n", 128.0);
printf("%a\n", 128.0);
printf("%16a|\n", 128.0);
printf("%16.2a|\n", 128.0);
printf("%-16.2a|\n", 128.0);
printf("%016.2a|\n", 128.0);
printf("%.2A\n", 3.141592);
printf("%g\n", 1.2345e+10);
printf("%g\n", 123.45);
return 0;
}

8
todo
View File

@ -31,15 +31,21 @@ stdio.h:
* The only reason to keep a linked list of all streams is to make sure they
are flushed after main() returns. I wonder if only remembering the files
with a buffer would increase performance.
* Formatted print, scan
* Formatted scan
* The float printing should include width specifiers
* %g should use decimal exponent
stdlib.h:
* Strtod base 16 must be correctly rounded
* Multibyte string functions
* Better PRNG
* Fix aligned_malloc
threads.h:
* TODO: add todo items
wchar.h:
* Basically everything
entry:
* Pretty sure there is a bug in counting wide chars for parsing argv