# Runtime Dispatch

> StringZilla for C

Every kernel exists in a serial form plus one or more per-ISA forms, named with a backend suffix (`_serial`, `_westmere`, `_goldmont`, `_haswell`, `_skylake`, `_icelake`, `_neon`, `_neonaes`, `_neonsha`, `_sve`, `_sve2`, `_sve2aes`, `_v128`, `_v128relaxed`, `_rvv`, `_rvvcrypto`, `_loongsonasx`, `_powervsx`), and the engines add one per GPU vendor, `_cuda`, `_rocm` and `_metal`.
Each verb also has a dispatch point, like `sz_find_best` or `sz_hash_best`, taking the kernels' arguments plus a capability mask before the trailing stream, and running the best capability the mask shares with the verb's list, `serial` first on the CPU.
It returns `sz_missing_kernel_k` when no capability in the mask has the kernel, as a GPU-only mask does for a CPU-only verb.

- __Library builds, `STRINGZILLA_HEADER_ONLY=0`, the default.__
  Every capability the toolchain builds is compiled into one binary, and the dispatch points pick among them by the mask each call passes.
  This is how the prebuilt libraries ship, so a single binary runs optimally on any CPU.
- __Header-only builds, `STRINGZILLA_HEADER_ONLY=1`.__
  The kernels your compiler flags enable inline into your translation unit, so calling one of them by name, like `sz_find_haswell`, costs no indirection at all.
  The dispatch points and finders compile to stubs returning `sz_missing_library_k`, while the C++ layer runs the serial kernels over its default mask, which is empty here.

Capabilities are introspectable at both compile and run time.
`sz_capability_t` is a 64-bit mask from `capabilities.h`, one bit per capability.
Within each architecture the bits ascend by preference, so the highest bit a mask shares with a verb's kernels names the kernel to run.

- __Serial__: `sz_cap_serial_k`, bit 0, which every CPU runs.
- __x86__: `sz_cap_westmere_k`, `sz_cap_goldmont_k`, `sz_cap_haswell_k`, `sz_cap_skylake_k`, `sz_cap_icelake_k`.
- __Arm__: `sz_cap_neon_k`, `sz_cap_neonaes_k`, `sz_cap_neonsha_k`, `sz_cap_sve_k`, `sz_cap_sve2_k`, `sz_cap_sve2aes_k`.
- __RISC-V__: `sz_cap_rvv_k`, `sz_cap_rvvcrypto_k`.
- __WebAssembly__: `sz_cap_v128_k`, `sz_cap_v128relaxed_k`.
- __LoongArch and Power__: `sz_cap_loongsonasx_k`, `sz_cap_powervsx_k`.
- __GPUs__: one baseline per vendor above every CPU bit, `sz_cap_cuda_k` at bit 48, `sz_cap_rocm_k` at 56, and `sz_cap_metal_k` at 60.
  CUDA generations follow its baseline: `sz_cap_hopper_k` at 51 for clusters from compute capability 9.0, and `sz_cap_blackwell_k` at 52 for cluster launch control from 10.0.

`sz_cap_cpus_k` and `sz_cap_gpus_k` group the CPU and the GPU bits, and `sz_cap_any_k` sets every bit.

```c
sz_status_t sz_capabilities_detected_cpu(sz_capability_t *capabilities); // what this CPU runs
sz_status_t sz_capabilities_compiled_cpu(sz_capability_t *capabilities); // what this build holds kernels for
sz_capability_t sz_capabilities_compiled_cpu_mask(void);                 // the same, constant in the calling unit
sz_status_t sz_capabilities_enabled_cpu(sz_capability_t *capabilities);  // both at once, always with serial
sz_status_t sz_thread_configure_cpu(sz_capability_t capabilities);       // once per dispatching thread
sz_status_t sz_device_count_cuda(sz_size_t *count);
sz_status_t sz_capabilities_detected_cuda(sz_size_t ordinal, sz_capability_t *capabilities);
sz_status_t sz_capabilities_compiled_cuda(sz_capability_t *capabilities);
sz_status_t sz_capabilities_enabled_cuda(sz_size_t ordinal, sz_capability_t *capabilities);
sz_size_t sz_capabilities_name(sz_capability_t capabilities, char *buffer, sz_size_t capacity); // "serial,haswell"
char const *sz_status_name(sz_status_t status);
```

