# Dot Products

> NumKong for C

Dot products are one of the broadest parts of the native SDK.
They include real, complex, packed-binary, mini-float, and mixed-precision forms.

```c
nk_f32c_t a[384];
nk_f32c_t b[384];
nk_f64c_t out = {0, 0};         // widened f32c → f64c output

nk_dot_f32c_best(a, b, 384, &out, capabilities, NULL);   // complex inner product
nk_vdot_f32c_best(a, b, 384, &out, capabilities, NULL);  // conjugated variant, like numpy.vdot
```

For quantized retrieval pipelines, the storage format often matters more than the nominal math family.
The native SDK lets you keep the compact representation and still get a widened output.

`#include <numkong/dot.h>`

## nk_dot_*_best

Dot product computing the sum of elementwise products between two vectors.

```c
nk_status_t nk_dot_f32_best(
    nk_f32_t const *a,
    nk_f32_t const *b,
    nk_size_t n,
    nk_f64_t *result,
    nk_capability_t capabilities,
    nk_stream_t stream);
```

- `nk_dot_f32_best`: a, b `nk_f32_t`, result `nk_f64_t`
- `nk_dot_f64_best`: a, b `nk_f64_t`, result `nk_f64_t`
- `nk_dot_f16_best`: a, b `nk_f16_t`, result `nk_f32_t`
- `nk_dot_bf16_best`: a, b `nk_bf16_t`, result `nk_f32_t`
- `nk_dot_i8_best`: a, b `nk_i8_t`, result `nk_i32_t`
- `nk_dot_u8_best`: a, b `nk_u8_t`, result `nk_u32_t`
- `nk_dot_i4_best`: a, b `nk_i4x2_t`, result `nk_i32_t`
- `nk_dot_u4_best`: a, b `nk_u4x2_t`, result `nk_u32_t`
- `nk_dot_e4m3_best`: a, b `nk_e4m3_t`, result `nk_f32_t`
- `nk_dot_e5m2_best`: a, b `nk_e5m2_t`, result `nk_f32_t`
- `nk_dot_e2m3_best`: a, b `nk_e2m3_t`, result `nk_f32_t`
- `nk_dot_e2m1_best`: a, b `nk_e2m1x2_t`, result `nk_f32_t`
- `nk_dot_e3m2_best`: a, b `nk_e3m2_t`, result `nk_f32_t`

- `nk_dot_f32` backends: serial, neon, sve, haswell, skylake, rvv, v128relaxed, powervsx, loongsonasx
- `nk_dot_f64` backends: serial, neon, sve, haswell, skylake, rvv, v128relaxed, powervsx, loongsonasx
- `nk_dot_f16` backends: serial, neon, neonfhm, svehalf, haswell, skylake, diamond, rvv, rvvhalf, v128relaxed, powervsx, loongsonasx
- `nk_dot_bf16` backends: serial, neon, neonbfdot, svebfdot, haswell, skylake, genoa, rvv, rvvbf16, v128, v128relaxed, powervsx, loongsonasx
- `nk_dot_i8` backends: serial, neonsdot, svesdot, haswell, skylake, icelake, alder, sierra, rvv, v128, v128relaxed, powervsx, loongsonasx
- `nk_dot_u8` backends: serial, neonsdot, svesdot, haswell, skylake, icelake, alder, sierra, rvv, v128, v128relaxed, powervsx, loongsonasx
- `nk_dot_i4` backends: serial, neonsdot, haswell, icelake, rvv, v128relaxed
- `nk_dot_u4` backends: serial, neonsdot, haswell, icelake, rvv, v128relaxed
- `nk_dot_e4m3` backends: serial, neon, neonfhm, neonbfdot, neonfp8, haswell, skylake, icelake, diamond, rvv, rvvhalf, rvvbf16, v128relaxed
- `nk_dot_e5m2` backends: serial, neon, neonfhm, neonbfdot, neonfp8, haswell, skylake, genoa, diamond, rvv, rvvhalf, rvvbf16, v128relaxed
- `nk_dot_e2m3` backends: serial, neon, neonsdot, neonfp8, haswell, skylake, icelake, alder, sierra, rvv, v128relaxed
- `nk_dot_e2m1` backends: serial, neonsdot, haswell, skylake, alder, sierra, rvv, v128relaxed
- `nk_dot_e3m2` backends: serial, neon, neonsdot, neonfp8, haswell, skylake, icelake, rvv, v128relaxed

