# Dot Products

> NumKong for Rust

Dot products span real, complex, quantized, and packed storage types.

```rust
use numkong::{Dot, VDot, f32c};

let a = [f32c { re: 1.0, im: 2.0 }, f32c { re: 3.0, im: 4.0 }];
let b = [f32c { re: 5.0, im: 6.0 }, f32c { re: 7.0, im: 8.0 }];

let dot = f32c::dot(&a, &b).unwrap();
let vdot = f32c::vdot(&a, &b).unwrap(); // like numpy.vdot, conjugated

println!("{dot:?} {vdot:?}");
```

`use numkong::Dot;`

`use numkong::VDot;`

## Dot

Computes the __dot product__ — the inner product — between two vectors.

```rust
pub trait Dot: StorageElement
```

d = ∑ᵢ aᵢ × bᵢ

Range: unbounded. Fails with [`Error::ShapeMismatch`](https://www.unum.cloud/docs/numkong/rust/quickstart.md#ShapeMismatch) if lengths differ, or
[`Error::KernelFailed`](https://www.unum.cloud/docs/numkong/rust/quickstart.md#KernelFailed) carrying the kernel's status.

Implemented for: `f64`, `f32`, [`f16`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16), [`bf16`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16), `i8`, `u8`, [`e4m3`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e4m3), [`e5m2`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e5m2), [`e2m3`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e2m3), [`e3m2`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e3m2),
[`i4x2`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#i4x2), [`u4x2`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#u4x2), [`u1x8`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#u1x8).

On [`u1x8`](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#u1x8) this is the binary inner product — the number of positions where both bits are set —
which is the intersection count that Tanimoto similarity divides by the union. Use
[`crate::Jaccard`](https://www.unum.cloud/docs/numkong/rust/set-similarity.md#Jaccard) when you want that ratio.

Examples: ```
use numkong::Dot;
let first = vec![1.0_f32, 2.0, 3.0];
let second = vec![4.0_f32, 5.0, 6.0];
let result = f32::dot(&#x26;first, &#x26;second).unwrap();
assert!((result - 32.0).abs() &#x3C; 1e-5);
```

Implementors: - `impl [Dot](#Dot) for f64`
- `impl [Dot](#Dot) for f32`
- `impl [Dot](#Dot) for [f16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16)`
- `impl [Dot](#Dot) for [bf16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16)`
- `impl [Dot](#Dot) for i8`
- `impl [Dot](#Dot) for u8`
- `impl [Dot](#Dot) for [e4m3](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e4m3)`
- `impl [Dot](#Dot) for [e5m2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e5m2)`
- `impl [Dot](#Dot) for [e2m3](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e2m3)`
- `impl [Dot](#Dot) for [e3m2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e3m2)`
- `impl [Dot](#Dot) for [i4x2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#i4x2)`
- `impl [Dot](#Dot) for [u4x2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#u4x2)`
- `impl [Dot](#Dot) for [u1x8](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#u1x8)`
- `impl [Dot](#Dot) for [f16c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16c)`
- `impl [Dot](#Dot) for [bf16c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16c)`
- `impl [Dot](#Dot) for [f32c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f32c)`
- `impl [Dot](#Dot) for [f64c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f64c)`

## Output

Result type of the dot product.

```rust
type Output;
```

## dot

Computes the dot product of two equally long slices.

```rust
fn dot(first: &[Self], second: &[Self]) -> Result<Self::Output, Error>
```

## inner

Alias for [`dot`](#dot).

```rust
fn inner(first: &[Self], second: &[Self]) -> Result<Self::Output, Error>
```

## VDot

Computes the conjugating dot product, the Hermitian inner product.

```rust
pub trait VDot: Dot
```

For real-valued types this is identical to [`Dot::dot`](#dot). For complex-valued types it computes ∑ᵢ
conj(aᵢ) × bᵢ, which is the convention used in quantum mechanics and most linear-algebra
textbooks — BLAS `cdotc`, NumPy [`vdot`](#vdot).

Unlike an ordinary complex dot product, the Hermitian form produces a proper inner product:
`vdot(x, x)` is always a non-negative real number equal to ‖x‖², and `vdot(x, y) == conj(vdot(y, x))`. This matters in retrieval and signal-processing pipelines where cancellation between a
vector and its conjugate should leave the norm intact.

Implementors: - `impl [VDot](#VDot) for f64`
- `impl [VDot](#VDot) for f32`
- `impl [VDot](#VDot) for [f16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16)`
- `impl [VDot](#VDot) for [bf16](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16)`
- `impl [VDot](#VDot) for i8`
- `impl [VDot](#VDot) for u8`
- `impl [VDot](#VDot) for [e4m3](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e4m3)`
- `impl [VDot](#VDot) for [e5m2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e5m2)`
- `impl [VDot](#VDot) for [e2m3](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e2m3)`
- `impl [VDot](#VDot) for [e3m2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#e3m2)`
- `impl [VDot](#VDot) for [i4x2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#i4x2)`
- `impl [VDot](#VDot) for [u4x2](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#u4x2)`
- `impl [VDot](#VDot) for [u1x8](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#u1x8)`
- `impl [VDot](#VDot) for [f16c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f16c)`
- `impl [VDot](#VDot) for [bf16c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#bf16c)`
- `impl [VDot](#VDot) for [f32c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f32c)`
- `impl [VDot](#VDot) for [f64c](https://www.unum.cloud/docs/numkong/rust/scalar-types.md#f64c)`

## vdot

Hermitian inner product.

```rust
fn vdot(first: &[Self], second: &[Self]) -> Result<Self::Output, Error>
```

On real-valued types this falls back to [`Dot::dot`](#dot); on complex
types it returns ∑ᵢ conj(aᵢ) × bᵢ computed in the widened accumulator described by
[`Dot::Output`](https://www.unum.cloud/docs/numkong/rust/sparse-operations.md#Output).

