# Curved Metrics

> NumKong for Rust

Curved-space kernels combine vectors with an extra metric tensor or covariance inverse.

```rust
use numkong::{Bilinear, Mahalanobis, f32c};

// Complex bilinear form: aᴴ M b
let a = [f32c { re: 1.0, im: 0.0 }; 16];
let b = [f32c { re: 0.0, im: 1.0 }; 16];
let metric = [f32c { re: 1.0, im: 0.0 }; 16 * 16];
let bilinear = f32c::bilinear(&a, &b, &metric).unwrap();

// Real Mahalanobis distance: √((a−b)ᵀ M⁻¹ (a−b))
let x = [1.0_f32; 32];
let y = [2.0_f32; 32];
let mut inv_cov = vec![0.0_f32; 32 * 32];
for i in 0..32 { inv_cov[i * 32 + i] = 1.0; } // identity matrix
let distance = f32::mahalanobis(&x, &y, &inv_cov).unwrap();
```

`use numkong::Bilinear;`

`use numkong::Mahalanobis;`

## Bilinear

Bilinear form computation: aᵀ × C × b where C is a metric tensor.

```rust
pub trait Bilinear: StorageElement
```

Computes the bilinear form of two vectors `a` and `b` with respect to a symmetric matrix `C`,
given in row-major order as a flat slice of length n².

Implementors: - `impl [Bilinear](#Bilinear) for f64`
- `impl [Bilinear](#Bilinear) for f32`
- `impl [Bilinear](#Bilinear) for [f16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16)`
- `impl [Bilinear](#Bilinear) for [bf16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16)`
- `impl [Bilinear](#Bilinear) for [f64c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f64c)`
- `impl [Bilinear](#Bilinear) for [f32c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f32c)`
- `impl [Bilinear](#Bilinear) for [f16c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16c)`
- `impl [Bilinear](#Bilinear) for [bf16c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16c)`

## Output

Output type for results.

```rust
type Output;
```

`f32` widens to `f64`; f16/bf16 use f32.

## bilinear

Computes the bilinear form aᵀ × C × b.

```rust
fn bilinear(a: &[Self], b: &[Self], c: &[Self]) -> Result<Self::Output, Error>
```

Arguments: - `a` - First vector of length n

- `b` - Second vector of length n

- `c` - Metric tensor, symmetric __[n,n]__ matrix in row-major order, flattened to
length n²

Errors: [`Error::InvalidShape`](https://www.unum.cloud/docs/numkong/rust/quickstart.md#InvalidShape) for empty vectors, [`Error::ShapeMismatch`](https://www.unum.cloud/docs/numkong/rust/quickstart.md#ShapeMismatch) if lengths
are incompatible, or [`Error::KernelFailed`](https://www.unum.cloud/docs/numkong/rust/quickstart.md#KernelFailed) carrying the kernel's status.

## Mahalanobis

Mahalanobis distance: √((a−b)ᵀ × C × (a−b)).

```rust
pub trait Mahalanobis: StorageElement
```

Computes the Mahalanobis distance between two vectors `a` and `b` with respect to an inverse
covariance matrix `C`, given in row-major order as a flat slice of length n².

Implementors: - `impl [Mahalanobis](#Mahalanobis) for f64`
- `impl [Mahalanobis](#Mahalanobis) for f32`
- `impl [Mahalanobis](#Mahalanobis) for [f16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16)`
- `impl [Mahalanobis](#Mahalanobis) for [bf16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16)`

## Output

Output type for results.

```rust
type Output;
```

`f32` widens to `f64`; f16/bf16 use f32.

## mahalanobis

Computes the Mahalanobis distance √((a−b)ᵀ × C × (a−b)).

```rust
fn mahalanobis(a: &[Self], b: &[Self], c: &[Self]) -> Result<Self::Output, Error>
```

Arguments: - `a` - First vector of length n

- `b` - Second vector of length n

- `c` - Inverse covariance matrix, a symmetric __[n,n]__ matrix in row-major order,
flattened to length n²

Errors: [`Error::InvalidShape`](https://www.unum.cloud/docs/numkong/rust/quickstart.md#InvalidShape) for empty vectors, [`Error::ShapeMismatch`](https://www.unum.cloud/docs/numkong/rust/quickstart.md#ShapeMismatch) if lengths
are incompatible, or [`Error::KernelFailed`](https://www.unum.cloud/docs/numkong/rust/quickstart.md#KernelFailed) carrying the kernel's status.