- `a` (in): The first vector.
- `b` (in): The second vector.
- `n` (in): Counts dimensions, a multiple of the values per byte.
- `result` (out): The output dot product value.
- `capabilities` (in): One device's capabilities, like [`nk_cpu_capabilities_enabled`](https://www.unum.cloud/docs/numkong/c/runtime-dispatch.md#nk_cpu_capabilities_enabled) reports.
- `stream` (in): Null on the CPU, or the GPU stream of that device to queue on.

Notes: The output value can be negative.

Notes: The output value is zero if and only if the two vectors are orthogonal.

Notes: Defined for floating-point, integer, and binary data types.

Statuses: - [`nk_missing_kernel_k`](https://www.unum.cloud/docs/numkong/c/quickstart.md#nk_missing_kernel_k) No capability in `capabilities` has it.

## nk_dot_u1_best

Dot product of two binary vectors, the number of bit positions both set.

```c
nk_status_t nk_dot_u1_best(
    nk_u1x8_t const *a,
    nk_u1x8_t const *b,
    nk_size_t n_bits,
    nk_u32_t *result,
    nk_capability_t capabilities,
    nk_stream_t stream);
```

- `nk_dot_u1` backends: serial, neon, haswell, icelake, rvv, rvvbb, v128, powervsx

- `a` (in): The first vector.
- `b` (in): The second vector.
- `n_bits` (in): Counts dimensions in bits, a multiple of the bits per byte.
- `result` (out): The output dot product value.
- `capabilities` (in): One device's capabilities, like [`nk_cpu_capabilities_enabled`](https://www.unum.cloud/docs/numkong/c/runtime-dispatch.md#nk_cpu_capabilities_enabled) reports.
- `stream` (in): Null on the CPU, or the GPU stream of that device to queue on.

Statuses: - [`nk_missing_kernel_k`](https://www.unum.cloud/docs/numkong/c/quickstart.md#nk_missing_kernel_k) No capability in `capabilities` has it.

## nk_dot_*_best

Complex dot product computing the sum of elementwise products between two complex vectors.

```c
nk_status_t nk_dot_f32c_best(
    nk_f32c_t const *a_pairs,
    nk_f32c_t const *b_pairs,
    nk_size_t count_pairs,
    nk_f64c_t *result,
    nk_capability_t capabilities,
    nk_stream_t stream);
```

- `nk_dot_f32c_best`: a_pairs, b_pairs `nk_f32c_t`, result `nk_f64c_t`
- `nk_dot_f64c_best`: a_pairs, b_pairs `nk_f64c_t`, result `nk_f64c_t`
- `nk_dot_f16c_best`: a_pairs, b_pairs `nk_f16c_t`, result `nk_f32c_t`
- `nk_dot_bf16c_best`: a_pairs, b_pairs `nk_bf16c_t`, result `nk_f32c_t`

- `nk_dot_f32c` backends: serial, neon, sve, haswell, skylake, rvv, v128relaxed
- `nk_dot_f64c` backends: serial, neon, sve, haswell, skylake, rvv, v128relaxed
- `nk_dot_f16c` backends: serial, neon, neonfhm, svehalf, haswell
- `nk_dot_bf16c` backends: serial, neonbfdot, haswell, genoa

- `a_pairs` (in): The first complex vector.
- `b_pairs` (in): The second complex vector.
- `count_pairs` (in): The number of complex pairs in the vectors.
- `result` (out): The output complex value as {real, imag}.
- `capabilities` (in): One device's capabilities, like [`nk_cpu_capabilities_enabled`](https://www.unum.cloud/docs/numkong/c/runtime-dispatch.md#nk_cpu_capabilities_enabled) reports.
- `stream` (in): Null on the CPU, or the GPU stream of that device to queue on.

Statuses: - [`nk_missing_kernel_k`](https://www.unum.cloud/docs/numkong/c/quickstart.md#nk_missing_kernel_k) No capability in `capabilities` has it.

## nk_vdot_*_best

Complex conjugate dot product between two complex vectors.

```c
nk_status_t nk_vdot_f32c_best(
    nk_f32c_t const *a_pairs,
    nk_f32c_t const *b_pairs,
    nk_size_t count_pairs,
    nk_f64c_t *result,
    nk_capability_t capabilities,
    nk_stream_t stream);
```

- `nk_vdot_f32c_best`: a_pairs, b_pairs `nk_f32c_t`, result `nk_f64c_t`
- `nk_vdot_f64c_best`: a_pairs, b_pairs `nk_f64c_t`, result `nk_f64c_t`
- `nk_vdot_f16c_best`: a_pairs, b_pairs `nk_f16c_t`, result `nk_f32c_t`
- `nk_vdot_bf16c_best`: a_pairs, b_pairs `nk_bf16c_t`, result `nk_f32c_t`

- `nk_vdot_f32c` backends: serial, neon, sve, haswell, skylake, rvv, v128relaxed
- `nk_vdot_f64c` backends: serial, neon, sve, haswell, skylake, rvv, v128relaxed
- `nk_vdot_f16c` backends: serial, neon, neonfhm, svehalf, haswell
- `nk_vdot_bf16c` backends: serial, neonbfdot, haswell, genoa

- `a_pairs` (in): The first complex vector.
- `b_pairs` (in): The second complex vector.
- `count_pairs` (in): The number of complex pairs in the vectors.
- `result` (out): The output complex value as {real, imag}.
- `capabilities` (in): One device's capabilities, like [`nk_cpu_capabilities_enabled`](https://www.unum.cloud/docs/numkong/c/runtime-dispatch.md#nk_cpu_capabilities_enabled) reports.
- `stream` (in): Null on the CPU, or the GPU stream of that device to queue on.

Statuses: - [`nk_missing_kernel_k`](https://www.unum.cloud/docs/numkong/c/quickstart.md#nk_missing_kernel_k) No capability in `capabilities` has it.

## nk_dot_output_dtype

Returns the output dtype for dot products.

```c
nk_dtype_t nk_dot_output_dtype(nk_dtype_t dtype);
```

## nk_dot_error_bound

Returns the error bound of dot products, per [`nk_accumulation_error_bound`](https://www.unum.cloud/docs/numkong/c/scalar-types.md#nk_accumulation_error_bound) of their output.

```c
nk_f64_t nk_dot_error_bound(nk_dtype_t dtype);
```

## nk_dot_find_kernel

Finds the dot product kernel of `kind` for `dtype`, from the best of `capabilities`.

```c
nk_status_t nk_dot_find_kernel(
    nk_kernel_kind_t kind,
    nk_dtype_t dtype,
    nk_capability_t capabilities,
    nk_kernel_punned_t *kernel,
    nk_capability_t *capability);
```

- `kind` (in): The verb whose kernel to find.
- `dtype` (in): The input type the kernel reads.
- `capabilities` (in): The mask to pick the best capability from.
- `kernel` (out): The kernel, or null when none of `capabilities` has it.
- `capability` (out): The capability the kernel belongs to, or zero.

Statuses: - [`nk_missing_kernel_k`](https://www.unum.cloud/docs/numkong/c/quickstart.md#nk_missing_kernel_k)
- [`nk_missing_library_k`](https://www.unum.cloud/docs/numkong/c/quickstart.md#nk_missing_library_k) Header-only.

