authorgravatar for hi@viri.moeviri <hi@viri.moe> 2022-04-01 15:21:07-06:00
committergravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2022-04-06 15:50:36+02:00
log7b7f45dc2a54aa9dfd6263b2654a5ccc8c5d2c82
treef9b890968f04e421d848c69b4c7113831770fd48
parentcb019b80ac8ae8ffd7f7dd619c4da29a83668cde

std.{fmt, math}: derive float constants from std

This also addresses a nit from #10133 where IntT might be a confusing name because it might imply signed integer (iX, not uX). We settled on TBits for math/float.zig so I've applied that change here too. When I originally wrote ldexp() I copied the name from parse_hex_float.

2 files changed, 16 insertions(+), 17 deletions(-)

lib/std/fmt/parse_hex_float.zig+8-9
...@@ -12,17 +12,16 @@ const assert = std.debug.assert;...@@ -12,17 +12,16 @@ const assert = std.debug.assert;
12pub fn parseHexFloat(comptime T: type, s: []const u8) !T {12pub fn parseHexFloat(comptime T: type, s: []const u8) !T {
13 assert(@typeInfo(T) == .Float);13 assert(@typeInfo(T) == .Float);
1414
15 const IntT = std.meta.Int(.unsigned, @typeInfo(T).Float.bits);15 const TBits = std.meta.Int(.unsigned, @typeInfo(T).Float.bits);
1616
17 const mantissa_bits = math.floatMantissaBits(T);17 const mantissa_bits = math.floatMantissaBits(T);
18 const exponent_bits = math.floatExponentBits(T);18 const exponent_bits = math.floatExponentBits(T);
19 const exponent_min = math.floatExponentMin(T);
20 const exponent_max = math.floatExponentMax(T);
1921
22 const exponent_bias = exponent_max;
20 const sign_shift = mantissa_bits + exponent_bits;23 const sign_shift = mantissa_bits + exponent_bits;
2124
22 const exponent_bias = (1 << (exponent_bits - 1)) - 1;
23 const exponent_min = 1 - exponent_bias;
24 const exponent_max = exponent_bias;
25
26 if (s.len == 0)25 if (s.len == 0)
27 return error.InvalidCharacter;26 return error.InvalidCharacter;
2827
...@@ -233,10 +232,10 @@ pub fn parseHexFloat(comptime T: type, s: []const u8) !T {...@@ -233,10 +232,10 @@ pub fn parseHexFloat(comptime T: type, s: []const u8) !T {
233 // Remove the implicit bit.232 // Remove the implicit bit.
234 mantissa &= @as(u128, (1 << mantissa_bits) - 1);233 mantissa &= @as(u128, (1 << mantissa_bits) - 1);
235234
236 const raw: IntT =235 const raw: TBits =
237 (if (negative) @as(IntT, 1) << sign_shift else 0) |236 (if (negative) @as(TBits, 1) << sign_shift else 0) |
238 @as(IntT, @bitCast(u16, exponent + exponent_bias)) << mantissa_bits |237 @as(TBits, @bitCast(u16, exponent + exponent_bias)) << mantissa_bits |
239 @truncate(IntT, mantissa);238 @truncate(TBits, mantissa);
240239
241 return @bitCast(T, raw);240 return @bitCast(T, raw);
242}241}
lib/std/math/ldexp.zig+8-8
...@@ -15,22 +15,22 @@ pub fn ldexp(x: anytype, n: i32) @TypeOf(x) {...@@ -15,22 +15,22 @@ pub fn ldexp(x: anytype, n: i32) @TypeOf(x) {
15 var shift = n;15 var shift = n;
1616
17 const T = @TypeOf(base);17 const T = @TypeOf(base);
18 const IntT = std.meta.Int(.unsigned, @bitSizeOf(T));18 const TBits = std.meta.Int(.unsigned, @bitSizeOf(T));
19 if (@typeInfo(T) != .Float) {19 if (@typeInfo(T) != .Float) {
20 @compileError("ldexp not implemented for " ++ @typeName(T));20 @compileError("ldexp not implemented for " ++ @typeName(T));
21 }21 }
2222
23 const mantissa_bits = math.floatMantissaBits(T);23 const mantissa_bits = math.floatMantissaBits(T);
24 const exponent_bits = math.floatExponentBits(T);24 const exponent_min = math.floatExponentMin(T);
25 const exponent_bias = (1 << (exponent_bits - 1)) - 1;25 const exponent_max = math.floatExponentMax(T);
26 const exponent_min = 1 - exponent_bias;26
27 const exponent_max = exponent_bias;27 const exponent_bias = exponent_max;
2828
29 // fix double rounding errors in subnormal ranges29 // fix double rounding errors in subnormal ranges
30 // https://git.musl-libc.org/cgit/musl/commit/src/math/ldexp.c?id=8c44a060243f04283ca68dad199aab90336141db30 // https://git.musl-libc.org/cgit/musl/commit/src/math/ldexp.c?id=8c44a060243f04283ca68dad199aab90336141db
31 const scale_min_expo = exponent_min + mantissa_bits + 1;31 const scale_min_expo = exponent_min + mantissa_bits + 1;
32 const scale_min = @bitCast(T, @as(IntT, scale_min_expo + exponent_bias) << mantissa_bits);32 const scale_min = @bitCast(T, @as(TBits, scale_min_expo + exponent_bias) << mantissa_bits);
33 const scale_max = @bitCast(T, @intCast(IntT, exponent_max + exponent_bias) << mantissa_bits);33 const scale_max = @bitCast(T, @intCast(TBits, exponent_max + exponent_bias) << mantissa_bits);
3434
35 // scale `shift` within floating point limits, if possible35 // scale `shift` within floating point limits, if possible
36 // second pass is possible due to subnormal range36 // second pass is possible due to subnormal range
...@@ -53,7 +53,7 @@ pub fn ldexp(x: anytype, n: i32) @TypeOf(x) {...@@ -53,7 +53,7 @@ pub fn ldexp(x: anytype, n: i32) @TypeOf(x) {
53 }53 }
54 }54 }
5555
56 return base * @bitCast(T, @intCast(IntT, shift + exponent_bias) << mantissa_bits);56 return base * @bitCast(T, @intCast(TBits, shift + exponent_bias) << mantissa_bits);
57}57}
5858
59test "math.ldexp" {59test "math.ldexp" {