diff --git a/CHANGELOG.md b/CHANGELOG.md index 046f082..ebcc9fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Added `jaccard_distance` function - Added `quantize_binary` function - Added `subvector` function +- Added concatenate operator for vectors - Updated comparison operators to support vectors with different dimensions ## 0.6.2 (2024-03-18) diff --git a/README.md b/README.md index 140f635..f8f6d14 100644 --- a/README.md +++ b/README.md @@ -725,6 +725,7 @@ Operator | Description | Added \+ | element-wise addition | \- | element-wise subtraction | \* | element-wise multiplication | 0.5.0 +\|\| | concatenate | unreleased <-> | Euclidean distance | <#> | negative inner product | <=> | cosine distance | diff --git a/sql/vector--0.6.2--0.7.0.sql b/sql/vector--0.6.2--0.7.0.sql index e3f7c20..1e326a7 100644 --- a/sql/vector--0.6.2--0.7.0.sql +++ b/sql/vector--0.6.2--0.7.0.sql @@ -7,6 +7,13 @@ CREATE FUNCTION quantize_binary(vector) RETURNS bit CREATE FUNCTION subvector(vector, int, int) RETURNS vector AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE; +CREATE FUNCTION vector_concat(vector, vector) RETURNS vector + AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE; + +CREATE OPERATOR || ( + LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_concat +); + CREATE FUNCTION hamming_distance(bit, bit) RETURNS float8 AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE; diff --git a/sql/vector.sql b/sql/vector.sql index 543ed5a..511003d 100644 --- a/sql/vector.sql +++ b/sql/vector.sql @@ -105,6 +105,9 @@ CREATE FUNCTION vector_avg(double precision[]) RETURNS vector CREATE FUNCTION vector_combine(double precision[], double precision[]) RETURNS double precision[] AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE; +CREATE FUNCTION vector_concat(vector, vector) RETURNS vector + AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE; + -- vector aggregates CREATE AGGREGATE avg(vector) ( @@ -194,6 +197,10 @@ CREATE OPERATOR * ( COMMUTATOR = * ); +CREATE OPERATOR || ( + LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_concat +); + CREATE OPERATOR < ( LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_lt, COMMUTATOR = > , NEGATOR = >= , diff --git a/src/vector.c b/src/vector.c index e678f51..cc5a450 100644 --- a/src/vector.c +++ b/src/vector.c @@ -909,6 +909,30 @@ subvector(PG_FUNCTION_ARGS) PG_RETURN_POINTER(result); } +/* + * Concatenate vectors + */ +PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_concat); +Datum +vector_concat(PG_FUNCTION_ARGS) +{ + Vector *a = PG_GETARG_VECTOR_P(0); + Vector *b = PG_GETARG_VECTOR_P(1); + Vector *result; + int dim = a->dim + b->dim; + + CheckDim(dim); + result = InitVector(dim); + + for (int i = 0; i < a->dim; i++) + result->x[i] = a->x[i]; + + for (int i = 0; i < b->dim; i++) + result->x[i + a->dim] = b->x[i]; + + PG_RETURN_POINTER(result); +} + /* * Internal helper to compare vectors */ diff --git a/test/expected/vector_functions.out b/test/expected/vector_functions.out index 8be1525..904c192 100644 --- a/test/expected/vector_functions.out +++ b/test/expected/vector_functions.out @@ -24,6 +24,14 @@ SELECT '[1e37]'::vector * '[1e37]'; ERROR: value out of range: overflow SELECT '[1e-37]'::vector * '[1e-37]'; ERROR: value out of range: underflow +SELECT '[1,2,3]'::vector || '[4,5]'::vector; + ?column? +------------- + [1,2,3,4,5] +(1 row) + +SELECT array_fill(0, ARRAY[16000])::vector || '[1]'::vector; +ERROR: vector cannot have more than 16000 dimensions SELECT '[1,2,3]'::vector < '[1,2,3]'; ?column? ---------- diff --git a/test/sql/vector_functions.sql b/test/sql/vector_functions.sql index 8e8cc6e..12c2248 100644 --- a/test/sql/vector_functions.sql +++ b/test/sql/vector_functions.sql @@ -6,6 +6,9 @@ SELECT '[1,2,3]'::vector * '[4,5,6]'; SELECT '[1e37]'::vector * '[1e37]'; SELECT '[1e-37]'::vector * '[1e-37]'; +SELECT '[1,2,3]'::vector || '[4,5]'::vector; +SELECT array_fill(0, ARRAY[16000])::vector || '[1]'::vector; + SELECT '[1,2,3]'::vector < '[1,2,3]'; SELECT '[1,2,3]'::vector < '[1,2]'; SELECT '[1,2,3]'::vector <= '[1,2,3]';