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 }