Commit dc08412895

MovingtoMars <liam@bumblebee.net.nz>
2016-01-28 07:28:43
basic float printing
1 parent e3cc0c2
Changed files (3)
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()
+}
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
 }
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")