aboutsummaryrefslogtreecommitdiff
path: root/lib/std/fmt/parse_float/common.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/common.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/common.zig')
-rw-r--r--lib/std/fmt/parse_float/common.zig91
1 files changed, 91 insertions, 0 deletions
diff --git a/lib/std/fmt/parse_float/common.zig b/lib/std/fmt/parse_float/common.zig
new file mode 100644
index 0000000000..c1b34a081b
--- /dev/null
+++ b/lib/std/fmt/parse_float/common.zig
@@ -0,0 +1,91 @@
+const std = @import("std");
+
+/// A custom N-bit floating point type, representing `f * 2^e`.
+/// e is biased, so it be directly shifted into the exponent bits.
+/// Negative exponent indicates an invalid result.
+pub fn BiasedFp(comptime T: type) type {
+ const MantissaT = mantissaType(T);
+
+ return struct {
+ const Self = @This();
+
+ /// The significant digits.
+ f: MantissaT,
+ /// The biased, binary exponent.
+ e: i32,
+
+ pub fn zero() Self {
+ return .{ .f = 0, .e = 0 };
+ }
+
+ pub fn zeroPow2(e: i32) Self {
+ return .{ .f = 0, .e = e };
+ }
+
+ pub fn inf(comptime FloatT: type) Self {
+ return .{ .f = 0, .e = (1 << std.math.floatExponentBits(FloatT)) - 1 };
+ }
+
+ pub fn eql(self: Self, other: Self) bool {
+ return self.f == other.f and self.e == other.e;
+ }
+
+ pub fn toFloat(self: Self, comptime FloatT: type, negative: bool) FloatT {
+ var word = self.f;
+ word |= @intCast(MantissaT, self.e) << std.math.floatMantissaBits(FloatT);
+ var f = floatFromUnsigned(FloatT, MantissaT, word);
+ if (negative) f = -f;
+ return f;
+ }
+ };
+}
+
+pub fn floatFromUnsigned(comptime T: type, comptime MantissaT: type, v: MantissaT) T {
+ return switch (T) {
+ f16 => @bitCast(f16, @truncate(u16, v)),
+ f32 => @bitCast(f32, @truncate(u32, v)),
+ f64 => @bitCast(f64, @truncate(u64, v)),
+ f128 => @bitCast(f128, v),
+ else => unreachable,
+ };
+}
+
+/// Represents a parsed floating point value as its components.
+pub fn Number(comptime T: type) type {
+ return struct {
+ exponent: i64,
+ mantissa: mantissaType(T),
+ negative: bool,
+ /// More than max_mantissa digits were found during parse
+ many_digits: bool,
+ /// The number was a hex-float (e.g. 0x1.234p567)
+ hex: bool,
+ };
+}
+
+/// Determine if 8 bytes are all decimal digits.
+/// This does not care about the order in which the bytes were loaded.
+pub fn isEightDigits(v: u64) bool {
+ const a = v +% 0x4646_4646_4646_4646;
+ const b = v -% 0x3030_3030_3030_3030;
+ return ((a | b) & 0x8080_8080_8080_8080) == 0;
+}
+
+pub fn isDigit(c: u8, comptime base: u8) bool {
+ std.debug.assert(base == 10 or base == 16);
+
+ return if (base == 10)
+ '0' <= c and c <= '9'
+ else
+ '0' <= c and c <= '9' or 'a' <= c and c <= 'f' or 'A' <= c and c <= 'F';
+}
+
+/// Returns the underlying storage type used for the mantissa of floating-point type.
+/// The output unsigned type must have at least as many bits as the input floating-point type.
+pub fn mantissaType(comptime T: type) type {
+ return switch (T) {
+ f16, f32, f64 => u64,
+ f128 => u128,
+ else => unreachable,
+ };
+}