# Vector

A collection of essential vector operations that provide foundational functionality for numerical computation, machine learning, and data analysis.

A collection of essential vector operations that provide foundational functionality for numerical computation, machine learning, and data analysis. These operations include distance measurements, similarity coefficients, and other basic and complex operations related to vectors. Through understanding and implementing these functions, we can perform a wide variety of tasks ranging from data processing to advanced statistical analyses.

<table>
  <thead>
    <tr>
      <th scope="col">Function</th>
      <th scope="col">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td scope="row" data-label="Function"><a href="#vectoradd"><code>vector::add()</code></a></td>
      <td scope="row" data-label="Description">Performs element-wise addition of two vectors</td>
    </tr>
    <tr>
      <td scope="row" data-label="Function"><a href="#vectorangle"><code>vector::angle()</code></a></td>
      <td scope="row" data-label="Description">Computes the angle between two vectors</td>
    </tr>
    <tr>
      <td scope="row" data-label="Function"><a href="#vectorcross"><code>vector::cross()</code></a></td>
      <td scope="row" data-label="Description">Computes the cross product of two vectors</td>
    </tr>
    <tr>
      <td scope="row" data-label="Function"><a href="#vectordivide"><code>vector::divide()</code></a></td>
      <td scope="row" data-label="Description">Performs element-wise division between two vectors</td>
    </tr>
    <tr>
      <td scope="row" data-label="Function"><a href="#vectordot"><code>vector::dot()</code></a></td>
      <td scope="row" data-label="Description">Computes the dot product of two vectors</td>
    </tr>
    <tr>
      <td scope="row" data-label="Function"><a href="#vectormagnitude"><code>vector::magnitude()</code></a></td>
      <td scope="row" data-label="Description">Computes the magnitude (or length) of a vector</td>
    </tr>
    <tr>
      <td scope="row" data-label="Function"><a href="#vectormultiply"><code>vector::multiply()</code></a></td>
      <td scope="row" data-label="Description">Performs element-wise multiplication of two vectors</td>
    </tr>
    <tr>
      <td scope="row" data-label="Function"><a href="#vectornormalize"><code>vector::normalize()</code></a></td>
      <td scope="row" data-label="Description">Computes the normalisation of a vector</td>
    </tr>
    <tr>
      <td scope="row" data-label="Function"><a href="#vectorproject"><code>vector::project()</code></a></td>
      <td scope="row" data-label="Description">Computes the projection of one vector onto another</td>
    </tr>
    <tr>
      <td scope="row" data-label="Function"><a href="#vectorscale"><code>vector::scale()</code></a></td>
      <td scope="row" data-label="Description">Multiplies each item in a vector</td>
    </tr>
    <tr>
      <td scope="row" data-label="Function"><a href="#vectorsum"><code>vector::sum()</code></a></td>
      <td scope="row" data-label="Description">Sums vectors element-wise, as a scalar or as a grouped aggregate</td>
    </tr>
    <tr>
      <td scope="row" data-label="Function"><a href="#vectorsubtract"><code>vector::subtract()</code></a></td>
      <td scope="row" data-label="Description">Performs element-wise subtraction between two vectors</td>
    </tr>
    <tr>
      <td scope="row" data-label="Function"><a href="#vectordistancechebyshev"><code>vector::distance::chebyshev()</code></a></td>
      <td scope="row" data-label="Description">Computes the Chebyshev distance</td>
    </tr>
    <tr>
      <td scope="row" data-label="Function"><a href="#vectordistanceeuclidean"><code>vector::distance::euclidean()</code></a></td>
      <td scope="row" data-label="Description">Computes the Euclidean distance between two vectors</td>
    </tr>
    <tr>
      <td scope="row" data-label="Function"><a href="#vectordistancehamming"><code>vector::distance::hamming()</code></a></td>
      <td scope="row" data-label="Description">Computes the Hamming distance between two vectors</td>
    </tr>
    <tr>
      <td scope="row" data-label="Function"><a href="#vectordistanceknn"><code>vector::distance::knn()</code></a></td>
      <td scope="row" data-label="Description">Returns the distance computed during the query</td>
    </tr>
    <tr>
      <td scope="row" data-label="Function"><a href="#vectordistancemanhattan"><code>vector::distance::manhattan()</code></a></td>
      <td scope="row" data-label="Description">Computes the Manhattan distance between two vectors</td>
    </tr>
    <tr>
      <td scope="row" data-label="Function"><a href="#vectordistancemahalanobis"><code>vector::distance::mahalanobis()</code></a></td>
      <td scope="row" data-label="Description">Computes the Mahalanobis distance between two vectors given a covariance matrix</td>
    </tr>
    <tr>
      <td scope="row" data-label="Function"><a href="#vectordistanceminkowski"><code>vector::distance::minkowski()</code></a></td>
      <td scope="row" data-label="Description">Computes the Minkowski distance between two vectors</td>
    </tr>
    <tr>
      <td scope="row" data-label="Function"><a href="#vectorsimilaritycosine"><code>vector::similarity::cosine()</code></a></td>
      <td scope="row" data-label="Description">Computes the Cosine similarity between two vectors</td>
    </tr>
    <tr>
      <td scope="row" data-label="Function"><a href="#vectorsimilarityjaccard"><code>vector::similarity::jaccard()</code></a></td>
      <td scope="row" data-label="Description">Computes the Jaccard similarity between two vectors</td>
    </tr>
    <tr>
      <td scope="row" data-label="Function"><a href="#vectorsimilaritypearson"><code>vector::similarity::pearson()</code></a></td>
      <td scope="row" data-label="Description">Computes the Pearson correlation coefficient between two vectors</td>
    </tr>
    <tr>
      <td scope="row" data-label="Function"><a href="#vectorsimilarityspearman"><code>vector::similarity::spearman()</code></a></td>
      <td scope="row" data-label="Description">Computes the Spearman rank correlation coefficient between two vectors</td>
    </tr>
  </tbody>
