# Probability Metrics

> NumKong for Python

Probability divergences deserve their own section because they are not just "one more distance".

```python
import numpy as np
import numkong as nk

p = np.array([0.2, 0.3, 0.5], dtype=np.float32)
q = np.array([0.1, 0.3, 0.6], dtype=np.float32)

kl_forward, kl_reverse = nk.kullbackleibler(p, q), nk.kullbackleibler(q, p)
assert kl_forward != kl_reverse, "KLD is asymmetric"

js_forward, js_reverse = nk.jensenshannon(p, q), nk.jensenshannon(q, p)
np.testing.assert_allclose(js_forward, js_reverse, atol=1e-6)  # JSD is symmetric
```

`import numkong`

## pointer_to_*

Return the address of the [`jensenshannon`](#jensenshannon) kernel for [`dtype`](https://www.unum.cloud/docs/numkong/python/mesh-alignment.md#dtype), as an integer.

```python
def pointer_to_jensenshannon(
    dtype: _FloatTypeName | _MiniFloatType,
    /,
) -> int
```

- `pointer_to_jensenshannon`
- `pointer_to_kullbackleibler`

## jensenshannon

Compute the Jensen-Shannon distance between two probability distributions.

```python
def jensenshannon(
    a: _BufferType,
    b: _BufferType,
    /,
    dtype: _FloatTypeName | _MiniFloatType | None = None,
    *,
    out: _BufferType | None = None,
    out_dtype: _FloatTypeName | _MiniFloatType | None = None,
    capabilities: Capability | int | None = ...,
    stream: int | None = ...,
) -> float | Tensor | None
```

Similar to [`scipy.spatial.distance.jensenshannon`](#jensenshannon). Two vectors give a scalar. Matrices pair row
i of `a` with row i of `b`, a single row pairing with every row of the other, into a new Tensor
of one result per pair, or into `out`, returning None.

- `a`: First probability vector or matrix.
- `b`: Second probability vector or matrix, of the dtype of `a`.
- `dtype`: Input dtype to read both buffers as, overriding the one they report.
- `out`: Output vector for the results.
- `out_dtype`: Result dtype, by default that of `out`, else float64.
- `capabilities`: Capabilities to run within: every CPU one by default, or for packed operands the mask that packed them.
- `stream`: A GPU stream pointer, left None on the CPU.

## jsd

Alias of [`jensenshannon`](#jensenshannon).

```python
def jsd(
    a: _BufferType,
    b: _BufferType,
    /,
    dtype: _FloatTypeName | _MiniFloatType | None = None,
    *,
    out: _BufferType | None = None,
    out_dtype: _FloatTypeName | _MiniFloatType | None = None,
    capabilities: Capability | int | None = ...,
    stream: int | None = ...,
) -> float | Tensor | None
```

- `capabilities`: Capabilities to run within: every CPU one by default, or for packed operands the mask that packed them.
- `stream`: A GPU stream pointer, left None on the CPU.

## kullbackleibler

Compute the Kullback-Leibler divergence between two probability distributions.

```python
def kullbackleibler(
    a: _BufferType,
    b: _BufferType,
    /,
    dtype: _FloatTypeName | _MiniFloatType | None = None,
    *,
    out: _BufferType | None = None,
    out_dtype: _FloatTypeName | _MiniFloatType | None = None,
    capabilities: Capability | int | None = ...,
    stream: int | None = ...,
) -> float | Tensor | None
```

Similar to `scipy.special.kl_div`. Two vectors give a scalar. Matrices pair row i of `a` with
row i of `b`, a single row pairing with every row of the other, into a new Tensor of one result
per pair, or into `out`, returning None.

- `a`: First probability vector or matrix.
- `b`: Second probability vector or matrix, of the dtype of `a`.
- `dtype`: Input dtype to read both buffers as, overriding the one they report.
- `out`: Output vector for the results.
- `out_dtype`: Result dtype, by default that of `out`, else float64.
- `capabilities`: Capabilities to run within: every CPU one by default, or for packed operands the mask that packed them.
- `stream`: A GPU stream pointer, left None on the CPU.

## kld

Alias of [`kullbackleibler`](#kullbackleibler).

```python
def kld(
    a: _BufferType,
    b: _BufferType,
    /,
    dtype: _FloatTypeName | _MiniFloatType | None = None,
    *,
    out: _BufferType | None = None,
    out_dtype: _FloatTypeName | _MiniFloatType | None = None,
    capabilities: Capability | int | None = ...,
    stream: int | None = ...,
) -> float | Tensor | None
```

- `capabilities`: Capabilities to run within: every CPU one by default, or for packed operands the mask that packed them.
- `stream`: A GPU stream pointer, left None on the CPU.