ROCm and Metal have the same four queries, spelled `sz_rocm_*` and `sz_metal_*`.
The library probes the CPU once per process and caches the answer, while header-only builds probe on every call.
The GPU queries ask the vendor's runtime every time, by that runtime's own device ordinal, and report no devices where the vendor isn't built.
The CPU probe inspects CPUID on x86, the AArch64 ID registers on Arm once the kernel's `HWCAP_CPUID` says it emulates `mrs`, falling back to NEON-only, `getauxval`/`riscv_hwprobe` on RISC-V, and the auxiliary-vector HWCAPs on LoongArch and Power.
Detection always reports the full hardware truth, independent of which tiers a build compiled in; `sz_capabilities_enabled_cpu()` intersects it with the compile-time mask.
Where the OS cannot be asked, detection reports only the capabilities the compiler's own flags guarantee, never the compiled ones, which the CPU may lack.
WebAssembly is the exception with no runtime probe at all — a module carrying unsupported SIMD opcodes fails validation at instantiation, so its capabilities are fixed at compile time.
Nothing is process-wide: narrowing the mask a call passes narrows the choice, so `capabilities & ~sz_cap_sve_k` skips SVE and `sz_cap_serial_k` alone runs the reference kernel.
A host-only process never starts a GPU driver, as only the GPU queries and the engines built for a GPU reach one.
`sz_thread_configure_cpu` prepares the calling thread for the capabilities it is given, and only those; every current capability needs nothing, so it is a no-op today, kept so bindings call it where NumKong's call theirs.

On Arm, having SVE in the capability mask doesn't mean SVE kernels always win: at the common 128-bit vector length the scalable kernels for length-sensitive operations — comparisons, memory transforms, substring search, UTF-8 token scanning — are often slower than their NEON twins, while crypto-heavy operations like hashing prefer SVE2 at any width.
So each such SVE kernel measures the register width on the running CPU (`svcntb`) and hands the 128-bit case to its NEON twin, and the dispatch point needs no special case.
To force a specific backend regardless, narrow the mask or call its kernel directly.

CMake, which every binding builds through, probes which capabilities the toolchain can __compile__: each capability's probe, `probes/<capability>.c`, calls one of its kernels, compiled header-only at the baseline flags as the library compiles it.
Each capability's headers scope its kernels with a target pragma, on every platform; LASX and POWER9 need GCC 15 or newer for that, as Clang's `lasxintrin.h` and `altivec.h` stay closed without `-mlasx` and `-mcpu=power9`.
Libraries compile every capability the toolchain builds and leave the rest to the mask each call passes; header-only builds enable the capabilities their own flags name.
`-D STRINGZILLA_TARGET_<CAPABILITY>=0` drops a capability from the libraries, and `=1` keeps one only where its probe compiles.

```c
#include <stdio.h>
#include <stringzilla/stringzilla.h>

int main(void) {
    sz_capability_t caps;
    sz_capabilities_enabled_cpu(&caps);
    char names[STRINGZILLA_CAPABILITIES_NAME_CAPACITY];
    sz_capabilities_name(caps, names, sizeof(names));
    printf("StringZilla %d.%d.%d, backends: %s\n", sz_version_major(), sz_version_minor(), sz_version_patch(), names);
    return 0;
}
```

You can also call any capability's kernel directly, with the same arguments short of the mask, when you have already established the target supports it — for example `sz_find_haswell(...)` or `sz_hash_icelake(...)` — which is handy for benchmarking and for pinning a code path in a controlled environment.

Picking a capability costs about a nanosecond per call: noise for long inputs, but not for hot short-string paths, like a sort's comparator or a per-token byte search.
There, call a capability's kernel directly, like `sz_order_neon` or `sz_find_byte_haswell`, or resolve one once through `sz_find_kernel_punned`, and call it many times:

```c
sz_kernel_order_t order = NULL;
sz_capability_t capability = 0;
sz_find_kernel_punned(sz_kernel_order_k, caps, (sz_kernel_punned_t *)&order, &capability);

sz_ordering_t ordering;
order("apple", 5, "banana", 6, &ordering, NULL);
```

