diff --git a/lib/std/sort.zig b/lib/std/sort.zig index 23707f1385..8705d24017 100644 --- a/lib/std/sort.zig +++ b/lib/std/sort.zig @@ -769,10 +769,38 @@ pub fn equalRange( context: anytype, comptime compareFn: fn (@TypeOf(context), T) std.math.Order, ) struct { usize, usize } { - return .{ - lowerBound(T, items, context, compareFn), - upperBound(T, items, context, compareFn), - }; + var low: usize = 0; + var high: usize = items.len; + + while (low < high) { + const mid = low + (high - low) / 2; + switch (compareFn(context, items[mid])) { + .gt => { + low = mid + 1; + }, + .lt => { + high = mid; + }, + .eq => { + return .{ + low + std.sort.lowerBound( + T, + items[low..mid], + context, + compareFn, + ), + mid + std.sort.upperBound( + T, + items[mid..high], + context, + compareFn, + ), + }; + }, + } + } + + return .{ low, low }; } test equalRange { @@ -800,6 +828,7 @@ test equalRange { try std.testing.expectEqual(.{ 6, 6 }, equalRange(i32, &[_]i32{ 2, 4, 8, 16, 32, 64 }, @as(i32, 100), S.orderI32)); try std.testing.expectEqual(.{ 2, 6 }, equalRange(i32, &[_]i32{ 2, 4, 8, 8, 8, 8, 15, 22 }, @as(i32, 8), S.orderI32)); try std.testing.expectEqual(.{ 2, 2 }, equalRange(u32, &[_]u32{ 2, 4, 8, 16, 32, 64 }, @as(u32, 5), S.orderU32)); + try std.testing.expectEqual(.{ 3, 5 }, equalRange(u32, &[_]u32{ 2, 3, 4, 5, 5 }, @as(u32, 5), S.orderU32)); try std.testing.expectEqual(.{ 1, 1 }, equalRange(f32, &[_]f32{ -54.2, -26.7, 0.0, 56.55, 100.1, 322.0 }, @as(f32, -33.4), S.orderF32)); try std.testing.expectEqual(.{ 3, 5 }, equalRange( []const u8,