mirror of https://github.com/flysand7/ciabatta.git
bad floats for printf
This commit is contained in:
parent
e96c840ce4
commit
8f0bf83f0b
|
@ -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
25
bake.py
|
@ -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')
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
8
todo
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue