# Set Similarity

> NumKong for C

Packed-binary metrics operate on packed words, not on byte-wise booleans.
That is why `u1x8_t` exists as a storage type instead of pretending that `bool[8]` is the right primitive.

```c
nk_u1x8_t a[128], b[128];
nk_u32_t hamming = 0;
nk_f32_t jaccard = 0;
nk_hamming_u1_best(a, b, 128 * 8, &hamming, capabilities, NULL);
nk_jaccard_u1_best(a, b, 128 * 8, &jaccard, capabilities, NULL);
```

`nk_jaccard_u32_best` is a dense word-wise kernel rather than a sorted-set operation.
It walks two arrays of `n` 32-bit words position by position and returns `1 - matches / n`.

```c
nk_u32_t a[] = {1, 3, 5, 7, 9}, b[] = {1, 3, 5, 8, 10};
nk_f32_t jaccard_words = 0;
nk_jaccard_u32_best(a, b, 5, &jaccard_words, capabilities, NULL); // 1 - matches / n
assert(jaccard_words > 0.0f && jaccard_words < 1.0f && "3 of 5 words match");
```

Sorted arrays of integer identifiers are handled by the sparse kernels instead, described below.

`#include <numkong/set.h>`

## nk_hamming_u1_best

Binary Hamming distance computing the number of differing bits between two binary vectors.

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

- `nk_hamming_u1` backends: serial, neon, sve, haswell, icelake, rvvbb, rvv, v128, powervsx, loongsonasx

- `a` (in): The first binary vector.
- `b` (in): The second binary vector.
- `n` (in): Counts dimensions, a multiple of the values per byte.
- `result` (out): The output distance 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 distance value is non-negative.

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

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_jaccard_u1_best

Binary Jaccard distance computing the ratio of differing bits to the union of bits.

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

- `nk_jaccard_u1` backends: serial, neon, sve, haswell, icelake, rvvbb, rvv, v128, powervsx, loongsonasx

- `a` (in): The first binary vector.
- `b` (in): The second binary vector.
- `n` (in): Counts dimensions, a multiple of the values per byte.
- `result` (out): The output distance 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 distance value is non-negative.

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

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_jaccard_u32_best

Integral Jaccard distance computing the ratio of differing bits to the union of bits.

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

- `nk_jaccard_u32` backends: serial, neon, sve, haswell, icelake, rvv, v128

- `a` (in): The first binary vector.
- `b` (in): The second binary vector.
- `n` (in): The number of 32-bit scalars in the vectors.
- `result` (out): The output distance 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 distance value is non-negative.

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

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_hamming_u8_best

Byte-level Hamming distance computing the number of differing bytes between two vectors.

```c
nk_status_t nk_hamming_u8_best(
    nk_u8_t const *a,
    nk_u8_t const *b,
    nk_size_t n,
    nk_u32_t *result,
    nk_capability_t capabilities,
    nk_stream_t stream);
```

- `nk_hamming_u8` backends: serial, neon, sve, haswell, icelake, rvv, v128, powervsx, loongsonasx

- `a` (in): The first byte vector.
- `b` (in): The second byte vector.
- `n` (in): The number of bytes in the vectors.
- `result` (out): The output distance 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 distance value is non-negative.

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

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_jaccard_u16_best

Integral Jaccard distance for 16-bit unsigned integer vectors.

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

- `nk_jaccard_u16` backends: serial, neon, sve, haswell, icelake, rvv, v128

- `a` (in): The first vector.
- `b` (in): The second vector.
- `n` (in): The number of 16-bit scalars in the vectors.
- `result` (out): The output distance 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 distance value is non-negative.

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

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_hamming_output_dtype

Returns the output dtype for Hamming distance.

```c
nk_dtype_t nk_hamming_output_dtype(nk_dtype_t dtype);
```

## nk_jaccard_output_dtype

Returns the output dtype for Jaccard distance.

```c
nk_dtype_t nk_jaccard_output_dtype(nk_dtype_t dtype);
```

## nk_set_find_kernel

Finds the set distance kernel of `kind` for `dtype`, from the best of `capabilities`.

```c
nk_status_t nk_set_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.

