Skip to content

Commit 4545771

Browse files
committed
Pass ArrayBitSet by reference instead of by value
`ArrayBitSet.isSet` was doing a memcpy of the entire `masks` array
1 parent 34887cf commit 4545771

File tree

1 file changed

+74
-44
lines changed

1 file changed

+74
-44
lines changed

lib/std/bit_set.zig

Lines changed: 74 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -399,14 +399,14 @@ pub fn ArrayBitSet(comptime MaskIntType: type, comptime size: usize) type {
399399

400400
/// Returns true if the bit at the specified index
401401
/// is present in the set, false otherwise.
402-
pub fn isSet(self: Self, index: usize) bool {
402+
pub fn isSet(self: *const Self, index: usize) bool {
403403
assert(index < bit_length);
404404
if (num_masks == 0) return false; // doesn't compile in this case
405405
return (self.masks[maskIndex(index)] & maskBit(index)) != 0;
406406
}
407407

408408
/// Returns the total number of set bits in this bit set.
409-
pub fn count(self: Self) usize {
409+
pub fn count(self: *const Self) usize {
410410
var total: usize = 0;
411411
for (self.masks) |mask| {
412412
total += @popCount(mask);
@@ -493,9 +493,10 @@ pub fn ArrayBitSet(comptime MaskIntType: type, comptime size: usize) type {
493493

494494
/// Flips all bits in this bit set which are present
495495
/// in the toggles bit set.
496-
pub fn toggleSet(self: *Self, toggles: Self) void {
496+
pub fn toggleSet(self: *Self, toggles: *const Self) void {
497+
const other = &toggles.masks;
497498
for (self.masks) |*mask, i| {
498-
mask.* ^= toggles.masks[i];
499+
mask.* ^= other[i];
499500
}
500501
}
501502

@@ -514,7 +515,7 @@ pub fn ArrayBitSet(comptime MaskIntType: type, comptime size: usize) type {
514515
/// Performs a union of two bit sets, and stores the
515516
/// result in the first one. Bits in the result are
516517
/// set if the corresponding bits were set in either input.
517-
pub fn setUnion(self: *Self, other: Self) void {
518+
pub fn setUnion(self: *Self, other: *const Self) void {
518519
for (self.masks) |*mask, i| {
519520
mask.* |= other.masks[i];
520521
}
@@ -523,15 +524,15 @@ pub fn ArrayBitSet(comptime MaskIntType: type, comptime size: usize) type {
523524
/// Performs an intersection of two bit sets, and stores
524525
/// the result in the first one. Bits in the result are
525526
/// set if the corresponding bits were set in both inputs.
526-
pub fn setIntersection(self: *Self, other: Self) void {
527+
pub fn setIntersection(self: *Self, other: *const Self) void {
527528
for (self.masks) |*mask, i| {
528529
mask.* &= other.masks[i];
529530
}
530531
}
531532

532533
/// Finds the index of the first set bit.
533534
/// If no bits are set, returns null.
534-
pub fn findFirstSet(self: Self) ?usize {
535+
pub fn findFirstSet(self: *const Self) ?usize {
535536
var offset: usize = 0;
536537
const mask = for (self.masks) |mask| {
537538
if (mask != 0) break mask;
@@ -555,7 +556,7 @@ pub fn ArrayBitSet(comptime MaskIntType: type, comptime size: usize) type {
555556

556557
/// Returns true iff every corresponding bit in both
557558
/// bit sets are the same.
558-
pub fn eql(self: Self, other: Self) bool {
559+
pub fn eql(self: *const Self, other: *const Self) bool {
559560
var i: usize = 0;
560561
return while (i < num_masks) : (i += 1) {
561562
if (self.masks[i] != other.masks[i]) {
@@ -566,57 +567,57 @@ pub fn ArrayBitSet(comptime MaskIntType: type, comptime size: usize) type {
566567

567568
/// Returns true iff the first bit set is the subset
568569
/// of the second one.
569-
pub fn subsetOf(self: Self, other: Self) bool {
570+
pub fn subsetOf(self: *const Self, other: *const Self) bool {
570571
return self.intersectWith(other).eql(self);
571572
}
572573

573574
/// Returns true iff the first bit set is the superset
574575
/// of the second one.
575-
pub fn supersetOf(self: Self, other: Self) bool {
576+
pub fn supersetOf(self: *const Self, other: *const Self) bool {
576577
return other.subsetOf(self);
577578
}
578579

579580
/// Returns the complement bit sets. Bits in the result
580581
/// are set if the corresponding bits were not set.
581-
pub fn complement(self: Self) Self {
582-
var result = self;
582+
pub fn complement(self: *const Self) Self {
583+
var result = self.*;
583584
result.toggleAll();
584585
return result;
585586
}
586587

587588
/// Returns the union of two bit sets. Bits in the
588589
/// result are set if the corresponding bits were set
589590
/// in either input.
590-
pub fn unionWith(self: Self, other: Self) Self {
591-
var result = self;
591+
pub fn unionWith(self: *const Self, other: *const Self) Self {
592+
var result = self.*;
592593
result.setUnion(other);
593594
return result;
594595
}
595596

596597
/// Returns the intersection of two bit sets. Bits in
597598
/// the result are set if the corresponding bits were
598599
/// set in both inputs.
599-
pub fn intersectWith(self: Self, other: Self) Self {
600-
var result = self;
600+
pub fn intersectWith(self: *const Self, other: *const Self) Self {
601+
var result = self.*;
601602
result.setIntersection(other);
602603
return result;
603604
}
604605

605606
/// Returns the xor of two bit sets. Bits in the
606607
/// result are set if the corresponding bits were
607608
/// not the same in both inputs.
608-
pub fn xorWith(self: Self, other: Self) Self {
609-
var result = self;
609+
pub fn xorWith(self: *const Self, other: *const Self) Self {
610+
var result = self.*;
610611
result.toggleSet(other);
611612
return result;
612613
}
613614

614615
/// Returns the difference of two bit sets. Bits in
615616
/// the result are set if set in the first but not
616617
/// set in the second set.
617-
pub fn differenceWith(self: Self, other: Self) Self {
618-
var result = self;
619-
result.setIntersection(other.complement());
618+
pub fn differenceWith(self: *const Self, other: *const Self) Self {
619+
var result = self.*;
620+
result.setIntersection(&other.complement());
620621
return result;
621622
}
622623

@@ -1360,6 +1361,7 @@ fn testSupersetOf(empty: anytype, full: anytype, even: anytype, odd: anytype, le
13601361
fn testBitSet(a: anytype, b: anytype, len: usize) !void {
13611362
try testing.expectEqual(len, a.capacity());
13621363
try testing.expectEqual(len, b.capacity());
1364+
const needs_ptr = @hasField(std.meta.Child(@TypeOf(a)), "masks") and @typeInfo(@TypeOf(@field(a, "masks"))) != .Pointer;
13631365

13641366
{
13651367
var i: usize = 0;
@@ -1416,7 +1418,12 @@ fn testBitSet(a: anytype, b: anytype, len: usize) !void {
14161418
}
14171419
}
14181420

1419-
a.setUnion(b.*);
1421+
if (comptime needs_ptr) {
1422+
a.setUnion(b);
1423+
} else {
1424+
a.setUnion(b.*);
1425+
}
1426+
14201427
{
14211428
var i: usize = 0;
14221429
while (i < len) : (i += 1) {
@@ -1443,7 +1450,11 @@ fn testBitSet(a: anytype, b: anytype, len: usize) !void {
14431450
try testing.expectEqual(@as(?usize, null), unset.next());
14441451
}
14451452

1446-
a.toggleSet(b.*);
1453+
if (comptime needs_ptr) {
1454+
a.toggleSet(b);
1455+
} else {
1456+
a.toggleSet(b.*);
1457+
}
14471458
{
14481459
try testing.expectEqual(len / 4, a.count());
14491460

@@ -1459,7 +1470,11 @@ fn testBitSet(a: anytype, b: anytype, len: usize) !void {
14591470
}
14601471
}
14611472

1462-
a.setIntersection(b.*);
1473+
if (comptime needs_ptr) {
1474+
a.setIntersection(b);
1475+
} else {
1476+
a.setIntersection(b.*);
1477+
}
14631478
{
14641479
try testing.expectEqual((len + 3) / 4, a.count());
14651480

@@ -1470,7 +1485,11 @@ fn testBitSet(a: anytype, b: anytype, len: usize) !void {
14701485
}
14711486
}
14721487

1473-
a.toggleSet(a.*);
1488+
if (comptime needs_ptr) {
1489+
a.toggleSet(a);
1490+
} else {
1491+
a.toggleSet(a.*);
1492+
}
14741493
{
14751494
var iter = a.iterator(.{});
14761495
try testing.expectEqual(@as(?usize, null), iter.next());
@@ -1570,21 +1589,27 @@ fn fillOdd(set: anytype, len: usize) void {
15701589
}
15711590

15721591
fn testPureBitSet(comptime Set: type) !void {
1573-
const empty = Set.initEmpty();
1574-
const full = Set.initFull();
1592+
var empty_ = Set.initEmpty();
1593+
var full_ = Set.initFull();
1594+
const needs_ptr = @hasField(Set, "masks") and @typeInfo(@TypeOf(empty_.masks)) != .Pointer;
15751595

1576-
const even = even: {
1596+
var even_ = even: {
15771597
var bit_set = Set.initEmpty();
15781598
fillEven(&bit_set, Set.bit_length);
15791599
break :even bit_set;
15801600
};
15811601

1582-
const odd = odd: {
1602+
var odd_ = odd: {
15831603
var bit_set = Set.initEmpty();
15841604
fillOdd(&bit_set, Set.bit_length);
15851605
break :odd bit_set;
15861606
};
15871607

1608+
var empty = if (needs_ptr) &empty_ else empty_;
1609+
var full = if (needs_ptr) &full_ else full_;
1610+
var even = if (needs_ptr) &even_ else even_;
1611+
var odd = if (needs_ptr) &odd_ else odd_;
1612+
15881613
try testSubsetOf(empty, full, even, odd, Set.bit_length);
15891614
try testSupersetOf(empty, full, even, odd, Set.bit_length);
15901615

@@ -1622,36 +1647,41 @@ fn testPureBitSet(comptime Set: type) !void {
16221647
try testing.expect(full.differenceWith(even).eql(odd));
16231648
}
16241649

1625-
fn testStaticBitSet(comptime Set: type) !void {
1650+
fn testStaticBitSet(comptime Set: type, comptime Container: @Type(.EnumLiteral)) !void {
16261651
var a = Set.initEmpty();
16271652
var b = Set.initFull();
16281653
try testing.expectEqual(@as(usize, 0), a.count());
16291654
try testing.expectEqual(@as(usize, Set.bit_length), b.count());
16301655

1631-
try testEql(a, b, Set.bit_length);
1656+
if (comptime Container == .ArrayBitSet) {
1657+
try testEql(&a, &b, Set.bit_length);
1658+
} else {
1659+
try testEql(a, b, Set.bit_length);
1660+
}
1661+
16321662
try testBitSet(&a, &b, Set.bit_length);
16331663

16341664
try testPureBitSet(Set);
16351665
}
16361666

16371667
test "IntegerBitSet" {
1638-
try testStaticBitSet(IntegerBitSet(0));
1639-
try testStaticBitSet(IntegerBitSet(1));
1640-
try testStaticBitSet(IntegerBitSet(2));
1641-
try testStaticBitSet(IntegerBitSet(5));
1642-
try testStaticBitSet(IntegerBitSet(8));
1643-
try testStaticBitSet(IntegerBitSet(32));
1644-
try testStaticBitSet(IntegerBitSet(64));
1645-
try testStaticBitSet(IntegerBitSet(127));
1668+
try testStaticBitSet(IntegerBitSet(0), .IntegerBitSet);
1669+
try testStaticBitSet(IntegerBitSet(1), .IntegerBitSet);
1670+
try testStaticBitSet(IntegerBitSet(2), .IntegerBitSet);
1671+
try testStaticBitSet(IntegerBitSet(5), .IntegerBitSet);
1672+
try testStaticBitSet(IntegerBitSet(8), .IntegerBitSet);
1673+
try testStaticBitSet(IntegerBitSet(32), .IntegerBitSet);
1674+
try testStaticBitSet(IntegerBitSet(64), .IntegerBitSet);
1675+
try testStaticBitSet(IntegerBitSet(127), .IntegerBitSet);
16461676
}
16471677

16481678
test "ArrayBitSet" {
16491679
inline for (.{ 0, 1, 2, 31, 32, 33, 63, 64, 65, 254, 500, 3000 }) |size| {
1650-
try testStaticBitSet(ArrayBitSet(u8, size));
1651-
try testStaticBitSet(ArrayBitSet(u16, size));
1652-
try testStaticBitSet(ArrayBitSet(u32, size));
1653-
try testStaticBitSet(ArrayBitSet(u64, size));
1654-
try testStaticBitSet(ArrayBitSet(u128, size));
1680+
try testStaticBitSet(ArrayBitSet(u8, size), .ArrayBitSet);
1681+
try testStaticBitSet(ArrayBitSet(u16, size), .ArrayBitSet);
1682+
try testStaticBitSet(ArrayBitSet(u32, size), .ArrayBitSet);
1683+
try testStaticBitSet(ArrayBitSet(u64, size), .ArrayBitSet);
1684+
try testStaticBitSet(ArrayBitSet(u128, size), .ArrayBitSet);
16551685
}
16561686
}
16571687

0 commit comments

Comments
 (0)