It picks exactly what the dispatch point picks for the same mask, and returns `sz_missing_kernel_k` when no capability in the mask has the kernel.
Each family exports its own finder over its kinds, like `sz_compare_find_kernel` in `compare.h`, and `sz_find_kernel_punned` covers every family through one entry point.
Every verb has a kind, `sz_kernel_<verb>_k`, and a pointer type to cast the result to, `sz_kernel_<verb>_t`, taking the dispatch point's arguments short of the mask.
`sz_kernel_name` spells a kind without its `sz_kernel_` prefix and `_k` suffix, like `"find_byte"`, and `sz_kernel_named` maps such a name back, or to `sz_kernel_unknown_k`.
Verbs of one shape share a type, like `sz_kernel_find_t` for both `sz_kernel_find_k` and `sz_kernel_rfind_k`, `sz_kernel_utf8_segmenter_t` for the four tiling UTF-8 segmenters, and `sz_kernel_utf8_tokenizer_t` for the newline, whitespace and delimiter finders.
In C++, every wrapper that takes a mask, like `sz::lookup` or `sz::argsort`, defaults to `sz::default_capabilities()`, the enabled CPU mask, while `sz::device_t::make(kind, ordinal)` opens one GPU to ask its `capabilities_enabled()`, and `sz::device_t::cpu().configure_thread(mask)` wraps `sz_thread_configure_cpu`.

`#include <stringzilla/types.h>`

`#include <stringzilla/capabilities.h>`

## sz_stream_t

Native CUDA cudaStream_t, ROCm hipStream_t, or Metal MTLCommandQueue handle.

```c
typedef void * sz_stream_t;
```

Null selects the current device's default CUDA/ROCm stream, Metal's default device queue, or synchronous execution on the CPU. The caller owns the handle.

## sz_capability_t

64-bit bitmask of the capabilities of one device.

```c
typedef sz_u64_t sz_capability_t;
```

## sz_kernel_kind_t

Every dispatch point a finder can resolve: one kind per verb, grouped by family.

```c
enum sz_kernel_kind_t
```

