aboutsummaryrefslogtreecommitdiff
path: root/lib/std/fmt/parse_float/FloatInfo.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-07-01 15:52:54 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-07-01 15:52:54 -0700
commitc89dd15e1be4959800dc7092d7dd4375253db7bc (patch)
treeca184ae53592efa21e67128a5f891d642d7f1118 /lib/std/fmt/parse_float/FloatInfo.zig
parent5466e87fce581f2ef90ac23bb80b1dbc05836fc6 (diff)
parent2360f8c490f3ec684ed64ff28e8c1fade249070b (diff)
downloadzig-c89dd15e1be4959800dc7092d7dd4375253db7bc.tar.gz
zig-c89dd15e1be4959800dc7092d7dd4375253db7bc.zip
Merge remote-tracking branch 'origin/master' into llvm14
Diffstat (limited to 'lib/std/fmt/parse_float/FloatInfo.zig')
-rw-r--r--lib/std/fmt/parse_float/FloatInfo.zig131
1 files changed, 131 insertions, 0 deletions
diff --git a/lib/std/fmt/parse_float/FloatInfo.zig b/lib/std/fmt/parse_float/FloatInfo.zig
new file mode 100644
index 0000000000..8fd95963b1
--- /dev/null
+++ b/lib/std/fmt/parse_float/FloatInfo.zig
@@ -0,0 +1,131 @@
+const std = @import("std");
+const Self = @This();
+
+// Minimum exponent that for a fast path case, or `-⌊(MANTISSA_EXPLICIT_BITS+1)/log2(5)⌋`
+min_exponent_fast_path: comptime_int,
+
+// Maximum exponent that for a fast path case, or `⌊(MANTISSA_EXPLICIT_BITS+1)/log2(5)⌋`
+max_exponent_fast_path: comptime_int,
+
+// Maximum exponent that can be represented for a disguised-fast path case.
+// This is `MAX_EXPONENT_FAST_PATH + ⌊(MANTISSA_EXPLICIT_BITS+1)/log2(10)⌋`
+max_exponent_fast_path_disguised: comptime_int,
+
+// Maximum mantissa for the fast-path (`1 << 53` for f64).
+max_mantissa_fast_path: comptime_int,
+
+// Smallest decimal exponent for a non-zero value. Including subnormals.
+smallest_power_of_ten: comptime_int,
+
+// Largest decimal exponent for a non-infinite value.
+largest_power_of_ten: comptime_int,
+
+// The number of bits in the significand, *excluding* the hidden bit.
+mantissa_explicit_bits: comptime_int,
+
+// Minimum exponent value `-(1 << (EXP_BITS - 1)) + 1`.
+minimum_exponent: comptime_int,
+
+// Round-to-even only happens for negative values of q
+// when q ≥ −4 in the 64-bit case and when q ≥ −17 in
+// the 32-bitcase.
+//
+// When q ≥ 0,we have that 5^q ≤ 2m+1. In the 64-bit case,we
+// have 5^q ≤ 2m+1 ≤ 2^54 or q ≤ 23. In the 32-bit case,we have
+// 5^q ≤ 2m+1 ≤ 2^25 or q ≤ 10.
+//
+// When q < 0, we have w ≥ (2m+1)×5^−q. We must have that w < 2^64
+// so (2m+1)×5^−q < 2^64. We have that 2m+1 > 2^53 (64-bit case)
+// or 2m+1 > 2^24 (32-bit case). Hence,we must have 2^53×5^−q < 2^64
+// (64-bit) and 2^24×5^−q < 2^64 (32-bit). Hence we have 5^−q < 2^11
+// or q ≥ −4 (64-bit case) and 5^−q < 2^40 or q ≥ −17 (32-bitcase).
+//
+// Thus we have that we only need to round ties to even when
+// we have that q ∈ [−4,23](in the 64-bit case) or q∈[−17,10]
+// (in the 32-bit case). In both cases,the power of five(5^|q|)
+// fits in a 64-bit word.
+min_exponent_round_to_even: comptime_int,
+max_exponent_round_to_even: comptime_int,
+
+// Largest exponent value `(1 << EXP_BITS) - 1`.
+infinite_power: comptime_int,
+
+// Following should compute based on derived calculations where possible.
+pub fn from(comptime T: type) Self {
+ return switch (T) {
+ f16 => .{
+ // Fast-Path
+ .min_exponent_fast_path = -4,
+ .max_exponent_fast_path = 4,
+ .max_exponent_fast_path_disguised = 7,
+ .max_mantissa_fast_path = 2 << std.math.floatMantissaBits(T),
+ // Slow + Eisel-Lemire
+ .mantissa_explicit_bits = std.math.floatMantissaBits(T),
+ .infinite_power = 0x1f,
+ // Eisel-Lemire
+ .smallest_power_of_ten = -26, // TODO: refine, fails one test
+ .largest_power_of_ten = 4,
+ .minimum_exponent = -15,
+ // w >= (2m+1) * 5^-q and w < 2^64
+ // => 2m+1 > 2^11
+ // => 2^11*5^-q < 2^64
+ // => 5^-q < 2^53
+ // => q >= -23
+ .min_exponent_round_to_even = -22,
+ .max_exponent_round_to_even = 5,
+ },
+ f32 => .{
+ // Fast-Path
+ .min_exponent_fast_path = -10,
+ .max_exponent_fast_path = 10,
+ .max_exponent_fast_path_disguised = 17,
+ .max_mantissa_fast_path = 2 << std.math.floatMantissaBits(T),
+ // Slow + Eisel-Lemire
+ .mantissa_explicit_bits = std.math.floatMantissaBits(T),
+ .infinite_power = 0xff,
+ // Eisel-Lemire
+ .smallest_power_of_ten = -65,
+ .largest_power_of_ten = 38,
+ .minimum_exponent = -127,
+ .min_exponent_round_to_even = -17,
+ .max_exponent_round_to_even = 10,
+ },
+ f64 => .{
+ // Fast-Path
+ .min_exponent_fast_path = -22,
+ .max_exponent_fast_path = 22,
+ .max_exponent_fast_path_disguised = 37,
+ .max_mantissa_fast_path = 2 << std.math.floatMantissaBits(T),
+ // Slow + Eisel-Lemire
+ .mantissa_explicit_bits = std.math.floatMantissaBits(T),
+ .infinite_power = 0x7ff,
+ // Eisel-Lemire
+ .smallest_power_of_ten = -342,
+ .largest_power_of_ten = 308,
+ .minimum_exponent = -1023,
+ .min_exponent_round_to_even = -4,
+ .max_exponent_round_to_even = 23,
+ },
+ f128 => .{
+ // Fast-Path
+ .min_exponent_fast_path = -48,
+ .max_exponent_fast_path = 48,
+ .max_exponent_fast_path_disguised = 82,
+ .max_mantissa_fast_path = 2 << std.math.floatMantissaBits(T),
+ // Slow + Eisel-Lemire
+ .mantissa_explicit_bits = std.math.floatMantissaBits(T),
+ .infinite_power = 0x7fff,
+ // Eisel-Lemire.
+ // NOTE: Not yet tested (no f128 eisel-lemire implementation)
+ .smallest_power_of_ten = -4966,
+ .largest_power_of_ten = 4932,
+ .minimum_exponent = -16382,
+ // 2^113 * 5^-q < 2^128
+ // 5^-q < 2^15
+ // => q >= -6
+ .min_exponent_round_to_even = -6,
+ .max_exponent_round_to_even = 49,
+ },
+ else => unreachable,
+ };
+}