# Curved Metrics

> NumKong for Python

Curved-space kernels use an extra metric tensor or inverse covariance and should not be mixed into the Euclidean section.

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

# Complex bilinear form: aᴴ M b
a = (np.ones(16) + 1j * np.zeros(16)).astype(np.complex64)
b = (np.zeros(16) + 1j * np.ones(16)).astype(np.complex64)
m = np.eye(16, dtype=np.complex64)
bilinear = nk.bilinear(a, b, m)

# Real Mahalanobis distance: √((a−b)ᵀ M⁻¹ (a−b))
x = np.ones(32, dtype=np.float32)
y = np.full(32, 2.0, dtype=np.float32)
inv_cov = np.eye(32, dtype=np.float32)
mahalanobis = nk.mahalanobis(x, y, inv_cov)
```

`import numkong`

## bilinear

Compute the bilinear form aᵀ × M × b of two vectors under a metric tensor M.

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

Similar to `numpy.dot(a, metric_tensor @ b)`.

- `a`: First vector.
- `b`: Second vector.
- `metric_tensor`: Matrix M defining the bilinear form.
- `dtype`: Input dtype to read every buffer as, overriding the one they report.
- `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.

## mahalanobis

Compute the Mahalanobis distance between two vectors given an inverse covariance matrix.

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

Similar to [`scipy.spatial.distance.mahalanobis`](#mahalanobis).

- `a`: First vector.
- `b`: Second vector.
- `inverse_covariance`: Inverse of the covariance matrix.
- `dtype`: Input dtype to read every buffer as, overriding the one they report.
- `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.