- `sz_kernel_unknown_k` = `0`: No kernel: what a finder resolves nothing for.
- `sz_kernel_equal_k`: Byte-wise equality of two equal-length strings.
- `sz_kernel_order_k`: Lexicographic three-way comparison.
- `sz_kernel_strings_to_tape_k`: Gather strings into a tape.
- `sz_kernel_strings_to_rows_k`: Write strings into NUL-padded rows.
- `sz_kernel_strings_escape_k`: Escape strings for a text format.
- `sz_kernel_strings_unescape_k`: Unescape strings from a text format.
- `sz_kernel_strings_lookup_k`: Map every byte of every string through a 256-entry table.
- `sz_kernel_strings_normalize_k`: Bring strings into a Unicode normalization form.
- `sz_kernel_strings_split_k`: Split a text at the bytes of a set into a tape.
- `sz_kernel_strings_split_lines_k`: Split a text at Unicode line breaks into a tape.
- `sz_kernel_strings_join_k`: Join columns of strings with frames around and between their rows.
- `sz_kernel_find_k`: First occurrence of a substring.
- `sz_kernel_rfind_k`: Last occurrence of a substring.
- `sz_kernel_find_byte_k`: First occurrence of a byte.
- `sz_kernel_rfind_byte_k`: Last occurrence of a byte.
- `sz_kernel_find_byteset_k`: First byte belonging to a set.
- `sz_kernel_rfind_byteset_k`: Last byte belonging to a set.
- `sz_kernel_find_strings_k`: First occurrence of a substring in every string of a collection.
- `sz_kernel_bytesum_k`: Sum of all bytes.
- `sz_kernel_hash_k`: One-shot 64-bit hash.
- `sz_kernel_hash_multiseed_k`: One string hashed under several seeds at once.
- `sz_kernel_hash_strings_k`: Every string of a collection hashed under one seed.
- `sz_kernel_fill_random_k`: Pseudo-random bytes from a seed.
- `sz_kernel_hash_state_init_k`: Streaming hash state initialization.
- `sz_kernel_hash_state_update_k`: Streaming hash state update.
- `sz_kernel_hash_state_digest_k`: Streaming hash state digest.
- `sz_kernel_sha256_state_init_k`: SHA-256 state initialization.
- `sz_kernel_sha256_state_update_k`: SHA-256 state update.
- `sz_kernel_sha256_state_digest_k`: SHA-256 state digest.
- `sz_kernel_sha256_multistate_update_k`: SHA-256 update of many independent states.
- `sz_kernel_sha256_multistate_digest_k`: SHA-256 digest of many independent states.
- `sz_kernel_aes256_key_init_k`: AES-256 key schedule.
- `sz_kernel_aes256_gcm_key_init_k`: AES-256-GCM key schedule and hash subkey.
- `sz_kernel_aes256_ctr_xor_k`: AES-256 counter-mode keystream XOR.
- `sz_kernel_aes256_gcm_encrypt_k`: One-shot AES-256-GCM encryption.
- `sz_kernel_aes256_gcm_decrypt_k`: One-shot AES-256-GCM decryption with tag verification.
- `sz_kernel_aes256_gcm_encryptor_init_k`: Streaming AES-256-GCM encryptor initialization.
- `sz_kernel_aes256_gcm_encryptor_associate_k`: Streaming AES-256-GCM encryptor associated data.
- `sz_kernel_aes256_gcm_encryptor_update_k`: Streaming AES-256-GCM encryptor update.
- `sz_kernel_aes256_gcm_encryptor_digest_k`: Streaming AES-256-GCM encryptor tag.
- `sz_kernel_aes256_gcm_decryptor_init_k`: Streaming AES-256-GCM decryptor initialization.
- `sz_kernel_aes256_gcm_decryptor_associate_k`: Streaming AES-256-GCM decryptor associated data.
- `sz_kernel_aes256_gcm_decryptor_update_unverified_k`: Streaming AES-256-GCM decryptor update, before verification.
- `sz_kernel_aes256_gcm_decryptor_verify_k`: Streaming AES-256-GCM decryptor tag verification.
- `sz_kernel_sort_order_k`: Stable argsort of a collection of strings.
- `sz_kernel_sort_uncased_order_k`: Stable case-insensitive argsort of a collection of strings.
- `sz_kernel_intersect_k`: Intersection of two collections of strings.
- `sz_kernel_utf8_count_k`: Count of UTF-8 runes.
- `sz_kernel_utf8_count_strings_k`: Validation and rune count of every string of a collection.
- `sz_kernel_utf8_seek_k`: Offset of the n-th UTF-8 rune.
- `sz_kernel_utf8_decode_k`: Batch UTF-8 decoding into code points.
- `sz_kernel_utf8_newlines_k`: Newline boundaries.
- `sz_kernel_utf8_whitespaces_k`: Whitespace boundaries.
- `sz_kernel_utf8_delimiters_k`: Delimiter boundaries.
- `sz_kernel_utf8_wordbreaks_k`: Unicode word boundaries.
- `sz_kernel_utf8_graphemes_k`: Unicode grapheme cluster boundaries.
- `sz_kernel_utf8_sentences_k`: Unicode sentence boundaries.
- `sz_kernel_utf8_linebreaks_k`: Unicode line-break opportunities.
- `sz_kernel_utf8_norm_k`: Unicode normalization.
- `sz_kernel_utf8_find_denormalized_k`: First byte not in the requested normalization form.
- `sz_kernel_utf8_uncased_fold_k`: Unicode case folding.
- `sz_kernel_utf8_uncased_needle_init_k`: Needle analysis for case-insensitive substring search.
- `sz_kernel_utf8_uncased_search_k`: Case-insensitive substring search.
- `sz_kernel_utf8_uncased_order_k`: Case-insensitive three-way comparison.
- `sz_kernel_utf8_find_cased_k`: First rune that has a case.
- `sz_kernel_levenshtein_engine_init_k`: Levenshtein engine preparation.
- `sz_kernel_levenshtein_distances_k`: Levenshtein distances of a batch against the prepared queries.
- `sz_kernel_overlap_engine_init_k`: Overlap engine preparation.
- `sz_kernel_overlap_scores_k`: Overlap scores of a batch against the prepared queries.
- `sz_kernel_substrings_engine_init_k`: Substrings engine preparation.
- `sz_kernel_substrings_contains_k`: Haystacks holding any of the prepared needles.
- `sz_kernel_substrings_counts_k`: Occurrence counts of the prepared needles.
- `sz_kernel_substrings_find_k`: Occurrences of the prepared needles.
- `sz_kernel_substrings_replace_k`: Replacement of the prepared needles.
- `sz_kernel_substrings_bm25_scores_k`: BM25 scores of the prepared needles.
- `sz_kernel_regex_engine_init_k`: Regex engine preparation.
- `sz_kernel_regex_contains_k`: Haystacks matching any of the prepared patterns.
- `sz_kernel_regex_counts_k`: Match counts of the prepared patterns.
- `sz_kernel_regex_find_k`: Matches of the prepared patterns.
- `sz_kernel_regex_replace_k`: Replacement of the prepared patterns' matches, naming their groups.
- `sz_kernel_regex_extract_k`: Groups of one prepared pattern's first match per haystack.
- `sz_kernel_subdocuments_engine_init_k`: Subdocuments engine preparation.
- `sz_kernel_subdocuments_contains_k`: Documents holding a node any of the prepared paths selects.
- `sz_kernel_subdocuments_counts_k`: Match counts of the prepared paths.
- `sz_kernel_subdocuments_find_k`: Matches of the prepared paths.

