Documentation Index
Fetch the complete documentation index at: https://mintlify.com/ziglang/zig/llms.txt
Use this file to discover all available pages before exploring further.
BitSet provides efficient storage and manipulation of sets of integers represented as bits.
Type Variants
Zig provides three BitSet types:
- StaticBitSet - Fixed size known at compile time
- DynamicBitSet - Runtime-sized with allocator
- DynamicBitSetUnmanaged - Runtime-sized without storing allocator
StaticBitSet
pub fn StaticBitSet(comptime size: usize) type
Fixed-size bit set with compile-time known size.
Creation
const BitSet = std.bit_set.StaticBitSet(128);
var bits = BitSet.initEmpty();
var all_set = BitSet.initFull();
Methods
initEmpty
pub fn initEmpty() StaticBitSet(size)
Creates a bit set with all bits unset.
initFull
pub fn initFull() StaticBitSet(size)
Creates a bit set with all bits set.
set
pub fn set(self: *StaticBitSet(size), index: usize) void
Sets the bit at the given index.
unset
pub fn unset(self: *StaticBitSet(size), index: usize) void
Clears the bit at the given index.
toggle
pub fn toggle(self: *StaticBitSet(size), index: usize) void
Toggles the bit at the given index.
isSet
pub fn isSet(self: StaticBitSet(size), index: usize) bool
Returns whether the bit at the given index is set.
count
pub fn count(self: StaticBitSet(size)) usize
Returns the number of set bits (population count).
setAll
pub fn setAll(self: *StaticBitSet(size)) void
Sets all bits.
unsetAll
pub fn unsetAll(self: *StaticBitSet(size)) void
Clears all bits.
toggleAll
pub fn toggleAll(self: *StaticBitSet(size)) void
Toggles all bits.
Set Operations
setUnion
pub fn setUnion(self: StaticBitSet(size), other: StaticBitSet(size)) StaticBitSet(size)
Returns the union of two bit sets (OR operation).
setIntersection
pub fn setIntersection(self: StaticBitSet(size), other: StaticBitSet(size)) StaticBitSet(size)
Returns the intersection of two bit sets (AND operation).
setDifference
pub fn setDifference(self: StaticBitSet(size), other: StaticBitSet(size)) StaticBitSet(size)
Returns the difference (bits in self but not in other).
toggleSet
pub fn toggleSet(self: *StaticBitSet(size), other: StaticBitSet(size)) void
Toggles all bits that are set in other (XOR operation).
Iteration
iterator
pub fn iterator(self: *const StaticBitSet(size)) Iterator
Returns an iterator over set bit indices.
var it = bits.iterator(.{});
while (it.next()) |index| {
std.debug.print("Bit {} is set\n", .{index});
}
Usage Example
const std = @import("std");
const StaticBitSet = std.bit_set.StaticBitSet;
pub fn main() void {
const BitSet = StaticBitSet(64);
var bits = BitSet.initEmpty();
// Set some bits
bits.set(5);
bits.set(10);
bits.set(42);
std.debug.print("Count: {}\n", .{bits.count()}); // 3
std.debug.print("Is 5 set? {}\n", .{bits.isSet(5)}); // true
std.debug.print("Is 7 set? {}\n", .{bits.isSet(7)}); // false
// Set operations
var other = BitSet.initEmpty();
other.set(5);
other.set(15);
const union_bits = bits.setUnion(other);
std.debug.print("Union count: {}\n", .{union_bits.count()}); // 4
const intersection = bits.setIntersection(other);
std.debug.print("Intersection count: {}\n", .{intersection.count()}); // 1
// Iterate
var it = bits.iterator(.{});
while (it.next()) |index| {
std.debug.print("Set: {}\n", .{index});
}
}
DynamicBitSet
Dynamically-sized bit set with an allocator.
Creation and Destruction
initEmpty
pub fn initEmpty(allocator: Allocator, bit_length: usize) !DynamicBitSet
Creates an empty bit set with the specified capacity.
initFull
pub fn initFull(allocator: Allocator, bit_length: usize) !DynamicBitSet
Creates a bit set with all bits set.
deinit
pub fn deinit(self: *DynamicBitSet) void
Frees the bit set’s memory.
Resizing
resize
pub fn resize(self: *DynamicBitSet, new_len: usize, value: bool) !void
Resizes the bit set. New bits are set to value.
Usage Example
const std = @import("std");
const DynamicBitSet = std.bit_set.DynamicBitSet;
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
var bits = try DynamicBitSet.initEmpty(allocator, 100);
defer bits.deinit();
bits.set(50);
bits.set(75);
std.debug.print("Count: {}\n", .{bits.count()});
// Resize
try bits.resize(200, false);
bits.set(150);
}
DynamicBitSetUnmanaged
pub const DynamicBitSetUnmanaged
Dynamically-sized bit set that doesn’t store the allocator.
All methods that allocate require passing the allocator explicitly.
Methods
Same as DynamicBitSet, but allocator is passed to each method:
pub fn initEmpty(allocator: Allocator, bit_length: usize) !DynamicBitSetUnmanaged
pub fn deinit(self: *DynamicBitSetUnmanaged, allocator: Allocator) void
pub fn resize(self: *DynamicBitSetUnmanaged, allocator: Allocator, new_len: usize, value: bool) !void
Use Cases
Tracking Visited Nodes
var visited = StaticBitSet(graph.node_count).initEmpty();
for (nodes_to_visit) |node_id| {
if (!visited.isSet(node_id)) {
visited.set(node_id);
// Process node
}
}
Flags and Permissions
const Permissions = StaticBitSet(8);
const READ = 0;
const WRITE = 1;
const EXECUTE = 2;
var perms = Permissions.initEmpty();
perms.set(READ);
perms.set(WRITE);
if (perms.isSet(WRITE)) {
// Allow write
}
Bloom Filters
var bloom = try DynamicBitSet.initEmpty(allocator, 1000);
defer bloom.deinit();
const hash1 = hashFunction1(key) % 1000;
const hash2 = hashFunction2(key) % 1000;
bloom.set(hash1);
bloom.set(hash2);
- Set/Unset/Toggle: O(1)
- Count: O(n) where n is number of machine words
- Set operations: O(n) where n is number of machine words
- Memory: ⌈size/8⌉ bytes plus overhead
BitSet operations are highly optimized using CPU instructions like popcnt for counting set bits.
- EnumSet - Type-safe bit set for enums (see std namespace)
- HashMap - When you need to map keys to boolean values