// Portable GPU kernel for string_matching.wildcard_match.
// Bindings: 0 params(len_a, len_b), 1 pattern, 2 input, 3 result u32.
@group(0) @binding(1) var<storage, read> pattern_words: array<u32>;
@group(0) @binding(2) var<storage, read> input_words: array<u32>;
@group(0) @binding(3) var<storage, read_write> result: array<u32>;
fn packed_byte(words: ptr<storage, array<u32>, read>, index: u32) -> u32 {
return ((*words)[index >> 2u] >> ((index & 3u) << 3u)) & 0xffu;
}
fn pbyte(index: u32) -> u32 { return packed_byte(&pattern_words, index); }
fn ibyte(index: u32) -> u32 { return packed_byte(&input_words, index); }
fn next_token(pc: u32) -> u32 {
if (pc < params.len_a && pbyte(pc) == 92u && pc + 1u < params.len_a) { return pc + 2u; }
return pc + 1u;
}
fn is_star(pc: u32) -> bool {
return pc < params.len_a && pbyte(pc) == 42u;
}
fn token_matches(pc: u32, input_index: u32) -> bool {
let b = pbyte(pc);
if (b == 92u && pc + 1u < params.len_a) { return pbyte(pc + 1u) == ibyte(input_index); }
if (b == 63u) { return true; }
return b == ibyte(input_index);
}
fn matches() -> bool {
var p = 0u;
var i = 0u;
var star = 0xffffffffu;
var retry = 0u;
loop {
if (i >= params.len_b) { break; }
if (p < params.len_a && is_star(p)) {
star = p;
p = p + 1u;
while (p < params.len_a && is_star(p)) { p = p + 1u; }
retry = i;
continue;
}
if (p < params.len_a && token_matches(p, i)) {
p = next_token(p);
i = i + 1u;
continue;
}
if (star != 0xffffffffu) {
p = star + 1u;
while (p < params.len_a && is_star(p)) { p = p + 1u; }
retry = retry + 1u;
i = retry;
continue;
}
return false;
}
while (p < params.len_a && is_star(p)) { p = p + 1u; }
return p == params.len_a;
}
@compute @workgroup_size(1, 1, 1)
fn string_matching_wildcard_match(@builtin(global_invocation_id) id: vec3<u32>) {
if (id.x == 0u) { result[0] = select(0u, 1u, matches()); }
}