lib/bench/src/stats/sets.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2
3 pub const Error = error{
4 CapacityOverflow,
5 SampleSetStorageTooSmall,
6 };
7
8 pub const Cursor = struct {
9 values: []u64,
10 offset: usize = 0,
11
12 pub fn init(values: []u64) Cursor {
13 return .{ .values = values };
14 }
15
16 pub fn take(
17 self: *Cursor,
18 comptime set_count: usize,
19 sample_count: u32,
20 ) Error![set_count][]u64 {
21 std.debug.assert(self.offset <= self.values.len);
22 const required = try valueCapacity(set_count, sample_count);
23 if (required > self.values.len - self.offset) return error.SampleSetStorageTooSmall;
24 const end = self.offset + required;
25 const result = try partition(set_count, self.values[self.offset..end], sample_count);
26 self.offset = end;
27 return result;
28 }
29
30 pub fn complete(self: *const Cursor) bool {
31 std.debug.assert(self.offset <= self.values.len);
32 return self.offset == self.values.len;
33 }
34 };
35
36 pub fn valueCapacity(comptime set_count: usize, sample_count: u32) Error!usize {
37 return std.math.mul(usize, set_count, sample_count) catch error.CapacityOverflow;
38 }
39
40 pub fn partition(
41 comptime set_count: usize,
42 values: []u64,
43 sample_count: u32,
44 ) Error![set_count][]u64 {
45 const required = try valueCapacity(set_count, sample_count);
46 if (values.len < required) return error.SampleSetStorageTooSmall;
47 const used = values[0..required];
48 @memset(used, 0);
49 var result: [set_count][]u64 = undefined;
50 for (&result, 0..) |*set, index| {
51 const start = index * @as(usize, sample_count);
52 set.* = used[start..][0..sample_count];
53 }
54 return result;
55 }