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 {...@@ -184,6 +184,14 @@ pub fn IntegerBitSet(comptime size: u16) type {
184 return @ctz(mask);184 return @ctz(mask);
185 }185 }
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
187 /// Finds the index of the first set bit, and unsets it.195 /// Finds the index of the first set bit, and unsets it.
188 /// If no bits are set, returns null.196 /// If no bits are set, returns null.
189 pub fn toggleFirstSet(self: *Self) ?usize {197 pub fn toggleFirstSet(self: *Self) ?usize {
...@@ -542,6 +550,24 @@ pub fn ArrayBitSet(comptime MaskIntType: type, comptime size: usize) type {...@@ -542,6 +550,24 @@ pub fn ArrayBitSet(comptime MaskIntType: type, comptime size: usize) type {
542 return offset + @ctz(mask);550 return offset + @ctz(mask);
543 }551 }
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
545 /// Finds the index of the first set bit, and unsets it.571 /// Finds the index of the first set bit, and unsets it.
546 /// If no bits are set, returns null.572 /// If no bits are set, returns null.
547 pub fn toggleFirstSet(self: *Self) ?usize {573 pub fn toggleFirstSet(self: *Self) ?usize {
...@@ -941,6 +967,24 @@ pub const DynamicBitSetUnmanaged = struct {...@@ -941,6 +967,24 @@ pub const DynamicBitSetUnmanaged = struct {
941 return offset + @ctz(mask[0]);967 return offset + @ctz(mask[0]);
942 }968 }
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
944 /// Finds the index of the first set bit, and unsets it.988 /// Finds the index of the first set bit, and unsets it.
945 /// If no bits are set, returns null.989 /// If no bits are set, returns null.
946 pub fn toggleFirstSet(self: *Self) ?usize {990 pub fn toggleFirstSet(self: *Self) ?usize {
...@@ -1160,6 +1204,12 @@ pub const DynamicBitSet = struct {...@@ -1160,6 +1204,12 @@ pub const DynamicBitSet = struct {
1160 return self.unmanaged.findFirstSet();1204 return self.unmanaged.findFirstSet();
1161 }1205 }
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
1163 /// Finds the index of the first set bit, and unsets it.1213 /// Finds the index of the first set bit, and unsets it.
1164 /// If no bits are set, returns null.1214 /// If no bits are set, returns null.
1165 pub fn toggleFirstSet(self: *Self) ?usize {1215 pub fn toggleFirstSet(self: *Self) ?usize {
...@@ -1514,8 +1564,10 @@ fn testBitSet(a: anytype, b: anytype, len: usize) !void {...@@ -1514,8 +1564,10 @@ fn testBitSet(a: anytype, b: anytype, len: usize) !void {
1514 }1564 }
1515 }1565 }
1516 try testing.expectEqual(@as(?usize, null), a.findFirstSet());1566 try testing.expectEqual(@as(?usize, null), a.findFirstSet());
1567 try testing.expectEqual(@as(?usize, null), a.findLastSet());
1517 try testing.expectEqual(@as(?usize, null), a.toggleFirstSet());1568 try testing.expectEqual(@as(?usize, null), a.toggleFirstSet());
1518 try testing.expectEqual(@as(?usize, null), a.findFirstSet());1569 try testing.expectEqual(@as(?usize, null), a.findFirstSet());
1570 try testing.expectEqual(@as(?usize, null), a.findLastSet());
1519 try testing.expectEqual(@as(?usize, null), a.toggleFirstSet());1571 try testing.expectEqual(@as(?usize, null), a.toggleFirstSet());
1520 try testing.expectEqual(@as(usize, 0), a.count());1572 try testing.expectEqual(@as(usize, 0), a.count());
15211573