## sz_kernel_punned_t

Any kernel, cast back to its signature before the call.

```c
typedef void(*) sz_kernel_punned_t(void);
```

## sz_kernel_name

Canonical name of a kernel kind - the spelling bindings parse and interchange formats carry; "unknown" for unrecognized values.

```c
char const * sz_kernel_name(sz_kernel_kind_t kind);
```

## sz_kernel_named

Inverse of [`sz_kernel_name`](#sz_kernel_name) over an explicit-length string; [`sz_kernel_unknown_k`](#sz_kernel_unknown_k) for unrecognized names.

```c
sz_kernel_kind_t sz_kernel_named(char const *name, sz_size_t length);
```

## sz_capabilities_compiled_cpu_mask

The capabilities whose kernels the `STRINGZILLA_TARGET_*` macros of the including unit compile, as a constant for consumers picking kits at compile time; in the library, the mask `sz_capabilities_compiled_cpu` reports.

```c
sz_capability_t sz_capabilities_compiled_cpu_mask(void);
```

Says nothing about the current CPU.

## sz_thread_configure_cpu

Prepares the calling thread for the kernels of `capabilities`, and only those.

```c
sz_status_t sz_thread_configure_cpu(sz_capability_t capabilities);
```

Call it once on each thread that dispatches. Every current capability needs nothing, so today it returns right away.

- `capabilities` (in): The capabilities to prepare for, like `sz_capabilities_enabled_cpu`.

## sz_capabilities_name

Writes `capabilities` as a comma-separated name list such as "serial,haswell,skylake".

```c
sz_size_t sz_capabilities_name(
    sz_capability_t capabilities,
    char *buffer,
    sz_size_t capacity);
```

- `capabilities` (in): The mask to name, like `sz_capabilities_detected_cpu` reports.
- `buffer` (out): Destination, always null-terminated; the list is truncated to fit.
- `capacity` (in): Size of `buffer`, like [`STRINGZILLA_CAPABILITIES_NAME_CAPACITY`](#STRINGZILLA_CAPABILITIES_NAME_CAPACITY); a zero capacity writes nothing.

## sz_find_kernel_punned

Finds the kernel of `kind` that its dispatch point would run for `capabilities`, to resolve it once and call it many times.

```c
sz_status_t sz_find_kernel_punned(
    sz_kernel_kind_t kind,
    sz_capability_t capabilities,
    sz_kernel_punned_t *kernel,
    sz_capability_t *capability);
```

- `kind` (in): What functionality, like [`sz_kernel_find_k`](#sz_kernel_find_k).
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `kernel` (out): The kernel, cast back to its `[sz_kernel_find_t](https://www.unum.cloud/docs/stringzilla/c/searching-and-counting.md#sz_kernel_find_t)` or sibling before the call, or null when none of `capabilities` has it.
- `capability` (out): The capability the kernel belongs to, or zero.

Statuses: - [`sz_missing_kernel_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_kernel_k) No capability in `capabilities` has it.
- [`sz_missing_library_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_library_k) Header-only builds.

## sz_stream_synchronize_best

Waits for everything enqueued on `stream`, after which what its rounds wrote is readable from the host.

```c
sz_status_t sz_stream_synchronize_best(
    sz_capability_t capabilities,
    sz_stream_t stream);
```

- `sz_stream_synchronize` backends: serial

- `capabilities` (in): One device's capabilities; its group picks the runtime that waits.
- `stream` (in): Null on the CPU, which has nothing to wait for. On a GPU, the stream to join, which also names the device, or null for the default stream of the default device.

Statuses: - [`sz_device_memory_mismatch_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_device_memory_mismatch_k) On a device, a `stream` it cannot use.
- [`sz_missing_gpu_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_gpu_k) A vendor this build lacks.

## sz_device_count_cuda

Counts the CUDA devices the process sees.

```c
sz_status_t sz_device_count_cuda(sz_size_t *count);
```

- `count` (out): The number of devices, zero without one.

Statuses: - [`sz_missing_gpu_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_gpu_k) Without one.

## sz_capabilities_detected_cuda

Reports the capabilities CUDA device `ordinal` runs.

```c
sz_status_t sz_capabilities_detected_cuda(
    sz_size_t ordinal,
    sz_capability_t *capabilities);
```

- `ordinal` (in): The CUDA runtime's device index, like `cudaSetDevice` takes.
- `capabilities` (out): The CUDA baseline and what the device runs, zero on failure.

Statuses: - [`sz_missing_gpu_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_gpu_k) Past the last device.

## sz_capabilities_compiled_cuda

Reports the CUDA capabilities this binary holds kernels for.

```c
sz_status_t sz_capabilities_compiled_cuda(
    sz_capability_t *capabilities);
```

- `capabilities` (out): The CUDA capabilities compiled in, zero without any.

## sz_capabilities_enabled_cuda

Reports the capabilities CUDA device `ordinal` runs that this binary holds kernels for.

```c
sz_status_t sz_capabilities_enabled_cuda(
    sz_size_t ordinal,
    sz_capability_t *capabilities);
```

- `ordinal` (in): The CUDA runtime's device index, like `cudaSetDevice` takes.
- `capabilities` (out): The CUDA baseline and what the device runs, zero on failure.

Statuses: - [`sz_missing_gpu_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_gpu_k) Past the last device.

## sz_stream_init_cuda

Creates a stream on CUDA device `ordinal` with `cudaStreamCreate`.

```c
sz_status_t sz_stream_init_cuda(sz_size_t ordinal, sz_stream_t *stream);
```

## sz_stream_free_cuda

Destroys a stream of [sz_stream_init_cuda](#sz_stream_init_cuda) with `cudaStreamDestroy`, once its work ends.

```c
sz_status_t sz_stream_free_cuda(sz_stream_t stream);
```

## sz_device_count_rocm

Counts the ROCm devices the process sees.

```c
sz_status_t sz_device_count_rocm(sz_size_t *count);
```

- `count` (out): The number of devices, zero without one.

Statuses: - [`sz_missing_gpu_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_gpu_k) Without one.

## sz_capabilities_detected_rocm

Reports the capabilities ROCm device `ordinal` runs.

```c
sz_status_t sz_capabilities_detected_rocm(
    sz_size_t ordinal,
    sz_capability_t *capabilities);
```

- `ordinal` (in): The HIP runtime's device index, like `hipSetDevice` takes.
- `capabilities` (out): The ROCm baseline and what the device runs, zero on failure.

Statuses: - [`sz_missing_gpu_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_gpu_k) Past the last device.

## sz_capabilities_compiled_rocm

Reports the ROCm capabilities this binary holds kernels for.

```c
sz_status_t sz_capabilities_compiled_rocm(
    sz_capability_t *capabilities);
```

- `capabilities` (out): The ROCm capabilities compiled in, zero without any.

## sz_capabilities_enabled_rocm

Reports the capabilities ROCm device `ordinal` runs that this binary holds kernels for.

```c
sz_status_t sz_capabilities_enabled_rocm(
    sz_size_t ordinal,
    sz_capability_t *capabilities);
```

- `ordinal` (in): The HIP runtime's device index, like `hipSetDevice` takes.
- `capabilities` (out): The ROCm baseline and what the device runs, zero on failure.

Statuses: - [`sz_missing_gpu_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_gpu_k) Past the last device.

## sz_stream_init_rocm

Creates a stream on ROCm device `ordinal` with `hipStreamCreate`.

```c
sz_status_t sz_stream_init_rocm(sz_size_t ordinal, sz_stream_t *stream);
```

## sz_stream_free_rocm

Destroys a stream of [sz_stream_init_rocm](#sz_stream_init_rocm) with `hipStreamDestroy`, once its work ends.

```c
sz_status_t sz_stream_free_rocm(sz_stream_t stream);
```

## sz_device_count_metal

Counts the Metal devices the system lists.

```c
sz_status_t sz_device_count_metal(sz_size_t *count);
```

- `count` (out): The number of devices, zero without one.

Statuses: - [`sz_missing_gpu_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_gpu_k) Without one.

## sz_capabilities_detected_metal

Reports the capabilities Metal device `ordinal` runs.

```c
sz_status_t sz_capabilities_detected_metal(
    sz_size_t ordinal,
    sz_capability_t *capabilities);
```

- `ordinal` (in): The device's position in the order the system lists them.
- `capabilities` (out): The Metal baseline when the device supports it, zero otherwise.

Statuses: - [`sz_missing_gpu_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_gpu_k) Past the last device.

## sz_capabilities_compiled_metal

Reports the Metal capabilities this binary holds kernels for.

```c
sz_status_t sz_capabilities_compiled_metal(
    sz_capability_t *capabilities);
```

- `capabilities` (out): The Metal capabilities compiled in, zero without any.

## sz_capabilities_enabled_metal

Reports the capabilities Metal device `ordinal` runs that this binary holds kernels for.

```c
sz_status_t sz_capabilities_enabled_metal(
    sz_size_t ordinal,
    sz_capability_t *capabilities);
```

- `ordinal` (in): The device's position in the order the system lists them.
- `capabilities` (out): The Metal baseline when the device supports it, zero otherwise.

Statuses: - [`sz_missing_gpu_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_missing_gpu_k) Past the last device.

## sz_stream_init_metal

Opens an `id<MTLCommandQueue>` stream on Metal device `ordinal` with `newCommandQueue`.

```c
sz_status_t sz_stream_init_metal(
    sz_size_t ordinal,
    sz_stream_t *stream);
```

## sz_stream_free_metal

Waits for a queue of [sz_stream_init_metal](#sz_stream_init_metal), then releases it.

```c
sz_status_t sz_stream_free_metal(sz_stream_t stream);
```

## STRINGZILLA_CAPABILITIES_NAME_CAPACITY

Buffer size [`sz_capabilities_name`](#sz_capabilities_name) never overruns, including its null terminator.

```c
#define STRINGZILLA_CAPABILITIES_NAME_CAPACITY 256
```

## sz_cap_serial_k

Serial (non-SIMD) fallback capability.

```c
#define sz_cap_serial_k ((sz_capability_t)1)
```

Always available.

## sz_cap_any_k

Mask representing any capability.

```c
#define sz_cap_any_k (~(sz_capability_t)0)
```

## sz_cap_westmere_k

x86 SSE4.2 with AES-NI, carry-less multiplication, BMI and LZCNT, as on Westmere.

```c
#define sz_cap_westmere_k ((sz_capability_t)1 <<1)
```

## sz_cap_goldmont_k

x86 SSSE3 and SSE4.1 with the SHA extensions, as on Goldmont.

```c
#define sz_cap_goldmont_k ((sz_capability_t)1 <<2)
```

## sz_cap_haswell_k

x86 AVX2 with FMA, BMI2, POPCNT and LZCNT, as on Haswell.

```c
#define sz_cap_haswell_k ((sz_capability_t)1 <<3)
```

## sz_cap_skylake_k

x86 AVX-512 F, VL, BW and DQ with AES-NI, as on Skylake servers.

```c
#define sz_cap_skylake_k ((sz_capability_t)1 <<4)
```

## sz_cap_icelake_k

x86 AVX-512 VBMI, VBMI2 and VNNI with VAES, VPCLMULQDQ and SHA, as on Ice Lake.

```c
#define sz_cap_icelake_k ((sz_capability_t)1 <<5)
```

## sz_cap_neon_k

Arm NEON, the Advanced SIMD of every Armv8.0-A core.

```c
#define sz_cap_neon_k ((sz_capability_t)1 <<6)
```

## sz_cap_neonaes_k

Arm NEON with the AES instructions, optional since Armv8.0-A.

```c
#define sz_cap_neonaes_k ((sz_capability_t)1 <<7)
```

## sz_cap_neonsha_k

Arm NEON with the SHA2 instructions, optional since Armv8.0-A.

```c
#define sz_cap_neonsha_k ((sz_capability_t)1 <<8)
```

## sz_cap_sve_k

Arm SVE, the Scalable Vector Extension, optional since Armv8.2-A.

```c
#define sz_cap_sve_k ((sz_capability_t)1 <<9)
```

## sz_cap_sve2_k

Arm SVE2, optional since Armv9.0-A.

```c
#define sz_cap_sve2_k ((sz_capability_t)1 <<10)
```

## sz_cap_sve2aes_k

Arm SVE2 with its AES instructions.

```c
#define sz_cap_sve2aes_k ((sz_capability_t)1 <<11)
```

## sz_cap_rvv_k

RISC-V Vector extension 1.0, with length-agnostic registers.

```c
#define sz_cap_rvv_k ((sz_capability_t)1 <<12)
```

## sz_cap_rvvcrypto_k

RISC-V Vector Crypto: the Zvkned AES and Zvknhb SHA extensions.

```c
#define sz_cap_rvvcrypto_k ((sz_capability_t)1 <<13)
```

## sz_cap_v128_k

WebAssembly 128-bit SIMD.

```c
#define sz_cap_v128_k ((sz_capability_t)1 <<14)
```

## sz_cap_v128relaxed_k

WebAssembly 128-bit SIMD with the relaxed SIMD instructions.

```c
#define sz_cap_v128relaxed_k ((sz_capability_t)1 <<15)
```

## sz_cap_loongsonasx_k

LoongArch Advanced SIMD eXtension, the 256-bit LASX.

```c
#define sz_cap_loongsonasx_k ((sz_capability_t)1 <<16)
```

## sz_cap_powervsx_k

IBM Power Vector-Scalar eXtension at the POWER9 level, ISA 3.0.

```c
#define sz_cap_powervsx_k ((sz_capability_t)1 <<17)
```

## sz_cap_cuda_k

NVIDIA GPUs through CUDA, on every device.

```c
#define sz_cap_cuda_k ((sz_capability_t)1 <<48)
```

## sz_cap_hopper_k

NVIDIA GPUs from compute capability 9.0, for clusters and their distributed shared memory.

```c
#define sz_cap_hopper_k ((sz_capability_t)1 <<51)
```

## sz_cap_blackwell_k

NVIDIA GPUs from compute capability 10.0, for cluster launch control.

```c
#define sz_cap_blackwell_k ((sz_capability_t)1 <<52)
```

## sz_cap_rocm_k

AMD GPUs through ROCm, on every device.

```c
#define sz_cap_rocm_k ((sz_capability_t)1 <<56)
```

## sz_cap_metal_k

Apple GPUs through Metal, on every device.

```c
#define sz_cap_metal_k ((sz_capability_t)1 <<60)
```

## sz_cap_gpus_k

Every GPU capability above, which the CPU queries never detect, compile or enable.

```c
#define sz_cap_gpus_k (sz_cap_cuda_k | sz_cap_hopper_k | sz_cap_blackwell_k | sz_cap_rocm_k | sz_cap_metal_k)
```

## sz_cap_cpus_k

Every CPU capability, the bits below the first GPU vendor's.

```c
#define sz_cap_cpus_k (sz_cap_cuda_k - 1)
```

