From dc084128954b99f93a0d974c3e5ed8347e9f1e8a Mon Sep 17 00:00:00 2001 From: MovingtoMars Date: Thu, 28 Jan 2016 19:28:43 +1300 Subject: [PATCH] basic float printing --- CMakeLists.txt | 1 + std/math.zig | 25 +++++++++++++++ std/std.zig | 82 ++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 std/math.zig diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e06248ac..b82abefcb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -124,6 +124,7 @@ set(ZIG_STD_SRC "${CMAKE_SOURCE_DIR}/std/errno.zig" "${CMAKE_SOURCE_DIR}/std/rand.zig" "${CMAKE_SOURCE_DIR}/std/mem.zig" + "${CMAKE_SOURCE_DIR}/std/math.zig" ) set(C_HEADERS_DEST "lib/zig/include") diff --git a/std/math.zig b/std/math.zig new file mode 100644 index 000000000..77a630d64 --- /dev/null +++ b/std/math.zig @@ -0,0 +1,25 @@ +pub fn f64_from_bits(bits: u64) -> f64 { + const bits2 = bits; + *(&f64)(&bits2) +} + +pub fn f64_to_bits(f: f64) -> u64 { + const f2 = f; + *(&u64)(&f2) +} + +pub fn f64_get_pos_inf() -> f64 { + f64_from_bits(0x7FF0000000000000) +} + +pub fn f64_get_neg_inf() -> f64 { + f64_from_bits(0xFFF0000000000000) +} + +pub fn f64_is_nan(f: f64) -> bool { + 0x7FFFFFFFFFFFFFFF == f64_to_bits(f) // TODO improve to catch all cases +} + +pub fn f64_is_inf(f: f64) -> bool { + f == f64_get_neg_inf() || f == f64_get_pos_inf() +} diff --git a/std/std.zig b/std/std.zig index 19aafbbb4..7b873cea5 100644 --- a/std/std.zig +++ b/std/std.zig @@ -1,5 +1,6 @@ import "syscall.zig"; import "errno.zig"; +import "math.zig"; pub const stdin_fileno = 0; pub const stdout_fileno = 1; @@ -43,6 +44,7 @@ pub error BadFd; const buffer_size = 4 * 1024; const max_u64_base10_digits = 20; +const max_f64_digits = 65; pub struct OutStream { fd: isize, @@ -92,7 +94,6 @@ pub struct OutStream { return amt_printed; } - pub fn print_i64(os: &OutStream, x: i64) -> %isize { if (os.index + max_u64_base10_digits >= os.buffer.len) { %return os.flush(); @@ -107,6 +108,19 @@ pub struct OutStream { return amt_printed; } + pub fn print_f64(os: &OutStream, x: f64) -> %isize { + if (os.index + max_f64_digits >= os.buffer.len) { + %return os.flush(); + } + const amt_printed = buf_print_f64(os.buffer[os.index...], x); + os.index += amt_printed; + + if (!os.buffered) { + %return os.flush(); + } + + return amt_printed; + } pub fn flush(os: &OutStream) -> %void { const amt_written = write(os.fd, os.buffer.ptr, os.index); @@ -199,7 +213,7 @@ fn char_to_digit(c: u8) -> u8 { } } -fn buf_print_i64(out_buf: []u8, x: i64) -> isize { +pub fn buf_print_i64(out_buf: []u8, x: i64) -> isize { if (x < 0) { out_buf[0] = '-'; return 1 + buf_print_u64(out_buf[1...], u64(-(x + 1)) + 1); @@ -208,7 +222,7 @@ fn buf_print_i64(out_buf: []u8, x: i64) -> isize { } } -fn buf_print_u64(out_buf: []u8, x: u64) -> isize { +pub fn buf_print_u64(out_buf: []u8, x: u64) -> isize { var buf: [max_u64_base10_digits]u8 = undefined; var a = x; var index = buf.len; @@ -229,6 +243,68 @@ fn buf_print_u64(out_buf: []u8, x: u64) -> isize { return len; } +pub fn buf_print_f64(out_buf: []u8, x: f64) -> isize { + if (x == f64_get_pos_inf()) { + const buf2 = "+Inf"; + @memcpy(&out_buf[0], &buf2[0], 4); + return 4; + } else if (x == f64_get_neg_inf()) { + const buf2 = "-Inf"; + @memcpy(&out_buf[0], &buf2[0], 4); + return 4; + } else if (f64_is_nan(x)) { + const buf2 = "NaN"; + @memcpy(&out_buf[0], &buf2[0], 3); + return 3; + } + + var buf: [max_f64_digits]u8 = undefined; + + var len: isize = 0; + + // 1 sign bit + // 11 exponent bits + // 52 significand bits (+ 1 implicit always non-zero bit) + + const bits = f64_to_bits(x); + if (bits & (1 << 63) != 0) { + %%stdout.printf("neg\n"); + buf[0] = '-'; + len += 1; + } + + const rexponent: i64 = i64((bits >> 52) & ((1 << 11) - 1)); + const exponent = rexponent - 1023 - 52; + /*%%stdout.printf("exponent: "); + %%stdout.print_i64(exponent); + %%stdout.printf("\n");*/ + + if (rexponent == 0) { + buf[len] = '0'; + len += 1; + @memcpy(&out_buf[0], &buf[0], len); + return len; + } + + const sig = (bits & ((1 << 52) - 1)) | (1 << 52); + /*%%stdout.printf("significand: "); + %%stdout.print_u64(sig); + %%stdout.printf("\n");*/ + + len += buf_print_u64(buf[len...], sig); + buf[len] = '*'; + len += 1; + buf[len] = '2'; + len += 1; + buf[len] = '^'; + len += 1; + len += buf_print_i64(buf[len...], exponent); + + @memcpy(&out_buf[0], &buf[0], len); + + len +} + fn min_isize(x: isize, y: isize) -> isize { if (x < y) x else y }