Lucas Santos
509639717a
std.equalRange: Compute lower and upper bounds simultaneously
...
The current implementation of `equalRange` just calls `lowerRange` and `upperRange`, but a lot of
the work done by these two functions can be shared. Specifically, each iteration gives information about whether the lower bound or the upper bound can be tightened. This leads to fewer iterations and, since there is one comparison per iteration, fewer comparisons.
Implementation adapted from [GCC](519ec1cfe9/libstdc%2B%2B-v3/include/bits/stl_algo.h (L2063) ).
This sample demonstrates the difference between the current implementation and mine:
```zig
fn S(comptime T: type) type {
return struct {
needle: T,
count: *usize,
pub fn order(context: @This(), item: T) std.math.Order {
context.count.* += 1;
return std.math.order(item, context.needle);
}
pub fn orderLength(context: @This(), item: []const u8) std.math.Order {
context.count.* += 1;
return std.math.order(item.len, context.needle);
}
};
}
pub fn main() !void {
var count: usize = 0;
try std.testing.expectEqual(.{ 0, 0 }, equalRange(i32, &[_]i32{}, S(i32){ .needle = 0, .count = &count }, S(i32).order));
try std.testing.expectEqual(.{ 0, 0 }, equalRange(i32, &[_]i32{ 2, 4, 8, 16, 32, 64 }, S(i32){ .needle = 0, .count = &count }, S(i32).order));
try std.testing.expectEqual(.{ 0, 1 }, equalRange(i32, &[_]i32{ 2, 4, 8, 16, 32, 64 }, S(i32){ .needle = 2, .count = &count }, S(i32).order));
try std.testing.expectEqual(.{ 2, 2 }, equalRange(i32, &[_]i32{ 2, 4, 8, 16, 32, 64 }, S(i32){ .needle = 5, .count = &count }, S(i32).order));
try std.testing.expectEqual(.{ 2, 3 }, equalRange(i32, &[_]i32{ 2, 4, 8, 16, 32, 64 }, S(i32){ .needle = 8, .count = &count }, S(i32).order));
try std.testing.expectEqual(.{ 5, 6 }, equalRange(i32, &[_]i32{ 2, 4, 8, 16, 32, 64 }, S(i32){ .needle = 64, .count = &count }, S(i32).order));
try std.testing.expectEqual(.{ 6, 6 }, equalRange(i32, &[_]i32{ 2, 4, 8, 16, 32, 64 }, S(i32){ .needle = 100, .count = &count }, S(i32).order));
try std.testing.expectEqual(.{ 2, 6 }, equalRange(i32, &[_]i32{ 2, 4, 8, 8, 8, 8, 15, 22 }, S(i32){ .needle = 8, .count = &count }, S(i32).order));
try std.testing.expectEqual(.{ 2, 2 }, equalRange(u32, &[_]u32{ 2, 4, 8, 16, 32, 64 }, S(u32){ .needle = 5, .count = &count }, S(u32).order));
try std.testing.expectEqual(.{ 1, 1 }, equalRange(f32, &[_]f32{ -54.2, -26.7, 0.0, 56.55, 100.1, 322.0 }, S(f32){ .needle = -33.4, .count = &count }, S(f32).order));
try std.testing.expectEqual(.{ 3, 5 }, equalRange(
[]const u8,
&[_][]const u8{ "Mars", "Venus", "Earth", "Saturn", "Uranus", "Mercury", "Jupiter", "Neptune" },
S(usize){ .needle = 6, .count = &count },
S(usize).orderLength,
));
std.debug.print("Count: {}\n", .{count});
}
```
For each comparison, we bump the count. With the current implementation, we get 57 comparisons. With mine, we get 43.
With contributions from @Olvilock.
This is my second attempt at this, since I messed up the [first one](https://github.com/ziglang/zig/pull/21290 ).
2024-09-23 13:03:06 -07:00
Alex Rønne Petersen
bdae7d97b9
test: Disable @bitCast of packed struct containing pointer temporarily.
...
TODO: Figure out what to do about this.
Context: https://discourse.llvm.org/t/rfc-remove-most-constant-expressions/63179
After changing our emit strategy for packed structs to just write to memory:
test-behavior
└─ run test behavior-x86_64-linux.6.5...6.5-gnu.2.38-x86_64-ReleaseSmall-libc
└─ zig test ReleaseSmall native failure
error: thread 44346 panic: attempt to unwrap error: ReinterpretDeclRef
/home/alexrp/Source/zig/src/Value.zig:571:42: 0x1f33514 in writeToPackedMemory (zig)
if (!val.ptrHasIntAddr(mod)) return error.ReinterpretDeclRef;
^
/home/alexrp/Source/zig/src/Value.zig:548:17: 0x1f32f45 in writeToPackedMemory (zig)
try field_val.writeToPackedMemory(field_ty, pt, buffer, bit_offset + bits);
^
/home/alexrp/Source/zig/src/codegen/llvm.zig:3706:89: 0x1ca2366 in lowerValueToInt (zig)
val.writeToPackedMemory(ty, pt, std.mem.sliceAsBytes(limbs)[0..bytes], 0) catch unreachable;
^
/home/alexrp/Source/zig/src/codegen/llvm.zig:4083:49: 0x1a33800 in lowerValue (zig)
return o.lowerValueToInt(llvm_int_ty, arg_val);
^
/home/alexrp/Source/zig/src/codegen/llvm.zig:4798:42: 0x2ec4e6a in resolveValue (zig)
const llvm_val = try o.lowerValue(val.toIntern());
^
/home/alexrp/Source/zig/src/codegen/llvm.zig:4789:47: 0x2ec4bd3 in resolveInst (zig)
const llvm_val = try self.resolveValue((try self.air.value(inst, self.ng.object.pt)).?);
^
/home/alexrp/Source/zig/src/codegen/llvm.zig:8996:49: 0x2f022e9 in airStore (zig)
const src_operand = try self.resolveInst(bin_op.rhs);
^
/home/alexrp/Source/zig/src/codegen/llvm.zig:4967:53: 0x29f7260 in genBody (zig)
.store => try self.airStore(inst, false),
^
/home/alexrp/Source/zig/src/codegen/llvm.zig:1682:19: 0x29f147c in updateFunc (zig)
fg.genBody(air.getMainBody()) catch |err| switch (err) {
^
/home/alexrp/Source/zig/src/link/Elf.zig:2916:70: 0x2eb0f15 in updateFunc (zig)
if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(pt, func_index, air, liveness);
^
/home/alexrp/Source/zig/src/link.zig:426:82: 0x29fbef5 in updateFunc (zig)
return @as(*tag.Type(), @fieldParentPtr("base", base)).updateFunc(pt, func_index, air, liveness);
^
/home/alexrp/Source/zig/src/Zcu/PerThread.zig:876:22: 0x25f3d9e in linkerUpdateFunc (zig)
lf.updateFunc(pt, func_index, air, liveness) catch |err| switch (err) {
^
/home/alexrp/Source/zig/src/Compilation.zig:3975:36: 0x21768fe in processOneCodegenJob (zig)
try pt.linkerUpdateFunc(func.func, func.air);
^
/home/alexrp/Source/zig/src/Compilation.zig:3928:36: 0x2176541 in queueCodegenJob (zig)
return processOneCodegenJob(tid, comp, codegen_job);
^
/home/alexrp/Source/zig/src/Compilation.zig:3682:37: 0x1e9d37f in processOneJob (zig)
try comp.queueCodegenJob(tid, .{ .func = .{
^
/home/alexrp/Source/zig/src/Compilation.zig:3638:30: 0x1c1f6c1 in performAllTheWorkInner (zig)
try processOneJob(@intFromEnum(Zcu.PerThread.Id.main), comp, job, main_progress_node);
^
/home/alexrp/Source/zig/src/Compilation.zig:3508:36: 0x1ab6e10 in performAllTheWork (zig)
try comp.performAllTheWorkInner(main_progress_node);
^
/home/alexrp/Source/zig/src/Compilation.zig:2269:31: 0x1ab25b9 in update (zig)
try comp.performAllTheWork(main_progress_node);
^
/home/alexrp/Source/zig/src/main.zig:4156:32: 0x1b01351 in serve (zig)
try comp.update(main_progress_node);
^
/home/alexrp/Source/zig/src/main.zig:3453:22: 0x1b20d7c in buildOutputType (zig)
try serve(
^
/home/alexrp/Source/zig/src/main.zig:267:31: 0x1969c54 in mainArgs (zig)
return buildOutputType(gpa, arena, args, .zig_test);
^
/home/alexrp/Source/zig/src/main.zig:199:20: 0x19669c5 in main (zig)
return mainArgs(gpa, arena, args);
^
/home/alexrp/Source/zig/lib/std/start.zig:614:37: 0x19664ee in main (zig)
const result = root.main() catch |err| {
^
../sysdeps/nptl/libc_start_call_main.h:58:16: 0x7a453da2814f in __libc_start_call_main (../sysdeps/x86/libc-start.c)
../csu/libc-start.c:360:3: 0x7a453da28208 in __libc_start_main_impl (../sysdeps/x86/libc-start.c)
???:?:?: 0x1966134 in ??? (???)
???:?:?: 0x0 in ??? (???)
2024-09-19 18:20:21 -07:00