| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | import "syscall.zig"; | 1 | import "syscall.zig"; |
| 2 | import "errno.zig"; | 2 | import "errno.zig"; |
| | 3 | import "math.zig"; |
| 3 | | 4 | |
| 4 | pub const stdin_fileno = 0; | 5 | pub const stdin_fileno = 0; |
| 5 | pub const stdout_fileno = 1; | 6 | pub const stdout_fileno = 1; |
| ... | @@ -43,6 +44,7 @@ pub error BadFd; | ... | @@ -43,6 +44,7 @@ pub error BadFd; |
| 43 | | 44 | |
| 44 | const buffer_size = 4 * 1024; | 45 | const buffer_size = 4 * 1024; |
| 45 | const max_u64_base10_digits = 20; | 46 | const max_u64_base10_digits = 20; |
| | 47 | const max_f64_digits = 65; |
| 46 | | 48 | |
| 47 | pub struct OutStream { | 49 | pub struct OutStream { |
| 48 | fd: isize, | 50 | fd: isize, |
| ... | @@ -92,7 +94,6 @@ pub struct OutStream { | ... | @@ -92,7 +94,6 @@ pub struct OutStream { |
| 92 | return amt_printed; | 94 | return amt_printed; |
| 93 | } | 95 | } |
| 94 | | 96 | |
| 95 | | | |
| 96 | pub fn print_i64(os: &OutStream, x: i64) -> %isize { | 97 | pub fn print_i64(os: &OutStream, x: i64) -> %isize { |
| 97 | if (os.index + max_u64_base10_digits >= os.buffer.len) { | 98 | if (os.index + max_u64_base10_digits >= os.buffer.len) { |
| 98 | %return os.flush(); | 99 | %return os.flush(); |
| ... | @@ -107,6 +108,19 @@ pub struct OutStream { | ... | @@ -107,6 +108,19 @@ pub struct OutStream { |
| 107 | return amt_printed; | 108 | return amt_printed; |
| 108 | } | 109 | } |
| 109 | | 110 | |
| | 111 | pub fn print_f64(os: &OutStream, x: f64) -> %isize { |
| | 112 | if (os.index + max_f64_digits >= os.buffer.len) { |
| | 113 | %return os.flush(); |
| | 114 | } |
| | 115 | const amt_printed = buf_print_f64(os.buffer[os.index...], x); |
| | 116 | os.index += amt_printed; |
| | 117 | |
| | 118 | if (!os.buffered) { |
| | 119 | %return os.flush(); |
| | 120 | } |
| | 121 | |
| | 122 | return amt_printed; |
| | 123 | } |
| 110 | | 124 | |
| 111 | pub fn flush(os: &OutStream) -> %void { | 125 | pub fn flush(os: &OutStream) -> %void { |
| 112 | const amt_written = write(os.fd, os.buffer.ptr, os.index); | 126 | const amt_written = write(os.fd, os.buffer.ptr, os.index); |
| ... | @@ -199,7 +213,7 @@ fn char_to_digit(c: u8) -> u8 { | ... | @@ -199,7 +213,7 @@ fn char_to_digit(c: u8) -> u8 { |
| 199 | } | 213 | } |
| 200 | } | 214 | } |
| 201 | | 215 | |
| 202 | fn buf_print_i64(out_buf: []u8, x: i64) -> isize { | 216 | pub fn buf_print_i64(out_buf: []u8, x: i64) -> isize { |
| 203 | if (x < 0) { | 217 | if (x < 0) { |
| 204 | out_buf[0] = '-'; | 218 | out_buf[0] = '-'; |
| 205 | return 1 + buf_print_u64(out_buf[1...], u64(-(x + 1)) + 1); | 219 | 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 { | ... | @@ -208,7 +222,7 @@ fn buf_print_i64(out_buf: []u8, x: i64) -> isize { |
| 208 | } | 222 | } |
| 209 | } | 223 | } |
| 210 | | 224 | |
| 211 | fn buf_print_u64(out_buf: []u8, x: u64) -> isize { | 225 | pub fn buf_print_u64(out_buf: []u8, x: u64) -> isize { |
| 212 | var buf: [max_u64_base10_digits]u8 = undefined; | 226 | var buf: [max_u64_base10_digits]u8 = undefined; |
| 213 | var a = x; | 227 | var a = x; |
| 214 | var index = buf.len; | 228 | var index = buf.len; |
| ... | @@ -229,6 +243,68 @@ fn buf_print_u64(out_buf: []u8, x: u64) -> isize { | ... | @@ -229,6 +243,68 @@ fn buf_print_u64(out_buf: []u8, x: u64) -> isize { |
| 229 | return len; | 243 | return len; |
| 230 | } | 244 | } |
| 231 | | 245 | |
| | 246 | pub fn buf_print_f64(out_buf: []u8, x: f64) -> isize { |
| | 247 | if (x == f64_get_pos_inf()) { |
| | 248 | const buf2 = "+Inf"; |
| | 249 | @memcpy(&out_buf[0], &buf2[0], 4); |
| | 250 | return 4; |
| | 251 | } else if (x == f64_get_neg_inf()) { |
| | 252 | const buf2 = "-Inf"; |
| | 253 | @memcpy(&out_buf[0], &buf2[0], 4); |
| | 254 | return 4; |
| | 255 | } else if (f64_is_nan(x)) { |
| | 256 | const buf2 = "NaN"; |
| | 257 | @memcpy(&out_buf[0], &buf2[0], 3); |
| | 258 | return 3; |
| | 259 | } |
| | 260 | |
| | 261 | var buf: [max_f64_digits]u8 = undefined; |
| | 262 | |
| | 263 | var len: isize = 0; |
| | 264 | |
| | 265 | // 1 sign bit |
| | 266 | // 11 exponent bits |
| | 267 | // 52 significand bits (+ 1 implicit always non-zero bit) |
| | 268 | |
| | 269 | const bits = f64_to_bits(x); |
| | 270 | if (bits & (1 << 63) != 0) { |
| | 271 | %%stdout.printf("neg\n"); |
| | 272 | buf[0] = '-'; |
| | 273 | len += 1; |
| | 274 | } |
| | 275 | |
| | 276 | const rexponent: i64 = i64((bits >> 52) & ((1 << 11) - 1)); |
| | 277 | const exponent = rexponent - 1023 - 52; |
| | 278 | /*%%stdout.printf("exponent: "); |
| | 279 | %%stdout.print_i64(exponent); |
| | 280 | %%stdout.printf("\n");*/ |
| | 281 | |
| | 282 | if (rexponent == 0) { |
| | 283 | buf[len] = '0'; |
| | 284 | len += 1; |
| | 285 | @memcpy(&out_buf[0], &buf[0], len); |
| | 286 | return len; |
| | 287 | } |
| | 288 | |
| | 289 | const sig = (bits & ((1 << 52) - 1)) | (1 << 52); |
| | 290 | /*%%stdout.printf("significand: "); |
| | 291 | %%stdout.print_u64(sig); |
| | 292 | %%stdout.printf("\n");*/ |
| | 293 | |
| | 294 | len += buf_print_u64(buf[len...], sig); |
| | 295 | buf[len] = '*'; |
| | 296 | len += 1; |
| | 297 | buf[len] = '2'; |
| | 298 | len += 1; |
| | 299 | buf[len] = '^'; |
| | 300 | len += 1; |
| | 301 | len += buf_print_i64(buf[len...], exponent); |
| | 302 | |
| | 303 | @memcpy(&out_buf[0], &buf[0], len); |
| | 304 | |
| | 305 | len |
| | 306 | } |
| | 307 | |
| 232 | fn min_isize(x: isize, y: isize) -> isize { | 308 | fn min_isize(x: isize, y: isize) -> isize { |
| 233 | if (x < y) x else y | 309 | if (x < y) x else y |
| 234 | } | 310 | } |