| author | |
| committer | |
| log | 6764a4522391d82c40fc54bae448b32366e3e6d8 |
| tree | fcb9d80ac056a2e81efb6e31915ee94866dea1b1 |
| parent | 1828f8eb8e1514578ed2da8d58536903f94b7ed0 |
| parent | 73fe5f63c6acc1b2e6fec51da545178ffd12180e |
2 files changed, 69 insertions(+), 24 deletions(-)
std/fmt/errol/index.zig+9-13| ... | @@ -32,13 +32,13 @@ pub fn errol3(value: f64, buffer: []u8) -> FloatDecimal { | ... | @@ -32,13 +32,13 @@ pub fn errol3(value: f64, buffer: []u8) -> FloatDecimal { |
| 32 | fn errol3u(val: f64, buffer: []u8) -> FloatDecimal { | 32 | fn errol3u(val: f64, buffer: []u8) -> FloatDecimal { |
| 33 | // check if in integer or fixed range | 33 | // check if in integer or fixed range |
| 34 | 34 | ||
| 35 | if (val >= 9.007199254740992e15 and val < 3.40282366920938e+38) { | 35 | if (val > 9.007199254740992e15 and val < 3.40282366920938e+38) { |
| 36 | return errolInt(val, buffer); | 36 | return errolInt(val, buffer); |
| 37 | } else if (val >= 16.0 and val < 9.007199254740992e15) { | 37 | } else if (val >= 16.0 and val < 9.007199254740992e15) { |
| 38 | return errolFixed(val, buffer); | 38 | return errolFixed(val, buffer); |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | 41 | ||
| 42 | // normalize the midpoint | 42 | // normalize the midpoint |
| 43 | 43 | ||
| 44 | const e = math.frexp(val).exponent; | 44 | const e = math.frexp(val).exponent; |
| ... | @@ -138,7 +138,7 @@ fn tableLowerBound(k: u64) -> usize { | ... | @@ -138,7 +138,7 @@ fn tableLowerBound(k: u64) -> usize { |
| 138 | 138 | ||
| 139 | while (j < enum3.len) { | 139 | while (j < enum3.len) { |
| 140 | if (enum3[j] < k) { | 140 | if (enum3[j] < k) { |
| 141 | j = 2 * k + 2; | 141 | j = 2 * j + 2; |
| 142 | } else { | 142 | } else { |
| 143 | i = j; | 143 | i = j; |
| 144 | j = 2 * j + 1; | 144 | j = 2 * j + 1; |
| ... | @@ -217,7 +217,7 @@ fn hpMul10(hp: &HP) { | ... | @@ -217,7 +217,7 @@ fn hpMul10(hp: &HP) { |
| 217 | 217 | ||
| 218 | hp.val *= 10.0; | 218 | hp.val *= 10.0; |
| 219 | hp.off *= 10.0; | 219 | hp.off *= 10.0; |
| 220 | 220 | ||
| 221 | var off = hp.val; | 221 | var off = hp.val; |
| 222 | off -= val * 8.0; | 222 | off -= val * 8.0; |
| 223 | off -= val * 2.0; | 223 | off -= val * 2.0; |
| ... | @@ -235,13 +235,13 @@ fn hpMul10(hp: &HP) { | ... | @@ -235,13 +235,13 @@ fn hpMul10(hp: &HP) { |
| 235 | fn errolInt(val: f64, buffer: []u8) -> FloatDecimal { | 235 | fn errolInt(val: f64, buffer: []u8) -> FloatDecimal { |
| 236 | const pow19 = u128(1e19); | 236 | const pow19 = u128(1e19); |
| 237 | 237 | ||
| 238 | assert((val >= 9.007199254740992e15) and val < (3.40282366920938e38)); | 238 | assert((val > 9.007199254740992e15) and val < (3.40282366920938e38)); |
| 239 | 239 | ||
| 240 | var mid = u128(val); | 240 | var mid = u128(val); |
| 241 | var low: u128 = mid - fpeint((fpnext(val) - val) / 2.0); | 241 | var low: u128 = mid - fpeint((fpnext(val) - val) / 2.0); |
| 242 | var high: u128 = mid + fpeint((val - fpprev(val)) / 2.0); | 242 | var high: u128 = mid + fpeint((val - fpprev(val)) / 2.0); |
| 243 | 243 | ||
| 244 | if (@bitCast(u64, val) & 0x1 != 0) { | 244 | if (@bitCast(u64, val) & 0x1 != 0) { |
| 245 | high -= 1; | 245 | high -= 1; |
| 246 | } else { | 246 | } else { |
| 247 | low -= 1; | 247 | low -= 1; |
| ... | @@ -347,11 +347,11 @@ fn errolFixed(val: f64, buffer: []u8) -> FloatDecimal { | ... | @@ -347,11 +347,11 @@ fn errolFixed(val: f64, buffer: []u8) -> FloatDecimal { |
| 347 | } | 347 | } |
| 348 | 348 | ||
| 349 | fn fpnext(val: f64) -> f64 { | 349 | fn fpnext(val: f64) -> f64 { |
| 350 | return @bitCast(f64, @bitCast(u64, val) + 1); | 350 | return @bitCast(f64, @bitCast(u64, val) +% 1); |
| 351 | } | 351 | } |
| 352 | 352 | ||
| 353 | fn fpprev(val: f64) -> f64 { | 353 | fn fpprev(val: f64) -> f64 { |
| 354 | return @bitCast(f64, @bitCast(u64, val) - 1); | 354 | return @bitCast(f64, @bitCast(u64, val) -% 1); |
| 355 | } | 355 | } |
| 356 | 356 | ||
| 357 | pub const c_digits_lut = []u8 { | 357 | pub const c_digits_lut = []u8 { |
| ... | @@ -510,10 +510,6 @@ fn u64toa(value_param: u64, buffer: []u8) -> usize { | ... | @@ -510,10 +510,6 @@ fn u64toa(value_param: u64, buffer: []u8) -> usize { |
| 510 | buf_index += 1; | 510 | buf_index += 1; |
| 511 | buffer[buf_index] = c_digits_lut[d8]; | 511 | buffer[buf_index] = c_digits_lut[d8]; |
| 512 | buf_index += 1; | 512 | buf_index += 1; |
| 513 | buffer[buf_index] = c_digits_lut[d8]; | ||
| 514 | buf_index += 1; | ||
| 515 | buffer[buf_index] = c_digits_lut[d8]; | ||
| 516 | buf_index += 1; | ||
| 517 | buffer[buf_index] = c_digits_lut[d8 + 1]; | 513 | buffer[buf_index] = c_digits_lut[d8 + 1]; |
| 518 | buf_index += 1; | 514 | buf_index += 1; |
| 519 | } else { | 515 | } else { |
| ... | @@ -613,7 +609,7 @@ fn fpeint(from: f64) -> u128 { | ... | @@ -613,7 +609,7 @@ fn fpeint(from: f64) -> u128 { |
| 613 | const bits = @bitCast(u64, from); | 609 | const bits = @bitCast(u64, from); |
| 614 | assert((bits & ((1 << 52) - 1)) == 0); | 610 | assert((bits & ((1 << 52) - 1)) == 0); |
| 615 | 611 | ||
| 616 | return u64(1) << u6(((bits >> 52) - 1023)); | 612 | return u128(1) << @truncate(u7, (bits >> 52) -% 1023); |
| 617 | } | 613 | } |
| 618 | 614 | ||
| 619 | 615 |
std/fmt/index.zig+60-11| ... | @@ -244,30 +244,47 @@ pub fn formatBuf(buf: []const u8, width: usize, | ... | @@ -244,30 +244,47 @@ pub fn formatBuf(buf: []const u8, width: usize, |
| 244 | } | 244 | } |
| 245 | 245 | ||
| 246 | pub fn formatFloat(value: var, context: var, output: fn(@typeOf(context), []const u8)->bool) -> bool { | 246 | pub fn formatFloat(value: var, context: var, output: fn(@typeOf(context), []const u8)->bool) -> bool { |
| 247 | var buffer: [20]u8 = undefined; | 247 | var x = f64(value); |
| 248 | const float_decimal = errol3(f64(value), buffer[0..]); | 248 | |
| 249 | if (float_decimal.exp != 0) { | 249 | // Errol doesn't handle these special cases. |
| 250 | if (!output(context, float_decimal.digits[0..1])) | 250 | if (math.isNan(x)) { |
| 251 | return false; | 251 | return output(context, "NaN"); |
| 252 | } else { | 252 | } |
| 253 | if (!output(context, "0")) | 253 | if (math.signbit(x)) { |
| 254 | if (!output(context, "-")) | ||
| 254 | return false; | 255 | return false; |
| 256 | x = -x; | ||
| 255 | } | 257 | } |
| 258 | if (math.isPositiveInf(x)) { | ||
| 259 | return output(context, "Infinity"); | ||
| 260 | } | ||
| 261 | if (x == 0.0) { | ||
| 262 | return output(context, "0.0"); | ||
| 263 | } | ||
| 264 | |||
| 265 | var buffer: [32]u8 = undefined; | ||
| 266 | const float_decimal = errol3(x, buffer[0..]); | ||
| 267 | if (!output(context, float_decimal.digits[0..1])) | ||
| 268 | return false; | ||
| 256 | if (!output(context, ".")) | 269 | if (!output(context, ".")) |
| 257 | return false; | 270 | return false; |
| 258 | if (float_decimal.digits.len > 1) { | 271 | if (float_decimal.digits.len > 1) { |
| 259 | const start = if (float_decimal.exp == 0) usize(0) else usize(1); | 272 | const num_digits = if (@typeOf(value) == f32) { |
| 260 | if (!output(context, float_decimal.digits[start .. math.min(usize(7), float_decimal.digits.len)])) | 273 | math.min(usize(9), float_decimal.digits.len) |
| 274 | } else { | ||
| 275 | float_decimal.digits.len | ||
| 276 | }; | ||
| 277 | if (!output(context, float_decimal.digits[1 .. num_digits])) | ||
| 261 | return false; | 278 | return false; |
| 262 | } else { | 279 | } else { |
| 263 | if (!output(context, "0")) | 280 | if (!output(context, "0")) |
| 264 | return false; | 281 | return false; |
| 265 | } | 282 | } |
| 266 | 283 | ||
| 267 | if (float_decimal.exp != 1 and float_decimal.exp != 0) { | 284 | if (float_decimal.exp != 1) { |
| 268 | if (!output(context, "e")) | 285 | if (!output(context, "e")) |
| 269 | return false; | 286 | return false; |
| 270 | if (!formatInt(float_decimal.exp, 10, false, 0, context, output)) | 287 | if (!formatInt(float_decimal.exp - 1, 10, false, 0, context, output)) |
| 271 | return false; | 288 | return false; |
| 272 | } | 289 | } |
| 273 | return true; | 290 | return true; |
| ... | @@ -514,6 +531,38 @@ test "fmt.format" { | ... | @@ -514,6 +531,38 @@ test "fmt.format" { |
| 514 | const result = bufPrint(buf1[0..], "u3: {}\n", value); | 531 | const result = bufPrint(buf1[0..], "u3: {}\n", value); |
| 515 | assert(mem.eql(u8, result, "u3: 5\n")); | 532 | assert(mem.eql(u8, result, "u3: 5\n")); |
| 516 | } | 533 | } |
| 534 | |||
| 535 | // TODO get these tests passing in release modes | ||
| 536 | // https://github.com/zig-lang/zig/issues/564 | ||
| 537 | if (builtin.mode == builtin.Mode.Debug) { | ||
| 538 | { | ||
| 539 | var buf1: [32]u8 = undefined; | ||
| 540 | const value: f32 = 12.34; | ||
| 541 | const result = bufPrint(buf1[0..], "f32: {}\n", value); | ||
| 542 | assert(mem.eql(u8, result, "f32: 1.23400001e1\n")); | ||
| 543 | } | ||
| 544 | { | ||
| 545 | var buf1: [32]u8 = undefined; | ||
| 546 | const value: f64 = -12.34e10; | ||
| 547 | const result = bufPrint(buf1[0..], "f64: {}\n", value); | ||
| 548 | assert(mem.eql(u8, result, "f64: -1.234e11\n")); | ||
| 549 | } | ||
| 550 | { | ||
| 551 | var buf1: [32]u8 = undefined; | ||
| 552 | const result = bufPrint(buf1[0..], "f64: {}\n", math.nan_f64); | ||
| 553 | assert(mem.eql(u8, result, "f64: NaN\n")); | ||
| 554 | } | ||
| 555 | { | ||
| 556 | var buf1: [32]u8 = undefined; | ||
| 557 | const result = bufPrint(buf1[0..], "f64: {}\n", math.inf_f64); | ||
| 558 | assert(mem.eql(u8, result, "f64: Infinity\n")); | ||
| 559 | } | ||
| 560 | { | ||
| 561 | var buf1: [32]u8 = undefined; | ||
| 562 | const result = bufPrint(buf1[0..], "f64: {}\n", -math.inf_f64); | ||
| 563 | assert(mem.eql(u8, result, "f64: -Infinity\n")); | ||
| 564 | } | ||
| 565 | } | ||
| 517 | } | 566 | } |
| 518 | 567 | ||
| 519 | pub fn trim(buf: []const u8) -> []const u8 { | 568 | pub fn trim(buf: []const u8) -> []const u8 { |