</table>

## `vector::add`

The `vector::add` function performs element-wise addition of two vectors, where each element in the first vector is added to the corresponding element in the second vector.

```surql title="API DEFINITION"
vector::add(array, $other: array) -> array
```
The following example shows this function, and its output, when used in a [`RETURN`](/docs/reference/query-language/statements/return.md) statement:

```surql
RETURN vector::add([1, 2, 3], [1, 2, 3]);

-- [2, 4, 6]
```

<br />

## `vector::angle`

The `vector::angle` function computes the angle between two vectors, providing a measure of the orientation difference between them.

```surql title="API DEFINITION"
vector::angle(array, $other: array) -> number
```

Both vectors must have the same dimension and a non-zero magnitude. A zero-magnitude input (including `[]`) returns an error.

The following example shows this function, and its output, when used in a [`RETURN`](/docs/reference/query-language/statements/return.md) statement:

```surql
RETURN vector::angle([5, 10, 15], [10, 5, 20]);

-- 0.36774908225917935f
```

<br />

## `vector::cross`

The `vector::cross` function computes the cross product of two vectors, which results in a vector that is orthogonal (perpendicular) to the plane containing the original vectors.

```surql title="API DEFINITION"
vector::cross(array, $other: array) -> array
```

The following example shows this function, and its output, when used in a [`RETURN`](/docs/reference/query-language/statements/return.md) statement:

```surql
RETURN vector::cross([1, 2, 3], [4, 5, 6]);

[-3, 6, -3]
```

<br />

## `vector::divide`

The `vector::divide` function performs element-wise division between two vectors, where each element in the first vector is divided by the corresponding element in the second vector.

```surql title="API DEFINITION"
vector::divide(array, $other: array) -> array
```

The divisor vector must not contain a zero. Division by zero returns an error instead of `NaN`.

The following example shows this function, and its output, when used in a [`RETURN`](/docs/reference/query-language/statements/return.md) statement:

```surql
RETURN vector::divide([4, 6], [2, 3]);

-- [2, 2]
```

<br />

## `vector::dot`

The `vector::dot` function computes the dot product of two vectors, which is the sum of the products of the corresponding entries of the two sequences of numbers.

```surql title="API DEFINITION"
vector::dot(array, $other: array) -> number
```

The following example shows this function, and its output, when used in a [`RETURN`](/docs/reference/query-language/statements/return.md) statement:

```surql
RETURN vector::dot([1, 2, 3], [1, 2, 3]);

-- 14
```

<br />

## `vector::magnitude`

The `vector::magnitude` function computes the magnitude (or length) of a vector, providing a measure of the size of the vector in multi-dimensional space.

```surql title="API DEFINITION"
vector::magnitude(array) -> number
```

An empty vector returns `0`.

The following example shows this function, and its output, when used in a [`RETURN`](/docs/reference/query-language/statements/return.md) statement:

```surql
RETURN vector::magnitude([ 1, 2, 3, 3, 3, 4, 5 ]);

-- 8.54400374531753f
```

<br />

## `vector::multiply`

The `vector::multiply` function performs element-wise multiplication of two vectors, where each element in the first vector is multiplied by the corresponding element in the second vector.

