authorgravatar for liam@bumblebee.net.nzMovingtoMars <liam@bumblebee.net.nz> 2016-01-29 20:55:38+13:00
committergravatar for liam@bumblebee.net.nzMovingtoMars <liam@bumblebee.net.nz> 2016-01-29 20:55:38+13:00
log90a32629c0120acba881c87e84b7291732703fbe
tree4e23c02fd45a68bff379b8787d253c2a631ce7ed
parent650fdded29da7d1e741d17c8a15c93c511266547

float printing mostly works


1 files changed, 132 insertions(+), 0 deletions(-)

std/std.zig+132
......@@ -108,6 +108,20 @@ pub struct OutStream {
108108 return amt_printed;
109109 }
110110
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, 4);
116 os.index += amt_printed;
117
118 if (!os.buffered) {
119 %return os.flush();
120 }
121
122 return amt_printed;
123 }
124
111125 pub fn flush(os: &OutStream) -> %void {
112126 const amt_written = write(os.fd, os.buffer.ptr, os.index);
113127 os.index = 0;
......@@ -229,6 +243,124 @@ pub fn buf_print_u64(out_buf: []u8, x: u64) -> isize {
229243 return len;
230244}
231245
246pub fn buf_print_f64(out_buf: []u8, x: f64, decimals: isize) -> isize {
247 var decs = decimals;
248 if (decs >= max_u64_base10_digits) {
249 decs = max_u64_base10_digits - 1;
250 }
251
252 if (x == f64_get_pos_inf()) {
253 const buf2 = "+Inf";
254 @memcpy(&out_buf[0], &buf2[0], buf2.len);
255 return 4;
256 } else if (x == f64_get_neg_inf()) {
257 const buf2 = "-Inf";
258 @memcpy(&out_buf[0], &buf2[0], buf2.len);
259 return 4;
260 } else if (f64_is_nan(x)) {
261 const buf2 = "NaN";
262 @memcpy(&out_buf[0], &buf2[0], buf2.len);
263 return 3;
264 }
265
266 var buf: [max_f64_digits]u8 = undefined;
267
268 var len: isize = 0;
269
270 // 1 sign bit
271 // 11 exponent bits
272 // 52 significand bits (+ 1 implicit always non-zero bit)
273
274 const bits = f64_to_bits(x);
275 if (bits & (1 << 63) != 0) {
276 buf[0] = '-';
277 len += 1;
278 }
279
280 const rexponent: i64 = i64((bits >> 52) & ((1 << 11) - 1));
281 const exponent = rexponent - 1023 - 52;
282
283 if (rexponent == 0) {
284 buf[len] = '0';
285 len += 1;
286 @memcpy(&out_buf[0], &buf[0], len);
287 return len;
288 }
289
290 const sig = (bits & ((1 << 52) - 1)) | (1 << 52);
291
292 if (exponent >= 0) {
293 // number is an integer
294
295 if (exponent >= 11) {
296 // use XeX form
297
298 // TODO support printing large floats
299 //len += buf_print_u64(buf[len...], sig << 10);
300 const str = "LARGEF64";
301 @memcpy(&buf[len], &str[0], str.len);
302 len += str.len;
303 } else {
304 // use typical form
305
306 len += buf_print_u64(buf[len...], sig << u64(exponent));
307 buf[len] = '.';
308 len += 1;
309
310 var i: isize = 0;
311 while (i < decs) {
312 buf[len] = '0';
313 len += 1;
314 i += 1;
315 }
316 }
317 } else {
318 // number is not an integer
319
320 // print out whole part
321 len += buf_print_u64(buf[len...], sig >> u64(-exponent));
322 buf[len] = '.';
323 len += 1;
324
325 // print out fractional part
326 // dec_num holds: fractional part * 10 ^ decs
327 var dec_num: u64 = 0;
328
329 var a: isize = 1;
330 var i: isize = 0;
331 while (i < decs) {
332 a *= 10;
333 i += 1;
334 }
335
336 // create a mask: 1's for the fractional part, 0's for whole part
337 var masked_sig = sig & ((1 << u64(-exponent)) - 1);
338 i = -1;
339 while (i >= exponent) {
340 var bit_set = ((1 << u64(i-exponent)) & masked_sig) != 0;
341
342 if (bit_set) {
343 dec_num += usize(a) >> usize(-i);
344 }
345
346 i -= 1;
347 }
348
349 len += decs;
350
351 i = len - 1;
352 while (i >= len - decs) {
353 buf[i] = '0' + u8(dec_num % 10);
354 dec_num /= 10;
355 i -= 1;
356 }
357 }
358
359 @memcpy(&out_buf[0], &buf[0], len);
360
361 len
362}
363
232364fn min_isize(x: isize, y: isize) -> isize {
233365 if (x < y) x else y
234366}