diff options
Diffstat (limited to '_tests/perf.zig')
| -rw-r--r-- | _tests/perf.zig | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/_tests/perf.zig b/_tests/perf.zig new file mode 100644 index 0000000..02c9226 --- /dev/null +++ b/_tests/perf.zig @@ -0,0 +1,105 @@ +const builtin = @import("builtin"); +const std = @import("std"); + +const endian = builtin.target.cpu.arch.endian(); + +const min = std.math.minInt(i52) + 1; +const max = std.math.maxInt(i52) - 1; + +export fn checkValidRange(int: i64) u8 { + return if (min < int and int < max) 1 else 0; +} + +export fn checkValidRange2(int: i64) u8 { + const x: u64 = @bitCast(int); + return if (if (int < 0) + x >> 51 == std.math.maxInt(u13) + else + x >> 51 == 0) 1 else 0; +} + +export fn isFixnum(v: u64) u8 { + const expt = v >> 52; + const rest = v << 13; + return if (expt == 0xfff and rest != 0) 1 else 0; +} + +export fn isFixnum2(v: u64) u8 { + const hi: u14 = @intCast(v >> 50); + return if (hi == (0xfff << 2 | 0b01)) 1 else 0; +} + +export fn sstrLen(x: u64) u8 { + const bytes: @Vector(8, u8) = @bitCast(x); + const nulls: @Vector(8, u8) = @splat(0); + const comps: u8 = @bitCast(bytes == nulls); + // Two bits will always be 0, since the actual short string starts at the + // third byte; third lowest or third highest depending on endianness. So, + // depending on endianness, either cut off the two leading bits and ensure + // that the second-last is set, or ensure that the second highest set, to + // limit the length to 6. + return switch (endian) { + .big => @clz(comps << 2 | 2), + .little => @ctz(comps | 64), + }; +} + +const positive_mask: u64 = 0xfff7ffffffffffff; + +fn unpackNegative(v: u64) i64 { + return @bitCast(v); +} + +fn unpackPositive(v: u64) i64 { + const uint: u64 = @bitCast(v); + return @bitCast(uint ^ positive_mask); +} + +fn packNegative(int: i64) u64 { + return @bitCast(int); +} + +fn packPositive(int: i64) u64 { + const uint: u64 = @bitCast(int); + return @bitCast(uint ^ positive_mask); +} + +export fn packFx(int: i64) u64 { + if (int < 0) { + return packNegative(int); + } else { + return packPositive(int); + } +} + +export fn packSstr(len: usize, s: [*]const u8) u64 { + var v: u64 = 0xfff3000000000000; + const buf: *[8]u8 = @ptrCast(&v); + @memcpy(buf[0 .. 0 + len], s); + return v; +} + +pub fn packSstrTest(buf: [*]const u64, len: usize) ?Value { + if (len > 6) return null; + + const v = switch (endian) { + .big => @byteSwap(buf[0]), + .little => buf[0], + }; + + const shift: u6 = 8 * @as(u6, @intCast(len)); + const mask = @as(u64, std.math.maxInt(u64)) << shift; + const s = Value{ .sstr = .{ .bytes = @intCast(v & ~mask) } }; + + // This effectively checks if there were any NUL bytes: + if (len != value.sstrLen(&s)) return null; + + return s; +} + +pub fn packSstrStatic(comptime s: []const u8) Value { + var val: u64 = undefined; + const buf: [*]align(8) u8 = @ptrCast(&val); + @memcpy(buf, s); + return pack(@ptrCast(buf), s.len).?; +} |
