# Quickstart

> NumKong for C

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

int main(void) {
    nk_f32_t a[] = {1, 2, 3};
    nk_f32_t b[] = {4, 5, 6};
    nk_f64_t dot = 0;
    nk_capability_t capabilities = nk_cap_serial_k;
    nk_cpu_capabilities_enabled(&capabilities); // the capabilities this CPU runs and this build holds
    nk_cpu_configure_thread(capabilities);
    nk_status_t status = nk_dot_f32_best(a, b, 3, &dot, capabilities, NULL); // widened f32 → f64 output
    printf("dot=%f, %s\n", dot, nk_status_name(status));
    return status != nk_success_k;
}
```

Every operation has one such dispatch point, named with `_best`, which runs the best capability in the mask it gets; the root README describes [the dispatch model](https://github.com/ashvardanian/NumKong/blob/main/README.md#dispatch-points--capability-masks) once.

### The C ABI

The C ABI keeps the operation family, input dtype, and output policy visible in the symbol name.
That makes widening obvious at the call site.

```c
#include <numkong/numkong.h>

nk_i8_t a[1536];
nk_i8_t b[1536];
nk_i32_t dot = 0;     // widened from int8 storage
nk_f32_t l2 = 0;      // widened from int8 storage

nk_dot_i8_best(a, b, 1536, &dot, capabilities, NULL);
nk_euclidean_i8_best(a, b, 1536, &l2, capabilities, NULL);
```

The examples below pass the `capabilities` of the Quickstart and a null stream, as every CPU call does.
Each capability kernel, like `nk_dot_i8_haswell`, is also callable directly with the same arguments short of the mask.
To resolve a kernel once and call it many times without naming a capability, library builds provide the punned finder:

```c
nk_metric_dense_punned_t angular = 0;
nk_capability_t capability = 0;
nk_find_kernel_punned(nk_kernel_angular_k, nk_f32_k, capabilities, (nk_kernel_punned_t *)&angular, &capability);

nk_f32_t a[768], b[768];
nk_f64_t result = 0; // widened f32 → f64 output
angular(a, b, 768, &result, NULL);
```

That is the lowest-level dynamic path.
The typed C++ wrappers usually read better unless you are building your own dispatch layer.

`#include <numkong/types.h>`

## nk_status_t

Outcome of every NumKong call that can fail: zero on success, negative when nothing was written.

```c
enum nk_status_t
```

Positive values are reserved for results written with a caveat.

Statuses fall into three categories, with no interruptions or defects to report. Resources: [`nk_bad_alloc_k`](#nk_bad_alloc_k), [`nk_missing_gpu_k`](#nk_missing_gpu_k), [`nk_device_code_mismatch_k`](#nk_device_code_mismatch_k), [`nk_missing_kernel_k`](#nk_missing_kernel_k) and [`nk_missing_library_k`](#nk_missing_library_k). Input: [`nk_unexpected_dimensions_k`](#nk_unexpected_dimensions_k), [`nk_device_memory_mismatch_k`](#nk_device_memory_mismatch_k) and [`nk_misaligned_k`](#nk_misaligned_k). State: [`nk_pack_mismatch_k`](#nk_pack_mismatch_k). Any verb that allocates, binds a device or touches a file may also return a Resources status. A verb's own block lists only what its contract adds.

- `nk_success_k` = `0`: Scheduled, or finished, without error.
- `nk_bad_alloc_k` = `-10`: The queue could not take more memory, or record another block.
- `nk_unexpected_dimensions_k` = `-15`: Operand shapes contradict each other, like head counts that don't divide.
- `nk_missing_gpu_k` = `-16`: No GPU of the vendor this build targets answers.
- `nk_device_code_mismatch_k` = `-17`: The device code lacks the kernel, or it failed to build, launch or finish.
- `nk_device_memory_mismatch_k` = `-18`: An operand lies in memory the device cannot address.
- `nk_missing_kernel_k` = `-19`: No capability in the capability mask has this kernel.
- `nk_misaligned_k` = `-20`: An operand or stride breaks the alignment contract.
- `nk_pack_mismatch_k` = `-21`: The buffer was packed by another capability or layout than the one reading it.
- `nk_missing_library_k` = `-22`: A dispatch point or finder called from a header-only build, which links no library.

Spellings: ```
char const * nk_status_name(nk_status_t status);
```