```surql title="API DEFINITION"
vector::multiply(array, $other: array) -> array
```
The following example shows this function, and its output, when used in a [`RETURN`](/docs/reference/query-language/statements/return.md) statement:

```surql
RETURN vector::multiply([1, 2, 3], [1, 2, 3]);

-- [1, 4, 9]
```

<br />

## `vector::normalize`

The `vector::normalize` function computes the normalisation of a vector, transforming it to a unit vector (a vector of length 1) that maintains the original direction.

```surql title="API DEFINITION"
vector::normalize(array) -> array
```

The vector must have a non-zero magnitude. A zero vector (including `[]`) returns an error.

The following example shows this function, and its output, when used in a [`RETURN`](/docs/reference/query-language/statements/return.md) statement:

```surql
RETURN vector::normalize([ 4, 3 ]);

-- [0.8f, 0.6f]
```

<br />

## `vector::project`

The `vector::project` function computes the projection of one vector onto another, providing a measure of the shadow of one vector on the other. The projection is obtained by multiplying the magnitude of the given vectors with the cosecant of the angle between the two vectors.

```surql title="API DEFINITION"
vector::project(array, $other: array) -> array
```

The second vector must have a non-zero magnitude. Projecting onto a zero vector (including `[]`) returns an error.

The following example shows this function, and its output, when used in a [`RETURN`](/docs/reference/query-language/statements/return.md) statement:

```surql
RETURN vector::project([1, 2, 3], [4, 5, 6]);

-- [1.6623376623376624f, 2.077922077922078f, 2.4935064935064934f]
```

<br />

## `vector::scale`

The `vector::scale` function multiplies each item in a vector by a number.

```surql title="API DEFINITION"
vector::scale(array, $other: number) -> array
```

The following example shows this function, and its output, when used in a [`RETURN`](/docs/reference/query-language/statements/return.md) statement:

```surql
RETURN vector::scale([3, 1, 5, -3, 7, 2], 5);

-- [15,	5, 25, -15, 35, 10]
```

<br />

## `vector::sum`

_(since v3.3.0)_

