mirror of https://github.com/flysand7/ciabatta.git
hex float print
This commit is contained in:
parent
3ab1c1ad29
commit
e96c840ce4
|
@ -1,3 +1,6 @@
|
||||||
[submodule "unicope"]
|
[submodule "unicope"]
|
||||||
path = unicope
|
path = unicope
|
||||||
url = https://github.com/bumbread/unicope.git
|
url = https://github.com/bumbread/unicope.git
|
||||||
|
[submodule "ryu"]
|
||||||
|
path = ryu
|
||||||
|
url = https://github.com/bumbread/ryu.git
|
||||||
|
|
38
bake.py
38
bake.py
|
@ -1,6 +1,20 @@
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import runpy
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Build dependencies rq
|
||||||
|
if not Path("ryu/ryu.lib").exists():
|
||||||
|
os.chdir('ryu')
|
||||||
|
runpy.run_path(path_name='bake.py')
|
||||||
|
os.chdir('..')
|
||||||
|
|
||||||
|
if not Path('unicope/unicope.lib').exists():
|
||||||
|
os.chdir('unicope')
|
||||||
|
subprocess.run(['bake.cmd'])
|
||||||
|
os.chdir('..')
|
||||||
|
|
||||||
|
|
||||||
# General compile options
|
# General compile options
|
||||||
|
|
||||||
|
@ -63,27 +77,29 @@ def nasm_compile(file_name):
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
||||||
|
|
||||||
if not do_cuik:
|
|
||||||
# Compile the platform-independent part
|
# Compile the platform-independent part
|
||||||
|
obj_paths = ['ryu/ryu.lib', 'unicope/unicope.lib']
|
||||||
compile_map = {}
|
compile_map = {}
|
||||||
compile_map['.c'] = clang_compile
|
|
||||||
compile_map['.asm'] = nasm_compile
|
compile_map['.asm'] = nasm_compile
|
||||||
compile(os.path.normpath('src/code'), compile_map)
|
|
||||||
|
|
||||||
|
if not do_cuik:
|
||||||
|
compile_map['.c'] = clang_compile
|
||||||
# Add the platform folder to includes and compile platform-dependent part
|
# Add the platform folder to includes and compile platform-dependent part
|
||||||
inc_folders.append(os.path.join('src', platform))
|
inc_folders.append(os.path.join('src', platform))
|
||||||
compile(os.path.normpath(os.path.join('src', platform)), compile_map)
|
compile(os.path.normpath(os.path.join('src', platform)), compile_map)
|
||||||
|
|
||||||
|
else:
|
||||||
|
src = 'src/code/*.c'
|
||||||
|
os_src = 'src/' + platform
|
||||||
|
cuik_flags += '-c -o ciabatta.obj'.split(' ') + [src, os_src]
|
||||||
|
subprocess.run(['cuik'] + cuik_flags)
|
||||||
|
obj_paths.append('ciabatta.obj')
|
||||||
|
|
||||||
|
compile(os.path.normpath('src/code'), compile_map)
|
||||||
|
|
||||||
# Make an archive of all object files
|
# Make an archive of all object files
|
||||||
obj_paths = []
|
|
||||||
for dir, _, f in os.walk('bin'):
|
for dir, _, f in os.walk('bin'):
|
||||||
if len(f) != 0:
|
if len(f) != 0:
|
||||||
obj_paths.append(os.path.join(dir, '*.obj'))
|
obj_paths.append(os.path.join(dir, '*.obj'))
|
||||||
subprocess.run(['llvm-ar', 'rc', 'ciabatta.lib'] + obj_paths)
|
subprocess.run(['llvm-ar', 'rc', 'ciabatta.lib'] + obj_paths)
|
||||||
else:
|
print('*.obj => ciabatta.lib')
|
||||||
src = os.path.join('src', 'code', '*.c')
|
|
||||||
os_src = os.path.join('src', platform)
|
|
||||||
cmd = cuik_flags + '-c -o ciabatta.obj'.split(' ') + [src, os_src]
|
|
||||||
print(cmd)
|
|
||||||
subprocess.run(['cuik'] + cmd)
|
|
||||||
subprocess.run('lib', '/out:ciabatta.lib', 'ciabatta.obj')
|
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit bfc7d0b020e34e5c32e9ffbc94c0abe5e8559d42
|
|
@ -1,8 +1,9 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <inttypes.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
typedef int (pfx(cbfn))(void *ctx, ctype ch);
|
typedef int (pfx(cbfn))(void *ctx, ctype ch);
|
||||||
|
|
||||||
|
@ -21,15 +22,6 @@ typedef int (pfx(cbfn))(void *ctx, ctype ch);
|
||||||
// Helper function declaration
|
// Helper function declaration
|
||||||
static inline int pfx(_isdigit)(ctype ch);
|
static inline int pfx(_isdigit)(ctype ch);
|
||||||
static inline int pfx(_atoi)(ctype const **sp, int *err);
|
static inline int pfx(_atoi)(ctype const **sp, int *err);
|
||||||
static inline int pfx(_out_rbuf)(
|
|
||||||
int w,
|
|
||||||
void *ctx,
|
|
||||||
pfx(cbfn) cb,
|
|
||||||
size_t len,
|
|
||||||
ctype *buf,
|
|
||||||
int width,
|
|
||||||
int flags
|
|
||||||
);
|
|
||||||
static inline int pfx(_ntoa)(
|
static inline int pfx(_ntoa)(
|
||||||
int w,
|
int w,
|
||||||
void *ctx,
|
void *ctx,
|
||||||
|
@ -41,6 +33,26 @@ static inline int pfx(_ntoa)(
|
||||||
int width,
|
int width,
|
||||||
int flags
|
int flags
|
||||||
);
|
);
|
||||||
|
static inline int pfx(_dtoh)(
|
||||||
|
int w,
|
||||||
|
void *ctx,
|
||||||
|
pfx(cbfn) cb,
|
||||||
|
double value,
|
||||||
|
int prec,
|
||||||
|
int width,
|
||||||
|
int flags
|
||||||
|
);
|
||||||
|
static inline int pfx(_infnantoa)(
|
||||||
|
int w,
|
||||||
|
void *ctx,
|
||||||
|
pfx(cbfn) cb,
|
||||||
|
double value,
|
||||||
|
int prec,
|
||||||
|
int width,
|
||||||
|
int flags
|
||||||
|
);
|
||||||
|
|
||||||
|
#define out(ch) do { if((w++, !cb(ctx, (ch)))) return -1; } while(0)
|
||||||
|
|
||||||
// Generic print
|
// Generic print
|
||||||
static int pfx(vprintfcb)(
|
static int pfx(vprintfcb)(
|
||||||
|
@ -53,10 +65,7 @@ static int pfx(vprintfcb)(
|
||||||
while(*fmt) {
|
while(*fmt) {
|
||||||
// Write a character if it's not a '%' sign
|
// Write a character if it's not a '%' sign
|
||||||
while(*fmt && *fmt != '%') {
|
while(*fmt && *fmt != '%') {
|
||||||
if(!cb(ctx, *fmt))
|
out(*fmt++);
|
||||||
return -1;
|
|
||||||
++w;
|
|
||||||
++fmt;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(*fmt == '%') {
|
if(*fmt == '%') {
|
||||||
|
@ -159,7 +168,7 @@ static int pfx(vprintfcb)(
|
||||||
case 'x':
|
case 'x':
|
||||||
case 'X':
|
case 'X':
|
||||||
case 'o':
|
case 'o':
|
||||||
case 'b':
|
case 'b': {
|
||||||
// Figure out the signedness and base
|
// Figure out the signedness and base
|
||||||
int base = 10;
|
int base = 10;
|
||||||
if(*fmt == 'x' || *fmt == 'X') base = 16;
|
if(*fmt == 'x' || *fmt == 'X') base = 16;
|
||||||
|
@ -205,8 +214,23 @@ static int pfx(vprintfcb)(
|
||||||
// Output integer
|
// Output integer
|
||||||
w = pfx(_ntoa)(w, ctx, cb, neg, value, base, prec, width, flags);
|
w = pfx(_ntoa)(w, ctx, cb, neg, value, base, prec, width, flags);
|
||||||
if(w < 0) return -1;
|
if(w < 0) return -1;
|
||||||
|
} break;
|
||||||
|
case 'a':
|
||||||
|
case 'A': {
|
||||||
|
if(*fmt == 'A') flags |= FLAG_UPPER;
|
||||||
|
++fmt;
|
||||||
|
double value = va_arg(va, double);
|
||||||
|
w = pfx(_dtoh)(w, ctx, cb, value, prec, width, flags);
|
||||||
|
if(w < 0) return -1;
|
||||||
|
} break;
|
||||||
|
case 'e':
|
||||||
|
case 'E':
|
||||||
|
case 'f':
|
||||||
|
case 'F':
|
||||||
|
case 'g':
|
||||||
|
case 'G':
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'f': ;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return w;
|
return w;
|
||||||
|
@ -268,40 +292,228 @@ static inline int pfx(_ntoa)(
|
||||||
if(ndigits > prec) prec = ndigits;
|
if(ndigits > prec) prec = ndigits;
|
||||||
int num_len = pref_len + prec;
|
int num_len = pref_len + prec;
|
||||||
int pad_len = width - num_len;
|
int pad_len = width - num_len;
|
||||||
// Print left-pad due to width
|
// Print left-pad due to width (TODO: zero pad should come after prefix?)
|
||||||
if(!(flags & FLAG_LEFT)) {
|
if(!(flags & FLAG_LEFT)) {
|
||||||
ctype pad_ch = ' ';
|
ctype pad_ch = ' ';
|
||||||
if(flags & FLAG_ZERO) pad_ch = '0';
|
if(flags & FLAG_ZERO) pad_ch = '0';
|
||||||
while(pad_len-- > 0) {
|
while(pad_len-- > 0) {
|
||||||
if(!cb(ctx, pad_ch)) return -1;
|
out(pad_ch);
|
||||||
++w;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Print prefix
|
// Print prefix
|
||||||
if(flags & FLAG_HASH) {
|
if(flags & FLAG_HASH) {
|
||||||
if((++w, !cb(ctx, '0'))) return -1;
|
out('0');
|
||||||
if(base == 16) { if((++w, !cb(ctx, 'x'))) return -1; }
|
if(base == 16) { out('x'); }
|
||||||
else if(base == 2) { if((++w, !cb(ctx, 'b'))) return -1; }
|
else if(base == 2) { out('b'); }
|
||||||
}
|
}
|
||||||
else if(neg) { if((++w, !cb(ctx, '-'))) return -1; }
|
else if(neg) { out('-'); }
|
||||||
else if(flags & FLAG_PLUS) { if((++w, !cb(ctx, '+'))) return -1; }
|
else if(flags & FLAG_PLUS) { out('+'); }
|
||||||
else if(flags & FLAG_SPACE) { if((++w, !cb(ctx, ' '))) return -1; }
|
else if(flags & FLAG_SPACE) { out(' '); }
|
||||||
// Print zero-pad due to precision
|
// Print zero-pad due to precision
|
||||||
for(int i = ndigits; i < prec; ++i) {
|
for(int i = ndigits; i < prec; ++i) {
|
||||||
if(!cb(ctx, '0')) return -1;
|
out('0');
|
||||||
++w;
|
|
||||||
}
|
}
|
||||||
// Output buffer in reverse
|
// Output buffer in reverse
|
||||||
if(ndigits) while(ndigits--) {
|
if(ndigits) while(ndigits--) {
|
||||||
if(!cb(ctx, digits[ndigits])) return -1;
|
out(digits[ndigits]);
|
||||||
++w;
|
|
||||||
}
|
}
|
||||||
// Print right-pad
|
// Print right-pad
|
||||||
if(flags & FLAG_LEFT) {
|
if(flags & FLAG_LEFT) {
|
||||||
while(pad_len-- > 0) {
|
while(pad_len-- > 0) {
|
||||||
if(!cb(ctx, ' ')) return -1;
|
out(' ');
|
||||||
++w;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int pfx(_infnantoa)(
|
||||||
|
int w,
|
||||||
|
void *ctx,
|
||||||
|
pfx(cbfn) cb,
|
||||||
|
double value,
|
||||||
|
int prec,
|
||||||
|
int width,
|
||||||
|
int flags
|
||||||
|
) {
|
||||||
|
char const *name = NULL;
|
||||||
|
int nchars = 0;
|
||||||
|
if(isinf(value)) name = "inf", nchars = 3;
|
||||||
|
if(isnan(value)) name = "nan", nchars = 3;
|
||||||
|
// Figure out prefix
|
||||||
|
int pref_len = 0;
|
||||||
|
union {
|
||||||
|
uint64_t bits;
|
||||||
|
double value;
|
||||||
|
} _ = {value};
|
||||||
|
uint64_t bits = _.bits;
|
||||||
|
uint64_t neg = bits >> 63;
|
||||||
|
if(neg) pref_len = 1;
|
||||||
|
else if(flags & FLAG_PLUS) pref_len = 1;
|
||||||
|
else if(flags & FLAG_SPACE) pref_len = 1;
|
||||||
|
// Figure out pad
|
||||||
|
int str_len = pref_len + nchars;
|
||||||
|
int pad_len = width - str_len;
|
||||||
|
// Print left-pad
|
||||||
|
if(!(flags & FLAG_LEFT)) {
|
||||||
|
while(pad_len-- > 0) {
|
||||||
|
out(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Print the prefix
|
||||||
|
if(neg) out('-');
|
||||||
|
else if(flags & FLAG_PLUS) out('+');
|
||||||
|
else if(flags & FLAG_SPACE) out(' ');
|
||||||
|
// Print the string
|
||||||
|
while(*name) {
|
||||||
|
out(*name++);
|
||||||
|
}
|
||||||
|
// Print right-pad
|
||||||
|
if(flags & FLAG_LEFT) {
|
||||||
|
while(pad_len-- > 0) {
|
||||||
|
out(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int pfx(_dtoh)(
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
// Disassemble the float into parts
|
||||||
|
union {
|
||||||
|
uint64_t bits;
|
||||||
|
double value;
|
||||||
|
} _ = {.value = value};
|
||||||
|
uint64_t bits = _.bits;
|
||||||
|
uint64_t neg = bits >> 63;
|
||||||
|
int64_t exp = (int64_t)((bits >> 52) & 0x7ff) - 1023;
|
||||||
|
int64_t mant = bits & ((UINT64_C(1)<<51)-1);
|
||||||
|
if(class == FP_SUBNORMAL || class == FP_ZERO) {
|
||||||
|
exp = 0;
|
||||||
|
}
|
||||||
|
// Figure out how many hex digits does mantissa take up (mant_digits_n)
|
||||||
|
// and the number of digits after decimal point (prec)
|
||||||
|
static ctype mant_buf[64] = {0};
|
||||||
|
int mant_digits_n;
|
||||||
|
int nonsig_digits_n = 0;
|
||||||
|
if(mant != 0) {
|
||||||
|
int64_t m = mant;
|
||||||
|
while((m & 0xf) == 0) {
|
||||||
|
++nonsig_digits_n;
|
||||||
|
m >>= 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nonsig_digits_n = 52/4;
|
||||||
|
}
|
||||||
|
mant_digits_n = 52/4 - nonsig_digits_n;
|
||||||
|
if((flags & FLAG_PREC) == 0) {
|
||||||
|
prec = mant_digits_n;
|
||||||
|
}
|
||||||
|
// Figure out how many symbols decimal point takes up (0 or 1)
|
||||||
|
int decimal_point_n = 1;
|
||||||
|
if(prec == 0) {
|
||||||
|
decimal_point_n = 0;
|
||||||
|
if(flags & FLAG_HASH) {
|
||||||
|
decimal_point_n = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Figure out how many digits exponent take up and it's sign
|
||||||
|
// also save exponent digits to a buffer starting from LSD
|
||||||
|
static ctype exp_buf[64] = {0};
|
||||||
|
int exp_digits_n = 0;
|
||||||
|
ctype exp_sign;
|
||||||
|
if(exp < 0) {
|
||||||
|
exp_sign = '-';
|
||||||
|
exp = -exp;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
exp_sign = '+';
|
||||||
|
}
|
||||||
|
{
|
||||||
|
int64_t e = exp;
|
||||||
|
do {
|
||||||
|
exp_buf[exp_digits_n++] = e % 10 + '0';
|
||||||
|
e /= 10;
|
||||||
|
} while(e != 0);
|
||||||
|
}
|
||||||
|
// Figure out sign symbol and number of chars it takes up (0 or 1)
|
||||||
|
int sign_n = 0;
|
||||||
|
ctype sign_ch;
|
||||||
|
if(value < 0) {
|
||||||
|
sign_n = 1;
|
||||||
|
sign_ch = '-';
|
||||||
|
}
|
||||||
|
else if(flags & FLAG_PLUS) {
|
||||||
|
sign_n = 1;
|
||||||
|
sign_ch = '+';
|
||||||
|
}
|
||||||
|
else if(flags & FLAG_SPACE) {
|
||||||
|
sign_n = 1;
|
||||||
|
sign_ch = ' ';
|
||||||
|
}
|
||||||
|
// Figure out the width of the number
|
||||||
|
int significand_width = 1 + decimal_point_n + prec;
|
||||||
|
int exp_part_width = 2 /*p+-*/ + exp_digits_n;
|
||||||
|
int n_width = sign_n + 2 /*0x*/ + significand_width + exp_part_width;
|
||||||
|
// Figure out width-padding required
|
||||||
|
int pad = 0;
|
||||||
|
if(width > n_width) pad = width - n_width;
|
||||||
|
// Print width left-pad if it's made out of space
|
||||||
|
if(!(flags & FLAG_LEFT) && !(flags & FLAG_ZERO)) while(pad-- > 0) {
|
||||||
|
out(' ');
|
||||||
|
}
|
||||||
|
// Print sign if there
|
||||||
|
if(sign_n)
|
||||||
|
out(sign_ch);
|
||||||
|
// Print 0x, 0X
|
||||||
|
out('0');
|
||||||
|
out((flags & FLAG_UPPER)? 'X' : 'x');
|
||||||
|
// Print width left-pad if it's made out of zero
|
||||||
|
if(!(flags & FLAG_LEFT) && (flags & FLAG_ZERO)) while(pad-- > 0) {
|
||||||
|
out('0');
|
||||||
|
}
|
||||||
|
// Print whole part
|
||||||
|
out((class == FP_SUBNORMAL || class == FP_ZERO)? '0' : '1');
|
||||||
|
// Print decimal point
|
||||||
|
if(decimal_point_n) out('.');
|
||||||
|
// Print precision padding
|
||||||
|
for(int i = mant_digits_n; i < prec; ++i) {
|
||||||
|
out('0');
|
||||||
|
}
|
||||||
|
if(prec < mant_digits_n) mant_digits_n = prec;
|
||||||
|
for(int i = 0; i != mant_digits_n; ++i) {
|
||||||
|
int bit = 52 - 4 - i;
|
||||||
|
int digit = (int)((mant >> bit) & 0xf);
|
||||||
|
ctype ch;
|
||||||
|
if(digit < 10)
|
||||||
|
ch = digit+'0';
|
||||||
|
else if(flags & FLAG_UPPER)
|
||||||
|
ch = digit+'A'-10;
|
||||||
|
else ch = digit+'a'-10;
|
||||||
|
out(ch);
|
||||||
|
}
|
||||||
|
// Print the exponent part
|
||||||
|
out((flags & FLAG_UPPER)? 'P' : 'p');
|
||||||
|
out(exp_sign);
|
||||||
|
if(exp_digits_n) do
|
||||||
|
out(exp_buf[exp_digits_n]);
|
||||||
|
while(exp_digits_n--);
|
||||||
|
// Print right-pad
|
||||||
|
if(flags & FLAG_LEFT) while(pad-- > 0) {
|
||||||
|
out(' ');
|
||||||
|
}
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef out
|
||||||
|
|
|
@ -4,7 +4,14 @@
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
int w = printf("%- 16.8da\n", INT_MIN);
|
printf("%a\n", 0.0);
|
||||||
printf("%d\n", w);
|
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);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue