Merge branch 'float-printing' of https://github.com/scurest/zig into better-float-printing

master
Andrew Kelley 2017-10-24 21:44:49 -04:00
commit 1e784839f1
2 changed files with 38 additions and 25 deletions

View File

@ -32,13 +32,13 @@ pub fn errol3(value: f64, buffer: []u8) -> FloatDecimal {
fn errol3u(val: f64, buffer: []u8) -> FloatDecimal {
// check if in integer or fixed range
if (val >= 9.007199254740992e15 and val < 3.40282366920938e+38) {
if (val > 9.007199254740992e15 and val < 3.40282366920938e+38) {
return errolInt(val, buffer);
} else if (val >= 16.0 and val < 9.007199254740992e15) {
return errolFixed(val, buffer);
}
// normalize the midpoint
const e = math.frexp(val).exponent;
@ -138,7 +138,7 @@ fn tableLowerBound(k: u64) -> usize {
while (j < enum3.len) {
if (enum3[j] < k) {
j = 2 * k + 2;
j = 2 * j + 2;
} else {
i = j;
j = 2 * j + 1;
@ -217,7 +217,7 @@ fn hpMul10(hp: &HP) {
hp.val *= 10.0;
hp.off *= 10.0;
var off = hp.val;
off -= val * 8.0;
off -= val * 2.0;
@ -235,13 +235,13 @@ fn hpMul10(hp: &HP) {
fn errolInt(val: f64, buffer: []u8) -> FloatDecimal {
const pow19 = u128(1e19);
assert((val >= 9.007199254740992e15) and val < (3.40282366920938e38));
assert((val > 9.007199254740992e15) and val < (3.40282366920938e38));
var mid = u128(val);
var low: u128 = mid - fpeint((fpnext(val) - val) / 2.0);
var high: u128 = mid + fpeint((val - fpprev(val)) / 2.0);
if (@bitCast(u64, val) & 0x1 != 0) {
if (@bitCast(u64, val) & 0x1 != 0) {
high -= 1;
} else {
low -= 1;
@ -347,11 +347,11 @@ fn errolFixed(val: f64, buffer: []u8) -> FloatDecimal {
}
fn fpnext(val: f64) -> f64 {
return @bitCast(f64, @bitCast(u64, val) + 1);
return @bitCast(f64, @bitCast(u64, val) +% 1);
}
fn fpprev(val: f64) -> f64 {
return @bitCast(f64, @bitCast(u64, val) - 1);
return @bitCast(f64, @bitCast(u64, val) -% 1);
}
pub const c_digits_lut = []u8 {
@ -510,10 +510,6 @@ fn u64toa(value_param: u64, buffer: []u8) -> usize {
buf_index += 1;
buffer[buf_index] = c_digits_lut[d8];
buf_index += 1;
buffer[buf_index] = c_digits_lut[d8];
buf_index += 1;
buffer[buf_index] = c_digits_lut[d8];
buf_index += 1;
buffer[buf_index] = c_digits_lut[d8 + 1];
buf_index += 1;
} else {
@ -613,7 +609,7 @@ fn fpeint(from: f64) -> u128 {
const bits = @bitCast(u64, from);
assert((bits & ((1 << 52) - 1)) == 0);
return u64(1) << u6(((bits >> 52) - 1023));
return u128(1) << @truncate(u7, (bits >> 52) -% 1023);
}

View File

@ -244,30 +244,47 @@ pub fn formatBuf(buf: []const u8, width: usize,
}
pub fn formatFloat(value: var, context: var, output: fn(@typeOf(context), []const u8)->bool) -> bool {
var buffer: [20]u8 = undefined;
const float_decimal = errol3(f64(value), buffer[0..]);
if (float_decimal.exp != 0) {
if (!output(context, float_decimal.digits[0..1]))
return false;
} else {
if (!output(context, "0"))
return false;
var x = f64(value);
// Errol doesn't handle these special cases.
if (math.isNan(x)) {
return output(context, "NaN");
}
if (math.signbit(x)) {
if (!output(context, "-"))
return false;
x = -x;
}
if (math.isPositiveInf(x)) {
return output(context, "Infinity");
}
if (x == 0.0) {
return output(context, "0.0");
}
var buffer: [32]u8 = undefined;
const float_decimal = errol3(x, buffer[0..]);
if (!output(context, float_decimal.digits[0..1]))
return false;
if (!output(context, "."))
return false;
if (float_decimal.digits.len > 1) {
const start = if (float_decimal.exp == 0) usize(0) else usize(1);
if (!output(context, float_decimal.digits[start .. math.min(usize(7), float_decimal.digits.len)]))
const num_digits = if (@typeOf(value) == f32) {
math.min(usize(9), float_decimal.digits.len)
} else {
float_decimal.digits.len
};
if (!output(context, float_decimal.digits[1 .. num_digits]))
return false;
} else {
if (!output(context, "0"))
return false;
}
if (float_decimal.exp != 1 and float_decimal.exp != 0) {
if (float_decimal.exp != 1) {
if (!output(context, "e"))
return false;
if (!formatInt(float_decimal.exp, 10, false, 0, context, output))
if (!formatInt(float_decimal.exp - 1, 10, false, 0, context, output))
return false;
}
return true;