| author | |
| committer | |
| log | 7b7f45dc2a54aa9dfd6263b2654a5ccc8c5d2c82 |
| tree | f9b890968f04e421d848c69b4c7113831770fd48 |
| parent | cb019b80ac8ae8ffd7f7dd619c4da29a83668cde |
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; |
| 12 | pub fn parseHexFloat(comptime T: type, s: []const u8) !T { | 12 | pub fn parseHexFloat(comptime T: type, s: []const u8) !T { |
| 13 | assert(@typeInfo(T) == .Float); | 13 | assert(@typeInfo(T) == .Float); |
| 14 | 14 | ||
| 15 | const IntT = std.meta.Int(.unsigned, @typeInfo(T).Float.bits); | 15 | const TBits = std.meta.Int(.unsigned, @typeInfo(T).Float.bits); |
| 16 | 16 | ||
| 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); | ||
| 19 | 21 | ||
| 22 | const exponent_bias = exponent_max; | ||
| 20 | const sign_shift = mantissa_bits + exponent_bits; | 23 | const sign_shift = mantissa_bits + exponent_bits; |
| 21 | 24 | ||
| 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; |
| 28 | 27 | ||
| ... | @@ -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); |
| 235 | 234 | ||
| 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); |
| 240 | 239 | ||
| 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; |
| 16 | 16 | ||
| 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 | } |
| 22 | 22 | ||
| 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; |
| 28 | 28 | ||
| 29 | // fix double rounding errors in subnormal ranges | 29 | // fix double rounding errors in subnormal ranges |
| 30 | // https://git.musl-libc.org/cgit/musl/commit/src/math/ldexp.c?id=8c44a060243f04283ca68dad199aab90336141db | 30 | // 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); |
| 34 | 34 | ||
| 35 | // scale `shift` within floating point limits, if possible | 35 | // scale `shift` within floating point limits, if possible |
| 36 | // second pass is possible due to subnormal range | 36 | // 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 | } |
| 55 | 55 | ||
| 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 | } |
| 58 | 58 | ||
| 59 | test "math.ldexp" { | 59 | test "math.ldexp" { |