authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2025-03-24 07:12:23-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-03-24 16:12:23+01:00
log972cab5bb027dce3d4f700e381bec3e1724c9504
treedcea2e1080577efad2ed2863d07a36e2a5268632
parentc1db72cdbcddb59aa4e9960f4c07de9781b296f6
signaturebadge-check Signed by PGP key B5690EEEBB952194

std: add bit_set.findLastSet() (#22411)


1 files changed, 52 insertions(+), 0 deletions(-)

lib/std/bit_set.zig+52
......@@ -184,6 +184,14 @@ pub fn IntegerBitSet(comptime size: u16) type {
184184 return @ctz(mask);
185185 }
186186
187 /// Finds the index of the last set bit.
188 /// If no bits are set, returns null.
189 pub fn findLastSet(self: Self) ?usize {
190 const mask = self.mask;
191 if (mask == 0) return null;
192 return bit_length - @clz(mask) - 1;
193 }
194
187195 /// Finds the index of the first set bit, and unsets it.
188196 /// If no bits are set, returns null.
189197 pub fn toggleFirstSet(self: *Self) ?usize {
......@@ -542,6 +550,24 @@ pub fn ArrayBitSet(comptime MaskIntType: type, comptime size: usize) type {
542550 return offset + @ctz(mask);
543551 }
544552
553 /// Finds the index of the last set bit.
554 /// If no bits are set, returns null.
555 pub fn findLastSet(self: Self) ?usize {
556 if (bit_length == 0) return null;
557 const bs = @bitSizeOf(MaskInt);
558 var len = bit_length / bs;
559 if (bit_length % bs != 0) len += 1;
560 var offset: usize = len * bs;
561 var idx: usize = len - 1;
562 while (self.masks[idx] == 0) : (idx -= 1) {
563 offset -= bs;
564 if (idx == 0) return null;
565 }
566 offset -= @clz(self.masks[idx]);
567 offset -= 1;
568 return offset;
569 }
570
545571 /// Finds the index of the first set bit, and unsets it.
546572 /// If no bits are set, returns null.
547573 pub fn toggleFirstSet(self: *Self) ?usize {
......@@ -941,6 +967,24 @@ pub const DynamicBitSetUnmanaged = struct {
941967 return offset + @ctz(mask[0]);
942968 }
943969
970 /// Finds the index of the last set bit.
971 /// If no bits are set, returns null.
972 pub fn findLastSet(self: Self) ?usize {
973 if (self.bit_length == 0) return null;
974 const bs = @bitSizeOf(MaskInt);
975 var len = self.bit_length / bs;
976 if (self.bit_length % bs != 0) len += 1;
977 var offset: usize = len * bs;
978 var idx: usize = len - 1;
979 while (self.masks[idx] == 0) : (idx -= 1) {
980 offset -= bs;
981 if (idx == 0) return null;
982 }
983 offset -= @clz(self.masks[idx]);
984 offset -= 1;
985 return offset;
986 }
987
944988 /// Finds the index of the first set bit, and unsets it.
945989 /// If no bits are set, returns null.
946990 pub fn toggleFirstSet(self: *Self) ?usize {
......@@ -1160,6 +1204,12 @@ pub const DynamicBitSet = struct {
11601204 return self.unmanaged.findFirstSet();
11611205 }
11621206
1207 /// Finds the index of the last set bit.
1208 /// If no bits are set, returns null.
1209 pub fn findLastSet(self: Self) ?usize {
1210 return self.unmanaged.findLastSet();
1211 }
1212
11631213 /// Finds the index of the first set bit, and unsets it.
11641214 /// If no bits are set, returns null.
11651215 pub fn toggleFirstSet(self: *Self) ?usize {
......@@ -1514,8 +1564,10 @@ fn testBitSet(a: anytype, b: anytype, len: usize) !void {
15141564 }
15151565 }
15161566 try testing.expectEqual(@as(?usize, null), a.findFirstSet());
1567 try testing.expectEqual(@as(?usize, null), a.findLastSet());
15171568 try testing.expectEqual(@as(?usize, null), a.toggleFirstSet());
15181569 try testing.expectEqual(@as(?usize, null), a.findFirstSet());
1570 try testing.expectEqual(@as(?usize, null), a.findLastSet());
15191571 try testing.expectEqual(@as(?usize, null), a.toggleFirstSet());
15201572 try testing.expectEqual(@as(usize, 0), a.count());
15211573