Added element-wise multiplication for vectors

This commit is contained in:
Andrew Kane
2023-07-15 20:19:51 -07:00
parent cd4ac17f9f
commit 08e7209810
7 changed files with 75 additions and 0 deletions

View File

@@ -2,6 +2,7 @@
- Added support for parallel index builds
- Added `l1_distance` function
- Added element-wise multiplication for vectors
## 0.4.4 (2023-06-12)

View File

@@ -343,6 +343,7 @@ Operator | Description
--- | ---
\+ | element-wise addition
\- | element-wise subtraction
\* | element-wise multiplication [unreleased]
<-> | Euclidean distance
<#> | negative inner product
<=> | cosine distance

View File

@@ -3,3 +3,11 @@
CREATE FUNCTION l1_distance(vector, vector) RETURNS float8
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_mul(vector, vector) RETURNS vector
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OPERATOR * (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_mul,
COMMUTATOR = *
);

View File

@@ -55,6 +55,9 @@ CREATE FUNCTION vector_add(vector, vector) RETURNS vector
CREATE FUNCTION vector_sub(vector, vector) RETURNS vector
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_mul(vector, vector) RETURNS vector
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- private functions
CREATE FUNCTION vector_lt(vector, vector) RETURNS bool
@@ -174,6 +177,11 @@ CREATE OPERATOR - (
COMMUTATOR = -
);
CREATE OPERATOR * (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_mul,
COMMUTATOR = *
);
CREATE OPERATOR < (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_lt,
COMMUTATOR = > , NEGATOR = >= ,

View File

@@ -125,6 +125,14 @@ float_overflow_error(void)
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("value out of range: overflow")));
}
static pg_noinline void
float_underflow_error(void)
{
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("value out of range: underflow")));
}
#endif
/*
@@ -759,6 +767,42 @@ vector_sub(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(result);
}
/*
* Multiply vectors
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_mul);
Datum
vector_mul(PG_FUNCTION_ARGS)
{
Vector *a = PG_GETARG_VECTOR_P(0);
Vector *b = PG_GETARG_VECTOR_P(1);
float *ax = a->x;
float *bx = b->x;
Vector *result;
float *rx;
CheckDims(a, b);
result = InitVector(a->dim);
rx = result->x;
/* Auto-vectorized */
for (int i = 0, imax = a->dim; i < imax; i++)
rx[i] = ax[i] * bx[i];
/* Check for overflow and underflow */
for (int i = 0, imax = a->dim; i < imax; i++)
{
if (isinf(rx[i]))
float_overflow_error();
if (rx[i] == 0 && !(ax[i] == 0 || bx[i] == 0))
float_underflow_error();
}
PG_RETURN_POINTER(result);
}
/*
* Internal helper to compare vectors
*/

View File

@@ -14,6 +14,16 @@ SELECT '[1,2,3]'::vector - '[4,5,6]';
SELECT '[-3e38]'::vector - '[3e38]';
ERROR: value out of range: overflow
SELECT '[1,2,3]'::vector * '[4,5,6]';
?column?
-----------
[4,10,18]
(1 row)
SELECT '[1e37]'::vector * '[1e37]';
ERROR: value out of range: overflow
SELECT '[1e-37]'::vector * '[1e-37]';
ERROR: value out of range: underflow
SELECT vector_dims('[1,2,3]');
vector_dims
-------------

View File

@@ -2,6 +2,9 @@ SELECT '[1,2,3]'::vector + '[4,5,6]';
SELECT '[3e38]'::vector + '[3e38]';
SELECT '[1,2,3]'::vector - '[4,5,6]';
SELECT '[-3e38]'::vector - '[3e38]';
SELECT '[1,2,3]'::vector * '[4,5,6]';
SELECT '[1e37]'::vector * '[1e37]';
SELECT '[1e-37]'::vector * '[1e-37]';
SELECT vector_dims('[1,2,3]');