Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ziglang/zig
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 1828f8eb8e15
Choose a base ref
...
head repository: ziglang/zig
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 6764a4522391
Choose a head ref
  • 5 commits
  • 2 files changed
  • 2 contributors

Commits on Oct 23, 2017

  1. Print better floats

    scurest committed Oct 23, 2017
    Copy the full SHA
    03a0dfb View commit details

Commits on Oct 24, 2017

  1. More corrections to float printing

    Testing suggests all f32s are now printed accurately.
    scurest committed Oct 24, 2017
    Copy the full SHA
    262b742 View commit details

Commits on Oct 25, 2017

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

    …better-float-printing
    andrewrk committed Oct 25, 2017
    Copy the full SHA
    1e78483 View commit details
  2. Copy the full SHA
    73fe5f6 View commit details
  3. Copy the full SHA
    6764a45 View commit details
Showing with 69 additions and 24 deletions.
  1. +9 −13 std/fmt/errol/index.zig
  2. +60 −11 std/fmt/index.zig
22 changes: 9 additions & 13 deletions std/fmt/errol/index.zig
Original file line number Diff line number Diff line change
@@ -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);
}


71 changes: 60 additions & 11 deletions std/fmt/index.zig
Original file line number Diff line number Diff line change
@@ -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"))
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;
@@ -514,6 +531,38 @@ test "fmt.format" {
const result = bufPrint(buf1[0..], "u3: {}\n", value);
assert(mem.eql(u8, result, "u3: 5\n"));
}

// TODO get these tests passing in release modes
// https://github.com/zig-lang/zig/issues/564
if (builtin.mode == builtin.Mode.Debug) {
{
var buf1: [32]u8 = undefined;
const value: f32 = 12.34;
const result = bufPrint(buf1[0..], "f32: {}\n", value);
assert(mem.eql(u8, result, "f32: 1.23400001e1\n"));
}
{
var buf1: [32]u8 = undefined;
const value: f64 = -12.34e10;
const result = bufPrint(buf1[0..], "f64: {}\n", value);
assert(mem.eql(u8, result, "f64: -1.234e11\n"));
}
{
var buf1: [32]u8 = undefined;
const result = bufPrint(buf1[0..], "f64: {}\n", math.nan_f64);
assert(mem.eql(u8, result, "f64: NaN\n"));
}
{
var buf1: [32]u8 = undefined;
const result = bufPrint(buf1[0..], "f64: {}\n", math.inf_f64);
assert(mem.eql(u8, result, "f64: Infinity\n"));
}
{
var buf1: [32]u8 = undefined;
const result = bufPrint(buf1[0..], "f64: {}\n", -math.inf_f64);
assert(mem.eql(u8, result, "f64: -Infinity\n"));
}
}
}

pub fn trim(buf: []const u8) -> []const u8 {