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 }