The `vector::sum` function adds vectors element-wise. It is available in two forms, matching other aggregates such as [`math::sum`](/docs/reference/query-language/functions/database-functions/math.md#mathsum):

- **Scalar** - sum a collection of vectors you already hold as `array<array<number>>`
- **Aggregate** - fold a vector-valued expression across the rows of a `GROUP BY` (or `GROUP ALL`)

```surql title="API DEFINITION"
vector::sum(array<array<number>>) -> array | none
```

An empty collection returns `NONE` (there is no dimension to produce a zero vector for). Two empty vectors sum to `[]`. Vectors in the collection must share the same dimension; a mismatch returns an error in the scalar form.

The following example shows the scalar form, and its output, when used in a [`RETURN`](/docs/reference/query-language/statements/return.md) statement:

```surql
RETURN vector::sum([[1, 2, 3], [4, 5, 6]]);
-- [5, 7, 9]

RETURN vector::sum([[1, 2], [3, 4], [5, 6]]);
-- [9, 12]

RETURN vector::sum([[1.5, 2.5], [1, 1]]);
-- [2.5f, 3.5f]

RETURN vector::sum([[], []]);
-- []

RETURN vector::sum([]);
-- NONE

RETURN [[1, 2], [3, 4]].vector_sum();
-- [4, 6]
```

### Aggregate form

As an aggregate, `vector::sum` keeps one running vector per group, so state stays O(dimension) rather than materialising every embedding with `array::group` then folding.

On the streaming path:

- Rows whose vector is `NONE` or `NULL` are skipped (same idea as a missing field for `math::sum`)
- A group that never sees a vector yields `NONE`
- A group whose vectors disagree on dimension yields `NULL`, not a partial sum

Together with [`vector::scale`](#vectorscale) and [`math::sum`](/docs/reference/query-language/functions/database-functions/math.md#mathsum), a weighted centroid is one query:

```surql
CREATE engagement:1 SET user = 'alice', weight = 2, embedding = [1, 0, 0] RETURN NONE;
CREATE engagement:2 SET user = 'alice', weight = 3, embedding = [0, 1, 0] RETURN NONE;
CREATE engagement:3 SET user = 'bob', weight = 1, embedding = [0, 0, 4] RETURN NONE;

SELECT
	user,
	vector::scale(
		vector::sum(vector::scale(embedding, weight)),
		1.0 / math::sum(weight)
	) AS interest
FROM engagement
GROUP BY user
ORDER BY user;

-- alice → [0.4f, 0.6000000000000001f, 0f]
-- bob   → [0f, 0f, 4f]

SELECT user, vector::sum(embedding) AS total
FROM engagement
GROUP BY user
ORDER BY user;

-- alice → [1, 1, 0]
-- bob   → [0, 0, 4]
```

> [!IMPORTANT]
> Write the reciprocal as a float (`1.0 / math::sum(weight)`). With integer weights, `1 / math::sum(weight)` is integer division and truncates to `0`, which scales the weighted total away entirely. Float weights promote the reciprocal on their own.

<br />

## `vector::subtract`

The `vector::subtract` function performs element-wise subtraction between two vectors, where each element in the second vector is subtracted from the corresponding element in the first vector.

```surql title="API DEFINITION"
vector::subtract(array, $other: array) -> array
```

The following example shows this function, and its output, when used in a [`RETURN`](/docs/reference/query-language/statements/return.md) statement:

```surql
RETURN vector::subtract([4, 5, 6], [3, 2, 1]);

-- [1, 3, 5]
```

<br />

## `vector::distance::chebyshev`

The `vector::distance::chebyshev` function computes the Chebyshev distance (also known as maximum value distance) between two vectors, which is the greatest of their differences along any coordinate dimension.

```surql title="API DEFINITION"
vector::distance::chebyshev(array, $other: array) -> number
```

Two empty vectors return `0`.

The following example shows this function, and its output, when used in a [`RETURN`](/docs/reference/query-language/statements/return.md) statement:

```surql
RETURN vector::distance::chebyshev([2, 4, 5, 3, 8, 2], [3, 1, 5, -3, 7, 2]);

-- 6f
```

<br />

## `vector::distance::euclidean`

The `vector::distance::euclidean` function computes the Euclidean distance between two vectors, providing a measure of the straight-line distance between two points in a multi-dimensional space.

```surql title="API DEFINITION"
vector::distance::euclidean(array, $other: array) -> number
```

The following example shows this function, and its output, when used in a [`RETURN`](/docs/reference/query-language/statements/return.md) statement:

```surql
RETURN vector::distance::euclidean([10, 50, 200], [400, 100, 20]);

-- 432.43496620879307f
```

<br />

## `vector::distance::hamming`

The `vector::distance::hamming` function computes the Hamming distance between two vectors, measuring the minimum number of substitutions required to change one vector into the other, useful for comparing strings or codes.

```surql title="API DEFINITION"
vector::distance::hamming(array, $other: array) -> number
```

The following example shows this function, and its output, when used in a [`RETURN`](/docs/reference/query-language/statements/return.md) statement:

```surql
RETURN vector::distance::hamming([1, 2, 2], [1, 2, 3]);

-- 1
```

<br />

## `vector::distance::knn`

The `vector::distance::knn` function returns the distance computed during the query by the Knn operator (avoiding recomputation).

```surql title="API DEFINITION"
vector::distance::knn() -> number
```

The following example shows this function, and its output, when used in a [`SELECT`](/docs/reference/query-language/statements/select.md) statement:

```surql
CREATE pts:1 SET point = [1,2,3,4];
CREATE pts:2 SET point = [4,5,6,7];
CREATE pts:3 SET point = [8,9,10,11];
SELECT id, vector::distance::knn() AS dist FROM pts
  WHERE point <|2,EUCLIDEAN|> [2,3,4,5];
```

```surql title="Output"
[
			{
				id: pts:1,
				dist: 2f
			},
			{
				id: pts:2,
				dist: 4f
			}
]
```

<br />

## `vector::distance::manhattan`

The `vector::distance::manhattan`  function computes the Manhattan distance (also known as the L1 norm or Taxicab geometry) between two vectors, which is the sum of the absolute differences of their corresponding elements.

```surql title="API DEFINITION"
vector::distance::manhattan(array, $other: array) -> number
```

The following example shows this function, and its output, when used in a [`RETURN`](/docs/reference/query-language/statements/return.md) statement:

```surql
RETURN vector::distance::manhattan([10, 20, 15, 10, 5], [12, 24, 18, 8, 7]);

-- 13
```

<br />

## `vector::distance::mahalanobis`

_(since v3.3.0)_

The `vector::distance::mahalanobis` function computes the [Mahalanobis distance](https://en.wikipedia.org/wiki/Mahalanobis_distance) between two vectors given a covariance matrix. Unlike Euclidean distance, it scales differences by the inverse of the covariance, so correlated dimensions are not double counted.

```surql title="API DEFINITION"
vector::distance::mahalanobis(array, $other: array, $covariance: array<array<number>>) -> number
```

The two vectors must share the same non-zero dimension. The covariance argument must be a square matrix of that dimension and must be symmetric positive-definite (validated via Cholesky decomposition). When the covariance is the identity matrix, the result matches [`vector::distance::euclidean`](#vectordistanceeuclidean).

The following example shows this function, and its output, when used in a [`RETURN`](/docs/reference/query-language/statements/return.md) statement:

```surql
RETURN vector::distance::mahalanobis([1, 2], [3, 4], [[1, 0], [0, 1]]);
-- 2.8284271247461903f  (same as euclidean for identity covariance)

RETURN vector::distance::mahalanobis([1, 2], [3, 4], [[2, 1], [1, 2]]);
-- 1.632993161855452f

RETURN vector::distance::mahalanobis([1, 2], [1, 2], [[2, 1], [1, 2]]);
-- 0f
```

A non-square matrix, a matrix that is not symmetric positive-definite, empty vectors, or a dimension mismatch returns an error.

<br />

## `vector::distance::minkowski`

The `vector::distance::minkowski` function computes the Minkowski distance between two vectors, a generalization of other distance metrics such as Euclidean and Manhattan when parameterised with different values of p.

```surql title="API DEFINITION"
vector::distance::minkowski(array, $other: array, $p_value: number) -> number
```

The following example shows this function, and its output, when used in a [`RETURN`](/docs/reference/query-language/statements/return.md) statement:

```surql
RETURN vector::distance::minkowski([10, 20, 15, 10, 5], [12, 24, 18, 8, 7], 3);

-- 4.862944131094279f
```

<br />

## `vector::similarity::cosine`

The `vector::similarity::cosine` function computes the Cosine similarity between two vectors, indicating the cosine of the angle between them, which is a measure of how closely two vectors are oriented to each other.

```surql title="API DEFINITION"
vector::similarity::cosine(array, $other: array) -> number
```

The following example shows this function, and its output, when used in a [`RETURN`](/docs/reference/query-language/statements/return.md) statement:

```surql
RETURN vector::similarity::cosine([10, 50, 200], [400, 100, 20]);

-- 0.15258215962441316f
```

<br />

## `vector::similarity::jaccard`

The `vector::similarity::jaccard` function computes the Jaccard similarity between two vectors, treating each vector as a set of numbers (intersection size divided by union size). Duplicate values in a vector count once.

```surql title="API DEFINITION"
vector::similarity::jaccard(array, $other: array) -> number
```

Two empty vectors return `1` (both sets are empty).

The following example shows this function, and its output, when used in a [`RETURN`](/docs/reference/query-language/statements/return.md) statement:

```surql
RETURN vector::similarity::jaccard([0,1,2,5,6], [0,2,3,4,5,7,9]);
-- 0.3333333333333333f

RETURN vector::similarity::jaccard([1, 2], [2, 2]);
-- 0.5f  (sets {1,2} and {2}; intersection 1, union 2)
```

<br />

## `vector::similarity::pearson`

The `vector::similarity::pearson` function computes the Pearson correlation coefficient between two vectors, reflecting the degree of linear relationship between them.

```surql title="API DEFINITION"
vector::similarity::pearson(array, array) -> number
```

Both vectors must have the same dimension of at least 2, and neither may have zero variance.

The following example shows this function, and its output, when used in a [`RETURN`](/docs/reference/query-language/statements/return.md) statement:

```surql
RETURN vector::similarity::pearson([1,2,3], [1,5,7]);

-- 0.9819805060619659f
```

<br />

## `vector::similarity::spearman`

_(since v3.3.0)_

The `vector::similarity::spearman` function computes the [Spearman rank correlation](https://en.wikipedia.org/wiki/Spearman%27s_rank_correlation_coefficient) between two vectors: each vector is converted to average ranks (ties share a rank), then Pearson correlation is applied to those ranks.

```surql title="API DEFINITION"
vector::similarity::spearman(array, $other: array) -> number
```

Both vectors must have the same dimension of at least 2, and neither may have zero variance after ranking (a constant vector returns an error).

The following example shows this function, and its output, when used in a [`RETURN`](/docs/reference/query-language/statements/return.md) statement:

```surql
RETURN vector::similarity::spearman([1, 2, 3], [1, 10, 100]);
-- 1f

RETURN vector::similarity::spearman([1, 2, 3], [3, 2, 1]);
-- -1f

RETURN vector::similarity::spearman([1, 2, 2, 3], [1, 2, 3, 4]);
-- 0.9486832980505138f  (ties use average ranks)
```

<br />

<br /><br />
