2671 lines
126 KiB
Zig
2671 lines
126 KiB
Zig
const builtin = @import("builtin");
|
|
pub const is_test = builtin.is_test;
|
|
pub const optimization_mode = builtin.mode;
|
|
const VariableArguments = @import("std").builtin.VaList;
|
|
extern "c" fn IsDebuggerPresent() bool;
|
|
extern "c" fn __errno_location() *c_int;
|
|
|
|
test {
|
|
_ = @import("lib_test.zig");
|
|
}
|
|
|
|
const CSlice = extern struct {
|
|
pointer: ?*anyopaque,
|
|
length: usize,
|
|
};
|
|
|
|
pub const KB = 1024;
|
|
pub const MB = 1024 * 1024;
|
|
pub const GB = 1024 * 1024 * 1024;
|
|
|
|
pub fn assert(ok: bool) void {
|
|
if (!ok) {
|
|
@branchHint(.unlikely);
|
|
unreachable;
|
|
}
|
|
}
|
|
|
|
fn errno() Error {
|
|
return @enumFromInt(__errno_location().*);
|
|
}
|
|
|
|
fn align_forward(T: type, value: T, alignment: T) T {
|
|
assert(alignment != 0);
|
|
const mask = alignment - 1;
|
|
const result = (value + mask) & ~mask;
|
|
return result;
|
|
}
|
|
|
|
pub fn align_forward_u64(value: u64, alignment: u64) u64 {
|
|
return align_forward(u64, value, alignment);
|
|
}
|
|
|
|
pub fn align_forward_u32(value: u32, alignment: u32) u32 {
|
|
return align_forward(u32, value, alignment);
|
|
}
|
|
|
|
pub fn is_power_of_two(value: anytype) bool {
|
|
return (value & (value - 1)) == 0;
|
|
}
|
|
|
|
pub fn next_power_of_two(n: u64) u64 {
|
|
var result = n;
|
|
result -= 1;
|
|
result |= result >> 1;
|
|
result |= result >> 2;
|
|
result |= result >> 4;
|
|
result |= result >> 8;
|
|
result |= result >> 16;
|
|
result |= result >> 32;
|
|
result += 1;
|
|
return result;
|
|
}
|
|
|
|
const ValueFromFlag = enum {
|
|
sub,
|
|
cmov,
|
|
};
|
|
const value_from_flag_kind = ValueFromFlag.sub;
|
|
|
|
pub fn value_from_flag(value: anytype, flag: anytype) @TypeOf(value) {
|
|
const flag_int: @TypeOf(value) = switch (@TypeOf(flag)) {
|
|
comptime_int => b: {
|
|
assert(flag == 1 or flag == 0);
|
|
break :b flag;
|
|
},
|
|
bool => @intFromBool(flag),
|
|
u1 => flag,
|
|
else => @compileError("Unhandled type: " ++ @typeName(@TypeOf(flag))),
|
|
};
|
|
|
|
const result = switch (value_from_flag_kind) {
|
|
.cmov => {
|
|
@compileError("TODO");
|
|
},
|
|
.sub => value & (@as(@TypeOf(value), 0) -% flag_int),
|
|
};
|
|
return result;
|
|
}
|
|
|
|
pub const Error = enum(c_int) {
|
|
SUCCESS = 0,
|
|
PERM = 1,
|
|
};
|
|
|
|
pub const u64_max = ~@as(u64, 0);
|
|
|
|
pub const file = struct {
|
|
pub const WriteOptions = packed struct {
|
|
executable: u1 = 0,
|
|
};
|
|
pub fn write(path: [:0]const u8, content: []const u8, options: WriteOptions) void {
|
|
const fd = os.File.open(path, .{
|
|
.write = 1,
|
|
.truncate = 1,
|
|
.create = 1,
|
|
.execute = options.executable,
|
|
}, .{
|
|
.read = 1,
|
|
.write = 1,
|
|
.execute = options.executable,
|
|
});
|
|
defer fd.close();
|
|
|
|
if (fd.is_valid()) {
|
|
fd.write(content);
|
|
}
|
|
}
|
|
|
|
pub fn read(arena: *Arena, path: [:0]const u8) []u8 {
|
|
const fd = os.File.open(path, .{
|
|
.read = 1,
|
|
}, .{
|
|
.read = 1,
|
|
});
|
|
defer fd.close();
|
|
var result: []u8 = undefined;
|
|
const ptr = @as(*[2]u64, @ptrCast(&result));
|
|
ptr[0] = 0;
|
|
ptr[1] = 0;
|
|
|
|
if (fd.is_valid()) {
|
|
const file_size = fd.get_size();
|
|
const file_buffer = arena.allocate_bytes(file_size, 1);
|
|
result = file_buffer[0..file_size];
|
|
fd.read(result, file_size);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
};
|
|
|
|
pub const os = struct {
|
|
const system = switch (builtin.os.tag) {
|
|
.windows => windows,
|
|
.linux => linux,
|
|
else => @compileError("TODO"),
|
|
};
|
|
pub const posix = switch (builtin.os.tag) {
|
|
.windows => @compileError("TODO"),
|
|
.linux => linux,
|
|
else => @compileError("TODO"),
|
|
};
|
|
|
|
pub const File = struct {
|
|
fd: Descriptor,
|
|
|
|
const Descriptor = system.FileDescriptor;
|
|
|
|
pub fn is_valid(fd: File) bool {
|
|
return system.fd_is_valid(fd.fd);
|
|
}
|
|
|
|
pub const OpenFlags = packed struct {
|
|
truncate: u1 = 0,
|
|
execute: u1 = 0,
|
|
write: u1 = 0,
|
|
read: u1 = 0,
|
|
create: u1 = 0,
|
|
directory: u1 = 0,
|
|
};
|
|
|
|
pub const Permissions = packed struct {
|
|
read: u1 = 1,
|
|
write: u1 = 1,
|
|
execute: u1 = 0,
|
|
};
|
|
|
|
pub fn open(path: [*:0]const u8, flags: OpenFlags, permissions: Permissions) File {
|
|
switch (builtin.os.tag) {
|
|
.windows => @compileError("TODO"),
|
|
else => {
|
|
const o = posix.O{
|
|
.ACCMODE = if (flags.read & flags.write != 0) .RDWR else if (flags.read != 0) .RDONLY else if (flags.write != 0) .WRONLY else unreachable,
|
|
.TRUNC = flags.truncate,
|
|
.CREAT = flags.create,
|
|
.DIRECTORY = flags.directory,
|
|
};
|
|
const mode: posix.mode_t = if (permissions.execute != 0) 0o755 else 0o644;
|
|
|
|
const fd = posix.open(path, o, mode);
|
|
return File{
|
|
.fd = fd,
|
|
};
|
|
},
|
|
}
|
|
}
|
|
|
|
pub fn close(fd: File) void {
|
|
switch (builtin.os.tag) {
|
|
.windows => {
|
|
@compileError("TODO");
|
|
},
|
|
else => {
|
|
const result = posix.close(fd.fd);
|
|
assert(result == 0);
|
|
},
|
|
}
|
|
}
|
|
|
|
pub fn get_size(fd: File) u64 {
|
|
switch (builtin.os.tag) {
|
|
.windows => {
|
|
@compileError("TODO");
|
|
},
|
|
else => {
|
|
var stat: posix.Stat = undefined;
|
|
const result = posix.fstat(fd.fd, &stat);
|
|
assert(result == 0);
|
|
return @intCast(stat.size);
|
|
},
|
|
}
|
|
}
|
|
|
|
pub fn write_partially(fd: File, content: []const u8) usize {
|
|
switch (builtin.os.tag) {
|
|
.windows => {
|
|
@compileError("TODO");
|
|
},
|
|
else => {
|
|
const syscall_result = posix.write(fd.fd, content.ptr, content.len);
|
|
if (syscall_result <= 0) {
|
|
abort();
|
|
} else {
|
|
return @intCast(syscall_result);
|
|
}
|
|
},
|
|
}
|
|
}
|
|
|
|
pub fn write(fd: File, content: []const u8) void {
|
|
var it = content;
|
|
while (it.len != 0) {
|
|
const written_bytes = fd.write_partially(it);
|
|
it.ptr += written_bytes;
|
|
it.len -= written_bytes;
|
|
}
|
|
}
|
|
|
|
pub fn read_partially(fd: File, buffer: [*]u8, byte_count: usize) usize {
|
|
switch (builtin.os.tag) {
|
|
.windows => {
|
|
@compileError("TODO");
|
|
},
|
|
else => {
|
|
const syscall_result = posix.read(fd.fd, buffer, byte_count);
|
|
if (syscall_result <= 0) {
|
|
abort();
|
|
} else {
|
|
return @intCast(syscall_result);
|
|
}
|
|
},
|
|
}
|
|
}
|
|
|
|
pub fn read(fd: File, buffer: []u8, byte_count: usize) void {
|
|
assert(byte_count <= buffer.len);
|
|
var it_byte_count: usize = 0;
|
|
while (it_byte_count < byte_count) {
|
|
const read_bytes = fd.read_partially(buffer.ptr + it_byte_count, byte_count - it_byte_count);
|
|
it_byte_count += read_bytes;
|
|
}
|
|
}
|
|
};
|
|
|
|
pub fn is_being_debugged() bool {
|
|
var result = false;
|
|
switch (builtin.os.tag) {
|
|
.linux => {
|
|
if (linux.ptrace(0, 0, 0, 0) == -1) {
|
|
result = errno() == Error.PERM;
|
|
}
|
|
},
|
|
.windows => IsDebuggerPresent(),
|
|
.macos => {},
|
|
else => @compileError("TODO"),
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
pub fn get_cpu_count() usize {
|
|
switch (builtin.os.tag) {
|
|
.windows => @compileError("TODO"),
|
|
else => {
|
|
var cpu_set: posix.cpu_set_t = undefined;
|
|
const result = posix.sched_getaffinity(0, @sizeOf(posix.cpu_set_t), &cpu_set);
|
|
assert(result == 0);
|
|
const cpu_count = posix.CPU_COUNT(cpu_set);
|
|
return cpu_count;
|
|
},
|
|
}
|
|
}
|
|
|
|
pub fn make_directory(path: [*:0]const u8) void {
|
|
switch (builtin.os.tag) {
|
|
.windows => @compileError("TODO"),
|
|
else => {
|
|
const result = posix.mkdir(path, 0o755);
|
|
_ = result;
|
|
},
|
|
}
|
|
}
|
|
|
|
const linux = struct {
|
|
pub const CPU_SETSIZE = 128;
|
|
pub const cpu_set_t = [CPU_SETSIZE / @sizeOf(usize)]usize;
|
|
pub const cpu_count_t = @Type(.{
|
|
.int = .{
|
|
.signedness = .unsigned,
|
|
.bits = log2_int(@as(u64, CPU_SETSIZE * 8)),
|
|
},
|
|
});
|
|
|
|
pub fn CPU_COUNT(set: cpu_set_t) cpu_count_t {
|
|
var sum: cpu_count_t = 0;
|
|
for (set) |x| {
|
|
sum += @popCount(x);
|
|
}
|
|
return sum;
|
|
}
|
|
|
|
const FileDescriptor = c_int;
|
|
|
|
fn fd_is_valid(fd: FileDescriptor) bool {
|
|
return fd >= 0;
|
|
}
|
|
|
|
pub const uid_t = u32;
|
|
pub const gid_t = u32;
|
|
pub const off_t = i64;
|
|
pub const ino_t = u64;
|
|
pub const dev_t = u64;
|
|
|
|
pub const timespec = extern struct {
|
|
seconds: isize,
|
|
nanoseconds: isize,
|
|
};
|
|
|
|
// The `stat` definition used by the Linux kernel.
|
|
pub const Stat = extern struct {
|
|
dev: dev_t,
|
|
ino: ino_t,
|
|
nlink: usize,
|
|
|
|
mode: u32,
|
|
uid: uid_t,
|
|
gid: gid_t,
|
|
__pad0: u32,
|
|
rdev: dev_t,
|
|
size: off_t,
|
|
blksize: isize,
|
|
blocks: i64,
|
|
|
|
atim: timespec,
|
|
mtim: timespec,
|
|
ctim: timespec,
|
|
__unused: [3]isize,
|
|
};
|
|
|
|
const PROT = packed struct(u32) {
|
|
read: u1,
|
|
write: u1,
|
|
exec: u1,
|
|
sem: u1 = 0,
|
|
_: u28 = 0,
|
|
};
|
|
const MAP = packed struct(u32) {
|
|
const Type = enum(u4) {
|
|
shared = 0x1,
|
|
private = 0x2,
|
|
shared_validate = 0x3,
|
|
};
|
|
|
|
type: Type = .private,
|
|
FIXED: u1 = 0,
|
|
ANONYMOUS: u1 = 0,
|
|
@"32BIT": u1 = 0,
|
|
_7: u1 = 0,
|
|
GROWSDOWN: u1 = 0,
|
|
_9: u2 = 0,
|
|
DENYWRITE: u1 = 0,
|
|
EXECUTABLE: u1 = 0,
|
|
LOCKED: u1 = 0,
|
|
NORESERVE: u1 = 0,
|
|
POPULATE: u1 = 0,
|
|
NONBLOCK: u1 = 0,
|
|
STACK: u1 = 0,
|
|
HUGETLB: u1 = 0,
|
|
SYNC: u1 = 0,
|
|
FIXED_NOREPLACE: u1 = 0,
|
|
_21: u5 = 0,
|
|
UNINITIALIZED: u1 = 0,
|
|
_: u5 = 0,
|
|
};
|
|
|
|
pub const ACCMODE = enum(u2) {
|
|
RDONLY = 0,
|
|
WRONLY = 1,
|
|
RDWR = 2,
|
|
};
|
|
|
|
const O = packed struct(u32) {
|
|
ACCMODE: ACCMODE,
|
|
_2: u4 = 0,
|
|
CREAT: u1 = 0,
|
|
EXCL: u1 = 0,
|
|
NOCTTY: u1 = 0,
|
|
TRUNC: u1 = 0,
|
|
APPEND: u1 = 0,
|
|
NONBLOCK: u1 = 0,
|
|
DSYNC: u1 = 0,
|
|
ASYNC: u1 = 0,
|
|
DIRECT: u1 = 0,
|
|
_15: u1 = 0,
|
|
DIRECTORY: u1 = 0,
|
|
NOFOLLOW: u1 = 0,
|
|
NOATIME: u1 = 0,
|
|
CLOEXEC: u1 = 0,
|
|
SYNC: u1 = 0,
|
|
PATH: u1 = 0,
|
|
TMPFILE: u1 = 0,
|
|
_: u9 = 0,
|
|
};
|
|
|
|
extern "c" fn ptrace(c_int, c_int, usize, usize) c_long;
|
|
extern "c" fn mmap(usize, usize, PROT, MAP, c_int, isize) *align(4096) anyopaque;
|
|
extern "c" fn mprotect(*anyopaque, usize, PROT) c_int;
|
|
extern "c" fn open(path: [*:0]const u8, oflag: O, ...) c_int;
|
|
extern "c" fn close(fd: system.FileDescriptor) c_int;
|
|
extern "c" fn fstat(fd: system.FileDescriptor, stat: *Stat) c_int;
|
|
extern "c" fn read(fd: system.FileDescriptor, pointer: [*]u8, byte_count: usize) isize;
|
|
extern "c" fn write(fd: system.FileDescriptor, pointer: [*]const u8, byte_count: usize) isize;
|
|
extern "c" fn sched_getaffinity(pid: c_int, size: usize, set: *cpu_set_t) c_int;
|
|
extern "c" fn mkdir(path: [*:0]const u8, mode: mode_t) c_int;
|
|
|
|
const mode_t = usize;
|
|
|
|
fn protection_flags(protection: ProtectionFlags) PROT {
|
|
const result = PROT{
|
|
.read = protection.read,
|
|
.write = protection.write,
|
|
.exec = protection.execute,
|
|
};
|
|
return result;
|
|
}
|
|
|
|
fn map_flags(map: MapFlags) MAP {
|
|
const result = MAP{
|
|
.type = if (map.private != 0) .private else .shared,
|
|
.ANONYMOUS = map.anonymous,
|
|
.NORESERVE = map.no_reserve,
|
|
.POPULATE = map.populate,
|
|
};
|
|
|
|
return result;
|
|
}
|
|
};
|
|
|
|
const windows = struct {
|
|
const HANDLE = ?*anyopaque;
|
|
};
|
|
|
|
const ProtectionFlags = packed struct {
|
|
read: u1,
|
|
write: u1,
|
|
execute: u1,
|
|
};
|
|
const MapFlags = packed struct {
|
|
private: u1,
|
|
anonymous: u1,
|
|
no_reserve: u1,
|
|
populate: u1,
|
|
};
|
|
|
|
pub fn reserve(base: u64, size: u64, protection: ProtectionFlags, map: MapFlags) *align(4096) anyopaque {
|
|
switch (builtin.os.tag) {
|
|
.windows => @compileError("TODO"),
|
|
else => {
|
|
const protection_flags = linux.protection_flags(protection);
|
|
const map_flags = linux.map_flags(map);
|
|
const address = linux.mmap(base, size, protection_flags, map_flags, -1, 0);
|
|
if (@intFromPtr(address) == u64_max) {
|
|
@branchHint(.unlikely);
|
|
unreachable;
|
|
}
|
|
return address;
|
|
},
|
|
}
|
|
}
|
|
|
|
pub fn commit(address: *anyopaque, size: u64, protection: ProtectionFlags) void {
|
|
switch (builtin.os.tag) {
|
|
.windows => @compileError("TODO"),
|
|
else => {
|
|
const protection_flags = linux.protection_flags(protection);
|
|
const result = linux.mprotect(address, size, protection_flags);
|
|
if (result != 0) {
|
|
unreachable;
|
|
}
|
|
},
|
|
}
|
|
}
|
|
|
|
pub fn abort() noreturn {
|
|
if (os.is_being_debugged()) {
|
|
@trap();
|
|
} else {
|
|
libc.exit(1);
|
|
}
|
|
}
|
|
|
|
pub fn get_stdout() File {
|
|
return switch (builtin.os.tag) {
|
|
.windows => @compileError("TODO"),
|
|
else => {
|
|
return File{
|
|
.fd = 1,
|
|
};
|
|
},
|
|
};
|
|
}
|
|
|
|
pub fn get_stderr() File {
|
|
return switch (builtin.os.tag) {
|
|
.windows => @compileError("TODO"),
|
|
else => {
|
|
return File{
|
|
.fd = 2,
|
|
};
|
|
},
|
|
};
|
|
}
|
|
|
|
pub fn absolute_path_stack(noalias buffer: []u8, noalias relative_path: [*:0]const u8) [:0]const u8 {
|
|
const real_path = libc.realpath(relative_path, buffer.ptr) orelse unreachable;
|
|
const result = cstring.to_slice(real_path);
|
|
assert(result.len < buffer.len);
|
|
return result;
|
|
}
|
|
|
|
pub fn absolute_path(arena: *Arena, noalias relative_path: [*:0]const u8) [:0]const u8 {
|
|
// TODO: pick a more correct number
|
|
var buffer: [4096]u8 = undefined;
|
|
return arena.duplicate_string(absolute_path_stack(&buffer, relative_path));
|
|
}
|
|
};
|
|
|
|
pub const libc = struct {
|
|
pub extern "c" fn exit(c_int) noreturn;
|
|
pub extern "c" fn memcmp(a: [*]const u8, b: [*]const u8, byte_count: usize) c_int;
|
|
pub extern "c" fn realpath(noalias path: [*:0]const u8, noalias resolved_path: [*]u8) ?[*:0]const u8;
|
|
};
|
|
|
|
pub const string = struct {
|
|
pub fn equal(a: []const u8, b: []const u8) bool {
|
|
var result = a.len == b.len;
|
|
if (result) {
|
|
result = libc.memcmp(a.ptr, b.ptr, a.len) == 0;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
pub fn first_character(str: []const u8, ch: u8) ?usize {
|
|
for (str, 0..) |existing_ch, i| {
|
|
if (ch == existing_ch) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
pub fn last_character(str: []const u8, ch: u8) ?usize {
|
|
var i = str.len;
|
|
while (i > 0) {
|
|
i -= 1;
|
|
|
|
if (str[i] == ch) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
};
|
|
|
|
pub const cstring = struct {
|
|
pub fn length(pointer: [*:0]const u8) usize {
|
|
var it = pointer;
|
|
while (it[0] != 0) {
|
|
it += 1;
|
|
}
|
|
|
|
const result = it - pointer;
|
|
return result;
|
|
}
|
|
|
|
pub fn to_slice(pointer: [*:0]const u8) [:0]const u8 {
|
|
return pointer[0..length(pointer) :0];
|
|
}
|
|
};
|
|
|
|
pub const Arena = struct {
|
|
reserved_size: u64,
|
|
position: u64,
|
|
os_position: u64,
|
|
granularity: u64,
|
|
reserved: [32]u8 = [1]u8{0} ** 32,
|
|
|
|
const minimum_position = @sizeOf(Arena);
|
|
|
|
const Initialization = struct {
|
|
reserved_size: u64,
|
|
granularity: u64,
|
|
initial_size: u64,
|
|
};
|
|
|
|
pub fn initialize(initialization: Initialization) *Arena {
|
|
const protection_flags = os.ProtectionFlags{
|
|
.read = 1,
|
|
.write = 1,
|
|
.execute = 0,
|
|
};
|
|
const map_flags = os.MapFlags{
|
|
.private = 1,
|
|
.anonymous = 1,
|
|
.no_reserve = 1,
|
|
.populate = 0,
|
|
};
|
|
const arena: *Arena = @ptrCast(os.reserve(0, initialization.reserved_size, protection_flags, map_flags));
|
|
os.commit(arena, initialization.initial_size, .{
|
|
.read = 1,
|
|
.write = 1,
|
|
.execute = 0,
|
|
});
|
|
|
|
arena.* = .{
|
|
.reserved_size = initialization.reserved_size,
|
|
.os_position = initialization.initial_size,
|
|
.position = minimum_position,
|
|
.granularity = initialization.granularity,
|
|
};
|
|
|
|
return arena;
|
|
}
|
|
|
|
const default_size = 4 * GB;
|
|
const minimum_granularity = 4 * KB;
|
|
|
|
pub fn initialize_default(initial_size: u64) *Arena {
|
|
const arena = initialize(.{
|
|
.reserved_size = default_size,
|
|
.granularity = minimum_granularity,
|
|
.initial_size = initial_size,
|
|
});
|
|
return arena;
|
|
}
|
|
|
|
pub fn allocate_bytes(arena: *Arena, size: u64, alignment: u64) [*]u8 {
|
|
const aligned_offset = align_forward_u64(arena.position, alignment);
|
|
const aligned_size_after = aligned_offset + size;
|
|
|
|
if (aligned_size_after > arena.os_position) {
|
|
const target_committed_size = align_forward_u64(aligned_size_after, arena.granularity);
|
|
const size_to_commit = target_committed_size - arena.os_position;
|
|
const commit_pointer = @as(*anyopaque, @ptrFromInt(@intFromPtr(arena) + arena.os_position));
|
|
os.commit(commit_pointer, size_to_commit, .{
|
|
.read = 1,
|
|
.write = 1,
|
|
.execute = 0,
|
|
});
|
|
arena.os_position = target_committed_size;
|
|
}
|
|
|
|
const result = @as([*]u8, @ptrFromInt(@intFromPtr(arena) + aligned_offset));
|
|
arena.position = aligned_size_after;
|
|
assert(arena.position <= arena.os_position);
|
|
|
|
return result;
|
|
}
|
|
|
|
pub fn allocate(arena: *Arena, T: type, count: usize) []T {
|
|
const result = arena.allocate_bytes(@sizeOf(T) * count, @alignOf(T));
|
|
const t_ptr: [*]T = @alignCast(@ptrCast(result));
|
|
const t_len = count;
|
|
return t_ptr[0..t_len];
|
|
}
|
|
|
|
pub fn allocate_one(arena: *Arena, T: type) *T {
|
|
const result = arena.allocate(T, 1);
|
|
return &result[0];
|
|
}
|
|
|
|
pub fn join_string(arena: *Arena, pieces: []const []const u8) [:0]u8 {
|
|
var size: u64 = 0;
|
|
for (pieces) |piece| {
|
|
size += piece.len;
|
|
}
|
|
|
|
const pointer = arena.allocate_bytes(size + 1, 1);
|
|
var i: u64 = 0;
|
|
for (pieces) |piece| {
|
|
@memcpy(pointer + i, piece);
|
|
i += piece.len;
|
|
}
|
|
|
|
assert(i == size);
|
|
pointer[i] = 0;
|
|
|
|
return pointer[0..size :0];
|
|
}
|
|
|
|
pub fn duplicate_string(arena: *Arena, str: []const u8) [:0]u8 {
|
|
const memory = arena.allocate_bytes(str.len + 1, 1);
|
|
@memcpy(memory, str);
|
|
memory[str.len] = 0;
|
|
return memory[0..str.len :0];
|
|
}
|
|
|
|
pub fn restore(arena: *Arena, position: u64) void {
|
|
assert(position <= arena.position);
|
|
const do_memset = false;
|
|
if (do_memset) {
|
|
@memset(@as([*]u8, @ptrCast(arena))[position..][0 .. arena.position - position], 0);
|
|
}
|
|
arena.position = position;
|
|
}
|
|
|
|
pub fn reset(arena: *Arena) void {
|
|
arena.restore(minimum_position);
|
|
}
|
|
};
|
|
|
|
pub const string_format = struct {
|
|
pub fn integer_hexadecimal(buffer: []u8, v: u64) u8 {
|
|
var byte_count: u8 = 0;
|
|
var value = v;
|
|
|
|
if (value) {
|
|
var reverse_buffer: [16]u8 = undefined;
|
|
var reverse_index: u8 = 0;
|
|
|
|
while (value) : (reverse_index += 1) {
|
|
const digit_value: u8 = value % 16;
|
|
const ascii_character = if (digit_value >= 10) (digit_value + 'a' - 10) else (digit_value + '0');
|
|
value /= 16;
|
|
reverse_buffer[reverse_index] = ascii_character;
|
|
}
|
|
|
|
while (reverse_index != 0) : (byte_count += 1) {
|
|
reverse_index -= 1;
|
|
buffer[byte_count] = reverse_buffer[reverse_index];
|
|
}
|
|
} else {
|
|
buffer[0] = '0';
|
|
byte_count += 1;
|
|
}
|
|
|
|
return byte_count;
|
|
}
|
|
|
|
pub fn integer_decimal(buffer: []u8, v: u64) u8 {
|
|
var byte_count: u8 = 0;
|
|
var value = v;
|
|
|
|
if (value != 0) {
|
|
var reverse_buffer: [64]u8 = undefined;
|
|
var reverse_index: u8 = 0;
|
|
|
|
while (value != 0) : (reverse_index += 1) {
|
|
const digit_value: u8 = @intCast(value % 10);
|
|
const ascii_character = digit_value + '0';
|
|
value /= 10;
|
|
reverse_buffer[reverse_index] = ascii_character;
|
|
}
|
|
|
|
while (reverse_index != 0) : (byte_count += 1) {
|
|
reverse_index -= 1;
|
|
buffer[byte_count] = reverse_buffer[reverse_index];
|
|
}
|
|
} else {
|
|
buffer[0] = '0';
|
|
byte_count += 1;
|
|
}
|
|
|
|
return byte_count;
|
|
}
|
|
const special_exponent = 0x7fffffff;
|
|
|
|
/// Any buffer used for `format` must be at least this large. This is asserted. A runtime check will
|
|
/// additionally be performed if more bytes are required.
|
|
pub const min_buffer_size = 53;
|
|
|
|
/// Returns the minimum buffer size needed to print every float of a specific type and format.
|
|
pub fn bufferSize(comptime mode: Format, comptime T: type) comptime_int {
|
|
comptime assert(@typeInfo(T) == .float);
|
|
return switch (mode) {
|
|
.scientific => 53,
|
|
// Based on minimum subnormal values.
|
|
.decimal => switch (@bitSizeOf(T)) {
|
|
16 => @max(15, min_buffer_size),
|
|
32 => 55,
|
|
64 => 347,
|
|
80 => 4996,
|
|
128 => 5011,
|
|
else => unreachable,
|
|
},
|
|
};
|
|
}
|
|
|
|
pub const FormatError = error{
|
|
BufferTooSmall,
|
|
};
|
|
|
|
pub const Format = enum {
|
|
scientific,
|
|
decimal,
|
|
};
|
|
|
|
pub const FormatOptions = struct {
|
|
mode: Format = .scientific,
|
|
precision: ?usize = null,
|
|
};
|
|
|
|
/// Format a floating-point value and write it to buffer. Returns a slice to the buffer containing
|
|
/// the string representation.
|
|
///
|
|
/// Full precision is the default. Any full precision float can be reparsed with std.fmt.parseFloat
|
|
/// unambiguously.
|
|
///
|
|
/// Scientific mode is recommended generally as the output is more compact and any type can be
|
|
/// written in full precision using a buffer of only `min_buffer_size`.
|
|
///
|
|
/// When printing full precision decimals, use `bufferSize` to get the required space. It is
|
|
/// recommended to bound decimal output with a fixed precision to reduce the required buffer size.
|
|
pub fn formatFloat(buf: []u8, v_: anytype, options: FormatOptions) FormatError![]const u8 {
|
|
const v = switch (@TypeOf(v_)) {
|
|
// comptime_float internally is a f128; this preserves precision.
|
|
comptime_float => @as(f128, v_),
|
|
else => v_,
|
|
};
|
|
|
|
const T = @TypeOf(v);
|
|
comptime assert(@typeInfo(T) == .float);
|
|
const I = @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(T) } });
|
|
|
|
const DT = if (@bitSizeOf(T) <= 64) u64 else u128;
|
|
const tables = switch (DT) {
|
|
u64 => if (@import("builtin").mode == .ReleaseSmall) &Backend64_TablesSmall else &Backend64_TablesFull,
|
|
u128 => &Backend128_Tables,
|
|
else => unreachable,
|
|
};
|
|
|
|
const has_explicit_leading_bit = float_mantissa_bits(T) - float_fractional_bits(T) != 0;
|
|
const d = binaryToDecimal(DT, @as(I, @bitCast(v)), float_mantissa_bits(T), float_exponent_bits(T), has_explicit_leading_bit, tables);
|
|
|
|
return switch (options.mode) {
|
|
.scientific => formatScientific(DT, buf, d, options.precision),
|
|
.decimal => formatDecimal(DT, buf, d, options.precision),
|
|
};
|
|
}
|
|
|
|
pub fn FloatDecimal(comptime T: type) type {
|
|
comptime assert(T == u64 or T == u128);
|
|
return struct {
|
|
mantissa: T,
|
|
exponent: i32,
|
|
sign: bool,
|
|
};
|
|
}
|
|
|
|
fn copySpecialStr(buf: []u8, f: anytype) []const u8 {
|
|
if (f.sign) {
|
|
buf[0] = '-';
|
|
}
|
|
const offset: usize = @intFromBool(f.sign);
|
|
if (f.mantissa != 0) {
|
|
@memcpy(buf[offset..][0..3], "nan");
|
|
return buf[0 .. 3 + offset];
|
|
}
|
|
@memcpy(buf[offset..][0..3], "inf");
|
|
return buf[0 .. 3 + offset];
|
|
}
|
|
|
|
fn writeDecimal(buf: []u8, value: anytype, count: usize) void {
|
|
var i: usize = 0;
|
|
|
|
while (i + 2 < count) : (i += 2) {
|
|
const c: u8 = @intCast(value.* % 100);
|
|
value.* /= 100;
|
|
const d = digits2(c);
|
|
buf[count - i - 1] = d[1];
|
|
buf[count - i - 2] = d[0];
|
|
}
|
|
|
|
while (i < count) : (i += 1) {
|
|
const c: u8 = @intCast(value.* % 10);
|
|
value.* /= 10;
|
|
buf[count - i - 1] = '0' + c;
|
|
}
|
|
}
|
|
|
|
fn isPowerOf10(n_: u128) bool {
|
|
var n = n_;
|
|
while (n != 0) : (n /= 10) {
|
|
if (n % 10 != 0) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
const RoundMode = enum {
|
|
/// 1234.56 = precision 2
|
|
decimal,
|
|
/// 1.23456e3 = precision 5
|
|
scientific,
|
|
};
|
|
|
|
fn round(comptime T: type, f: FloatDecimal(T), mode: RoundMode, precision: usize) FloatDecimal(T) {
|
|
var round_digit: usize = 0;
|
|
var output = f.mantissa;
|
|
var exp = f.exponent;
|
|
const olength = decimalLength(output);
|
|
|
|
switch (mode) {
|
|
.decimal => {
|
|
if (f.exponent > 0) {
|
|
round_digit = (olength - 1) + precision + @as(usize, @intCast(f.exponent));
|
|
} else {
|
|
const min_exp_required = @as(usize, @intCast(-f.exponent));
|
|
if (precision + olength > min_exp_required) {
|
|
round_digit = precision + olength - min_exp_required;
|
|
}
|
|
}
|
|
},
|
|
.scientific => {
|
|
round_digit = 1 + precision;
|
|
},
|
|
}
|
|
|
|
if (round_digit < olength) {
|
|
var nlength = olength;
|
|
for (round_digit + 1..olength) |_| {
|
|
output /= 10;
|
|
exp += 1;
|
|
nlength -= 1;
|
|
}
|
|
|
|
if (output % 10 >= 5) {
|
|
output /= 10;
|
|
output += 1;
|
|
exp += 1;
|
|
|
|
// e.g. 9999 -> 10000
|
|
if (isPowerOf10(output)) {
|
|
output /= 10;
|
|
exp += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return .{
|
|
.mantissa = output,
|
|
.exponent = exp,
|
|
.sign = f.sign,
|
|
};
|
|
}
|
|
|
|
/// Write a FloatDecimal to a buffer in scientific form.
|
|
///
|
|
/// The buffer provided must be greater than `min_buffer_size` in length. If no precision is
|
|
/// specified, this function will never return an error. If a precision is specified, up to
|
|
/// `8 + precision` bytes will be written to the buffer. An error will be returned if the content
|
|
/// will not fit.
|
|
///
|
|
/// It is recommended to bound decimal formatting with an exact precision.
|
|
pub fn formatScientific(comptime T: type, buf: []u8, f_: FloatDecimal(T), precision: ?usize) FormatError![]const u8 {
|
|
assert(buf.len >= min_buffer_size);
|
|
var f = f_;
|
|
|
|
if (f.exponent == special_exponent) {
|
|
return copySpecialStr(buf, f);
|
|
}
|
|
|
|
if (precision) |prec| {
|
|
f = round(T, f, .scientific, prec);
|
|
}
|
|
|
|
var output = f.mantissa;
|
|
const olength = decimalLength(output);
|
|
|
|
if (precision) |prec| {
|
|
// fixed bound: sign(1) + leading_digit(1) + point(1) + exp_sign(1) + exp_max(4)
|
|
const req_bytes = 8 + prec;
|
|
if (buf.len < req_bytes) {
|
|
return error.BufferTooSmall;
|
|
}
|
|
}
|
|
|
|
// Step 5: Print the scientific representation
|
|
var index: usize = 0;
|
|
if (f.sign) {
|
|
buf[index] = '-';
|
|
index += 1;
|
|
}
|
|
|
|
// 1.12345
|
|
writeDecimal(buf[index + 2 ..], &output, olength - 1);
|
|
buf[index] = '0' + @as(u8, @intCast(output % 10));
|
|
buf[index + 1] = '.';
|
|
index += 2;
|
|
const dp_index = index;
|
|
if (olength > 1) index += olength - 1 else index -= 1;
|
|
|
|
if (precision) |prec| {
|
|
index += @intFromBool(olength == 1);
|
|
if (prec > olength - 1) {
|
|
const len = prec - (olength - 1);
|
|
@memset(buf[index..][0..len], '0');
|
|
index += len;
|
|
} else {
|
|
index = dp_index + prec - @intFromBool(prec == 0);
|
|
}
|
|
}
|
|
|
|
// e100
|
|
buf[index] = 'e';
|
|
index += 1;
|
|
var exp = f.exponent + @as(i32, @intCast(olength)) - 1;
|
|
if (exp < 0) {
|
|
buf[index] = '-';
|
|
index += 1;
|
|
exp = -exp;
|
|
}
|
|
var uexp: u32 = @intCast(exp);
|
|
const elength = decimalLength(uexp);
|
|
writeDecimal(buf[index..], &uexp, elength);
|
|
index += elength;
|
|
|
|
return buf[0..index];
|
|
}
|
|
|
|
/// Write a FloatDecimal to a buffer in decimal form.
|
|
///
|
|
/// The buffer provided must be greater than `min_buffer_size` bytes in length. If no precision is
|
|
/// specified, this may still return an error. If precision is specified, `2 + precision` bytes will
|
|
/// always be written.
|
|
pub fn formatDecimal(comptime T: type, buf: []u8, f_: FloatDecimal(T), precision: ?usize) FormatError![]const u8 {
|
|
assert(buf.len >= min_buffer_size);
|
|
var f = f_;
|
|
|
|
if (f.exponent == special_exponent) {
|
|
return copySpecialStr(buf, f);
|
|
}
|
|
|
|
if (precision) |prec| {
|
|
f = round(T, f, .decimal, prec);
|
|
}
|
|
|
|
var output = f.mantissa;
|
|
const olength = decimalLength(output);
|
|
|
|
// fixed bound: leading_digit(1) + point(1)
|
|
const req_bytes = if (f.exponent >= 0)
|
|
@as(usize, 2) + @abs(f.exponent) + olength + (precision orelse 0)
|
|
else
|
|
@as(usize, 2) + @max(@abs(f.exponent) + olength, precision orelse 0);
|
|
if (buf.len < req_bytes) {
|
|
return error.BufferTooSmall;
|
|
}
|
|
|
|
// Step 5: Print the decimal representation
|
|
var index: usize = 0;
|
|
if (f.sign) {
|
|
buf[index] = '-';
|
|
index += 1;
|
|
}
|
|
|
|
const dp_offset = f.exponent + cast_i32(olength);
|
|
if (dp_offset <= 0) {
|
|
// 0.000001234
|
|
buf[index] = '0';
|
|
buf[index + 1] = '.';
|
|
index += 2;
|
|
const dp_index = index;
|
|
|
|
const dp_poffset: u32 = @intCast(-dp_offset);
|
|
@memset(buf[index..][0..dp_poffset], '0');
|
|
index += dp_poffset;
|
|
writeDecimal(buf[index..], &output, olength);
|
|
index += olength;
|
|
|
|
if (precision) |prec| {
|
|
const dp_written = index - dp_index;
|
|
if (prec > dp_written) {
|
|
@memset(buf[index..][0 .. prec - dp_written], '0');
|
|
}
|
|
index = dp_index + prec - @intFromBool(prec == 0);
|
|
}
|
|
} else {
|
|
// 123456000
|
|
const dp_uoffset: usize = @intCast(dp_offset);
|
|
if (dp_uoffset >= olength) {
|
|
writeDecimal(buf[index..], &output, olength);
|
|
index += olength;
|
|
@memset(buf[index..][0 .. dp_uoffset - olength], '0');
|
|
index += dp_uoffset - olength;
|
|
|
|
if (precision) |prec| {
|
|
if (prec != 0) {
|
|
buf[index] = '.';
|
|
index += 1;
|
|
@memset(buf[index..][0..prec], '0');
|
|
index += prec;
|
|
}
|
|
}
|
|
} else {
|
|
// 12345.6789
|
|
writeDecimal(buf[index + dp_uoffset + 1 ..], &output, olength - dp_uoffset);
|
|
buf[index + dp_uoffset] = '.';
|
|
const dp_index = index + dp_uoffset + 1;
|
|
writeDecimal(buf[index..], &output, dp_uoffset);
|
|
index += olength + 1;
|
|
|
|
if (precision) |prec| {
|
|
const dp_written = olength - dp_uoffset;
|
|
if (prec > dp_written) {
|
|
@memset(buf[index..][0 .. prec - dp_written], '0');
|
|
}
|
|
index = dp_index + prec - @intFromBool(prec == 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
return buf[0..index];
|
|
}
|
|
|
|
fn cast_i32(v: anytype) i32 {
|
|
return @intCast(v);
|
|
}
|
|
|
|
/// Convert a binary float representation to decimal.
|
|
pub fn binaryToDecimal(comptime T: type, bits: T, mantissa_bits: Log2Int(T), exponent_bits: u5, explicit_leading_bit: bool, comptime tables: anytype) FloatDecimal(T) {
|
|
if (T != tables.T) {
|
|
@compileError("table type does not match backend type: " ++ @typeName(tables.T) ++ " != " ++ @typeName(T));
|
|
}
|
|
|
|
const bias = (@as(u32, 1) << (exponent_bits - 1)) - 1;
|
|
const ieee_sign = ((bits >> (mantissa_bits + exponent_bits)) & 1) != 0;
|
|
const ieee_mantissa = bits & ((@as(T, 1) << mantissa_bits) - 1);
|
|
const ieee_exponent: u32 = @intCast((bits >> mantissa_bits) & ((@as(T, 1) << exponent_bits) - 1));
|
|
|
|
if (ieee_exponent == 0 and ieee_mantissa == 0) {
|
|
return .{
|
|
.mantissa = 0,
|
|
.exponent = 0,
|
|
.sign = ieee_sign,
|
|
};
|
|
}
|
|
if (ieee_exponent == ((@as(u32, 1) << exponent_bits) - 1)) {
|
|
return .{
|
|
.mantissa = if (explicit_leading_bit) ieee_mantissa & ((@as(T, 1) << (mantissa_bits - 1)) - 1) else ieee_mantissa,
|
|
.exponent = special_exponent,
|
|
.sign = ieee_sign,
|
|
};
|
|
}
|
|
|
|
var e2: i32 = undefined;
|
|
var m2: T = undefined;
|
|
if (explicit_leading_bit) {
|
|
if (ieee_exponent == 0) {
|
|
e2 = 1 - cast_i32(bias) - cast_i32(mantissa_bits) + 1 - 2;
|
|
} else {
|
|
e2 = cast_i32(ieee_exponent) - cast_i32(bias) - cast_i32(mantissa_bits) + 1 - 2;
|
|
}
|
|
m2 = ieee_mantissa;
|
|
} else {
|
|
if (ieee_exponent == 0) {
|
|
e2 = 1 - cast_i32(bias) - cast_i32(mantissa_bits) - 2;
|
|
m2 = ieee_mantissa;
|
|
} else {
|
|
e2 = cast_i32(ieee_exponent) - cast_i32(bias) - cast_i32(mantissa_bits) - 2;
|
|
m2 = (@as(T, 1) << mantissa_bits) | ieee_mantissa;
|
|
}
|
|
}
|
|
const even = (m2 & 1) == 0;
|
|
const accept_bounds = even;
|
|
|
|
// Step 2: Determine the interval of legal decimal representations.
|
|
const mv = 4 * m2;
|
|
const mm_shift: u1 = @intFromBool((ieee_mantissa != if (explicit_leading_bit) (@as(T, 1) << (mantissa_bits - 1)) else 0) or (ieee_exponent == 0));
|
|
|
|
// Step 3: Convert to a decimal power base using 128-bit arithmetic.
|
|
var vr: T = undefined;
|
|
var vp: T = undefined;
|
|
var vm: T = undefined;
|
|
var e10: i32 = undefined;
|
|
var vm_is_trailing_zeros = false;
|
|
var vr_is_trailing_zeros = false;
|
|
if (e2 >= 0) {
|
|
const q: u32 = log10Pow2(@intCast(e2)) - @intFromBool(e2 > 3);
|
|
e10 = cast_i32(q);
|
|
const k: i32 = @intCast(tables.POW5_INV_BITCOUNT + pow5Bits(q) - 1);
|
|
const i: u32 = @intCast(-e2 + cast_i32(q) + k);
|
|
|
|
const pow5 = tables.computeInvPow5(q);
|
|
vr = tables.mulShift(4 * m2, &pow5, i);
|
|
vp = tables.mulShift(4 * m2 + 2, &pow5, i);
|
|
vm = tables.mulShift(4 * m2 - 1 - mm_shift, &pow5, i);
|
|
|
|
if (q <= tables.bound1) {
|
|
if (mv % 5 == 0) {
|
|
vr_is_trailing_zeros = multipleOfPowerOf5(mv, if (tables.adjust_q) q -% 1 else q);
|
|
} else if (accept_bounds) {
|
|
vm_is_trailing_zeros = multipleOfPowerOf5(mv - 1 - mm_shift, q);
|
|
} else {
|
|
vp -= @intFromBool(multipleOfPowerOf5(mv + 2, q));
|
|
}
|
|
}
|
|
} else {
|
|
const q: u32 = log10Pow5(@intCast(-e2)) - @intFromBool(-e2 > 1);
|
|
e10 = cast_i32(q) + e2;
|
|
const i: i32 = -e2 - cast_i32(q);
|
|
const k: i32 = cast_i32(pow5Bits(@intCast(i))) - tables.POW5_BITCOUNT;
|
|
const j: u32 = @intCast(cast_i32(q) - k);
|
|
|
|
const pow5 = tables.computePow5(@intCast(i));
|
|
vr = tables.mulShift(4 * m2, &pow5, j);
|
|
vp = tables.mulShift(4 * m2 + 2, &pow5, j);
|
|
vm = tables.mulShift(4 * m2 - 1 - mm_shift, &pow5, j);
|
|
|
|
if (q <= 1) {
|
|
vr_is_trailing_zeros = true;
|
|
if (accept_bounds) {
|
|
vm_is_trailing_zeros = mm_shift == 1;
|
|
} else {
|
|
vp -= 1;
|
|
}
|
|
} else if (q < tables.bound2) {
|
|
vr_is_trailing_zeros = multipleOfPowerOf2(mv, if (tables.adjust_q) q - 1 else q);
|
|
}
|
|
}
|
|
|
|
// Step 4: Find the shortest decimal representation in the interval of legal representations.
|
|
var removed: u32 = 0;
|
|
var last_removed_digit: u8 = 0;
|
|
|
|
while (vp / 10 > vm / 10) {
|
|
vm_is_trailing_zeros = vm_is_trailing_zeros and vm % 10 == 0;
|
|
vr_is_trailing_zeros = vr_is_trailing_zeros and last_removed_digit == 0;
|
|
last_removed_digit = @intCast(vr % 10);
|
|
vr /= 10;
|
|
vp /= 10;
|
|
vm /= 10;
|
|
removed += 1;
|
|
}
|
|
|
|
if (vm_is_trailing_zeros) {
|
|
while (vm % 10 == 0) {
|
|
vr_is_trailing_zeros = vr_is_trailing_zeros and last_removed_digit == 0;
|
|
last_removed_digit = @intCast(vr % 10);
|
|
vr /= 10;
|
|
vp /= 10;
|
|
vm /= 10;
|
|
removed += 1;
|
|
}
|
|
}
|
|
|
|
if (vr_is_trailing_zeros and (last_removed_digit == 5) and (vr % 2 == 0)) {
|
|
last_removed_digit = 4;
|
|
}
|
|
|
|
return .{
|
|
.mantissa = vr + @intFromBool((vr == vm and (!accept_bounds or !vm_is_trailing_zeros)) or last_removed_digit >= 5),
|
|
.exponent = e10 + cast_i32(removed),
|
|
.sign = ieee_sign,
|
|
};
|
|
}
|
|
|
|
fn decimalLength(v: anytype) u32 {
|
|
switch (@TypeOf(v)) {
|
|
u32, u64 => {
|
|
assert(v < 100000000000000000);
|
|
if (v >= 10000000000000000) return 17;
|
|
if (v >= 1000000000000000) return 16;
|
|
if (v >= 100000000000000) return 15;
|
|
if (v >= 10000000000000) return 14;
|
|
if (v >= 1000000000000) return 13;
|
|
if (v >= 100000000000) return 12;
|
|
if (v >= 10000000000) return 11;
|
|
if (v >= 1000000000) return 10;
|
|
if (v >= 100000000) return 9;
|
|
if (v >= 10000000) return 8;
|
|
if (v >= 1000000) return 7;
|
|
if (v >= 100000) return 6;
|
|
if (v >= 10000) return 5;
|
|
if (v >= 1000) return 4;
|
|
if (v >= 100) return 3;
|
|
if (v >= 10) return 2;
|
|
return 1;
|
|
},
|
|
u128 => {
|
|
const LARGEST_POW10 = (@as(u128, 5421010862427522170) << 64) | 687399551400673280;
|
|
var p10 = LARGEST_POW10;
|
|
var i: u32 = 39;
|
|
while (i > 0) : (i -= 1) {
|
|
if (v >= p10) return i;
|
|
p10 /= 10;
|
|
}
|
|
return 1;
|
|
},
|
|
else => unreachable,
|
|
}
|
|
}
|
|
|
|
// floor(log_10(2^e))
|
|
fn log10Pow2(e: u32) u32 {
|
|
assert(e <= 1 << 15);
|
|
return @intCast((@as(u64, @intCast(e)) * 169464822037455) >> 49);
|
|
}
|
|
|
|
// floor(log_10(5^e))
|
|
fn log10Pow5(e: u32) u32 {
|
|
assert(e <= 1 << 15);
|
|
return @intCast((@as(u64, @intCast(e)) * 196742565691928) >> 48);
|
|
}
|
|
|
|
// if (e == 0) 1 else ceil(log_2(5^e))
|
|
fn pow5Bits(e: u32) u32 {
|
|
assert(e <= 1 << 15);
|
|
return @intCast(((@as(u64, @intCast(e)) * 163391164108059) >> 46) + 1);
|
|
}
|
|
|
|
fn pow5Factor(value_: anytype) u32 {
|
|
var count: u32 = 0;
|
|
var value = value_;
|
|
while (value > 0) : ({
|
|
count += 1;
|
|
value /= 5;
|
|
}) {
|
|
if (value % 5 != 0) return count;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
fn multipleOfPowerOf5(value: anytype, p: u32) bool {
|
|
const T = @TypeOf(value);
|
|
assert(@typeInfo(T) == .int);
|
|
return pow5Factor(value) >= p;
|
|
}
|
|
|
|
fn multipleOfPowerOf2(value: anytype, p: u32) bool {
|
|
const T = @TypeOf(value);
|
|
assert(@typeInfo(T) == .int);
|
|
return (value & ((@as(T, 1) << @as(Log2Int(T), @intCast(p))) - 1)) == 0;
|
|
}
|
|
|
|
fn mulShift128(m: u128, mul: *const [4]u64, j: u32) u128 {
|
|
assert(j > 128);
|
|
const a: [2]u64 = .{ @truncate(m), @truncate(m >> 64) };
|
|
const r = mul_128_256_shift(&a, mul, j, 0);
|
|
return (@as(u128, r[1]) << 64) | r[0];
|
|
}
|
|
|
|
fn mul_128_256_shift(a: *const [2]u64, b: *const [4]u64, shift: u32, corr: u32) [4]u64 {
|
|
assert(shift > 0);
|
|
assert(shift < 256);
|
|
|
|
const b00 = @as(u128, a[0]) * b[0];
|
|
const b01 = @as(u128, a[0]) * b[1];
|
|
const b02 = @as(u128, a[0]) * b[2];
|
|
const b03 = @as(u128, a[0]) * b[3];
|
|
const b10 = @as(u128, a[1]) * b[0];
|
|
const b11 = @as(u128, a[1]) * b[1];
|
|
const b12 = @as(u128, a[1]) * b[2];
|
|
const b13 = @as(u128, a[1]) * b[3];
|
|
|
|
const s0 = b00;
|
|
const s1 = b01 +% b10;
|
|
const c1: u128 = @intFromBool(s1 < b01);
|
|
const s2 = b02 +% b11;
|
|
const c2: u128 = @intFromBool(s2 < b02);
|
|
const s3 = b03 +% b12;
|
|
const c3: u128 = @intFromBool(s3 < b03);
|
|
|
|
const p0 = s0 +% (s1 << 64);
|
|
const d0: u128 = @intFromBool(p0 < b00);
|
|
const q1 = s2 +% (s1 >> 64) +% (s3 << 64);
|
|
const d1: u128 = @intFromBool(q1 < s2);
|
|
const p1 = q1 +% (c1 << 64) +% d0;
|
|
const d2: u128 = @intFromBool(p1 < q1);
|
|
const p2 = b13 +% (s3 >> 64) +% c2 +% (c3 << 64) +% d1 +% d2;
|
|
|
|
var r0: u128 = undefined;
|
|
var r1: u128 = undefined;
|
|
if (shift < 128) {
|
|
const cshift: u7 = @intCast(shift);
|
|
const sshift: u7 = @intCast(128 - shift);
|
|
r0 = corr +% ((p0 >> cshift) | (p1 << sshift));
|
|
r1 = ((p1 >> cshift) | (p2 << sshift)) +% @intFromBool(r0 < corr);
|
|
} else if (shift == 128) {
|
|
r0 = corr +% p1;
|
|
r1 = p2 +% @intFromBool(r0 < corr);
|
|
} else {
|
|
const ashift: u7 = @intCast(shift - 128);
|
|
const sshift: u7 = @intCast(256 - shift);
|
|
r0 = corr +% ((p1 >> ashift) | (p2 << sshift));
|
|
r1 = (p2 >> ashift) +% @intFromBool(r0 < corr);
|
|
}
|
|
|
|
return .{ @truncate(r0), @truncate(r0 >> 64), @truncate(r1), @truncate(r1 >> 64) };
|
|
}
|
|
|
|
pub const Backend128_Tables = struct {
|
|
const T = u128;
|
|
const mulShift = mulShift128;
|
|
const POW5_INV_BITCOUNT = FLOAT128_POW5_INV_BITCOUNT;
|
|
const POW5_BITCOUNT = FLOAT128_POW5_BITCOUNT;
|
|
|
|
const bound1 = 55;
|
|
const bound2 = 127;
|
|
const adjust_q = true;
|
|
|
|
fn computePow5(i: u32) [4]u64 {
|
|
const base = i / FLOAT128_POW5_TABLE_SIZE;
|
|
const base2 = base * FLOAT128_POW5_TABLE_SIZE;
|
|
const mul = &FLOAT128_POW5_SPLIT[base];
|
|
if (i == base2) {
|
|
return mul.*;
|
|
} else {
|
|
const offset = i - base2;
|
|
const m = &FLOAT128_POW5_TABLE[offset];
|
|
const delta = pow5Bits(i) - pow5Bits(base2);
|
|
|
|
const shift: u6 = @intCast(2 * (i % 32));
|
|
const corr: u32 = @intCast((FLOAT128_POW5_ERRORS[i / 32] >> shift) & 3);
|
|
return mul_128_256_shift(m, mul, delta, corr);
|
|
}
|
|
}
|
|
|
|
fn computeInvPow5(i: u32) [4]u64 {
|
|
const base = (i + FLOAT128_POW5_TABLE_SIZE - 1) / FLOAT128_POW5_TABLE_SIZE;
|
|
const base2 = base * FLOAT128_POW5_TABLE_SIZE;
|
|
const mul = &FLOAT128_POW5_INV_SPLIT[base]; // 1 / 5^base2
|
|
if (i == base2) {
|
|
return .{ mul[0] + 1, mul[1], mul[2], mul[3] };
|
|
} else {
|
|
const offset = base2 - i;
|
|
const m = &FLOAT128_POW5_TABLE[offset]; // 5^offset
|
|
const delta = pow5Bits(base2) - pow5Bits(i);
|
|
|
|
const shift: u6 = @intCast(2 * (i % 32));
|
|
const corr: u32 = @intCast(((FLOAT128_POW5_INV_ERRORS[i / 32] >> shift) & 3) + 1);
|
|
return mul_128_256_shift(m, mul, delta, corr);
|
|
}
|
|
}
|
|
};
|
|
|
|
fn mulShift64(m: u64, mul: *const [2]u64, j: u32) u64 {
|
|
assert(j > 64);
|
|
const b0 = @as(u128, m) * mul[0];
|
|
const b2 = @as(u128, m) * mul[1];
|
|
|
|
if (j < 128) {
|
|
const shift: u6 = @intCast(j - 64);
|
|
return @intCast(((b0 >> 64) + b2) >> shift);
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
pub const Backend64_TablesFull = struct {
|
|
const T = u64;
|
|
const mulShift = mulShift64;
|
|
const POW5_INV_BITCOUNT = FLOAT64_POW5_INV_BITCOUNT;
|
|
const POW5_BITCOUNT = FLOAT64_POW5_BITCOUNT;
|
|
|
|
const bound1 = 21;
|
|
const bound2 = 63;
|
|
const adjust_q = false;
|
|
|
|
fn computePow5(i: u32) [2]u64 {
|
|
return FLOAT64_POW5_SPLIT[i];
|
|
}
|
|
|
|
fn computeInvPow5(i: u32) [2]u64 {
|
|
return FLOAT64_POW5_INV_SPLIT[i];
|
|
}
|
|
};
|
|
|
|
pub const Backend64_TablesSmall = struct {
|
|
const T = u64;
|
|
const mulShift = mulShift64;
|
|
const POW5_INV_BITCOUNT = FLOAT64_POW5_INV_BITCOUNT;
|
|
const POW5_BITCOUNT = FLOAT64_POW5_BITCOUNT;
|
|
|
|
const bound1 = 21;
|
|
const bound2 = 63;
|
|
const adjust_q = false;
|
|
|
|
fn computePow5(i: u32) [2]u64 {
|
|
const base = i / FLOAT64_POW5_TABLE_SIZE;
|
|
const base2 = base * FLOAT64_POW5_TABLE_SIZE;
|
|
const mul = &FLOAT64_POW5_SPLIT2[base];
|
|
if (i == base2) {
|
|
return .{ mul[0], mul[1] };
|
|
} else {
|
|
const offset = i - base2;
|
|
const m = FLOAT64_POW5_TABLE[offset];
|
|
const b0 = @as(u128, m) * mul[0];
|
|
const b2 = @as(u128, m) * mul[1];
|
|
const delta: u7 = @intCast(pow5Bits(i) - pow5Bits(base2));
|
|
const shift: u5 = @intCast((i % 16) << 1);
|
|
const shifted_sum = ((b0 >> delta) + (b2 << (64 - delta))) + 1 + ((FLOAT64_POW5_OFFSETS[i / 16] >> shift) & 3);
|
|
return .{ @truncate(shifted_sum), @truncate(shifted_sum >> 64) };
|
|
}
|
|
}
|
|
|
|
fn computeInvPow5(i: u32) [2]u64 {
|
|
const base = (i + FLOAT64_POW5_TABLE_SIZE - 1) / FLOAT64_POW5_TABLE_SIZE;
|
|
const base2 = base * FLOAT64_POW5_TABLE_SIZE;
|
|
const mul = &FLOAT64_POW5_INV_SPLIT2[base]; // 1 / 5^base2
|
|
if (i == base2) {
|
|
return .{ mul[0], mul[1] };
|
|
} else {
|
|
const offset = base2 - i;
|
|
const m = FLOAT64_POW5_TABLE[offset]; // 5^offset
|
|
const b0 = @as(u128, m) * (mul[0] - 1);
|
|
const b2 = @as(u128, m) * mul[1]; // 1/5^base2 * 5^offset = 1/5^(base2-offset) = 1/5^i
|
|
const delta: u7 = @intCast(pow5Bits(base2) - pow5Bits(i));
|
|
const shift: u5 = @intCast((i % 16) << 1);
|
|
const shifted_sum = ((b0 >> delta) + (b2 << (64 - delta))) + 1 + ((FLOAT64_POW5_INV_OFFSETS[i / 16] >> shift) & 3);
|
|
return .{ @truncate(shifted_sum), @truncate(shifted_sum >> 64) };
|
|
}
|
|
}
|
|
};
|
|
|
|
const FLOAT64_POW5_INV_BITCOUNT = 125;
|
|
const FLOAT64_POW5_BITCOUNT = 125;
|
|
|
|
// zig fmt: off
|
|
//
|
|
// f64 small tables: 816 bytes
|
|
|
|
const FLOAT64_POW5_TABLE_SIZE: comptime_int = FLOAT64_POW5_TABLE.len;
|
|
|
|
const FLOAT64_POW5_TABLE: [26]u64 = .{
|
|
1, 5,
|
|
25, 125,
|
|
625, 3125,
|
|
15625, 78125,
|
|
390625, 1953125,
|
|
9765625, 48828125,
|
|
244140625, 1220703125,
|
|
6103515625, 30517578125,
|
|
152587890625, 762939453125,
|
|
3814697265625, 19073486328125,
|
|
95367431640625, 476837158203125,
|
|
2384185791015625, 11920928955078125,
|
|
59604644775390625, 298023223876953125,
|
|
};
|
|
|
|
const FLOAT64_POW5_SPLIT2: [13][2]u64 = .{
|
|
.{ 0, 1152921504606846976 },
|
|
.{ 0, 1490116119384765625 },
|
|
.{ 1032610780636961552, 1925929944387235853 },
|
|
.{ 7910200175544436838, 1244603055572228341 },
|
|
.{ 16941905809032713930, 1608611746708759036 },
|
|
.{ 13024893955298202172, 2079081953128979843 },
|
|
.{ 6607496772837067824, 1343575221513417750 },
|
|
.{ 17332926989895652603, 1736530273035216783 },
|
|
.{ 13037379183483547984, 2244412773384604712 },
|
|
.{ 1605989338741628675, 1450417759929778918 },
|
|
.{ 9630225068416591280, 1874621017369538693 },
|
|
.{ 665883850346957067, 1211445438634777304 },
|
|
.{ 14931890668723713708, 1565756531257009982 }
|
|
};
|
|
|
|
const FLOAT64_POW5_OFFSETS: [21]u32 = .{
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
|
0x40000000, 0x59695995, 0x55545555, 0x56555515,
|
|
0x41150504, 0x40555410, 0x44555145, 0x44504540,
|
|
0x45555550, 0x40004000, 0x96440440, 0x55565565,
|
|
0x54454045, 0x40154151, 0x55559155, 0x51405555,
|
|
0x00000105,
|
|
};
|
|
|
|
const FLOAT64_POW5_INV_SPLIT2: [15][2]u64 = .{
|
|
.{ 1, 2305843009213693952 },
|
|
.{ 5955668970331000884, 1784059615882449851 },
|
|
.{ 8982663654677661702, 1380349269358112757 },
|
|
.{ 7286864317269821294, 2135987035920910082 },
|
|
.{ 7005857020398200553, 1652639921975621497 },
|
|
.{ 17965325103354776697, 1278668206209430417 },
|
|
.{ 8928596168509315048, 1978643211784836272 },
|
|
.{ 10075671573058298858, 1530901034580419511 },
|
|
.{ 597001226353042382, 1184477304306571148 },
|
|
.{ 1527430471115325346, 1832889850782397517 },
|
|
.{ 12533209867169019542, 1418129833677084982 },
|
|
.{ 5577825024675947042, 2194449627517475473 },
|
|
.{ 11006974540203867551, 1697873161311732311 },
|
|
.{ 10313493231639821582, 1313665730009899186 },
|
|
.{ 12701016819766672773, 2032799256770390445 }
|
|
};
|
|
|
|
const FLOAT64_POW5_INV_OFFSETS: [19]u32 = .{
|
|
0x54544554, 0x04055545, 0x10041000, 0x00400414,
|
|
0x40010000, 0x41155555, 0x00000454, 0x00010044,
|
|
0x40000000, 0x44000041, 0x50454450, 0x55550054,
|
|
0x51655554, 0x40004000, 0x01000001, 0x00010500,
|
|
0x51515411, 0x05555554, 0x00000000,
|
|
};
|
|
|
|
|
|
// zig fmt: off
|
|
|
|
// f64 full tables: 10688 bytes
|
|
|
|
const FLOAT64_POW5_SPLIT: [326][2]u64 = .{
|
|
.{ 0, 1152921504606846976 }, .{ 0, 1441151880758558720 },
|
|
.{ 0, 1801439850948198400 }, .{ 0, 2251799813685248000 },
|
|
.{ 0, 1407374883553280000 }, .{ 0, 1759218604441600000 },
|
|
.{ 0, 2199023255552000000 }, .{ 0, 1374389534720000000 },
|
|
.{ 0, 1717986918400000000 }, .{ 0, 2147483648000000000 },
|
|
.{ 0, 1342177280000000000 }, .{ 0, 1677721600000000000 },
|
|
.{ 0, 2097152000000000000 }, .{ 0, 1310720000000000000 },
|
|
.{ 0, 1638400000000000000 }, .{ 0, 2048000000000000000 },
|
|
.{ 0, 1280000000000000000 }, .{ 0, 1600000000000000000 },
|
|
.{ 0, 2000000000000000000 }, .{ 0, 1250000000000000000 },
|
|
.{ 0, 1562500000000000000 }, .{ 0, 1953125000000000000 },
|
|
.{ 0, 1220703125000000000 }, .{ 0, 1525878906250000000 },
|
|
.{ 0, 1907348632812500000 }, .{ 0, 1192092895507812500 },
|
|
.{ 0, 1490116119384765625 }, .{ 4611686018427387904, 1862645149230957031 },
|
|
.{ 9799832789158199296, 1164153218269348144 }, .{ 12249790986447749120, 1455191522836685180 },
|
|
.{ 15312238733059686400, 1818989403545856475 }, .{ 14528612397897220096, 2273736754432320594 },
|
|
.{ 13692068767113150464, 1421085471520200371 }, .{ 12503399940464050176, 1776356839400250464 },
|
|
.{ 15629249925580062720, 2220446049250313080 }, .{ 9768281203487539200, 1387778780781445675 },
|
|
.{ 7598665485932036096, 1734723475976807094 }, .{ 274959820560269312, 2168404344971008868 },
|
|
.{ 9395221924704944128, 1355252715606880542 }, .{ 2520655369026404352, 1694065894508600678 },
|
|
.{ 12374191248137781248, 2117582368135750847 }, .{ 14651398557727195136, 1323488980084844279 },
|
|
.{ 13702562178731606016, 1654361225106055349 }, .{ 3293144668132343808, 2067951531382569187 },
|
|
.{ 18199116482078572544, 1292469707114105741 }, .{ 8913837547316051968, 1615587133892632177 },
|
|
.{ 15753982952572452864, 2019483917365790221 }, .{ 12152082354571476992, 1262177448353618888 },
|
|
.{ 15190102943214346240, 1577721810442023610 }, .{ 9764256642163156992, 1972152263052529513 },
|
|
.{ 17631875447420442880, 1232595164407830945 }, .{ 8204786253993389888, 1540743955509788682 },
|
|
.{ 1032610780636961552, 1925929944387235853 }, .{ 2951224747111794922, 1203706215242022408 },
|
|
.{ 3689030933889743652, 1504632769052528010 }, .{ 13834660704216955373, 1880790961315660012 },
|
|
.{ 17870034976990372916, 1175494350822287507 }, .{ 17725857702810578241, 1469367938527859384 },
|
|
.{ 3710578054803671186, 1836709923159824231 }, .{ 26536550077201078, 2295887403949780289 },
|
|
.{ 11545800389866720434, 1434929627468612680 }, .{ 14432250487333400542, 1793662034335765850 },
|
|
.{ 8816941072311974870, 2242077542919707313 }, .{ 17039803216263454053, 1401298464324817070 },
|
|
.{ 12076381983474541759, 1751623080406021338 }, .{ 5872105442488401391, 2189528850507526673 },
|
|
.{ 15199280947623720629, 1368455531567204170 }, .{ 9775729147674874978, 1710569414459005213 },
|
|
.{ 16831347453020981627, 2138211768073756516 }, .{ 1296220121283337709, 1336382355046097823 },
|
|
.{ 15455333206886335848, 1670477943807622278 }, .{ 10095794471753144002, 2088097429759527848 },
|
|
.{ 6309871544845715001, 1305060893599704905 }, .{ 12499025449484531656, 1631326116999631131 },
|
|
.{ 11012095793428276666, 2039157646249538914 }, .{ 11494245889320060820, 1274473528905961821 },
|
|
.{ 532749306367912313, 1593091911132452277 }, .{ 5277622651387278295, 1991364888915565346 },
|
|
.{ 7910200175544436838, 1244603055572228341 }, .{ 14499436237857933952, 1555753819465285426 },
|
|
.{ 8900923260467641632, 1944692274331606783 }, .{ 12480606065433357876, 1215432671457254239 },
|
|
.{ 10989071563364309441, 1519290839321567799 }, .{ 9124653435777998898, 1899113549151959749 },
|
|
.{ 8008751406574943263, 1186945968219974843 }, .{ 5399253239791291175, 1483682460274968554 },
|
|
.{ 15972438586593889776, 1854603075343710692 }, .{ 759402079766405302, 1159126922089819183 },
|
|
.{ 14784310654990170340, 1448908652612273978 }, .{ 9257016281882937117, 1811135815765342473 },
|
|
.{ 16182956370781059300, 2263919769706678091 }, .{ 7808504722524468110, 1414949856066673807 },
|
|
.{ 5148944884728197234, 1768687320083342259 }, .{ 1824495087482858639, 2210859150104177824 },
|
|
.{ 1140309429676786649, 1381786968815111140 }, .{ 1425386787095983311, 1727233711018888925 },
|
|
.{ 6393419502297367043, 2159042138773611156 }, .{ 13219259225790630210, 1349401336733506972 },
|
|
.{ 16524074032238287762, 1686751670916883715 }, .{ 16043406521870471799, 2108439588646104644 },
|
|
.{ 803757039314269066, 1317774742903815403 }, .{ 14839754354425000045, 1647218428629769253 },
|
|
.{ 4714634887749086344, 2059023035787211567 }, .{ 9864175832484260821, 1286889397367007229 },
|
|
.{ 16941905809032713930, 1608611746708759036 }, .{ 2730638187581340797, 2010764683385948796 },
|
|
.{ 10930020904093113806, 1256727927116217997 }, .{ 18274212148543780162, 1570909908895272496 },
|
|
.{ 4396021111970173586, 1963637386119090621 }, .{ 5053356204195052443, 1227273366324431638 },
|
|
.{ 15540067292098591362, 1534091707905539547 }, .{ 14813398096695851299, 1917614634881924434 },
|
|
.{ 13870059828862294966, 1198509146801202771 }, .{ 12725888767650480803, 1498136433501503464 },
|
|
.{ 15907360959563101004, 1872670541876879330 }, .{ 14553786618154326031, 1170419088673049581 },
|
|
.{ 4357175217410743827, 1463023860841311977 }, .{ 10058155040190817688, 1828779826051639971 },
|
|
.{ 7961007781811134206, 2285974782564549964 }, .{ 14199001900486734687, 1428734239102843727 },
|
|
.{ 13137066357181030455, 1785917798878554659 }, .{ 11809646928048900164, 2232397248598193324 },
|
|
.{ 16604401366885338411, 1395248280373870827 }, .{ 16143815690179285109, 1744060350467338534 },
|
|
.{ 10956397575869330579, 2180075438084173168 }, .{ 6847748484918331612, 1362547148802608230 },
|
|
.{ 17783057643002690323, 1703183936003260287 }, .{ 17617136035325974999, 2128979920004075359 },
|
|
.{ 17928239049719816230, 1330612450002547099 }, .{ 17798612793722382384, 1663265562503183874 },
|
|
.{ 13024893955298202172, 2079081953128979843 }, .{ 5834715712847682405, 1299426220705612402 },
|
|
.{ 16516766677914378815, 1624282775882015502 }, .{ 11422586310538197711, 2030353469852519378 },
|
|
.{ 11750802462513761473, 1268970918657824611 }, .{ 10076817059714813937, 1586213648322280764 },
|
|
.{ 12596021324643517422, 1982767060402850955 }, .{ 5566670318688504437, 1239229412751781847 },
|
|
.{ 2346651879933242642, 1549036765939727309 }, .{ 7545000868343941206, 1936295957424659136 },
|
|
.{ 4715625542714963254, 1210184973390411960 }, .{ 5894531928393704067, 1512731216738014950 },
|
|
.{ 16591536947346905892, 1890914020922518687 }, .{ 17287239619732898039, 1181821263076574179 },
|
|
.{ 16997363506238734644, 1477276578845717724 }, .{ 2799960309088866689, 1846595723557147156 },
|
|
.{ 10973347230035317489, 1154122327223216972 }, .{ 13716684037544146861, 1442652909029021215 },
|
|
.{ 12534169028502795672, 1803316136286276519 }, .{ 11056025267201106687, 2254145170357845649 },
|
|
.{ 18439230838069161439, 1408840731473653530 }, .{ 13825666510731675991, 1761050914342066913 },
|
|
.{ 3447025083132431277, 2201313642927583642 }, .{ 6766076695385157452, 1375821026829739776 },
|
|
.{ 8457595869231446815, 1719776283537174720 }, .{ 10571994836539308519, 2149720354421468400 },
|
|
.{ 6607496772837067824, 1343575221513417750 }, .{ 17482743002901110588, 1679469026891772187 },
|
|
.{ 17241742735199000331, 2099336283614715234 }, .{ 15387775227926763111, 1312085177259197021 },
|
|
.{ 5399660979626290177, 1640106471573996277 }, .{ 11361262242960250625, 2050133089467495346 },
|
|
.{ 11712474920277544544, 1281333180917184591 }, .{ 10028907631919542777, 1601666476146480739 },
|
|
.{ 7924448521472040567, 2002083095183100924 }, .{ 14176152362774801162, 1251301934489438077 },
|
|
.{ 3885132398186337741, 1564127418111797597 }, .{ 9468101516160310080, 1955159272639746996 },
|
|
.{ 15140935484454969608, 1221974545399841872 }, .{ 479425281859160394, 1527468181749802341 },
|
|
.{ 5210967620751338397, 1909335227187252926 }, .{ 17091912818251750210, 1193334516992033078 },
|
|
.{ 12141518985959911954, 1491668146240041348 }, .{ 15176898732449889943, 1864585182800051685 },
|
|
.{ 11791404716994875166, 1165365739250032303 }, .{ 10127569877816206054, 1456707174062540379 },
|
|
.{ 8047776328842869663, 1820883967578175474 }, .{ 836348374198811271, 2276104959472719343 },
|
|
.{ 7440246761515338900, 1422565599670449589 }, .{ 13911994470321561530, 1778206999588061986 },
|
|
.{ 8166621051047176104, 2222758749485077483 }, .{ 2798295147690791113, 1389224218428173427 },
|
|
.{ 17332926989895652603, 1736530273035216783 }, .{ 17054472718942177850, 2170662841294020979 },
|
|
.{ 8353202440125167204, 1356664275808763112 }, .{ 10441503050156459005, 1695830344760953890 },
|
|
.{ 3828506775840797949, 2119787930951192363 }, .{ 86973725686804766, 1324867456844495227 },
|
|
.{ 13943775212390669669, 1656084321055619033 }, .{ 3594660960206173375, 2070105401319523792 },
|
|
.{ 2246663100128858359, 1293815875824702370 }, .{ 12031700912015848757, 1617269844780877962 },
|
|
.{ 5816254103165035138, 2021587305976097453 }, .{ 5941001823691840913, 1263492066235060908 },
|
|
.{ 7426252279614801142, 1579365082793826135 }, .{ 4671129331091113523, 1974206353492282669 },
|
|
.{ 5225298841145639904, 1233878970932676668 }, .{ 6531623551432049880, 1542348713665845835 },
|
|
.{ 3552843420862674446, 1927935892082307294 }, .{ 16055585193321335241, 1204959932551442058 },
|
|
.{ 10846109454796893243, 1506199915689302573 }, .{ 18169322836923504458, 1882749894611628216 },
|
|
.{ 11355826773077190286, 1176718684132267635 }, .{ 9583097447919099954, 1470898355165334544 },
|
|
.{ 11978871809898874942, 1838622943956668180 }, .{ 14973589762373593678, 2298278679945835225 },
|
|
.{ 2440964573842414192, 1436424174966147016 }, .{ 3051205717303017741, 1795530218707683770 },
|
|
.{ 13037379183483547984, 2244412773384604712 }, .{ 8148361989677217490, 1402757983365377945 },
|
|
.{ 14797138505523909766, 1753447479206722431 }, .{ 13884737113477499304, 2191809349008403039 },
|
|
.{ 15595489723564518921, 1369880843130251899 }, .{ 14882676136028260747, 1712351053912814874 },
|
|
.{ 9379973133180550126, 2140438817391018593 }, .{ 17391698254306313589, 1337774260869386620 },
|
|
.{ 3292878744173340370, 1672217826086733276 }, .{ 4116098430216675462, 2090272282608416595 },
|
|
.{ 266718509671728212, 1306420176630260372 }, .{ 333398137089660265, 1633025220787825465 },
|
|
.{ 5028433689789463235, 2041281525984781831 }, .{ 10060300083759496378, 1275800953740488644 },
|
|
.{ 12575375104699370472, 1594751192175610805 }, .{ 1884160825592049379, 1993438990219513507 },
|
|
.{ 17318501580490888525, 1245899368887195941 }, .{ 7813068920331446945, 1557374211108994927 },
|
|
.{ 5154650131986920777, 1946717763886243659 }, .{ 915813323278131534, 1216698602428902287 },
|
|
.{ 14979824709379828129, 1520873253036127858 }, .{ 9501408849870009354, 1901091566295159823 },
|
|
.{ 12855909558809837702, 1188182228934474889 }, .{ 2234828893230133415, 1485227786168093612 },
|
|
.{ 2793536116537666769, 1856534732710117015 }, .{ 8663489100477123587, 1160334207943823134 },
|
|
.{ 1605989338741628675, 1450417759929778918 }, .{ 11230858710281811652, 1813022199912223647 },
|
|
.{ 9426887369424876662, 2266277749890279559 }, .{ 12809333633531629769, 1416423593681424724 },
|
|
.{ 16011667041914537212, 1770529492101780905 }, .{ 6179525747111007803, 2213161865127226132 },
|
|
.{ 13085575628799155685, 1383226165704516332 }, .{ 16356969535998944606, 1729032707130645415 },
|
|
.{ 15834525901571292854, 2161290883913306769 }, .{ 2979049660840976177, 1350806802445816731 },
|
|
.{ 17558870131333383934, 1688508503057270913 }, .{ 8113529608884566205, 2110635628821588642 },
|
|
.{ 9682642023980241782, 1319147268013492901 }, .{ 16714988548402690132, 1648934085016866126 },
|
|
.{ 11670363648648586857, 2061167606271082658 }, .{ 11905663298832754689, 1288229753919426661 },
|
|
.{ 1047021068258779650, 1610287192399283327 }, .{ 15143834390605638274, 2012858990499104158 },
|
|
.{ 4853210475701136017, 1258036869061940099 }, .{ 1454827076199032118, 1572546086327425124 },
|
|
.{ 1818533845248790147, 1965682607909281405 }, .{ 3442426662494187794, 1228551629943300878 },
|
|
.{ 13526405364972510550, 1535689537429126097 }, .{ 3072948650933474476, 1919611921786407622 },
|
|
.{ 15755650962115585259, 1199757451116504763 }, .{ 15082877684217093670, 1499696813895630954 },
|
|
.{ 9630225068416591280, 1874621017369538693 }, .{ 8324733676974063502, 1171638135855961683 },
|
|
.{ 5794231077790191473, 1464547669819952104 }, .{ 7242788847237739342, 1830684587274940130 },
|
|
.{ 18276858095901949986, 2288355734093675162 }, .{ 16034722328366106645, 1430222333808546976 },
|
|
.{ 1596658836748081690, 1787777917260683721 }, .{ 6607509564362490017, 2234722396575854651 },
|
|
.{ 1823850468512862308, 1396701497859909157 }, .{ 6891499104068465790, 1745876872324886446 },
|
|
.{ 17837745916940358045, 2182346090406108057 }, .{ 4231062170446641922, 1363966306503817536 },
|
|
.{ 5288827713058302403, 1704957883129771920 }, .{ 6611034641322878003, 2131197353912214900 },
|
|
.{ 13355268687681574560, 1331998346195134312 }, .{ 16694085859601968200, 1664997932743917890 },
|
|
.{ 11644235287647684442, 2081247415929897363 }, .{ 4971804045566108824, 1300779634956185852 },
|
|
.{ 6214755056957636030, 1625974543695232315 }, .{ 3156757802769657134, 2032468179619040394 },
|
|
.{ 6584659645158423613, 1270292612261900246 }, .{ 17454196593302805324, 1587865765327375307 },
|
|
.{ 17206059723201118751, 1984832206659219134 }, .{ 6142101308573311315, 1240520129162011959 },
|
|
.{ 3065940617289251240, 1550650161452514949 }, .{ 8444111790038951954, 1938312701815643686 },
|
|
.{ 665883850346957067, 1211445438634777304 }, .{ 832354812933696334, 1514306798293471630 },
|
|
.{ 10263815553021896226, 1892883497866839537 }, .{ 17944099766707154901, 1183052186166774710 },
|
|
.{ 13206752671529167818, 1478815232708468388 }, .{ 16508440839411459773, 1848519040885585485 },
|
|
.{ 12623618533845856310, 1155324400553490928 }, .{ 15779523167307320387, 1444155500691863660 },
|
|
.{ 1277659885424598868, 1805194375864829576 }, .{ 1597074856780748586, 2256492969831036970 },
|
|
.{ 5609857803915355770, 1410308106144398106 }, .{ 16235694291748970521, 1762885132680497632 },
|
|
.{ 1847873790976661535, 2203606415850622041 }, .{ 12684136165428883219, 1377254009906638775 },
|
|
.{ 11243484188358716120, 1721567512383298469 }, .{ 219297180166231438, 2151959390479123087 },
|
|
.{ 7054589765244976505, 1344974619049451929 }, .{ 13429923224983608535, 1681218273811814911 },
|
|
.{ 12175718012802122765, 2101522842264768639 }, .{ 14527352785642408584, 1313451776415480399 },
|
|
.{ 13547504963625622826, 1641814720519350499 }, .{ 12322695186104640628, 2052268400649188124 },
|
|
.{ 16925056528170176201, 1282667750405742577 }, .{ 7321262604930556539, 1603334688007178222 },
|
|
.{ 18374950293017971482, 2004168360008972777 }, .{ 4566814905495150320, 1252605225005607986 },
|
|
.{ 14931890668723713708, 1565756531257009982 }, .{ 9441491299049866327, 1957195664071262478 },
|
|
.{ 1289246043478778550, 1223247290044539049 }, .{ 6223243572775861092, 1529059112555673811 },
|
|
.{ 3167368447542438461, 1911323890694592264 }, .{ 1979605279714024038, 1194577431684120165 },
|
|
.{ 7086192618069917952, 1493221789605150206 }, .{ 18081112809442173248, 1866527237006437757 },
|
|
.{ 13606538515115052232, 1166579523129023598 }, .{ 7784801107039039482, 1458224403911279498 },
|
|
.{ 507629346944023544, 1822780504889099373 }, .{ 5246222702107417334, 2278475631111374216 },
|
|
.{ 3278889188817135834, 1424047269444608885 }, .{ 8710297504448807696, 1780059086805761106 }
|
|
};
|
|
|
|
const FLOAT64_POW5_INV_SPLIT: [342][2]u64 = .{
|
|
.{ 1, 2305843009213693952 }, .{ 11068046444225730970, 1844674407370955161 },
|
|
.{ 5165088340638674453, 1475739525896764129 }, .{ 7821419487252849886, 1180591620717411303 },
|
|
.{ 8824922364862649494, 1888946593147858085 }, .{ 7059937891890119595, 1511157274518286468 },
|
|
.{ 13026647942995916322, 1208925819614629174 }, .{ 9774590264567735146, 1934281311383406679 },
|
|
.{ 11509021026396098440, 1547425049106725343 }, .{ 16585914450600699399, 1237940039285380274 },
|
|
.{ 15469416676735388068, 1980704062856608439 }, .{ 16064882156130220778, 1584563250285286751 },
|
|
.{ 9162556910162266299, 1267650600228229401 }, .{ 7281393426775805432, 2028240960365167042 },
|
|
.{ 16893161185646375315, 1622592768292133633 }, .{ 2446482504291369283, 1298074214633706907 },
|
|
.{ 7603720821608101175, 2076918743413931051 }, .{ 2393627842544570617, 1661534994731144841 },
|
|
.{ 16672297533003297786, 1329227995784915872 }, .{ 11918280793837635165, 2126764793255865396 },
|
|
.{ 5845275820328197809, 1701411834604692317 }, .{ 15744267100488289217, 1361129467683753853 },
|
|
.{ 3054734472329800808, 2177807148294006166 }, .{ 17201182836831481939, 1742245718635204932 },
|
|
.{ 6382248639981364905, 1393796574908163946 }, .{ 2832900194486363201, 2230074519853062314 },
|
|
.{ 5955668970331000884, 1784059615882449851 }, .{ 1075186361522890384, 1427247692705959881 },
|
|
.{ 12788344622662355584, 2283596308329535809 }, .{ 13920024512871794791, 1826877046663628647 },
|
|
.{ 3757321980813615186, 1461501637330902918 }, .{ 10384555214134712795, 1169201309864722334 },
|
|
.{ 5547241898389809503, 1870722095783555735 }, .{ 4437793518711847602, 1496577676626844588 },
|
|
.{ 10928932444453298728, 1197262141301475670 }, .{ 17486291911125277965, 1915619426082361072 },
|
|
.{ 6610335899416401726, 1532495540865888858 }, .{ 12666966349016942027, 1225996432692711086 },
|
|
.{ 12888448528943286597, 1961594292308337738 }, .{ 17689456452638449924, 1569275433846670190 },
|
|
.{ 14151565162110759939, 1255420347077336152 }, .{ 7885109000409574610, 2008672555323737844 },
|
|
.{ 9997436015069570011, 1606938044258990275 }, .{ 7997948812055656009, 1285550435407192220 },
|
|
.{ 12796718099289049614, 2056880696651507552 }, .{ 2858676849947419045, 1645504557321206042 },
|
|
.{ 13354987924183666206, 1316403645856964833 }, .{ 17678631863951955605, 2106245833371143733 },
|
|
.{ 3074859046935833515, 1684996666696914987 }, .{ 13527933681774397782, 1347997333357531989 },
|
|
.{ 10576647446613305481, 2156795733372051183 }, .{ 15840015586774465031, 1725436586697640946 },
|
|
.{ 8982663654677661702, 1380349269358112757 }, .{ 18061610662226169046, 2208558830972980411 },
|
|
.{ 10759939715039024913, 1766847064778384329 }, .{ 12297300586773130254, 1413477651822707463 },
|
|
.{ 15986332124095098083, 2261564242916331941 }, .{ 9099716884534168143, 1809251394333065553 },
|
|
.{ 14658471137111155161, 1447401115466452442 }, .{ 4348079280205103483, 1157920892373161954 },
|
|
.{ 14335624477811986218, 1852673427797059126 }, .{ 7779150767507678651, 1482138742237647301 },
|
|
.{ 2533971799264232598, 1185710993790117841 }, .{ 15122401323048503126, 1897137590064188545 },
|
|
.{ 12097921058438802501, 1517710072051350836 }, .{ 5988988032009131678, 1214168057641080669 },
|
|
.{ 16961078480698431330, 1942668892225729070 }, .{ 13568862784558745064, 1554135113780583256 },
|
|
.{ 7165741412905085728, 1243308091024466605 }, .{ 11465186260648137165, 1989292945639146568 },
|
|
.{ 16550846638002330379, 1591434356511317254 }, .{ 16930026125143774626, 1273147485209053803 },
|
|
.{ 4951948911778577463, 2037035976334486086 }, .{ 272210314680951647, 1629628781067588869 },
|
|
.{ 3907117066486671641, 1303703024854071095 }, .{ 6251387306378674625, 2085924839766513752 },
|
|
.{ 16069156289328670670, 1668739871813211001 }, .{ 9165976216721026213, 1334991897450568801 },
|
|
.{ 7286864317269821294, 2135987035920910082 }, .{ 16897537898041588005, 1708789628736728065 },
|
|
.{ 13518030318433270404, 1367031702989382452 }, .{ 6871453250525591353, 2187250724783011924 },
|
|
.{ 9186511415162383406, 1749800579826409539 }, .{ 11038557946871817048, 1399840463861127631 },
|
|
.{ 10282995085511086630, 2239744742177804210 }, .{ 8226396068408869304, 1791795793742243368 },
|
|
.{ 13959814484210916090, 1433436634993794694 }, .{ 11267656730511734774, 2293498615990071511 },
|
|
.{ 5324776569667477496, 1834798892792057209 }, .{ 7949170070475892320, 1467839114233645767 },
|
|
.{ 17427382500606444826, 1174271291386916613 }, .{ 5747719112518849781, 1878834066219066582 },
|
|
.{ 15666221734240810795, 1503067252975253265 }, .{ 12532977387392648636, 1202453802380202612 },
|
|
.{ 5295368560860596524, 1923926083808324180 }, .{ 4236294848688477220, 1539140867046659344 },
|
|
.{ 7078384693692692099, 1231312693637327475 }, .{ 11325415509908307358, 1970100309819723960 },
|
|
.{ 9060332407926645887, 1576080247855779168 }, .{ 14626963555825137356, 1260864198284623334 },
|
|
.{ 12335095245094488799, 2017382717255397335 }, .{ 9868076196075591040, 1613906173804317868 },
|
|
.{ 15273158586344293478, 1291124939043454294 }, .{ 13369007293925138595, 2065799902469526871 },
|
|
.{ 7005857020398200553, 1652639921975621497 }, .{ 16672732060544291412, 1322111937580497197 },
|
|
.{ 11918976037903224966, 2115379100128795516 }, .{ 5845832015580669650, 1692303280103036413 },
|
|
.{ 12055363241948356366, 1353842624082429130 }, .{ 841837113407818570, 2166148198531886609 },
|
|
.{ 4362818505468165179, 1732918558825509287 }, .{ 14558301248600263113, 1386334847060407429 },
|
|
.{ 12225235553534690011, 2218135755296651887 }, .{ 2401490813343931363, 1774508604237321510 },
|
|
.{ 1921192650675145090, 1419606883389857208 }, .{ 17831303500047873437, 2271371013423771532 },
|
|
.{ 6886345170554478103, 1817096810739017226 }, .{ 1819727321701672159, 1453677448591213781 },
|
|
.{ 16213177116328979020, 1162941958872971024 }, .{ 14873036941900635463, 1860707134196753639 },
|
|
.{ 15587778368262418694, 1488565707357402911 }, .{ 8780873879868024632, 1190852565885922329 },
|
|
.{ 2981351763563108441, 1905364105417475727 }, .{ 13453127855076217722, 1524291284333980581 },
|
|
.{ 7073153469319063855, 1219433027467184465 }, .{ 11317045550910502167, 1951092843947495144 },
|
|
.{ 12742985255470312057, 1560874275157996115 }, .{ 10194388204376249646, 1248699420126396892 },
|
|
.{ 1553625868034358140, 1997919072202235028 }, .{ 8621598323911307159, 1598335257761788022 },
|
|
.{ 17965325103354776697, 1278668206209430417 }, .{ 13987124906400001422, 2045869129935088668 },
|
|
.{ 121653480894270168, 1636695303948070935 }, .{ 97322784715416134, 1309356243158456748 },
|
|
.{ 14913111714512307107, 2094969989053530796 }, .{ 8241140556867935363, 1675975991242824637 },
|
|
.{ 17660958889720079260, 1340780792994259709 }, .{ 17189487779326395846, 2145249268790815535 },
|
|
.{ 13751590223461116677, 1716199415032652428 }, .{ 18379969808252713988, 1372959532026121942 },
|
|
.{ 14650556434236701088, 2196735251241795108 }, .{ 652398703163629901, 1757388200993436087 },
|
|
.{ 11589965406756634890, 1405910560794748869 }, .{ 7475898206584884855, 2249456897271598191 },
|
|
.{ 2291369750525997561, 1799565517817278553 }, .{ 9211793429904618695, 1439652414253822842 },
|
|
.{ 18428218302589300235, 2303443862806116547 }, .{ 7363877012587619542, 1842755090244893238 },
|
|
.{ 13269799239553916280, 1474204072195914590 }, .{ 10615839391643133024, 1179363257756731672 },
|
|
.{ 2227947767661371545, 1886981212410770676 }, .{ 16539753473096738529, 1509584969928616540 },
|
|
.{ 13231802778477390823, 1207667975942893232 }, .{ 6413489186596184024, 1932268761508629172 },
|
|
.{ 16198837793502678189, 1545815009206903337 }, .{ 5580372605318321905, 1236652007365522670 },
|
|
.{ 8928596168509315048, 1978643211784836272 }, .{ 18210923379033183008, 1582914569427869017 },
|
|
.{ 7190041073742725760, 1266331655542295214 }, .{ 436019273762630246, 2026130648867672343 },
|
|
.{ 7727513048493924843, 1620904519094137874 }, .{ 9871359253537050198, 1296723615275310299 },
|
|
.{ 4726128361433549347, 2074757784440496479 }, .{ 7470251503888749801, 1659806227552397183 },
|
|
.{ 13354898832594820487, 1327844982041917746 }, .{ 13989140502667892133, 2124551971267068394 },
|
|
.{ 14880661216876224029, 1699641577013654715 }, .{ 11904528973500979224, 1359713261610923772 },
|
|
.{ 4289851098633925465, 2175541218577478036 }, .{ 18189276137874781665, 1740432974861982428 },
|
|
.{ 3483374466074094362, 1392346379889585943 }, .{ 1884050330976640656, 2227754207823337509 },
|
|
.{ 5196589079523222848, 1782203366258670007 }, .{ 15225317707844309248, 1425762693006936005 },
|
|
.{ 5913764258841343181, 2281220308811097609 }, .{ 8420360221814984868, 1824976247048878087 },
|
|
.{ 17804334621677718864, 1459980997639102469 }, .{ 17932816512084085415, 1167984798111281975 },
|
|
.{ 10245762345624985047, 1868775676978051161 }, .{ 4507261061758077715, 1495020541582440929 },
|
|
.{ 7295157664148372495, 1196016433265952743 }, .{ 7982903447895485668, 1913626293225524389 },
|
|
.{ 10075671573058298858, 1530901034580419511 }, .{ 4371188443704728763, 1224720827664335609 },
|
|
.{ 14372599139411386667, 1959553324262936974 }, .{ 15187428126271019657, 1567642659410349579 },
|
|
.{ 15839291315758726049, 1254114127528279663 }, .{ 3206773216762499739, 2006582604045247462 },
|
|
.{ 13633465017635730761, 1605266083236197969 }, .{ 14596120828850494932, 1284212866588958375 },
|
|
.{ 4907049252451240275, 2054740586542333401 }, .{ 236290587219081897, 1643792469233866721 },
|
|
.{ 14946427728742906810, 1315033975387093376 }, .{ 16535586736504830250, 2104054360619349402 },
|
|
.{ 5849771759720043554, 1683243488495479522 }, .{ 15747863852001765813, 1346594790796383617 },
|
|
.{ 10439186904235184007, 2154551665274213788 }, .{ 15730047152871967852, 1723641332219371030 },
|
|
.{ 12584037722297574282, 1378913065775496824 }, .{ 9066413911450387881, 2206260905240794919 },
|
|
.{ 10942479943902220628, 1765008724192635935 }, .{ 8753983955121776503, 1412006979354108748 },
|
|
.{ 10317025513452932081, 2259211166966573997 }, .{ 874922781278525018, 1807368933573259198 },
|
|
.{ 8078635854506640661, 1445895146858607358 }, .{ 13841606313089133175, 1156716117486885886 },
|
|
.{ 14767872471458792434, 1850745787979017418 }, .{ 746251532941302978, 1480596630383213935 },
|
|
.{ 597001226353042382, 1184477304306571148 }, .{ 15712597221132509104, 1895163686890513836 },
|
|
.{ 8880728962164096960, 1516130949512411069 }, .{ 10793931984473187891, 1212904759609928855 },
|
|
.{ 17270291175157100626, 1940647615375886168 }, .{ 2748186495899949531, 1552518092300708935 },
|
|
.{ 2198549196719959625, 1242014473840567148 }, .{ 18275073973719576693, 1987223158144907436 },
|
|
.{ 10930710364233751031, 1589778526515925949 }, .{ 12433917106128911148, 1271822821212740759 },
|
|
.{ 8826220925580526867, 2034916513940385215 }, .{ 7060976740464421494, 1627933211152308172 },
|
|
.{ 16716827836597268165, 1302346568921846537 }, .{ 11989529279587987770, 2083754510274954460 },
|
|
.{ 9591623423670390216, 1667003608219963568 }, .{ 15051996368420132820, 1333602886575970854 },
|
|
.{ 13015147745246481542, 2133764618521553367 }, .{ 3033420566713364587, 1707011694817242694 },
|
|
.{ 6116085268112601993, 1365609355853794155 }, .{ 9785736428980163188, 2184974969366070648 },
|
|
.{ 15207286772667951197, 1747979975492856518 }, .{ 1097782973908629988, 1398383980394285215 },
|
|
.{ 1756452758253807981, 2237414368630856344 }, .{ 5094511021344956708, 1789931494904685075 },
|
|
.{ 4075608817075965366, 1431945195923748060 }, .{ 6520974107321544586, 2291112313477996896 },
|
|
.{ 1527430471115325346, 1832889850782397517 }, .{ 12289990821117991246, 1466311880625918013 },
|
|
.{ 17210690286378213644, 1173049504500734410 }, .{ 9090360384495590213, 1876879207201175057 },
|
|
.{ 18340334751822203140, 1501503365760940045 }, .{ 14672267801457762512, 1201202692608752036 },
|
|
.{ 16096930852848599373, 1921924308174003258 }, .{ 1809498238053148529, 1537539446539202607 },
|
|
.{ 12515645034668249793, 1230031557231362085 }, .{ 1578287981759648052, 1968050491570179337 },
|
|
.{ 12330676829633449412, 1574440393256143469 }, .{ 13553890278448669853, 1259552314604914775 },
|
|
.{ 3239480371808320148, 2015283703367863641 }, .{ 17348979556414297411, 1612226962694290912 },
|
|
.{ 6500486015647617283, 1289781570155432730 }, .{ 10400777625036187652, 2063650512248692368 },
|
|
.{ 15699319729512770768, 1650920409798953894 }, .{ 16248804598352126938, 1320736327839163115 },
|
|
.{ 7551343283653851484, 2113178124542660985 }, .{ 6041074626923081187, 1690542499634128788 },
|
|
.{ 12211557331022285596, 1352433999707303030 }, .{ 1091747655926105338, 2163894399531684849 },
|
|
.{ 4562746939482794594, 1731115519625347879 }, .{ 7339546366328145998, 1384892415700278303 },
|
|
.{ 8053925371383123274, 2215827865120445285 }, .{ 6443140297106498619, 1772662292096356228 },
|
|
.{ 12533209867169019542, 1418129833677084982 }, .{ 5295740528502789974, 2269007733883335972 },
|
|
.{ 15304638867027962949, 1815206187106668777 }, .{ 4865013464138549713, 1452164949685335022 },
|
|
.{ 14960057215536570740, 1161731959748268017 }, .{ 9178696285890871890, 1858771135597228828 },
|
|
.{ 14721654658196518159, 1487016908477783062 }, .{ 4398626097073393881, 1189613526782226450 },
|
|
.{ 7037801755317430209, 1903381642851562320 }, .{ 5630241404253944167, 1522705314281249856 },
|
|
.{ 814844308661245011, 1218164251424999885 }, .{ 1303750893857992017, 1949062802279999816 },
|
|
.{ 15800395974054034906, 1559250241823999852 }, .{ 5261619149759407279, 1247400193459199882 },
|
|
.{ 12107939454356961969, 1995840309534719811 }, .{ 5997002748743659252, 1596672247627775849 },
|
|
.{ 8486951013736837725, 1277337798102220679 }, .{ 2511075177753209390, 2043740476963553087 },
|
|
.{ 13076906586428298482, 1634992381570842469 }, .{ 14150874083884549109, 1307993905256673975 },
|
|
.{ 4194654460505726958, 2092790248410678361 }, .{ 18113118827372222859, 1674232198728542688 },
|
|
.{ 3422448617672047318, 1339385758982834151 }, .{ 16543964232501006678, 2143017214372534641 },
|
|
.{ 9545822571258895019, 1714413771498027713 }, .{ 15015355686490936662, 1371531017198422170 },
|
|
.{ 5577825024675947042, 2194449627517475473 }, .{ 11840957649224578280, 1755559702013980378 },
|
|
.{ 16851463748863483271, 1404447761611184302 }, .{ 12204946739213931940, 2247116418577894884 },
|
|
.{ 13453306206113055875, 1797693134862315907 }, .{ 3383947335406624054, 1438154507889852726 },
|
|
.{ 16482362180876329456, 2301047212623764361 }, .{ 9496540929959153242, 1840837770099011489 },
|
|
.{ 11286581558709232917, 1472670216079209191 }, .{ 5339916432225476010, 1178136172863367353 },
|
|
.{ 4854517476818851293, 1885017876581387765 }, .{ 3883613981455081034, 1508014301265110212 },
|
|
.{ 14174937629389795797, 1206411441012088169 }, .{ 11611853762797942306, 1930258305619341071 },
|
|
.{ 5600134195496443521, 1544206644495472857 }, .{ 15548153800622885787, 1235365315596378285 },
|
|
.{ 6430302007287065643, 1976584504954205257 }, .{ 16212288050055383484, 1581267603963364205 },
|
|
.{ 12969830440044306787, 1265014083170691364 }, .{ 9683682259845159889, 2024022533073106183 },
|
|
.{ 15125643437359948558, 1619218026458484946 }, .{ 8411165935146048523, 1295374421166787957 },
|
|
.{ 17147214310975587960, 2072599073866860731 }, .{ 10028422634038560045, 1658079259093488585 },
|
|
.{ 8022738107230848036, 1326463407274790868 }, .{ 9147032156827446534, 2122341451639665389 },
|
|
.{ 11006974540203867551, 1697873161311732311 }, .{ 5116230817421183718, 1358298529049385849 },
|
|
.{ 15564666937357714594, 2173277646479017358 }, .{ 1383687105660440706, 1738622117183213887 },
|
|
.{ 12174996128754083534, 1390897693746571109 }, .{ 8411947361780802685, 2225436309994513775 },
|
|
.{ 6729557889424642148, 1780349047995611020 }, .{ 5383646311539713719, 1424279238396488816 },
|
|
.{ 1235136468979721303, 2278846781434382106 }, .{ 15745504434151418335, 1823077425147505684 },
|
|
.{ 16285752362063044992, 1458461940118004547 }, .{ 5649904260166615347, 1166769552094403638 },
|
|
.{ 5350498001524674232, 1866831283351045821 }, .{ 591049586477829062, 1493465026680836657 },
|
|
.{ 11540886113407994219, 1194772021344669325 }, .{ 18673707743239135, 1911635234151470921 },
|
|
.{ 14772334225162232601, 1529308187321176736 }, .{ 8128518565387875758, 1223446549856941389 },
|
|
.{ 1937583260394870242, 1957514479771106223 }, .{ 8928764237799716840, 1566011583816884978 },
|
|
.{ 14521709019723594119, 1252809267053507982 }, .{ 8477339172590109297, 2004494827285612772 },
|
|
.{ 17849917782297818407, 1603595861828490217 }, .{ 6901236596354434079, 1282876689462792174 },
|
|
.{ 18420676183650915173, 2052602703140467478 }, .{ 3668494502695001169, 1642082162512373983 },
|
|
.{ 10313493231639821582, 1313665730009899186 }, .{ 9122891541139893884, 2101865168015838698 },
|
|
.{ 14677010862395735754, 1681492134412670958 }, .{ 673562245690857633, 1345193707530136767 }
|
|
};
|
|
|
|
// zig fmt: off
|
|
//
|
|
// f128 small tables: 9072 bytes
|
|
|
|
const FLOAT128_POW5_INV_BITCOUNT = 249;
|
|
const FLOAT128_POW5_BITCOUNT = 249;
|
|
const FLOAT128_POW5_TABLE_SIZE: comptime_int = FLOAT128_POW5_TABLE.len;
|
|
|
|
const FLOAT128_POW5_TABLE: [56][2]u64 = .{
|
|
.{ 1, 0 },
|
|
.{ 5, 0 },
|
|
.{ 25, 0 },
|
|
.{ 125, 0 },
|
|
.{ 625, 0 },
|
|
.{ 3125, 0 },
|
|
.{ 15625, 0 },
|
|
.{ 78125, 0 },
|
|
.{ 390625, 0 },
|
|
.{ 1953125, 0 },
|
|
.{ 9765625, 0 },
|
|
.{ 48828125, 0 },
|
|
.{ 244140625, 0 },
|
|
.{ 1220703125, 0 },
|
|
.{ 6103515625, 0 },
|
|
.{ 30517578125, 0 },
|
|
.{ 152587890625, 0 },
|
|
.{ 762939453125, 0 },
|
|
.{ 3814697265625, 0 },
|
|
.{ 19073486328125, 0 },
|
|
.{ 95367431640625, 0 },
|
|
.{ 476837158203125, 0 },
|
|
.{ 2384185791015625, 0 },
|
|
.{ 11920928955078125, 0 },
|
|
.{ 59604644775390625, 0 },
|
|
.{ 298023223876953125, 0 },
|
|
.{ 1490116119384765625, 0 },
|
|
.{ 7450580596923828125, 0 },
|
|
.{ 359414837200037393, 2 },
|
|
.{ 1797074186000186965, 10 },
|
|
.{ 8985370930000934825, 50 },
|
|
.{ 8033366502585570893, 252 },
|
|
.{ 3273344365508751233, 1262 },
|
|
.{ 16366721827543756165, 6310 },
|
|
.{ 8046632842880574361, 31554 },
|
|
.{ 3339676066983768573, 157772 },
|
|
.{ 16698380334918842865, 788860 },
|
|
.{ 9704925379756007861, 3944304 },
|
|
.{ 11631138751360936073, 19721522 },
|
|
.{ 2815461535676025517, 98607613 },
|
|
.{ 14077307678380127585, 493038065 },
|
|
.{ 15046306170771983077, 2465190328 },
|
|
.{ 1444554559021708921, 12325951644 },
|
|
.{ 7222772795108544605, 61629758220 },
|
|
.{ 17667119901833171409, 308148791101 },
|
|
.{ 14548623214327650581, 1540743955509 },
|
|
.{ 17402883850509598057, 7703719777548 },
|
|
.{ 13227442957709783821, 38518598887744 },
|
|
.{ 10796982567420264257, 192592994438723 },
|
|
.{ 17091424689682218053, 962964972193617 },
|
|
.{ 11670147153572883801, 4814824860968089 },
|
|
.{ 3010503546735764157, 24074124304840448 },
|
|
.{ 15052517733678820785, 120370621524202240 },
|
|
.{ 1475612373555897461, 601853107621011204 },
|
|
.{ 7378061867779487305, 3009265538105056020 },
|
|
.{ 18443565265187884909, 15046327690525280101 },
|
|
};
|
|
|
|
const FLOAT128_POW5_SPLIT: [89][4]u64 = .{
|
|
.{ 0, 0, 0, 72057594037927936 },
|
|
.{ 0, 5206161169240293376, 4575641699882439235, 73468396926392969 },
|
|
.{ 3360510775605221349, 6983200512169538081, 4325643253124434363, 74906821675075173 },
|
|
.{ 11917660854915489451, 9652941469841108803, 946308467778435600, 76373409087490117 },
|
|
.{ 1994853395185689235, 16102657350889591545, 6847013871814915412, 77868710555449746 },
|
|
.{ 958415760277438274, 15059347134713823592, 7329070255463483331, 79393288266368765 },
|
|
.{ 2065144883315240188, 7145278325844925976, 14718454754511147343, 80947715414629833 },
|
|
.{ 8980391188862868935, 13709057401304208685, 8230434828742694591, 82532576417087045 },
|
|
.{ 432148644612782575, 7960151582448466064, 12056089168559840552, 84148467132788711 },
|
|
.{ 484109300864744403, 15010663910730448582, 16824949663447227068, 85795995087002057 },
|
|
.{ 14793711725276144220, 16494403799991899904, 10145107106505865967, 87475779699624060 },
|
|
.{ 15427548291869817042, 12330588654550505203, 13980791795114552342, 89188452518064298 },
|
|
.{ 9979404135116626552, 13477446383271537499, 14459862802511591337, 90934657454687378 },
|
|
.{ 12385121150303452775, 9097130814231585614, 6523855782339765207, 92715051028904201 },
|
|
.{ 1822931022538209743, 16062974719797586441, 3619180286173516788, 94530302614003091 },
|
|
.{ 12318611738248470829, 13330752208259324507, 10986694768744162601, 96381094688813589 },
|
|
.{ 13684493829640282333, 7674802078297225834, 15208116197624593182, 98268123094297527 },
|
|
.{ 5408877057066295332, 6470124174091971006, 15112713923117703147, 100192097295163851 },
|
|
.{ 11407083166564425062, 18189998238742408185, 4337638702446708282, 102153740646605557 },
|
|
.{ 4112405898036935485, 924624216579956435, 14251108172073737125, 104153790666259019 },
|
|
.{ 16996739107011444789, 10015944118339042475, 2395188869672266257, 106192999311487969 },
|
|
.{ 4588314690421337879, 5339991768263654604, 15441007590670620066, 108272133262096356 },
|
|
.{ 2286159977890359825, 14329706763185060248, 5980012964059367667, 110391974208576409 },
|
|
.{ 9654767503237031099, 11293544302844823188, 11739932712678287805, 112553319146000238 },
|
|
.{ 11362964448496095896, 7990659682315657680, 251480263940996374, 114756980673665505 },
|
|
.{ 1423410421096377129, 14274395557581462179, 16553482793602208894, 117003787300607788 },
|
|
.{ 2070444190619093137, 11517140404712147401, 11657844572835578076, 119294583757094535 },
|
|
.{ 7648316884775828921, 15264332483297977688, 247182277434709002, 121630231312217685 },
|
|
.{ 17410896758132241352, 10923914482914417070, 13976383996795783649, 124011608097704390 },
|
|
.{ 9542674537907272703, 3079432708831728956, 14235189590642919676, 126439609438067572 },
|
|
.{ 10364666969937261816, 8464573184892924210, 12758646866025101190, 128915148187220428 },
|
|
.{ 14720354822146013883, 11480204489231511423, 7449876034836187038, 131439155071681461 },
|
|
.{ 1692907053653558553, 17835392458598425233, 1754856712536736598, 134012579040499057 },
|
|
.{ 5620591334531458755, 11361776175667106627, 13350215315297937856, 136636387622027174 },
|
|
.{ 17455759733928092601, 10362573084069962561, 11246018728801810510, 139311567287686283 },
|
|
.{ 2465404073814044982, 17694822665274381860, 1509954037718722697, 142039123822846312 },
|
|
.{ 2152236053329638369, 11202280800589637091, 16388426812920420176, 72410041352485523 },
|
|
.{ 17319024055671609028, 10944982848661280484, 2457150158022562661, 73827744744583080 },
|
|
.{ 17511219308535248024, 5122059497846768077, 2089605804219668451, 75273205100637900 },
|
|
.{ 10082673333144031533, 14429008783411894887, 12842832230171903890, 76746965869337783 },
|
|
.{ 16196653406315961184, 10260180891682904501, 10537411930446752461, 78249581139456266 },
|
|
.{ 15084422041749743389, 234835370106753111, 16662517110286225617, 79781615848172976 },
|
|
.{ 8199644021067702606, 3787318116274991885, 7438130039325743106, 81343645993472659 },
|
|
.{ 12039493937039359765, 9773822153580393709, 5945428874398357806, 82936258850702722 },
|
|
.{ 984543865091303961, 7975107621689454830, 6556665988501773347, 84560053193370726 },
|
|
.{ 9633317878125234244, 16099592426808915028, 9706674539190598200, 86215639518264828 },
|
|
.{ 6860695058870476186, 4471839111886709592, 7828342285492709568, 87903640274981819 },
|
|
.{ 14583324717644598331, 4496120889473451238, 5290040788305728466, 89624690099949049 },
|
|
.{ 18093669366515003715, 12879506572606942994, 18005739787089675377, 91379436055028227 },
|
|
.{ 17997493966862379937, 14646222655265145582, 10265023312844161858, 93168537870790806 },
|
|
.{ 12283848109039722318, 11290258077250314935, 9878160025624946825, 94992668194556404 },
|
|
.{ 8087752761883078164, 5262596608437575693, 11093553063763274413, 96852512843287537 },
|
|
.{ 15027787746776840781, 12250273651168257752, 9290470558712181914, 98748771061435726 },
|
|
.{ 15003915578366724489, 2937334162439764327, 5404085603526796602, 100682155783835929 },
|
|
.{ 5225610465224746757, 14932114897406142027, 2774647558180708010, 102653393903748137 },
|
|
.{ 17112957703385190360, 12069082008339002412, 3901112447086388439, 104663226546146909 },
|
|
.{ 4062324464323300238, 3992768146772240329, 15757196565593695724, 106712409346361594 },
|
|
.{ 5525364615810306701, 11855206026704935156, 11344868740897365300, 108801712734172003 },
|
|
.{ 9274143661888462646, 4478365862348432381, 18010077872551661771, 110931922223466333 },
|
|
.{ 12604141221930060148, 8930937759942591500, 9382183116147201338, 113103838707570263 },
|
|
.{ 14513929377491886653, 1410646149696279084, 587092196850797612, 115318278760358235 },
|
|
.{ 2226851524999454362, 7717102471110805679, 7187441550995571734, 117576074943260147 },
|
|
.{ 5527526061344932763, 2347100676188369132, 16976241418824030445, 119878076118278875 },
|
|
.{ 6088479778147221611, 17669593130014777580, 10991124207197663546, 122225147767136307 },
|
|
.{ 11107734086759692041, 3391795220306863431, 17233960908859089158, 124618172316667879 },
|
|
.{ 7913172514655155198, 17726879005381242552, 641069866244011540, 127058049470587962 },
|
|
.{ 12596991768458713949, 15714785522479904446, 6035972567136116512, 129545696547750811 },
|
|
.{ 16901996933781815980, 4275085211437148707, 14091642539965169063, 132082048827034281 },
|
|
.{ 7524574627987869240, 15661204384239316051, 2444526454225712267, 134668059898975949 },
|
|
.{ 8199251625090479942, 6803282222165044067, 16064817666437851504, 137304702024293857 },
|
|
.{ 4453256673338111920, 15269922543084434181, 3139961729834750852, 139992966499426682 },
|
|
.{ 15841763546372731299, 3013174075437671812, 4383755396295695606, 142733864029230733 },
|
|
.{ 9771896230907310329, 4900659362437687569, 12386126719044266361, 72764212553486967 },
|
|
.{ 9420455527449565190, 1859606122611023693, 6555040298902684281, 74188850200884818 },
|
|
.{ 5146105983135678095, 2287300449992174951, 4325371679080264751, 75641380576797959 },
|
|
.{ 11019359372592553360, 8422686425957443718, 7175176077944048210, 77122349788024458 },
|
|
.{ 11005742969399620716, 4132174559240043701, 9372258443096612118, 78632314633490790 },
|
|
.{ 8887589641394725840, 8029899502466543662, 14582206497241572853, 80171842813591127 },
|
|
.{ 360247523705545899, 12568341805293354211, 14653258284762517866, 81741513143625247 },
|
|
.{ 12314272731984275834, 4740745023227177044, 6141631472368337539, 83341915771415304 },
|
|
.{ 441052047733984759, 7940090120939869826, 11750200619921094248, 84973652399183278 },
|
|
.{ 3436657868127012749, 9187006432149937667, 16389726097323041290, 86637336509772529 },
|
|
.{ 13490220260784534044, 15339072891382896702, 8846102360835316895, 88333593597298497 },
|
|
.{ 4125672032094859833, 158347675704003277, 10592598512749774447, 90063061402315272 },
|
|
.{ 12189928252974395775, 2386931199439295891, 7009030566469913276, 91826390151586454 },
|
|
.{ 9256479608339282969, 2844900158963599229, 11148388908923225596, 93624242802550437 },
|
|
.{ 11584393507658707408, 2863659090805147914, 9873421561981063551, 95457295292572042 },
|
|
.{ 13984297296943171390, 1931468383973130608, 12905719743235082319, 97326236793074198 },
|
|
.{ 5837045222254987499, 10213498696735864176, 14893951506257020749, 99231769968645227 },
|
|
};
|
|
|
|
// Unfortunately, the results are sometimes off by one or two. We use an additional
|
|
// lookup table to store those cases and adjust the result.
|
|
const FLOAT128_POW5_ERRORS: [156]u64 = .{
|
|
0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x9555596400000000,
|
|
0x65a6569525565555, 0x4415551445449655, 0x5105015504144541, 0x65a69969a6965964,
|
|
0x5054955969959656, 0x5105154515554145, 0x4055511051591555, 0x5500514455550115,
|
|
0x0041140014145515, 0x1005440545511051, 0x0014405450411004, 0x0414440010500000,
|
|
0x0044000440010040, 0x5551155000004001, 0x4554555454544114, 0x5150045544005441,
|
|
0x0001111400054501, 0x6550955555554554, 0x1504159645559559, 0x4105055141454545,
|
|
0x1411541410405454, 0x0415555044545555, 0x0014154115405550, 0x1540055040411445,
|
|
0x0000000500000000, 0x5644000000000000, 0x1155555591596555, 0x0410440054569565,
|
|
0x5145100010010005, 0x0555041405500150, 0x4141450455140450, 0x0000000144000140,
|
|
0x5114004001105410, 0x4444100404005504, 0x0414014410001015, 0x5145055155555015,
|
|
0x0141041444445540, 0x0000100451541414, 0x4105041104155550, 0x0500501150451145,
|
|
0x1001050000004114, 0x5551504400141045, 0x5110545410151454, 0x0100001400004040,
|
|
0x5040010111040000, 0x0140000150541100, 0x4400140400104110, 0x5011014405545004,
|
|
0x0000000044155440, 0x0000000010000000, 0x1100401444440001, 0x0040401010055111,
|
|
0x5155155551405454, 0x0444440015514411, 0x0054505054014101, 0x0451015441115511,
|
|
0x1541411401140551, 0x4155104514445110, 0x4141145450145515, 0x5451445055155050,
|
|
0x4400515554110054, 0x5111145104501151, 0x565a655455500501, 0x5565555555525955,
|
|
0x0550511500405695, 0x4415504051054544, 0x6555595965555554, 0x0100915915555655,
|
|
0x5540001510001001, 0x5450051414000544, 0x1405010555555551, 0x5555515555644155,
|
|
0x5555055595496555, 0x5451045004415000, 0x5450510144040144, 0x5554155555556455,
|
|
0x5051555495415555, 0x5555554555555545, 0x0000000010005455, 0x4000005000040000,
|
|
0x5565555555555954, 0x5554559555555505, 0x9645545495552555, 0x4000400055955564,
|
|
0x0040000000000001, 0x4004100100000000, 0x5540040440000411, 0x4565555955545644,
|
|
0x1140659549651556, 0x0100000410010000, 0x5555515400004001, 0x5955545555155255,
|
|
0x5151055545505556, 0x5051454510554515, 0x0501500050415554, 0x5044154005441005,
|
|
0x1455445450550455, 0x0010144055144545, 0x0000401100000004, 0x1050145050000010,
|
|
0x0415004554011540, 0x1000510100151150, 0x0100040400001144, 0x0000000000000000,
|
|
0x0550004400000100, 0x0151145041451151, 0x0000400400005450, 0x0000100044010004,
|
|
0x0100054100050040, 0x0504400005410010, 0x4011410445500105, 0x0000404000144411,
|
|
0x0101504404500000, 0x0000005044400400, 0x0000000014000100, 0x0404440414000000,
|
|
0x5554100410000140, 0x4555455544505555, 0x5454105055455455, 0x0115454155454015,
|
|
0x4404110000045100, 0x4400001100101501, 0x6596955956966a94, 0x0040655955665965,
|
|
0x5554144400100155, 0xa549495401011041, 0x5596555565955555, 0x5569965959549555,
|
|
0x969565a655555456, 0x0000001000000000, 0x0000000040000140, 0x0000040100000000,
|
|
0x1415454400000000, 0x5410415411454114, 0x0400040104000154, 0x0504045000000411,
|
|
0x0000001000000010, 0x5554000000001040, 0x5549155551556595, 0x1455541055515555,
|
|
0x0510555454554541, 0x9555555555540455, 0x6455456555556465, 0x4524565555654514,
|
|
0x5554655255559545, 0x9555455441155556, 0x0000000051515555, 0x0010005040000550,
|
|
0x5044044040000000, 0x1045040440010500, 0x0000400000040000, 0x0000000000000000,
|
|
};
|
|
|
|
const FLOAT128_POW5_INV_SPLIT: [89][4]u64 = .{
|
|
.{ 0, 0, 0, 144115188075855872 },
|
|
.{ 1573859546583440065, 2691002611772552616, 6763753280790178510, 141347765182270746 },
|
|
.{ 12960290449513840412, 12345512957918226762, 18057899791198622765, 138633484706040742 },
|
|
.{ 7615871757716765416, 9507132263365501332, 4879801712092008245, 135971326161092377 },
|
|
.{ 7869961150745287587, 5804035291554591636, 8883897266325833928, 133360288657597085 },
|
|
.{ 2942118023529634767, 15128191429820565086, 10638459445243230718, 130799390525667397 },
|
|
.{ 14188759758411913794, 5362791266439207815, 8068821289119264054, 128287668946279217 },
|
|
.{ 7183196927902545212, 1952291723540117099, 12075928209936341512, 125824179589281448 },
|
|
.{ 5672588001402349748, 17892323620748423487, 9874578446960390364, 123407996258356868 },
|
|
.{ 4442590541217566325, 4558254706293456445, 10343828952663182727, 121038210542800766 },
|
|
.{ 3005560928406962566, 2082271027139057888, 13961184524927245081, 118713931475986426 },
|
|
.{ 13299058168408384786, 17834349496131278595, 9029906103900731664, 116434285200389047 },
|
|
.{ 5414878118283973035, 13079825470227392078, 17897304791683760280, 114198414639042157 },
|
|
.{ 14609755883382484834, 14991702445765844156, 3269802549772755411, 112005479173303009 },
|
|
.{ 15967774957605076027, 2511532636717499923, 16221038267832563171, 109854654326805788 },
|
|
.{ 9269330061621627145, 3332501053426257392, 16223281189403734630, 107745131455483836 },
|
|
.{ 16739559299223642282, 1873986623300664530, 6546709159471442872, 105676117443544318 },
|
|
.{ 17116435360051202055, 1359075105581853924, 2038341371621886470, 103646834405281051 },
|
|
.{ 17144715798009627550, 3201623802661132408, 9757551605154622431, 101656519392613377 },
|
|
.{ 17580479792687825857, 6546633380567327312, 15099972427870912398, 99704424108241124 },
|
|
.{ 9726477118325522902, 14578369026754005435, 11728055595254428803, 97789814624307808 },
|
|
.{ 134593949518343635, 5715151379816901985, 1660163707976377376, 95911971106466306 },
|
|
.{ 5515914027713859358, 7124354893273815720, 5548463282858794077, 94070187543243255 },
|
|
.{ 6188403395862945512, 5681264392632320838, 15417410852121406654, 92263771480600430 },
|
|
.{ 15908890877468271457, 10398888261125597540, 4817794962769172309, 90492043761593298 },
|
|
.{ 1413077535082201005, 12675058125384151580, 7731426132303759597, 88754338271028867 },
|
|
.{ 1486733163972670293, 11369385300195092554, 11610016711694864110, 87050001685026843 },
|
|
.{ 8788596583757589684, 3978580923851924802, 9255162428306775812, 85378393225389919 },
|
|
.{ 7203518319660962120, 15044736224407683725, 2488132019818199792, 83738884418690858 },
|
|
.{ 4004175967662388707, 18236988667757575407, 15613100370957482671, 82130858859985791 },
|
|
.{ 18371903370586036463, 53497579022921640, 16465963977267203307, 80553711981064899 },
|
|
.{ 10170778323887491315, 1999668801648976001, 10209763593579456445, 79006850823153334 },
|
|
.{ 17108131712433974546, 16825784443029944237, 2078700786753338945, 77489693813976938 },
|
|
.{ 17221789422665858532, 12145427517550446164, 5391414622238668005, 76001670549108934 },
|
|
.{ 4859588996898795878, 1715798948121313204, 3950858167455137171, 74542221577515387 },
|
|
.{ 13513469241795711526, 631367850494860526, 10517278915021816160, 73110798191218799 },
|
|
.{ 11757513142672073111, 2581974932255022228, 17498959383193606459, 143413724438001539 },
|
|
.{ 14524355192525042817, 5640643347559376447, 1309659274756813016, 140659771648132296 },
|
|
.{ 2765095348461978538, 11021111021896007722, 3224303603779962366, 137958702611185230 },
|
|
.{ 12373410389187981037, 13679193545685856195, 11644609038462631561, 135309501808182158 },
|
|
.{ 12813176257562780151, 3754199046160268020, 9954691079802960722, 132711173221007413 },
|
|
.{ 17557452279667723458, 3237799193992485824, 17893947919029030695, 130162739957935629 },
|
|
.{ 14634200999559435155, 4123869946105211004, 6955301747350769239, 127663243886350468 },
|
|
.{ 2185352760627740240, 2864813346878886844, 13049218671329690184, 125211745272516185 },
|
|
.{ 6143438674322183002, 10464733336980678750, 6982925169933978309, 122807322428266620 },
|
|
.{ 1099509117817174576, 10202656147550524081, 754997032816608484, 120449071364478757 },
|
|
.{ 2410631293559367023, 17407273750261453804, 15307291918933463037, 118136105451200587 },
|
|
.{ 12224968375134586697, 1664436604907828062, 11506086230137787358, 115867555084305488 },
|
|
.{ 3495926216898000888, 18392536965197424288, 10992889188570643156, 113642567358547782 },
|
|
.{ 8744506286256259680, 3966568369496879937, 18342264969761820037, 111460305746896569 },
|
|
.{ 7689600520560455039, 5254331190877624630, 9628558080573245556, 109319949786027263 },
|
|
.{ 11862637625618819436, 3456120362318976488, 14690471063106001082, 107220694767852583 },
|
|
.{ 5697330450030126444, 12424082405392918899, 358204170751754904, 105161751436977040 },
|
|
.{ 11257457505097373622, 15373192700214208870, 671619062372033814, 103142345693961148 },
|
|
.{ 16850355018477166700, 1913910419361963966, 4550257919755970531, 101161718304283822 },
|
|
.{ 9670835567561997011, 10584031339132130638, 3060560222974851757, 99219124612893520 },
|
|
.{ 7698686577353054710, 11689292838639130817, 11806331021588878241, 97313834264240819 },
|
|
.{ 12233569599615692137, 3347791226108469959, 10333904326094451110, 95445130927687169 },
|
|
.{ 13049400362825383933, 17142621313007799680, 3790542585289224168, 93612312028186576 },
|
|
.{ 12430457242474442072, 5625077542189557960, 14765055286236672238, 91814688482138969 },
|
|
.{ 4759444137752473128, 2230562561567025078, 4954443037339580076, 90051584438315940 },
|
|
.{ 7246913525170274758, 8910297835195760709, 4015904029508858381, 88322337023761438 },
|
|
.{ 12854430245836432067, 8135139748065431455, 11548083631386317976, 86626296094571907 },
|
|
.{ 4848827254502687803, 4789491250196085625, 3988192420450664125, 84962823991462151 },
|
|
.{ 7435538409611286684, 904061756819742353, 14598026519493048444, 83331295300025028 },
|
|
.{ 11042616160352530997, 8948390828345326218, 10052651191118271927, 81731096615594853 },
|
|
.{ 11059348291563778943, 11696515766184685544, 3783210511290897367, 80161626312626082 },
|
|
.{ 7020010856491885826, 5025093219346041680, 8960210401638911765, 78622294318500592 },
|
|
.{ 17732844474490699984, 7820866704994446502, 6088373186798844243, 77112521891678506 },
|
|
.{ 688278527545590501, 3045610706602776618, 8684243536999567610, 75631741404109150 },
|
|
.{ 2734573255120657297, 3903146411440697663, 9470794821691856713, 74179396127820347 },
|
|
.{ 15996457521023071259, 4776627823451271680, 12394856457265744744, 72754940025605801 },
|
|
.{ 13492065758834518331, 7390517611012222399, 1630485387832860230, 142715675091463768 },
|
|
.{ 13665021627282055864, 9897834675523659302, 17907668136755296849, 139975126841173266 },
|
|
.{ 9603773719399446181, 10771916301484339398, 10672699855989487527, 137287204938390542 },
|
|
.{ 3630218541553511265, 8139010004241080614, 2876479648932814543, 134650898807055963 },
|
|
.{ 8318835909686377084, 9525369258927993371, 2796120270400437057, 132065217277054270 },
|
|
.{ 11190003059043290163, 12424345635599592110, 12539346395388933763, 129529188211565064 },
|
|
.{ 8701968833973242276, 820569587086330727, 2315591597351480110, 127041858141569228 },
|
|
.{ 5115113890115690487, 16906305245394587826, 9899749468931071388, 124602291907373862 },
|
|
.{ 15543535488939245974, 10945189844466391399, 3553863472349432246, 122209572307020975 },
|
|
.{ 7709257252608325038, 1191832167690640880, 15077137020234258537, 119862799751447719 },
|
|
.{ 7541333244210021737, 9790054727902174575, 5160944773155322014, 117561091926268545 },
|
|
.{ 12297384708782857832, 1281328873123467374, 4827925254630475769, 115303583460052092 },
|
|
.{ 13243237906232367265, 15873887428139547641, 3607993172301799599, 113089425598968120 },
|
|
.{ 11384616453739611114, 15184114243769211033, 13148448124803481057, 110917785887682141 },
|
|
.{ 17727970963596660683, 1196965221832671990, 14537830463956404138, 108787847856377790 },
|
|
.{ 17241367586707330931, 8880584684128262874, 11173506540726547818, 106698810713789254 },
|
|
.{ 7184427196661305643, 14332510582433188173, 14230167953789677901, 104649889046128358 },
|
|
};
|
|
|
|
const FLOAT128_POW5_INV_ERRORS: [154]u64 = .{
|
|
0x1144155514145504, 0x0000541555401141, 0x0000000000000000, 0x0154454000000000,
|
|
0x4114105515544440, 0x0001001111500415, 0x4041411410011000, 0x5550114515155014,
|
|
0x1404100041554551, 0x0515000450404410, 0x5054544401140004, 0x5155501005555105,
|
|
0x1144141000105515, 0x0541500000500000, 0x1104105540444140, 0x4000015055514110,
|
|
0x0054010450004005, 0x4155515404100005, 0x5155145045155555, 0x1511555515440558,
|
|
0x5558544555515555, 0x0000000000000010, 0x5004000000000050, 0x1415510100000010,
|
|
0x4545555444514500, 0x5155151555555551, 0x1441540144044554, 0x5150104045544400,
|
|
0x5450545401444040, 0x5554455045501400, 0x4655155555555145, 0x1000010055455055,
|
|
0x1000004000055004, 0x4455405104000005, 0x4500114504150545, 0x0000000014000000,
|
|
0x5450000000000000, 0x5514551511445555, 0x4111501040555451, 0x4515445500054444,
|
|
0x5101500104100441, 0x1545115155545055, 0x0000000000000000, 0x1554000000100000,
|
|
0x5555545595551555, 0x5555051851455955, 0x5555555555555559, 0x0000400011001555,
|
|
0x0000004400040000, 0x5455511555554554, 0x5614555544115445, 0x6455156145555155,
|
|
0x5455855455415455, 0x5515555144555545, 0x0114400000145155, 0x0000051000450511,
|
|
0x4455154554445100, 0x4554150141544455, 0x65955555559a5965, 0x5555555854559559,
|
|
0x9569654559616595, 0x1040044040005565, 0x1010010500011044, 0x1554015545154540,
|
|
0x4440555401545441, 0x1014441450550105, 0x4545400410504145, 0x5015111541040151,
|
|
0x5145051154000410, 0x1040001044545044, 0x4001400000151410, 0x0540000044040000,
|
|
0x0510555454411544, 0x0400054054141550, 0x1001041145001100, 0x0000000140000000,
|
|
0x0000000014100000, 0x1544005454000140, 0x4050055505445145, 0x0011511104504155,
|
|
0x5505544415045055, 0x1155154445515554, 0x0000000000004555, 0x0000000000000000,
|
|
0x5101010510400004, 0x1514045044440400, 0x5515519555515555, 0x4554545441555545,
|
|
0x1551055955551515, 0x0150000011505515, 0x0044005040400000, 0x0004001004010050,
|
|
0x0000051004450414, 0x0114001101001144, 0x0401000001000001, 0x4500010001000401,
|
|
0x0004100000005000, 0x0105000441101100, 0x0455455550454540, 0x5404050144105505,
|
|
0x4101510540555455, 0x1055541411451555, 0x5451445110115505, 0x1154110010101545,
|
|
0x1145140450054055, 0x5555565415551554, 0x1550559555555555, 0x5555541545045141,
|
|
0x4555455450500100, 0x5510454545554555, 0x1510140115045455, 0x1001050040111510,
|
|
0x5555454555555504, 0x9954155545515554, 0x6596656555555555, 0x0140410051555559,
|
|
0x0011104010001544, 0x965669659a680501, 0x5655a55955556955, 0x4015111014404514,
|
|
0x1414155554505145, 0x0540040011051404, 0x1010000000015005, 0x0010054050004410,
|
|
0x5041104014000100, 0x4440010500100001, 0x1155510504545554, 0x0450151545115541,
|
|
0x4000100400110440, 0x1004440010514440, 0x0000115050450000, 0x0545404455541500,
|
|
0x1051051555505101, 0x5505144554544144, 0x4550545555515550, 0x0015400450045445,
|
|
0x4514155400554415, 0x4555055051050151, 0x1511441450001014, 0x4544554510404414,
|
|
0x4115115545545450, 0x5500541555551555, 0x5550010544155015, 0x0144414045545500,
|
|
0x4154050001050150, 0x5550511111000145, 0x1114504055000151, 0x5104041101451040,
|
|
0x0010501401051441, 0x0010501450504401, 0x4554585440044444, 0x5155555951450455,
|
|
0x0040000400105555, 0x0000000000000001,
|
|
};
|
|
|
|
pub fn float_mantissa_bits(comptime T: type) comptime_int {
|
|
comptime assert(@typeInfo(T) == .float);
|
|
|
|
return switch (@typeInfo(T).float.bits) {
|
|
16 => 10,
|
|
32 => 23,
|
|
64 => 52,
|
|
80 => 64,
|
|
128 => 112,
|
|
else => @compileError("unknown floating point type " ++ @typeName(T)),
|
|
};
|
|
}
|
|
|
|
/// Returns the number of fractional bits in the mantissa of floating point type T.
|
|
pub fn float_fractional_bits(comptime T: type) comptime_int {
|
|
comptime assert(@typeInfo(T) == .float);
|
|
|
|
// standard IEEE floats have an implicit 0.m or 1.m integer part
|
|
// f80 is special and has an explicitly stored bit in the MSB
|
|
// this function corresponds to `MANT_DIG - 1' from C
|
|
return switch (@typeInfo(T).float.bits) {
|
|
16 => 10,
|
|
32 => 23,
|
|
64 => 52,
|
|
80 => 63,
|
|
128 => 112,
|
|
else => @compileError("unknown floating point type " ++ @typeName(T)),
|
|
};
|
|
}
|
|
|
|
pub fn float_exponent_bits(comptime T: type) comptime_int {
|
|
comptime assert(@typeInfo(T) == .float);
|
|
|
|
return switch (@typeInfo(T).float.bits) {
|
|
16 => 5,
|
|
32 => 8,
|
|
64 => 11,
|
|
80 => 15,
|
|
128 => 15,
|
|
else => @compileError("unknown floating point type " ++ @typeName(T)),
|
|
};
|
|
}
|
|
pub fn digits2(value: u8) [2]u8 {
|
|
if (builtin.mode == .ReleaseSmall) {
|
|
return .{ @intCast('0' + value / 10), @intCast('0' + value % 10) };
|
|
} else {
|
|
return "00010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899"[value * 2 ..][0..2].*;
|
|
}
|
|
}
|
|
|
|
pub fn Log2Int(comptime T: type) type {
|
|
// comptime ceil log2
|
|
if (T == comptime_int) return comptime_int;
|
|
const bits: u16 = @typeInfo(T).int.bits;
|
|
const log2_bits = 16 - @clz(bits - 1);
|
|
return @Type(.{
|
|
.int = .{
|
|
.signedness = .unsigned,
|
|
.bits = log2_bits,
|
|
},
|
|
});
|
|
}
|
|
|
|
// zig fmt: on
|
|
};
|
|
|
|
pub fn and_bool_branchless(a: bool, b: bool) bool {
|
|
return (@intFromBool(a) & @intFromBool(b)) != 0;
|
|
}
|
|
|
|
pub fn or_bool_branchless(a: bool, b: bool) bool {
|
|
return (@intFromBool(a) | @intFromBool(b)) != 0;
|
|
}
|
|
|
|
fn is_character_between_ranges(ch: u8, start: u8, end: u8) bool {
|
|
return and_bool_branchless(ch >= start, ch <= end);
|
|
}
|
|
|
|
fn is_decimal_digit(ch: u8) bool {
|
|
return is_character_between_ranges(ch, '0', '9');
|
|
}
|
|
|
|
fn is_hex_digit_alpha_lower(ch: u8) bool {
|
|
return is_character_between_ranges(ch, 'a', 'f');
|
|
}
|
|
|
|
fn is_hex_digit_alpha_upper(ch: u8) bool {
|
|
return is_character_between_ranges(ch, 'A', 'F');
|
|
}
|
|
|
|
fn is_hex_digit_alpha(ch: u8) bool {
|
|
return or_bool_branchless(is_hex_digit_alpha_lower(ch), is_hex_digit_alpha_upper(ch));
|
|
}
|
|
|
|
pub fn is_hex_digit(ch: u8) bool {
|
|
return or_bool_branchless(is_decimal_digit(ch), is_hex_digit_alpha(ch));
|
|
}
|
|
|
|
inline fn log2_int(v: anytype) u8 {
|
|
assert(v != 0);
|
|
return @bitSizeOf(@TypeOf(v)) - 1 - @clz(v);
|
|
}
|
|
|
|
fn hex_digit_count(v: u64) u8 {
|
|
return if (v != 0) log2_int(v) / log2_int(@as(u64, 16)) + 1 else 1;
|
|
}
|
|
|
|
pub const left_brace = '{';
|
|
pub const right_brace = '}';
|
|
|
|
const IntegerFormatOptions = struct {
|
|
kind: Kind,
|
|
width: u32,
|
|
|
|
const Kind = enum {
|
|
hexadecimal,
|
|
decimal,
|
|
octal,
|
|
binary,
|
|
};
|
|
};
|
|
|
|
fn integer_format_options(pointer: [*:0]const u8, index: *usize) IntegerFormatOptions {
|
|
var result = IntegerFormatOptions{
|
|
.kind = .decimal,
|
|
.width = 0,
|
|
};
|
|
|
|
if (pointer[index.*] == ':') {
|
|
index.* += 1;
|
|
|
|
while (pointer[index.*] != right_brace) {
|
|
switch (pointer[index.*]) {
|
|
'x' => {
|
|
result.kind = .hexadecimal;
|
|
index.* += 1;
|
|
},
|
|
'd' => {
|
|
result.kind = .decimal;
|
|
index.* += 1;
|
|
},
|
|
'o' => {
|
|
result.kind = .octal;
|
|
index.* += 1;
|
|
},
|
|
'b' => {
|
|
result.kind = .binary;
|
|
index.* += 1;
|
|
},
|
|
'w' => {
|
|
index.* += 1;
|
|
|
|
if (pointer[index.*] != '=') {
|
|
os.abort();
|
|
}
|
|
|
|
index.* += 1;
|
|
|
|
const start = index.*;
|
|
|
|
while (is_decimal_digit(pointer[index.*])) {
|
|
index.* += 1;
|
|
}
|
|
const end = index.*;
|
|
|
|
result.width = @intCast(parse.integer_decimal(pointer[start..end]));
|
|
},
|
|
else => unreachable,
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
pub fn format_va(buffer: []u8, format_string: [*:0]const u8, variable_arguments: *VariableArguments) usize {
|
|
var read_byte_count: usize = 0;
|
|
var written_byte_count: usize = 0;
|
|
|
|
while (format_string[read_byte_count] != 0) {
|
|
while (true) {
|
|
const ch = format_string[read_byte_count];
|
|
|
|
switch (ch) {
|
|
else => {
|
|
buffer[written_byte_count] = ch;
|
|
written_byte_count += 1;
|
|
read_byte_count += 1;
|
|
},
|
|
0 => break,
|
|
left_brace => {
|
|
read_byte_count += 1;
|
|
|
|
const next_ch = format_string[read_byte_count];
|
|
|
|
switch (next_ch) {
|
|
left_brace => os.abort(),
|
|
'c' => {
|
|
os.abort();
|
|
},
|
|
'f' => {
|
|
os.abort();
|
|
},
|
|
's' => {
|
|
os.abort();
|
|
},
|
|
'u' => {
|
|
read_byte_count += 1;
|
|
|
|
const bit_count_start = read_byte_count;
|
|
while (is_decimal_digit(format_string[read_byte_count])) {
|
|
read_byte_count += 1;
|
|
}
|
|
|
|
const bit_count_end = read_byte_count;
|
|
|
|
const bit_count_string = format_string[bit_count_start..bit_count_end];
|
|
const bit_count = parse.integer_decimal(bit_count_string);
|
|
|
|
const original_value: u64 = switch (bit_count) {
|
|
8, 16, 32 => @cVaArg(variable_arguments, u32),
|
|
64 => @cVaArg(variable_arguments, u64),
|
|
else => unreachable,
|
|
};
|
|
|
|
const options = integer_format_options(format_string, &read_byte_count);
|
|
|
|
switch (options.kind) {
|
|
.hexadecimal => {
|
|
const digit_count = hex_digit_count(original_value);
|
|
_ = digit_count;
|
|
os.abort();
|
|
},
|
|
.decimal => {
|
|
const decimal_buffer = buffer[written_byte_count..];
|
|
const decimal_written_byte_count = string_format.integer_decimal(decimal_buffer, original_value);
|
|
written_byte_count += decimal_written_byte_count;
|
|
},
|
|
.octal, .binary => os.abort(),
|
|
}
|
|
},
|
|
else => os.abort(),
|
|
}
|
|
|
|
if (format_string[read_byte_count] != right_brace) {
|
|
os.abort();
|
|
}
|
|
|
|
read_byte_count += 1;
|
|
|
|
break;
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
_ = &written_byte_count;
|
|
_ = &variable_arguments;
|
|
return written_byte_count;
|
|
}
|
|
|
|
pub fn format(buffer_pointer: [*]u8, buffer_length: usize, format_string: [*:0]const u8, ...) callconv(.C) usize {
|
|
var variable_arguments = @cVaStart();
|
|
const byte_count = format_va(buffer_pointer[0..buffer_length], format_string, &variable_arguments);
|
|
@cVaEnd(&variable_arguments);
|
|
return byte_count;
|
|
}
|
|
|
|
pub const GlobalState = struct {
|
|
arena: *Arena,
|
|
thread_count: usize,
|
|
|
|
pub var initialized = false;
|
|
|
|
pub fn initialize() void {
|
|
assert(!initialized);
|
|
defer initialized = true;
|
|
const thread_count = os.get_cpu_count();
|
|
global = .{
|
|
.arena = Arena.initialize_default(2 * MB),
|
|
.thread_count = thread_count,
|
|
};
|
|
}
|
|
};
|
|
pub var global: GlobalState = undefined;
|
|
|
|
pub const parse = struct {
|
|
pub fn integer_hexadecimal(str: []const u8) u64 {
|
|
var value: u64 = 0;
|
|
|
|
for (str) |ch| {
|
|
assert(is_hex_digit(ch));
|
|
value = accumulate_hexadecimal(value, ch);
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
pub fn accumulate_hexadecimal(accumulator: u64, ch: u8) u64 {
|
|
const value_to_add: u64 = if (is_decimal_digit(ch)) ch - '0' else if (is_hex_digit_alpha_upper(ch))
|
|
ch - 'A' + 10
|
|
else if (is_hex_digit_alpha_lower(ch))
|
|
ch - 'a' + 10
|
|
else
|
|
unreachable;
|
|
return (accumulator * 16) + value_to_add;
|
|
}
|
|
|
|
pub fn integer_decimal(str: []const u8) u64 {
|
|
var value: u64 = 0;
|
|
|
|
for (str) |ch| {
|
|
assert(is_decimal_digit(ch));
|
|
value = accumulate_decimal(value, ch);
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
pub fn accumulate_decimal(accumulator: u64, ch: u8) u64 {
|
|
return (accumulator * 10) + (ch - '0');
|
|
}
|
|
};
|
|
|
|
test "parse integer decimal" {
|
|
const std = @import("std");
|
|
const expect = std.testing.expect;
|
|
try expect(parse.integer_decimal("0") == 0);
|
|
try expect(parse.integer_decimal("5") == 5);
|
|
try expect(parse.integer_decimal("10") == 10);
|
|
try expect(parse.integer_decimal("901283") == 901283);
|
|
try expect(parse.integer_decimal("189234819023129038") == 189234819023129038);
|
|
}
|
|
|
|
test "parse integer hexadecimal" {
|
|
const std = @import("std");
|
|
const expect = std.testing.expect;
|
|
try expect(parse.integer_hexadecimal("0") == 0);
|
|
try expect(parse.integer_hexadecimal("5") == 5);
|
|
try expect(parse.integer_hexadecimal("10") == 0x10);
|
|
try expect(parse.integer_hexadecimal("901283") == 0x901283);
|
|
try expect(parse.integer_hexadecimal("1892348190231290") == 0x1892348190231290);
|
|
try expect(parse.integer_hexadecimal("1b92a48c90d3e2f0") == 0x1b92a48c90d3e2f0);
|
|
}
|
|
|
|
fn vprint(format_string: [*:0]const u8, args: *VariableArguments) void {
|
|
var buffer: [16 * 1024]u8 = undefined;
|
|
const slice = format_va(&buffer, format_string, args);
|
|
print_string(slice);
|
|
}
|
|
|
|
pub fn print(format_string: [*:0]const u8, ...) callconv(.C) void {
|
|
const args = @cVaStart();
|
|
vprint(format_string, &args);
|
|
@cVaEnd(&args);
|
|
}
|
|
|
|
pub const print_string = print_string_stderr;
|
|
|
|
pub fn print_string_stdout(str: []const u8) void {
|
|
os.get_stdout().write(str);
|
|
}
|
|
|
|
pub fn print_string_stderr(str: []const u8) void {
|
|
os.get_stderr().write(str);
|
|
}
|