lib/accy/src/kernel/library/extent.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2
3 pub const runtime_extent_max: u64 = @as(u64, @intCast(std.math.maxInt(i32)));
4
5 pub fn indexExtent(extent: u64) !i64 {
6 return std.math.cast(i64, extent) orelse error.ExtentOverflowsIndexRange;
7 }
8
9 pub fn indexProduct(lhs: u64, rhs: u64) !i64 {
10 const product = std.math.mul(u64, lhs, rhs) catch return error.ExtentOverflowsIndexRange;
11 return indexExtent(product);
12 }
13
14 pub fn runtimeExtentArgument(extent: u64) !u32 {
15 if (extent == 0 or extent > runtime_extent_max) return error.ExtentOverflowsIndexRange;
16 return @intCast(extent);
17 }
18
19 pub fn blockCountWithinLimit(extent: u64, threads: u32, max_blocks: u32) bool {
20 if (threads == 0) return false;
21 return extent <= @as(u64, threads) * max_blocks;
22 }
23
24 const testing = std.testing;
25
26 test "index extent accepts the full unsigned index range" {
27 try testing.expectEqual(@as(i64, 0), try indexExtent(0));
28 try testing.expectEqual(@as(i64, std.math.maxInt(i64)), try indexExtent(@as(u64, @intCast(std.math.maxInt(i64)))));
29 try testing.expectError(error.ExtentOverflowsIndexRange, indexExtent(@as(u64, @intCast(std.math.maxInt(i64))) + 1));
30 }
31
32 test "index product checks overflow before conversion" {
33 try testing.expectEqual(@as(i64, 12), try indexProduct(3, 4));
34 try testing.expectError(error.ExtentOverflowsIndexRange, indexProduct(std.math.maxInt(u64), 2));
35 }
36
37 test "runtime extent argument bounds to nonzero i32 range" {
38 try testing.expectEqual(@as(u32, 1), try runtimeExtentArgument(1));
39 try testing.expectEqual(@as(u32, @intCast(runtime_extent_max)), try runtimeExtentArgument(runtime_extent_max));
40 try testing.expectError(error.ExtentOverflowsIndexRange, runtimeExtentArgument(0));
41 try testing.expectError(error.ExtentOverflowsIndexRange, runtimeExtentArgument(runtime_extent_max + 1));
42 }
43
44 test "block count limit rejects oversized extents without overflowing" {
45 try testing.expect(blockCountWithinLimit(1, 32, 4));
46 try testing.expect(blockCountWithinLimit(128, 32, 4));
47 try testing.expect(!blockCountWithinLimit(129, 32, 4));
48 try testing.expect(!blockCountWithinLimit(std.math.maxInt(u64), 32, 1024));
49 try testing.expect(!blockCountWithinLimit(1, 0, 1024));
50 }