Added sum aggregate

This commit is contained in:
Andrew Kane
2023-07-15 20:25:30 -07:00
parent 08e7209810
commit ed1bc3e856
7 changed files with 96 additions and 0 deletions

View File

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

View File

@@ -364,6 +364,7 @@ vector_norm(vector) → double precision | Euclidean norm
Function | Description
--- | ---
avg(vector) → vector | arithmetic mean
sum(vector) → vector | sum [unreleased]
## Installation Notes

View File

@@ -11,3 +11,15 @@ CREATE OPERATOR * (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_mul,
COMMUTATOR = *
);
CREATE FUNCTION vector_sum(double precision[]) RETURNS vector
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE AGGREGATE sum(vector) (
SFUNC = vector_accum,
STYPE = double precision[],
FINALFUNC = vector_sum,
COMBINEFUNC = vector_combine,
INITCOND = '{0}',
PARALLEL = SAFE
);

View File

@@ -99,6 +99,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_sum(double precision[]) RETURNS vector
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- aggregates
CREATE AGGREGATE avg(vector) (
@@ -110,6 +113,15 @@ CREATE AGGREGATE avg(vector) (
PARALLEL = SAFE
);
CREATE AGGREGATE sum(vector) (
SFUNC = vector_accum,
STYPE = double precision[],
FINALFUNC = vector_sum,
COMBINEFUNC = vector_combine,
INITCOND = '{0}',
PARALLEL = SAFE
);
-- cast functions
CREATE FUNCTION vector(vector, integer, boolean) RETURNS vector

View File

@@ -1077,3 +1077,42 @@ vector_avg(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(result);
}
/*
* Sum vectors
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_sum);
Datum
vector_sum(PG_FUNCTION_ARGS)
{
ArrayType *statearray = PG_GETARG_ARRAYTYPE_P(0);
float8 *statevalues;
float8 n;
uint16 dim;
Vector *result;
/* Check array before using */
statevalues = CheckStateArray(statearray, "vector_sum");
n = statevalues[0];
/* SQL defines AVG of no values to be NULL */
if (n == 0.0)
PG_RETURN_NULL();
/* Create vector */
dim = STATE_DIMS(statearray);
CheckDim(dim);
result = InitVector(dim);
for (int i = 0; i < dim; i++)
{
result->x[i] = statevalues[i + 1];
/* Check for overflow */
if (isinf(result->x[i]))
float_overflow_error();
CheckElement(result->x[i]);
}
PG_RETURN_POINTER(result);
}

View File

@@ -132,3 +132,27 @@ SELECT avg(v) FROM unnest(ARRAY['[1,2]'::vector, '[3]']) v;
ERROR: expected 2 dimensions, not 1
SELECT vector_avg(array_agg(n)) FROM generate_series(1, 16002) n;
ERROR: vector cannot have more than 16000 dimensions
SELECT sum(v) FROM unnest(ARRAY['[1,2,3]'::vector, '[3,5,7]']) v;
sum
----------
[4,7,10]
(1 row)
SELECT sum(v) FROM unnest(ARRAY['[1,2,3]'::vector, '[3,5,7]', NULL]) v;
sum
----------
[4,7,10]
(1 row)
SELECT sum(v) FROM unnest(ARRAY[]::vector[]) v;
sum
-----
(1 row)
SELECT sum(v) FROM unnest(ARRAY['[1,2]'::vector, '[3]']) v;
ERROR: expected 2 dimensions, not 1
SELECT sum(v) FROM unnest(ARRAY['[3e38]'::vector, '[3e38]']) v;
ERROR: value out of range: overflow
SELECT vector_sum(array_agg(n)) FROM generate_series(1, 16002) n;
ERROR: vector cannot have more than 16000 dimensions

View File

@@ -34,3 +34,10 @@ SELECT avg(v) FROM unnest(ARRAY['[1,2,3]'::vector, '[3,5,7]', NULL]) v;
SELECT avg(v) FROM unnest(ARRAY[]::vector[]) v;
SELECT avg(v) FROM unnest(ARRAY['[1,2]'::vector, '[3]']) v;
SELECT vector_avg(array_agg(n)) FROM generate_series(1, 16002) n;
SELECT sum(v) FROM unnest(ARRAY['[1,2,3]'::vector, '[3,5,7]']) v;
SELECT sum(v) FROM unnest(ARRAY['[1,2,3]'::vector, '[3,5,7]', NULL]) v;
SELECT sum(v) FROM unnest(ARRAY[]::vector[]) v;
SELECT sum(v) FROM unnest(ARRAY['[1,2]'::vector, '[3]']) v;
SELECT sum(v) FROM unnest(ARRAY['[3e38]'::vector, '[3e38]']) v;
SELECT vector_sum(array_agg(n)) FROM generate_series(1, 16002) n;